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

processor.cpp

Go to the documentation of this file.
00001 /*
00002  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00003  * Copyright (c) 2000-2006 Baylor College of Medicine
00004  *
00005  * This software is issued under a joint BSD/GNU license. You may use the
00006  * source code in this file under either license. However, note that the
00007  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00008  * so you are responsible for compliance with the licenses of these packages
00009  * if you opt to use BSD licensing. The warranty disclaimer below holds
00010  * in either instance.
00011  *
00012  * This complete copyright notice must be included in any revised version of the
00013  * source code. Additional authorship citations may be added, but existing
00014  * author citations must be preserved.
00015  *
00016  * This program is free software; you can redistribute it and/or modify
00017  * it under the terms of the GNU General Public License as published by
00018  * the Free Software Foundation; either version 2 of the License, or
00019  * (at your option) any later version.
00020  *
00021  * This program is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00024  * GNU General Public License for more details.
00025  *
00026  * You should have received a copy of the GNU General Public License
00027  * along with this program; if not, write to the Free Software
00028  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00029  *
00030  * */
00031 
00032 #include "processor.h"
00033 #include "sparx/processor_sparx.h"
00034 #include "plugins/processor_template.h"
00035 #include "cmp.h"
00036 #include "ctf.h"
00037 #include "xydata.h"
00038 #include "emdata.h"
00039 #include "emassert.h"
00040 #include "randnum.h"
00041 #include "symmetry.h"
00042 #include "averager.h"
00043 
00044 #include <gsl/gsl_randist.h>
00045 #include <gsl/gsl_statistics.h>
00046 #include <gsl/gsl_wavelet.h>
00047 #include <gsl/gsl_wavelet2d.h>
00048 #include <gsl/gsl_multimin.h>
00049 #include <algorithm>
00050 #include <ctime>
00051 
00052 #ifdef EMAN2_USING_CUDA
00053 //#include "cuda/cuda_util.h"
00054 #include "cuda/cuda_processor.h"
00055 #endif // EMAN2_USING_CUDA
00056 
00057 using namespace EMAN;
00058 using std::reverse;
00059 
00060 const string SNREvalProcessor::NAME = "eval.maskedsnr";
00061 const string AmpweightFourierProcessor::NAME = "filter.ampweight";
00062 const string ConvolutionProcessor::NAME = "math.convolution";
00063 const string XGradientProcessor::NAME = "math.edge.xgradient";
00064 const string YGradientProcessor::NAME = "math.edge.ygradient";
00065 const string ZGradientProcessor::NAME = "math.edge.zgradient";
00066 const string Wiener2DAutoAreaProcessor::NAME = "filter.wiener2dauto";
00067 const string Wiener2DFourierProcessor::NAME = "filter.wiener2d";
00068 const string CtfSimProcessor::NAME = "math.simulatectf";
00069 const string LinearRampFourierProcessor::NAME = "filter.linearfourier";
00070 const string LoGFourierProcessor::NAME = "filter.LoG";
00071 const string DoGFourierProcessor::NAME = "filter.DoG";
00072 const string HighpassAutoPeakProcessor::NAME = "filter.highpass.autopeak";
00073 const string LinearRampProcessor::NAME = "eman1.filter.ramp";
00074 const string AbsoluateValueProcessor::NAME = "math.absvalue";
00075 const string FloorValueProcessor::NAME = "math.floor";
00076 const string BooleanProcessor::NAME = "threshold.notzero";
00077 const string KmeansSegmentProcessor::NAME = "segment.kmeans";
00078 const string DistanceSegmentProcessor::NAME = "segment.distance";
00079 const string WatershedProcessor::NAME = "segment.watershed";
00080 const string RecipCarefullyProcessor::NAME = "math.reciprocal";
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 StripeXYProcessor::NAME = "math.xystripefix";
00179 const string IndexMaskFileProcessor::NAME = "mask.fromfile";
00180 const string CoordinateMaskFileProcessor::NAME = "mask.fromfile.sizediff";
00181 const string PaintProcessor::NAME = "mask.paint";
00182 const string DirectionalSumProcessor::NAME = "misc.directional_sum";
00183 template<> const string BinaryOperateProcessor<MaxPixelOperator>::NAME = "math.max";            // These 2 should not really be processors
00184 template<> const string BinaryOperateProcessor<MinPixelOperator>::NAME = "math.min";
00185 const string MaxPixelOperator::NAME = "math.max";
00186 const string MinPixelOperator::NAME = "math.min";
00187 const string MatchSFProcessor::NAME = "filter.matchto";
00188 const string SetSFProcessor::NAME = "filter.setstrucfac";
00189 const string SmartMaskProcessor::NAME = "mask.smart";
00190 const string IterBinMaskProcessor::NAME = "mask.addshells.gauss";
00191 const string TestImagePureGaussian::NAME = "testimage.puregaussian";
00192 const string TestImageFourierNoiseGaussian::NAME = "testimage.noise.fourier.gaussian";
00193 const string TestImageFourierNoiseProfile::NAME = "testimage.noise.fourier.profile";
00194 const string CTFSNRWeightProcessor::NAME = "ctf.snr.weight";
00195 const string TestImageLineWave::NAME = "testimage.linewave";
00196 const string TestTomoImage::NAME = "testimage.tomo.objects";
00197 const string TestImageGradient::NAME = "testimage.gradient";
00198 const string TestImageAxes::NAME = "testimage.axes";
00199 const string TestImageGaussian::NAME = "testimage.gaussian";
00200 const string TestImageScurve::NAME = "testimage.scurve";
00201 const string TestImageSphericalWave::NAME = "testimage.sphericalwave";
00202 const string TestImageSinewave::NAME = "testimage.sinewave";
00203 const string TestImageSinewaveCircular::NAME = "testimage.sinewave.circular";
00204 const string TestImageSquarecube::NAME = "testimage.squarecube";
00205 const string TestImageEllipse::NAME = "testimage.ellipsoid";
00206 const string TestImageHollowEllipse::NAME = "testimage.ellipsoid.hollow";
00207 const string TestImageCirclesphere::NAME = "testimage.circlesphere";
00208 const string TestImageNoiseUniformRand::NAME = "testimage.noise.uniform.rand";
00209 const string TestImageNoiseGauss::NAME = "testimage.noise.gauss";
00210 const string TestImageCylinder::NAME = "testimage.cylinder";
00211 const string CCDNormProcessor::NAME = "filter.ccdnorm";
00212 const string WaveletProcessor::NAME = "basis.wavelet";
00213 const string TomoTiltEdgeMaskProcessor::NAME = "tomo.tiltedgemask";
00214 const string TomoTiltAngleWeightProcessor::NAME = "tomo.tiltangleweight";
00215 const string FFTProcessor::NAME = "basis.fft";
00216 const string RadialProcessor::NAME = "mask.radialprofile";
00217 const string HistogramBin::NAME = "histogram.bin";
00218 const string ModelEMCylinderProcessor::NAME = "math.model_em_cylinder";
00219 const string ApplyPolynomialProfileToHelix::NAME = "math.poly_radial_profile";
00220 const string BinarySkeletonizerProcessor::NAME="gorgon.binary_skel";
00221 const string MirrorProcessor::NAME = "xform.mirror";
00222 const string NewLowpassTopHatProcessor::NAME = "filter.lowpass.tophat";
00223 const string NewHighpassTopHatProcessor::NAME = "filter.highpass.tophat";
00224 const string NewBandpassTopHatProcessor::NAME = "filter.bandpass.tophat";
00225 const string NewHomomorphicTopHatProcessor::NAME = "filter.homomorphic.tophat";
00226 const string NewLowpassGaussProcessor::NAME = "filter.lowpass.gauss";
00227 const string LowpassAutoBProcessor::NAME="filter.lowpass.autob";
00228 const string NewHighpassGaussProcessor::NAME = "filter.highpass.gauss";
00229 const string NewBandpassGaussProcessor::NAME = "filter.bandpass.gauss";
00230 const string NewHomomorphicGaussProcessor::NAME = "filter.homomorphic.gauss";
00231 const string NewInverseGaussProcessor::NAME = "filter.gaussinverse";
00232 const string SHIFTProcessor::NAME = "filter.shift";
00233 const string InverseKaiserI0Processor::NAME = "filter.kaiser_io_inverse";
00234 const string InverseKaiserSinhProcessor::NAME = "filter.kaisersinhinverse";
00235 const string NewRadialTableProcessor::NAME = "filter.radialtable";
00236 const string LowpassRandomPhaseProcessor::NAME = "filter.lowpass.randomphase";
00237 const string NewLowpassButterworthProcessor::NAME = "filter.lowpass.butterworth";
00238 const string NewHighpassButterworthProcessor::NAME = "filter.highpass.butterworth";
00239 const string NewHomomorphicButterworthProcessor::NAME = "filter.homomorphic.butterworth";
00240 const string NewLowpassTanhProcessor::NAME = "filter.lowpass.tanh";
00241 const string NewHighpassTanhProcessor::NAME = "filter.highpass.tanh";
00242 const string NewHomomorphicTanhProcessor::NAME = "filter.homomorphic.tanh";
00243 const string NewBandpassTanhProcessor::NAME = "filter.bandpass.tanh";
00244 const string CTF_Processor::NAME = "filter.CTF_";
00245 const string ConvolutionKernelProcessor::NAME = "filter.convolution.kernel";
00246 const string RotateInFSProcessor::NAME = "rotateinfs";
00247 
00248 //#ifdef EMAN2_USING_CUDA
00249 //const string CudaMultProcessor::NAME = "cuda.math.mult";
00250 //const string CudaCorrelationProcessor::NAME = "cuda.correlate";
00251 //#endif //EMAN2_USING_CUDA
00252 
00253 #if 0
00254 //const string XYZProcessor::NAME = "XYZ";
00255 #endif  //0
00256 
00257 
00258 template <> Factory < Processor >::Factory()
00259 {
00260         force_add<HighpassAutoPeakProcessor>();
00261         force_add<LinearRampFourierProcessor>();
00262         force_add<LoGFourierProcessor>();
00263         force_add<DoGFourierProcessor>();
00264 
00265         force_add<AmpweightFourierProcessor>();
00266         force_add<Wiener2DFourierProcessor>();
00267         force_add<LowpassAutoBProcessor>();
00268         
00269         force_add<LinearPyramidProcessor>();
00270         force_add<LinearRampProcessor>();
00271         force_add<AbsoluateValueProcessor>();
00272         force_add<FloorValueProcessor>();
00273         force_add<BooleanProcessor>();
00274         force_add<KmeansSegmentProcessor>();
00275         force_add<DistanceSegmentProcessor>();
00276         force_add<ValuePowProcessor>();
00277         force_add<ValueSquaredProcessor>();
00278         force_add<ValueSqrtProcessor>();
00279         force_add<Rotate180Processor>();
00280         force_add<TransformProcessor>();
00281         force_add<ScaleTransformProcessor>();
00282         force_add<ApplySymProcessor>();
00283         force_add<IntTranslateProcessor>();
00284         force_add<RecipCarefullyProcessor>();
00285 
00286         force_add<ClampingProcessor>();
00287         force_add<NSigmaClampingProcessor>();
00288 
00289         force_add<ToZeroProcessor>();
00290         force_add<ToMinvalProcessor>();
00291         force_add<CutToZeroProcessor>();
00292         force_add<BinarizeProcessor>();
00293 //      force_add<BinarizeAmpProcessor>();
00294         force_add<BinarizeFourierProcessor>();
00295         force_add<CollapseProcessor>();
00296         force_add<LinearXformProcessor>();
00297 
00298         force_add<ExpProcessor>();
00299         force_add<RangeThresholdProcessor>();
00300         force_add<SigmaProcessor>();
00301         force_add<LogProcessor>();
00302         force_add<FiniteProcessor>();
00303 
00304         force_add< BinaryOperateProcessor<MaxPixelOperator> >();
00305         force_add< BinaryOperateProcessor<MinPixelOperator> >();
00306 
00307         force_add<PaintProcessor>();
00308         force_add<WatershedProcessor>();
00309         force_add<MaskSharpProcessor>();
00310         force_add<MaskEdgeMeanProcessor>();
00311         force_add<MaskNoiseProcessor>();
00312         force_add<MaskGaussProcessor>();
00313         force_add<MaskGaussNonuniformProcessor>();
00314         force_add<MaskGaussInvProcessor>();
00315 
00316         force_add<MaxShrinkProcessor>();
00317         force_add<MinShrinkProcessor>();
00318         force_add<MeanShrinkProcessor>();
00319         force_add<MedianShrinkProcessor>();
00320         force_add<FFTResampleProcessor>();
00321         force_add<NonConvexProcessor>();
00322 
00323         force_add<MakeRadiusSquaredProcessor>();
00324         force_add<MakeRadiusProcessor>();
00325 
00326         force_add<ComplexNormPixel>();
00327 
00328         force_add<LaplacianProcessor>();
00329         force_add<ZeroConstantProcessor>();
00330 
00331         force_add<BoxMedianProcessor>();
00332         force_add<BoxSigmaProcessor>();
00333         force_add<BoxMaxProcessor>();
00334 
00335         force_add<MinusPeakProcessor>();
00336         force_add<PeakOnlyProcessor>();
00337         force_add<DiffBlockProcessor>();
00338 
00339         force_add<CutoffBlockProcessor>();
00340 //      force_add<GradientRemoverProcessor>();
00341         force_add<GradientPlaneRemoverProcessor>();
00342         force_add<FlattenBackgroundProcessor>();
00343         force_add<VerticalStripeProcessor>();
00344         force_add<RealToFFTProcessor>();
00345         force_add<SigmaZeroEdgeProcessor>();
00346         force_add<RampProcessor>();
00347 
00348         force_add<BeamstopProcessor>();
00349         force_add<MeanZeroEdgeProcessor>();
00350         force_add<AverageXProcessor>();
00351         force_add<DecayEdgeProcessor>();
00352         force_add<ZeroEdgeRowProcessor>();
00353         force_add<ZeroEdgePlaneProcessor>();
00354 
00355         force_add<BilateralProcessor>();
00356 
00357         force_add<ConvolutionProcessor>();
00358 
00359         force_add<NormalizeStdProcessor>();
00360         force_add<NormalizeUnitProcessor>();
00361         force_add<NormalizeUnitSumProcessor>();
00362         force_add<NormalizeMaskProcessor>();
00363         force_add<NormalizeEdgeMeanProcessor>();
00364         force_add<NormalizeCircleMeanProcessor>();
00365         force_add<NormalizeLREdgeMeanProcessor>();
00366         force_add<NormalizeMaxMinProcessor>();
00367         force_add<NormalizeByMassProcessor>();
00368         force_add<NormalizeRowProcessor>();
00369         force_add<NormalizeRampNormVar>();
00370 
00371         force_add<HistogramBin>();
00372 
00373         force_add<NormalizeToLeastSquareProcessor>();
00374 
00375         force_add<RotationalAverageProcessor>();
00376         force_add<RotationalSubstractProcessor>();
00377         force_add<FlipProcessor>();
00378         force_add<TransposeProcessor>();
00379         force_add<MirrorProcessor>();
00380 
00381         force_add<AddNoiseProcessor>();
00382         force_add<AddSigmaNoiseProcessor>();
00383         force_add<AddRandomNoiseProcessor>();
00384 
00385         force_add<PhaseToCenterProcessor>();
00386         force_add<PhaseToCornerProcessor>();
00387         force_add<FourierToCenterProcessor>();
00388         force_add<FourierToCornerProcessor>();
00389         force_add<AutoMask2DProcessor>();
00390         force_add<AutoMask3DProcessor>();
00391         force_add<AutoMask3D2Processor>();
00392         force_add<AddMaskShellProcessor>();
00393         force_add<AutoMaskAsymUnit>();
00394 
00395         force_add<CTFSNRWeightProcessor>();
00396 
00397         force_add<ToMassCenterProcessor>();
00398         force_add<PhaseToMassCenterProcessor>();
00399         force_add<ACFCenterProcessor>();
00400         force_add<SNRProcessor>();
00401 
00402         force_add<XGradientProcessor>();
00403         force_add<YGradientProcessor>();
00404         force_add<ZGradientProcessor>();
00405 
00406         force_add<FileFourierProcessor>();
00407 
00408         force_add<SymSearchProcessor>();
00409         force_add<StripeXYProcessor>();
00410         force_add<LocalNormProcessor>();
00411 
00412         force_add<IndexMaskFileProcessor>();
00413         force_add<CoordinateMaskFileProcessor>();
00414         force_add<SetSFProcessor>();
00415         force_add<MatchSFProcessor>();
00416 
00417         force_add<SmartMaskProcessor>();
00418         force_add<IterBinMaskProcessor>();
00419 
00420         force_add<TestImageGaussian>();
00421         force_add<TestImagePureGaussian>();
00422         force_add<TestImageSinewave>();
00423         force_add<TestImageSphericalWave>();
00424         force_add<TestImageSinewaveCircular>();
00425         force_add<TestImageSquarecube>();
00426         force_add<TestImageCirclesphere>();
00427         force_add<TestImageAxes>();
00428         force_add<TestImageNoiseUniformRand>();
00429         force_add<TestImageNoiseGauss>();
00430         force_add<TestImageScurve>();
00431         force_add<TestImageCylinder>();
00432         force_add<TestImageGradient>();
00433         force_add<TestTomoImage>();
00434         force_add<TestImageLineWave>();
00435         force_add<TestImageEllipse>();
00436         force_add<TestImageHollowEllipse>();
00437         force_add<TestImageFourierNoiseGaussian>();
00438         force_add<TestImageFourierNoiseProfile>();
00439 
00440         force_add<TomoTiltEdgeMaskProcessor>();
00441         force_add<TomoTiltAngleWeightProcessor>();
00442 
00443         force_add<NewLowpassTopHatProcessor>();
00444         force_add<NewHighpassTopHatProcessor>();
00445         force_add<NewBandpassTopHatProcessor>();
00446         force_add<NewHomomorphicTopHatProcessor>();
00447         force_add<NewLowpassGaussProcessor>();
00448         force_add<NewHighpassGaussProcessor>();
00449         force_add<NewBandpassGaussProcessor>();
00450         force_add<NewHomomorphicGaussProcessor>();
00451         force_add<NewInverseGaussProcessor>();
00452         force_add<LowpassRandomPhaseProcessor>();
00453         force_add<NewLowpassButterworthProcessor>();
00454         force_add<NewHighpassButterworthProcessor>();
00455         force_add<NewHomomorphicButterworthProcessor>();
00456         force_add<NewLowpassTanhProcessor>();
00457         force_add<NewHighpassTanhProcessor>();
00458         force_add<NewBandpassTanhProcessor>();
00459         force_add<NewHomomorphicTanhProcessor>();
00460         force_add<NewRadialTableProcessor>();
00461         force_add<InverseKaiserI0Processor>();
00462         force_add<InverseKaiserSinhProcessor>();
00463         force_add<CCDNormProcessor>();
00464         force_add<CTF_Processor>();
00465         force_add<SHIFTProcessor>();
00466 
00467         force_add<WaveletProcessor>();
00468         force_add<FFTProcessor>();
00469         force_add<RadialProcessor>();
00470 
00471         force_add<DirectionalSumProcessor>();
00472         force_add<ConvolutionKernelProcessor>();
00473         
00474         //Gorgon-related processors
00475         force_add<ModelEMCylinderProcessor>();
00476         force_add<ApplyPolynomialProfileToHelix>();
00477         force_add<BinarySkeletonizerProcessor>();
00478         force_add<RotateInFSProcessor>();
00479 
00480 //#ifdef EMAN2_USING_CUDA
00481 //      force_add<CudaMultProcessor>();
00482 //      force_add<CudaCorrelationProcessor>();
00483 //#endif // EMAN2_USING_CUDA
00484 
00485 //      force_add<XYZProcessor>();
00486 }
00487 
00488 void FiniteProcessor::process_pixel(float *x) const
00489 {
00490         if ( !Util::goodf(x) ) {
00491                 *x = to;
00492         }
00493 }
00494 
00495 
00496 EMData* Processor::process(const EMData * const image)
00497 {
00498         EMData * result = image->copy();
00499         process_inplace(result);
00500         return result;
00501 }
00502 
00503 void ImageProcessor::process_inplace(EMData * image)
00504 {
00505         if (!image) {
00506                 LOGWARN("NULL image");
00507                 return;
00508         }
00509 
00510         EMData *processor_image = create_processor_image();
00511 
00512         if (image->is_complex()) {
00513                 (*image) *= *processor_image;
00514         }
00515         else {
00516                 EMData *fft = image->do_fft();
00517                 (*fft) *= (*processor_image);
00518                 EMData *ift = fft->do_ift();
00519 
00520                 float *data = image->get_data();
00521                 float *t = data;
00522                 float *ift_data = ift->get_data();
00523 
00524                 data = ift_data;
00525                 ift_data = t;
00526 
00527                 ift->update();
00528 
00529                 if( fft )
00530                 {
00531                         delete fft;
00532                         fft = 0;
00533                 }
00534 
00535                 if( ift )
00536                 {
00537                         delete ift;
00538                         ift = 0;
00539                 }
00540         }
00541 
00542         image->update();
00543 }
00544 
00545 #define FFTRADIALOVERSAMPLE 4
00546 void FourierProcessor::process_inplace(EMData * image)
00547 {
00548         if (!image) {
00549                 LOGWARN("NULL Image");
00550                 return;
00551         }
00552 
00553         preprocess(image);
00554 
00555         int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
00556         float step=0.5f/array_size;
00557 
00558         vector < float >yarray(array_size);
00559 
00560         create_radial_func(yarray);
00561 
00562         if (image->is_complex()) {
00563                 image->apply_radial_func(0, step, yarray);
00564         }
00565         else {
00566                 EMData *fft = image->do_fft();
00567                 fft->apply_radial_func(0, step, yarray);
00568                 EMData *ift = fft->do_ift();
00569 
00570                 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
00571 
00572                 //ift->update(); Unecessary
00573 
00574                 if( fft )
00575                 {
00576                         delete fft;
00577                         fft = 0;
00578                 }
00579 
00580                 if( ift )
00581                 {
00582                         delete ift;
00583                         ift = 0;
00584                 }
00585         }
00586 
00587         image->update();
00588 }
00589 
00590 void FourierAnlProcessor::process_inplace(EMData * image)
00591 {
00592         if (!image) {
00593                 LOGWARN("NULL Image");
00594                 return;
00595         }
00596 
00597         preprocess(image);
00598 
00599 //      int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
00600 //      float step=0.5f/array_size;
00601 //
00602 //      vector < float >yarray(array_size);
00603 
00604 
00605         if (image->is_complex()) {
00606                 vector <float>yarray = image->calc_radial_dist(image->get_ysize()/2,0,1.0,1);
00607                 create_radial_func(yarray,image);
00608                 image->apply_radial_func(0, 0.5f/yarray.size(), yarray);
00609         }
00610         else {
00611                 EMData *fft = image->do_fft();
00612                 vector <float>yarray = fft->calc_radial_dist(fft->get_ysize()/2,0,1.0,1);
00613                 create_radial_func(yarray,image);
00614                 fft->apply_radial_func(0, 0.5f/yarray.size(), yarray,0);                // 4/30/10 stevel turned off interpolation to fix problem with matched filter
00615                 EMData *ift = fft->do_ift();
00616 
00617                 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
00618 
00619                 //ift->update(); Unecessary
00620 
00621                 delete fft;
00622                 delete ift;
00623 
00624         }
00625 
00626         image->update();
00627 }
00628 
00629 void LowpassAutoBProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const{
00630         float apix=(float)image->get_attr("apix_x");
00631         int verbose=(int)params["verbose"];
00632 //      int adaptnoise=params.set_default("adaptnoise",0);
00633         float noisecutoff=(float)params.set_default("noisecutoff",0.0);
00634         if (apix<=0 || apix>7.0f) throw ImageFormatException("0 < apix_x < 7.0");
00635         float ds=1.0f/(apix*image->get_xsize());        // 0.5 is because radial mask is 2x oversampled
00636         unsigned int start=(int)floor(1.0/(15.0*ds));
00637         unsigned int end=radial_mask.size()-2;
00638         if (noisecutoff>0) end=(int)floor(noisecutoff/ds);
00639         if (end>radial_mask.size()-2) {
00640                 printf("WARNING: specified noisecutoff too close to Nyquist, reset !");
00641                 end=radial_mask.size()-2;
00642         }
00643         if (end<start+2) {
00644                 printf("WARNING: noise cutoff too close to 15 A ! Results will not be good...");
00645                 start=end-5;
00646         }
00647 
00648         FILE *out=NULL;
00649         if (verbose>2)  out=fopen("fitplot.txt","w");
00650         int N=(radial_mask.size()-start-2);
00651         float *x=(float *)malloc(N*sizeof(float));
00652         float *y=(float *)malloc(N*sizeof(float));
00653         float *dy=(float *)malloc(N*sizeof(float));
00654         for (unsigned int i=start; i<radial_mask.size()-2; i++ ) {              // -2 is arbitrary because sometimes the last pixel or two have funny values
00655                 x[i-start]=ds*ds*i*i;
00656                 if (radial_mask[i]>0) y[i-start]=log(radial_mask[i]); // ok
00657                 else if (i>start) y[i-start]=y[i-start-1];              // not good
00658                 else y[i-start]=0.0;                                                    // bad
00659                 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
00660                 if (out) fprintf(out,"%f\t%f\n",x[i-start],y[i-start]);
00661         }
00662         if (out) fclose(out);
00663 
00664         float slope=0,intercept=0;
00665         Util::calc_least_square_fit(end-start, x,y,&slope,&intercept,1);
00666 
00667         if (verbose) printf("slope=%f  intercept=%f\n",slope,intercept);
00668 
00669         float B=(float)params["bfactor"]+slope*4.0f/2.0f;               // *4 is for Henderson definition, 2.0 is for intensity vs amplitude
00670         float B2=(float)params["bfactor"];
00671 
00672         if (verbose) printf("User B = %1.2f  Corrective B = %1.2f  Total B=%1.3f\n",(float)params["bfactor"],slope*2.0,B);
00673 
00674         float cutval=exp(-B*pow(end*ds,2.0f)/4.0f)/exp(-B2*pow(end*ds,2.0f)/4.0f);
00675         for (unsigned int i=0; i<radial_mask.size(); i++) {
00676                 if (i<=end) radial_mask[i]=exp(-B*pow(i*ds,2.0f)/4.0f);
00677                 else radial_mask[i]=cutval*exp(-B2*pow(i*ds,2.0f)/4.0f);
00678         }
00679         if (verbose>1) Util::save_data(0,ds,radial_mask,"filter.txt");
00680 
00681         free(x);
00682         free(y);
00683         free(dy);
00684  }
00685 
00686 void SNREvalProcessor::process_inplace(EMData * image)
00687 {
00688         int ys=image->get_ysize();
00689 
00690         EMData *mask1=new EMData(ys,ys,1);
00691         mask1->process_inplace("mask.gaussian",Dict("outer_radius", ys/2.0));
00692         EMData *mask2=mask1->copy();
00693         mask2->mult(-1.0f);
00694         mask2->add(1.0);
00695         mask2->process_inplace("mask.decayedge2d",Dict("width",4));
00696 
00697 /*
00698 
00699 
00700 
00701 mask1=EMData(ys2,ys2,1)
00702                 mask1.to_one()
00703                 mask1.process_inplace("mask.gaussian",{"outer_radius":radius})
00704                 mask2=mask1.copy()*-1+1
00705 #               mask1.process_inplace("mask.decayedge2d",{"width":4})
00706                 mask2.process_inplace("mask.decayedge2d",{"width":4})
00707                 mask1.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
00708                 mask2.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
00709                 ratio1=mask1.get_attr("square_sum")/(ys*ys)     #/1.035
00710                 ratio2=mask2.get_attr("square_sum")/(ys*ys)
00711                 masks[(ys,radius)]=(mask1,ratio1,mask2,ratio2)
00712 
00713 
00714 
00715 */
00716 }
00717 
00718 void AmpweightFourierProcessor::process_inplace(EMData * image)
00719 {
00720         EMData *fft;
00721         float *fftd;
00722         int f=0;
00723 //      static float sum1=0,sum1a=0;
00724 //      static double sum2=0,sum2a=0;
00725 
00726         if (!image) {
00727                 LOGWARN("NULL Image");
00728                 return;
00729         }
00730 
00731         if (!image->is_complex()) {
00732                 fft = image->do_fft();
00733                 fftd = fft->get_data();
00734                 f=1;
00735         }
00736         else {
00737                 fft=image;
00738                 fftd=image->get_data();
00739         }
00740         float *sumd = NULL;
00741         if (sum) sumd=sum->get_data();
00742 //printf("%d %d    %d %d\n",fft->get_xsize(),fft->get_ysize(),sum->get_xsize(),sum->get_ysize());
00743         size_t n = (size_t)fft->get_xsize()*fft->get_ysize()*fft->get_zsize();
00744         for (size_t i=0; i<n; i+=2) {
00745                 float c;
00746                 if (dosqrt) c=pow(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1],0.25f);
00747 #ifdef  _WIN32
00748                 else c = static_cast<float>(_hypot(fftd[i],fftd[i+1]));
00749 #else
00750                 else c = static_cast<float>(hypot(fftd[i],fftd[i+1]));
00751 #endif  //_WIN32
00752                 if (c==0) c=1.0e-30f;   // prevents divide by zero in normalization
00753                 fftd[i]*=c;
00754                 fftd[i+1]*=c;
00755                 if (sumd) { sumd[i]+=c; sumd[i+1]+=0; }
00756 
00757                 // debugging
00758 /*              if (i==290*1+12) {
00759                         sum1+=fftd[i];
00760                         sum2+=fftd[i];
00761                         printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1,sum2,fftd[i],fftd[i+1],sumd[i],c);
00762                 }
00763                 if (i==290*50+60) {
00764                         sum1a+=fftd[i];
00765                         sum2a+=fftd[i];
00766                         printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1a,sum2a,fftd[i],fftd[i+1],sumd[i],c);
00767         }*/
00768         }
00769 
00770         if (f) {
00771                 fft->update();
00772                 EMData *ift=fft->do_ift();
00773                 memcpy(image->get_data(),ift->get_data(),n*sizeof(float));
00774                 delete fft;
00775                 delete ift;
00776         }
00777 
00778         sum->update();
00779         image->update();
00780 
00781 }
00782 
00783 void DistanceSegmentProcessor::process_inplace(EMData *)
00784 {
00785         printf("Process inplace not implemented. Please use process.\n");
00786         return;
00787 }
00788 
00789 
00790 EMData *DistanceSegmentProcessor::process(const EMData * const image)
00791 {
00792         EMData * result = image->copy();
00793 
00794         float thr = params.set_default("thr",0.9f);
00795         float minsegsep = params.set_default("minsegsep",5.0f);
00796         float maxsegsep = params.set_default("maxsegsep",5.1f);
00797         int verbose = params.set_default("verbose",0);
00798 
00799         vector<Pixel> pixels=image->calc_highest_locations(thr);
00800 
00801         vector<float> centers(3);       // only 1 to start
00802         int nx=image->get_xsize();
00803         int ny=image->get_ysize();
00804         int nz=image->get_zsize();
00805 //      int nxy=nx*ny;
00806 
00807         // seed the process with the highest valued point
00808         centers[0]=(float)pixels[0].x;
00809         centers[1]=(float)pixels[0].y;
00810         centers[2]=(float)pixels[0].z;
00811         pixels.erase(pixels.begin());
00812 
00813         // outer loop. We add one center per iteration
00814         // This is NOT a very efficient algorithm, it assumes points are fairly sparse
00815         while (pixels.size()>0) {
00816                 // iterate over pixels until we find a new center (then stop), delete any 'bad' pixels
00817                 // no iterators because we remove elements
00818 
00819                 for (unsigned int i=0; i<pixels.size(); i++) {
00820 
00821                         Pixel p=pixels[i];
00822                         // iterate over existing centers to see if this pixel should be removed ... technically we only should need to check the last center
00823                         for (unsigned int j=0; j<centers.size(); j+=3) {
00824                                 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
00825                                 if (d<minsegsep) {              // conflicts with existing center, erase
00826                                         pixels.erase(pixels.begin()+i);
00827                                         i--;
00828                                         break;
00829                                 }
00830                         }
00831                 }
00832 
00833                 int found=0;
00834                 for (unsigned int i=0; i<pixels.size() && found==0; i++) {
00835                         Pixel p=pixels[i];
00836 
00837                         // iterate again to see if this may be a new valid center. Start at the end so we tend to build chains
00838                         for (unsigned int j=centers.size()-3; j>0; j-=3) {
00839                                 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
00840                                 if (d<maxsegsep) {              // we passed minsegsep question already, so we know we're in the 'good' range
00841                                         centers.push_back((float)p.x);
00842                                         centers.push_back((float)p.y);
00843                                         centers.push_back((float)p.z);
00844                                         pixels.erase(pixels.begin()+i); // in the centers list now, don't need it any more
00845                                         found=1;
00846                                         break;
00847                                 }
00848                         }
00849                 }
00850 
00851                 // If we went through the whole list and didn't find one, we need to reseed again
00852                 if (!found && pixels.size()) {
00853                         if (verbose) printf("New chain\n");
00854                         centers.push_back((float)pixels[0].x);
00855                         centers.push_back((float)pixels[0].y);
00856                         centers.push_back((float)pixels[0].z);
00857                         pixels.erase(pixels.begin());
00858                 }
00859 
00860                 if (verbose) printf("%d points found\n",(int)(centers.size()/3));
00861         }
00862 
00863         // after we have our list of centers classify pixels
00864         for (int z=0; z<nz; z++) {
00865                 for (int y=0; y<ny; y++) {
00866                         for (int x=0; x<nz; x++) {
00867                                 if (image->get_value_at(x,y,z)<thr) {
00868                                         result->set_value_at(x,y,z,-1.0);               //below threshold -> -1 (unclassified)
00869                                         continue;
00870                                 }
00871                                 int bcls=-1;                    // best matching class
00872                                 float bdist=(float)(nx+ny+nz);  // distance for best class
00873                                 for (unsigned int c=0; c<centers.size()/3; c++) {
00874                                         float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
00875                                         if (d<bdist) { bdist=d; bcls=c; }
00876                                 }
00877                                 result->set_value_at(x,y,z,(float)bcls);                // set the pixel to the class number
00878                         }
00879                 }
00880         }
00881 
00882         result->set_attr("segment_centers",centers);
00883 
00884         return result;
00885 }
00886 
00887 EMData* ApplySymProcessor::process(const EMData * const image)
00888 {
00889         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1"));
00890         vector<Transform> transforms = sym->get_syms();
00891         
00892         Averager* imgavg = Factory<Averager>::get((string)params.set_default("avger","mean"));
00893         for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
00894                 Transform t = *trans_it;
00895                 EMData* transformed = image->process("xform",Dict("transform",&t));
00896                 imgavg->add_image(transformed);
00897                 delete transformed;
00898         }
00899         return imgavg->finish();
00900 }
00901 
00902 void ApplySymProcessor::process_inplace(EMData* image)
00903 {
00904         cout << "Not implemented yet" << endl;
00905 }
00906 
00907 EMData* KmeansSegmentProcessor::process(const EMData * const image)
00908 {
00909         EMData * result = image->copy();
00910 
00911         int nseg = params.set_default("nseg",12);
00912         float thr = params.set_default("thr",-1.0e30f);
00913         int ampweight = params.set_default("ampweight",1);
00914         float maxsegsize = params.set_default("maxsegsize",10000.0f);
00915         float minsegsep = params.set_default("minsegsep",0.0f);
00916         int maxiter = params.set_default("maxiter",100);
00917         int maxvoxmove = params.set_default("maxvoxmove",25);
00918         int verbose = params.set_default("verbose",0);
00919 
00920         vector<float> centers(nseg*3);
00921         vector<float> count(nseg);
00922         int nx=image->get_xsize();
00923         int ny=image->get_ysize();
00924         int nz=image->get_zsize();
00925 //      int nxy=nx*ny;
00926 
00927         // seed
00928         for (int i=0; i<nseg*3; i+=3) {
00929                 centers[i]=  Util::get_frand(0.0f,(float)nx);
00930                 centers[i+1]=Util::get_frand(0.0f,(float)ny);
00931                 centers[i+2]=Util::get_frand(0.0f,(float)nz);
00932         }
00933 
00934         for (int iter=0; iter<maxiter; iter++) {
00935                 // **** classify
00936                 size_t pixmov=0;                // count of moved pixels
00937                 for (int z=0; z<nz; z++) {
00938                         for (int y=0; y<ny; y++) {
00939                                 for (int x=0; x<nz; x++) {
00940                                         if (image->get_value_at(x,y,z)<thr) {
00941                                                 result->set_value_at(x,y,z,-1.0);               //below threshold -> -1 (unclassified)
00942                                                 continue;
00943                                         }
00944                                         int bcls=-1;                    // best matching class
00945                                         float bdist=(float)(nx+ny+nz);  // distance for best class
00946                                         for (int c=0; c<nseg; c++) {
00947                                                 float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
00948                                                 if (d<bdist) { bdist=d; bcls=c; }
00949                                         }
00950                                         if ((int)result->get_value_at(x,y,z)!=bcls) pixmov++;
00951                                         if (bdist>maxsegsize) result->set_value_at(x,y,z,-1);           // pixel is too far from any center
00952                                         else result->set_value_at(x,y,z,(float)bcls);           // set the pixel to the class number
00953                                 }
00954                         }
00955                 }
00956 
00957                 // **** adjust centers
00958                 for (int i=0; i<nseg*3; i++) centers[i]=0;
00959                 for (int i=0; i<nseg; i++) count[i]=0;
00960 
00961                 // weighted sums
00962                 for (int z=0; z<nz; z++) {
00963                         for (int y=0; y<ny; y++) {
00964                                 for (int x=0; x<nz; x++) {
00965                                         int cls = (int)result->get_value_at(x,y,z);
00966                                         if (cls==-1) continue;
00967                                         float w=1.0;
00968                                         if (ampweight) w=image->get_value_at(x,y,z);
00969 
00970                                         centers[cls*3]+=x*w;
00971                                         centers[cls*3+1]+=y*w;
00972                                         centers[cls*3+2]+=z*w;
00973                                         count[cls]+=w;
00974                                 }
00975                         }
00976                 }
00977 
00978                 // now each becomes center of mass, or gets randomly reseeded
00979                 int nreseed=0;
00980                 for (int c=0; c<nseg; c++) {
00981                         // reseed
00982                         if (count[c]==0) {
00983                                 nreseed++;
00984                                 do {
00985                                         centers[c*3]=  Util::get_frand(0.0f,(float)nx);
00986                                         centers[c*3+1]=Util::get_frand(0.0f,(float)ny);
00987                                         centers[c*3+2]=Util::get_frand(0.0f,(float)nz);
00988                                 } 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
00989                         }
00990                         // center of mass
00991                         else {
00992                                 centers[c*3]/=count[c];
00993                                 centers[c*3+1]/=count[c];
00994                                 centers[c*3+2]/=count[c];
00995                         }
00996                 }
00997 
00998                 // with minsegsep, check separation
00999                 if (minsegsep>0) {
01000                         for (int c1=0; c1<nseg-1; c1++) {
01001                                 for (int c2=c1+1; c2<nseg; c2++) {
01002                                         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) {
01003                                                 nreseed++;
01004                                                 do {
01005                                                         centers[c1*3]=  Util::get_frand(0.0f,(float)nx);
01006                                                         centers[c1*3+1]=Util::get_frand(0.0f,(float)ny);
01007                                                         centers[c1*3+2]=Util::get_frand(0.0f,(float)nz);
01008                                                 } while (image->get_value_at((int)centers[c1*3],(int)centers[c1*3+1],(int)centers[c1*3+2])<thr);
01009                                         }
01010                                 }
01011                         }
01012                 }
01013 
01014 
01015                 if (verbose) printf("Iteration %3d: %6ld voxels moved, %3d classes reseeded\n",iter,pixmov,nreseed);
01016                 if (nreseed==0 && pixmov<(size_t)maxvoxmove) break;             // termination conditions met
01017         }
01018 
01019         result->set_attr("segment_centers",centers);
01020 
01021         return result;
01022 }
01023 
01024 void KmeansSegmentProcessor::process_inplace(EMData *)
01025 {
01026         printf("Process inplace not implemented. Please use process.\n");
01027         return;
01028 }
01029 
01030 
01031 void LinearPyramidProcessor::process_inplace(EMData *image) {
01032 
01033         if (image->get_zsize()!=1) { throw ImageDimensionException("Only 2-D images supported"); }
01034 
01035         float *d=image->get_data();
01036         int nx=image->get_xsize();
01037         int ny=image->get_ysize();
01038 
01039         for (int y=0; y<ny; y++) {
01040                 for (int x=0; x<nx; x++) {
01041                         int l=x+y*nx;
01042                         d[l]*=1.0f-abs(x-nx/2)*abs(y-ny/2)*4.0f/(nx*ny);
01043                 }
01044         }
01045         image->update();
01046 }
01047 
01048 EMData * Wiener2DAutoAreaProcessor::process(const EMData * image)
01049 {
01050 // TODO NOT IMPLEMENTED YET !!!
01051         EMData *ret = 0;
01052         const EMData *fft;
01053         float *fftd;
01054         int f=0;
01055 
01056         if (!image) {
01057                 LOGWARN("NULL Image");
01058                 return ret;
01059         }
01060         throw NullPointerException("Processor not yet implemented");
01061 
01062         if (!image->is_complex()) {
01063                 fft = image->do_fft();
01064                 fftd = fft->get_data();
01065                 f=1;
01066         }
01067         else {
01068                 fft=image;
01069                 fftd=image->get_data();
01070         }
01071 
01072         return ret;
01073 }
01074 
01075 void Wiener2DAutoAreaProcessor::process_inplace(EMData *image) {
01076         EMData *tmp=process(image);
01077         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
01078         delete tmp;
01079         image->update();
01080         return;
01081 }
01082 
01083 
01084 EMData * Wiener2DFourierProcessor::process(const EMData *in)
01085 {
01086         const EMData *in2 = 0;
01087         if (in->is_complex()) in2=in;
01088         else in=in->do_fft();
01089 
01090         EMData *filt = in->copy_head();
01091         Ctf *ictf = ctf;
01092 
01093         if (!ictf) ctf=(Ctf *)in->get_attr("ctf");
01094 
01095         ictf->compute_2d_complex(filt,Ctf::CTF_WIENER_FILTER);
01096         filt->mult(*in2);
01097         EMData *ret=filt->do_ift();
01098 
01099         delete filt;
01100         if (!in->is_complex()) delete in2;
01101 
01102         if(!ictf && ctf) {delete ctf; ctf=0;}
01103         return(ret);
01104 /*      const EMData *fft;
01105         float *fftd;
01106         int f=0;
01107 
01108         if (!image) {
01109                 LOGWARN("NULL Image");
01110                 return ret;
01111         }
01112 
01113         if (!image->is_complex()) {
01114                 fft = image->do_fft();
01115                 fftd = fft->get_data();
01116                 f=1;
01117         }
01118         else {
01119                 fft=image;
01120                 fftd=image->get_data();
01121         }
01122         powd=image->get_data();
01123 
01124         int bad=0;
01125         for (int i=0; i<image->get_xsize()*image->get_ysize(); i+=2) {
01126                 snr=(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1]-powd[i])/powd[i];
01127                 if (snr<0) { bad++; snr=0; }
01128 
01129         }
01130 
01131         print("%d bad pixels\n",snr);
01132 */      return ret;
01133 
01134 }
01135 
01136 void Wiener2DFourierProcessor::process_inplace(EMData *image) {
01137         EMData *tmp=process(image);
01138         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
01139         delete tmp;
01140         image->update();
01141         return;
01142 }
01143 
01144 void LinearRampFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01145 {
01146         Assert(radial_mask.size() > 0);
01147         for (size_t i = 0; i < radial_mask.size(); i++) {
01148                 radial_mask[i] = (float)i;
01149         }
01150 }
01151 
01152 void LowpassRandomPhaseProcessor::create_radial_func(vector < float >&radial_mask) const { };
01153 
01154 void LowpassRandomPhaseProcessor::process_inplace(EMData *image)
01155 {
01156         float cutoff=0;
01157         preprocess(image);
01158         if( params.has_key("cutoff_abs") ) {
01159                 cutoff=(float)params["cutoff_abs"];
01160         }
01161         else {
01162                 printf("A cutoff_* parameter is required by filter.lowpass.randomphase\n");
01163                 return;
01164         }
01165         
01166         
01167         if (image->get_zsize()==1) {
01168                 int flag=0;
01169                 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
01170                 image->ri2ap();
01171                 int nx=image->get_xsize();
01172                 int ny=image->get_ysize();
01173                 
01174                 int z=0;
01175                 float *data=image->get_data();
01176                 for (int y=-ny/2; y<ny/2; y++) {
01177                         for (int x=0; x<nx/2+1; x++) {
01178                                 if (hypot(x/float(nx),y/float(ny))>=cutoff) {
01179                                         size_t idx=image->get_complex_index_fast(x,y,z);                // location of the amplitude
01180                                         data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
01181                                 }
01182                         }
01183                 }
01184 
01185                 image->ap2ri();
01186 
01187                 if (flag) {
01188                         image->do_ift_inplace();
01189                         image->depad();
01190                 }
01191         }
01192         else {          // 3D
01193                 int flag=0;
01194                 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
01195                 image->ri2ap();
01196                 int nx=image->get_xsize();
01197                 int ny=image->get_ysize();
01198                 int nz=image->get_zsize();
01199                 
01200                 float *data=image->get_data();
01201                 for (int z=-nz/2; z<nz/2; z++) {
01202                         for (int y=-ny/2; y<ny/2; y++) {
01203                                 for (int x=0; x<nx/2+1; x++) {
01204                                         if (Util::hypot3(x/float(nx),y/float(ny),z/float(nz))>=cutoff) {
01205                                                 size_t idx=image->get_complex_index_fast(x,y,z);                // location of the amplitude
01206                                                 data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
01207                                         }
01208                                 }
01209                         }
01210                 }
01211                 image->ap2ri();
01212 
01213                 if (flag) {
01214                         image->do_ift_inplace();
01215                         image->depad();
01216                 }
01217         }
01218 }
01219 
01220 void HighpassAutoPeakProcessor::preprocess(EMData * image)
01221 {
01222         if(params.has_key("apix")) {
01223                 image->set_attr("apix_x", (float)params["apix"]);
01224                 image->set_attr("apix_y", (float)params["apix"]);
01225                 image->set_attr("apix_z", (float)params["apix"]);
01226         }
01227 
01228         const Dict dict = image->get_attr_dict();
01229 
01230         if( params.has_key("cutoff_abs") ) {
01231                 highpass = params["cutoff_abs"];
01232         }
01233         else if( params.has_key("cutoff_freq") ) {
01234                 highpass = (float)params["cutoff_freq"] * (float)dict["apix_x"] * (float)dict["nx"] / 2.0f;
01235         }
01236         else if( params.has_key("cutoff_pixels") ) {
01237                 highpass = (float)params["cutoff_pixels"] / (float)dict["nx"];
01238         }
01239 }
01240 
01241 void HighpassAutoPeakProcessor::create_radial_func(vector < float >&radial_mask, EMData *) const
01242 {
01243         unsigned int c;
01244 
01245 //      for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
01246         for (c=2; c<radial_mask.size(); c++) if (radial_mask[c-1]<=radial_mask[c]) break;
01247         if (c>highpass) c=(unsigned int)highpass;               // the *2 is for the 2x oversampling
01248 
01249         radial_mask[0]=0.0;
01250 //      for (int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?radial_mask[c+1]/radial_mask[i]:1.0);
01251         for (unsigned int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?0.0f:1.0f);
01252 
01253         printf("%f %d\n",highpass,c);
01254 //      for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
01255 
01256 }
01257 
01258 void LinearRampProcessor::create_radial_func(vector < float >&radial_mask) const
01259 {
01260         Assert(radial_mask.size() > 0);
01261         float x = 0.0f , step = 0.5f/radial_mask.size();
01262         size_t size=radial_mask.size();
01263         for (size_t i = 0; i < size; i++) {
01264                 radial_mask[i] = intercept + ((slope - intercept) * i) / (size - 1.0f);
01265                 x += step;
01266         }
01267 }
01268 
01269 void LoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01270 {
01271         
01272         Assert(radial_mask.size() > 0);
01273         float x = 0.0f , nqstep = 0.5f/radial_mask.size();
01274         size_t size=radial_mask.size();
01275         float var = sigma*sigma;
01276         for (size_t i = 0; i < size; i++) {
01277                 radial_mask[i] = ((x*x - var)/var*var)*exp(-x*x/2*var);
01278                 x += nqstep;
01279         }
01280 }
01281 
01282 void DoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01283 {
01284         
01285         Assert(radial_mask.size() > 0);
01286         float x = 0.0f , nqstep = 0.5f/radial_mask.size();
01287         size_t size=radial_mask.size();
01288         float norm = 1.0f/sqrt(2*M_PI);
01289         for (size_t i = 0; i < size; i++) {
01290                 radial_mask[i] = norm*((1.0f/sigma1*exp(-x*x/(2.0f*sigma1*sigma1))) - (1.0f/sigma2*exp(-x*x/(2.0f*sigma2*sigma2))));
01291                 x += nqstep;
01292         }
01293 }
01294 
01295 void RealPixelProcessor::process_inplace(EMData * image)
01296 {
01297         if (!image) {
01298                 LOGWARN("NULL Image");
01299                 return;
01300         }
01301 
01302         maxval = image->get_attr("maximum");
01303         mean = image->get_attr("mean");
01304         sigma = image->get_attr("sigma");
01305 
01306         calc_locals(image);
01307 
01308         size_t size = (size_t)image->get_xsize() *
01309                           (size_t)image->get_ysize() *
01310                           (size_t)image->get_zsize();
01311         float *data = image->get_data();
01312 
01313         for (size_t i = 0; i < size; ++i) {
01314                 process_pixel(&data[i]);
01315         }
01316         image->update();
01317 }
01318 
01319 void CoordinateProcessor::process_inplace(EMData * image)
01320 {
01321         if (!image) {
01322                 LOGWARN("NULL Image");
01323                 return;
01324         }
01325 
01326         maxval = image->get_attr("maximum");
01327         mean = image->get_attr("mean");
01328         sigma = image->get_attr("sigma");
01329         nx = image->get_xsize();
01330         ny = image->get_ysize();
01331         nz = image->get_zsize();
01332         is_complex = image->is_complex();
01333 
01334         calc_locals(image);
01335 
01336 
01337         if (!is_valid()) {
01338                 return;
01339         }
01340 
01341         float *data = image->get_data();
01342         size_t i = 0;
01343 
01344         for (int z = 0; z < nz; z++) {
01345                 for (int y = 0; y < ny; y++) {
01346                         for (int x = 0; x < nx; x++) {
01347                                 process_pixel(&data[i], x, y, z);
01348                                 ++i;
01349                         }
01350                 }
01351         }
01352         image->update();
01353 }
01354 
01355 void PaintProcessor::process_inplace(EMData *image) {
01356         int nx=image->get_xsize();
01357         int ny=image->get_ysize();
01358         int nz=image->get_zsize();
01359 
01360         if (nz==1) {
01361                 float r;
01362                 for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
01363                         for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
01364                                 r=sqrt(float(Util::square(i-x)+Util::square(j-y)));
01365                                 if (r>r2 && r>r1) continue;
01366                                 if (r>r1) image->set_value_at(i,j,0,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
01367                                 else image->set_value_at(i,j,0,v1);
01368                         }
01369                 }
01370         }
01371         else {
01372                 float r;
01373                 for (int k=(z<r2?0:z-r2); k<(z+r2>nz?nz:z+r2); k++) {
01374                         for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
01375                                 for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
01376                                 r=sqrt(float(Util::square(i-x)+Util::square(j-y)+Util::square(k-z)));
01377                                 if (r>r2 && r>r1) continue;
01378                                 if (r>r1) image->set_value_at(i,j,k,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
01379                                 else image->set_value_at(i,j,k,v1);
01380                                 }
01381                         }
01382                 }
01383         }
01384         image->update();
01385 }
01386 
01387 void WatershedProcessor::process_inplace(EMData * image) {
01388         vector<float> xpoints = params["xpoints"];
01389         vector<float> ypoints = params["ypoints"];
01390         vector<float> zpoints = params["zpoints"];
01391 
01392         vector<int> x(xpoints.begin(),xpoints.end());
01393         vector<int> y(ypoints.begin(),ypoints.end());
01394         vector<int> z(zpoints.begin(),zpoints.end());
01395 
01396 
01397         // throw if vector lengths are unequal
01398 
01399 //      float maxval = -99999;
01400         /*
01401         for(unsigned int i = 0; i < xpoints.size(); ++i) {
01402                 float val = image->get_value_at(x[i],y[i],z[i]);
01403                 if (val > maxval) {
01404                         maxval = val;
01405                 }
01406         }*/
01407 
01408         float minval = params["minval"];
01409 
01410         EMData* mask = new EMData(*image);
01411         mask->to_zero();
01412 
01413         // Set the original mask values
01414         for(unsigned int i = 0; i < xpoints.size(); ++i) {
01415                 try {
01416                         mask->set_value_at(x[i],y[i],z[i], (float)(i+1));
01417                 } catch (...) {
01418                         continue;
01419                 }
01420         }
01421         mask->write_image("seeds2.mrc");
01422 //      int dis = 500;
01423 //      float dx = (maxval-minval)/((float) dis - 1);
01424 
01425 
01426 //      for(int i = 0; i < dis; ++i) {
01427 //              float val = maxval-i*dx;
01428 
01429                 while( true ) {
01430                         bool cont= false;
01431                         for(unsigned int j = 0; j < xpoints.size(); ++j)
01432                         {
01433 
01434                                 Vec3i coord(x[j],y[j],z[j]);
01435                                 vector<Vec3i> region;
01436                                 region.push_back(coord);
01437                                 vector<Vec3i> find_region_input = region;
01438                                 while (true) {
01439                                         vector<Vec3i> v = find_region(mask,find_region_input, j+1, region);
01440                                         if (v.size() == 0 ) break;
01441                                         else find_region_input = v;
01442                                 }
01443 
01444                                 vector<Vec3i> tmp(region.begin(),region.end());
01445                                 region.clear();
01446                                 for(vector<Vec3i>::const_iterator it = tmp.begin(); it != tmp.end(); ++it ) {
01447                                         vector<Vec3i> tmp2 = watershed(mask, image, minval, *it, j+1);
01448                                         copy(tmp2.begin(),tmp2.end(),back_inserter(region));
01449                                 }
01450                                 if (region.size() != 0) cont = true;
01451                         }
01452 
01453                         if (!cont) break;
01454                 }
01455 //      }
01456 
01457         memcpy(image->get_data(),mask->get_data(),sizeof(float)*image->get_size());
01458         image->update();
01459 }
01460 
01461 
01462 vector<Vec3i > WatershedProcessor::find_region(EMData* mask,const vector<Vec3i >& coords, const int mask_value, vector<Vec3i >& region)
01463 {
01464         static vector<Vec3i> two_six_connected;
01465         if (two_six_connected.size() == 0) {
01466                 for(int i = -1; i <= 1; ++i) {
01467                         for(int j = -1; j <= 1; ++j) {
01468                                 for(int  k = -1; k <= 1; ++k) {
01469                                         if ( j != 0 || i != 0 || k != 0) {
01470                                                 two_six_connected.push_back(Vec3i(i,j,k));
01471                                         }
01472                                 }
01473                         }
01474                 }
01475         }
01476 
01477         vector<Vec3i> ret;
01478         for(vector<Vec3i>::const_iterator it = two_six_connected.begin(); it != two_six_connected.end(); ++it ) {
01479                 for(vector<Vec3i>::const_iterator it2 = coords.begin(); it2 != coords.end(); ++it2 ) {
01480                         if  (mask->get_value_at((*it2)[0],(*it2)[1],(*it2)[2]) != mask_value) throw;
01481                         Vec3i c = (*it)+(*it2);
01482 
01483                         if ( c[0] < 0 || c[0] >= mask->get_xsize()) continue;
01484                         if ( c[1] < 0 || c[1] >= mask->get_ysize()) continue;
01485                         if ( c[2] < 0 || c[2] >= mask->get_zsize()) continue;
01486 
01487                         if( mask->get_value_at(c[0],c[1],c[2]) == mask_value ) {
01488                                 if (find(ret.begin(),ret.end(),c) == ret.end()) {
01489                                         if (find(region.begin(),region.end(),c) == region.end()) {
01490                                                 region.push_back(c);
01491                                                 ret.push_back(c);
01492                                         }
01493                                 }
01494                         }
01495                 }
01496         }
01497         return ret;
01498 }
01499 
01500 vector<Vec3i > WatershedProcessor::watershed(EMData* mask, EMData* image, const float&, const Vec3i& coordinate, const int mask_value)
01501 {
01502         static vector<Vec3i> two_six_connected;
01503         if (two_six_connected.size() == 0) {
01504                 for(int i = -1; i <= 1; ++i) {
01505                         for(int j = -1; j <= 1; ++j) {
01506                                 for(int  k = -1; k <= 1; ++k) {
01507                                         if ( j != 0 || i != 0 || k != 0) {
01508                                                 two_six_connected.push_back(Vec3i(i,j,k));
01509                                         }
01510                                 }
01511                         }
01512                 }
01513         }
01514 
01515         if  (mask->get_value_at(coordinate[0],coordinate[1],coordinate[2]) != mask_value) throw;
01516 
01517         vector<Vec3i> ret;
01518         for(vector<Vec3i>::const_iterator it = two_six_connected.begin(); it != two_six_connected.end(); ++it ) {
01519                 Vec3i c = (*it)+coordinate;
01520 
01521                 if ( c[0] < 0 || c[0] >= image->get_xsize()) continue;
01522                 if ( c[1] < 0 || c[1] >= image->get_ysize()) continue;
01523                 if ( c[2] < 0 || c[2] >= image->get_zsize()) continue;
01524 
01525         //      cout << image->get_value_at(c[0],c[1],c[2] ) << " " << threshold << endl;
01526                 if( image->get_value_at(c[0],c[1],c[2]) != 0 && (mask->get_value_at(c[0],c[1],c[2]) == 0 )) {
01527                         //cout << "Added something " << mask_value << endl;
01528                         mask->set_value_at(c[0],c[1],c[2], (float)mask_value);
01529                         ret.push_back(c);
01530                 }
01531         }
01532         return ret;
01533 }
01534 
01535 
01536 void CircularMaskProcessor::calc_locals(EMData *)
01537 {
01538         xc = Util::fast_floor(nx/2.0f) + dx;
01539         yc = Util::fast_floor(ny/2.0f) + dy;
01540         zc = Util::fast_floor(nz/2.0f) + dz;
01541 
01542         if (outer_radius < 0) {
01543                 outer_radius = nx / 2 + outer_radius +1;
01544                 outer_radius_square = outer_radius * outer_radius;
01545         }
01546 
01547         if (inner_radius <= 0) {
01548                 inner_radius_square = 0;
01549         }
01550 }
01551 
01552 
01553 void MaskEdgeMeanProcessor::calc_locals(EMData * image)
01554 {
01555         if (!image) {
01556                 throw NullPointerException("NULL image");
01557         }
01558         int nitems = 0;
01559         float sum = 0;
01560         float *data = image->get_data();
01561         size_t i = 0;
01562 
01563         xc = Util::fast_floor(nx/2.0f) + dx;
01564         yc = Util::fast_floor(ny/2.0f) + dy;
01565         zc = Util::fast_floor(nz/2.0f) + dz;
01566         
01567         for (int z = 0; z < nz; ++z) {
01568                 for (int y = 0; y < ny; ++y) {
01569                         for (int x = 0; x < nx; ++x) {
01570                                 float x1 = sqrt((x - xc) * (x - xc) + (y - yc) * (y - yc) + (z - zc) * (z - zc));
01571                                 if (x1 <= outer_radius + ring_width && x1 >= outer_radius - ring_width) {
01572                                         sum += data[i];
01573                                         ++nitems;
01574                                 }
01575                                 ++i;
01576                         }
01577                 }
01578         }
01579 
01580         ring_avg = sum / nitems;
01581 }
01582 
01583 void ToMinvalProcessor::process_inplace(EMData * image)
01584 {
01585         if (!image) {
01586                 LOGWARN("NULL Image");
01587                 return;
01588         }
01589 
01590         float minval = params.set_default("minval",0.0f);
01591         float newval = params.set_default("newval",minval);
01592 
01593         size_t size = (size_t)image->get_xsize() *
01594                           (size_t)image->get_ysize() *
01595                           (size_t)image->get_zsize();
01596         float *data = image->get_data();
01597 
01598 
01599 
01600         for (size_t i = 0; i < size; ++i) {
01601                 if (data[i]<minval) data[i]=newval;
01602         }
01603         image->update();
01604 }
01605 
01606 
01607 void ComplexPixelProcessor::process_inplace(EMData * image)
01608 {
01609         if (!image) {
01610                 LOGWARN("NULL image");
01611                 return;
01612         }
01613         if (!image->is_complex()) {
01614                 LOGWARN("cannot apply complex processor on a real image. Nothing is done.");
01615                 return;
01616         }
01617 
01618         size_t size = (size_t)image->get_xsize() *
01619                           (size_t)image->get_ysize() *
01620                           (size_t)image->get_zsize();
01621         float *data = image->get_data();
01622 
01623         image->ri2ap();
01624 
01625         for (size_t i = 0; i < size; i += 2) {
01626                 process_pixel(data);
01627                 data += 2;
01628         }
01629 
01630         image->update();
01631         image->ap2ri();
01632 }
01633 
01634 
01635 
01636 void AreaProcessor::process_inplace(EMData * image)
01637 {
01638         if (!image) {
01639                 LOGWARN("NULL Image");
01640                 return;
01641         }
01642 
01643         float *data = image->get_data();
01644 
01645         nx = image->get_xsize();
01646         ny = image->get_ysize();
01647         nz = image->get_zsize();
01648 
01649         int n = (areasize - 1) / 2;
01650         matrix_size = areasize * areasize;
01651 
01652         if (nz > 1) {
01653                 matrix_size *= areasize;
01654         }
01655 
01656         float *matrix = new float[matrix_size];
01657         kernel = new float[matrix_size];
01658 
01659         size_t cpysize = areasize * sizeof(float);
01660         size_t start = (nx * ny + nx + 1) * n;
01661 
01662         int xend = nx - n;
01663         int yend = ny - n;
01664 
01665         int zstart = n;
01666         int zend = nz - n;
01667 
01668         int zbox_start = 0;
01669         int zbox_end = areasize;
01670 
01671         if (nz == 1) {
01672                 zstart = 0;
01673                 zend = 1;
01674                 zbox_end = 1;
01675         }
01676 
01677         size_t nsec = (size_t)nx * (size_t)ny;
01678         int box_nsec = areasize * areasize;
01679 
01680         create_kernel();
01681 
01682         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01683         float *data2 = new float[total_size];
01684         memcpy(data2, data, total_size * sizeof(float));
01685 
01686         size_t k;
01687         for (int z = zstart; z < zend; z++) {
01688                 for (int y = n; y < yend; y++) {
01689                         for (int x = n; x < xend; x++) {
01690 
01691                                 k = (size_t)z * nsec + y * nx + x;
01692 
01693                                 for (int bz = zbox_start; bz < zbox_end; bz++) {
01694                                         for (int by = 0; by < areasize; by++) {
01695                                                 memcpy(&matrix[(size_t)bz * box_nsec + by * areasize],
01696                                                            &data2[k - start + bz * nsec + by * nx], cpysize);
01697                                         }
01698                                 }
01699 
01700                                 process_pixel(&data[k], (float) x, (float) y, (float) z, matrix);
01701                         }
01702                 }
01703         }
01704 
01705         if( matrix )
01706         {
01707                 delete[]matrix;
01708                 matrix = 0;
01709         }
01710 
01711         if( kernel )
01712         {
01713                 delete[]kernel;
01714                 kernel = 0;
01715         }
01716         image->update();
01717 }
01718 
01719 
01720 void LaplacianProcessor::create_kernel() const
01721 {
01722         if (nz == 1) {
01723                 memset(kernel, 0, areasize * areasize);
01724                 kernel[1] = -0.25f;
01725                 kernel[3] = -0.25f;
01726                 kernel[5] = -0.25f;
01727                 kernel[7] = -0.25f;
01728                 kernel[4] = 1;
01729         }
01730         else {
01731                 memset(kernel, 0, (size_t)areasize * areasize * areasize);
01732                 kernel[4] = -1.0f / 6.0f;
01733                 kernel[10] = -1.0f / 6.0f;
01734                 kernel[12] = -1.0f / 6.0f;
01735                 kernel[14] = -1.0f / 6.0f;
01736                 kernel[16] = -1.0f / 6.0f;
01737                 kernel[22] = -1.0f / 6.0f;
01738                 kernel[13] = 1;
01739         }
01740 }
01741 
01742 void BoxStatProcessor::process_inplace(EMData * image)
01743 {
01744         if (!image) {
01745                 LOGWARN("NULL Image");
01746                 return;
01747         }
01748 
01749         int nx = image->get_xsize();
01750         int ny = image->get_ysize();
01751         int nz = image->get_zsize();
01752 
01753         int n = params.set_default("radius",1);
01754         int areasize = 2 * n + 1;
01755 
01756         int matrix_size = areasize * areasize;
01757         if (nz > 1) {
01758                 matrix_size *= areasize;
01759         }
01760 
01761         float *array = new float[matrix_size];
01762 //      image->process_inplace("normalize");
01763 
01764         float *data = image->get_data();
01765         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01766         float *data2 = new float[total_size];
01767         memcpy(data2, data, total_size * sizeof(float));
01768 
01769         int z_begin = 0;
01770         int z_end = 1;
01771         int nzz=0;
01772         if (nz > 1) {
01773                 z_begin = n;
01774                 z_end = nz - n;
01775                 nzz=n;
01776         }
01777 
01778         int nxy = nx * ny;
01779 
01780         for (int k = z_begin; k < z_end; k++) {
01781                 size_t knxy = (size_t)k * nxy;
01782 
01783                 for (int j = n; j < ny - n; j++) {
01784                         int jnx = j * nx;
01785 
01786                         for (int i = n; i < nx - n; i++) {
01787                                 size_t s = 0;
01788 
01789                                 for (int i2 = i - n; i2 <= i + n; i2++) {
01790                                         for (int j2 = j - n; j2 <= j + n; j2++) {
01791                                                 for (int k2 = k - nzz; k2 <= k + nzz; k2++) {
01792                                                         array[s] = data2[i2 + j2 * nx + (size_t)k2 * nxy];
01793                                                         ++s;
01794                                                 }
01795                                         }
01796                                 }
01797 
01798                                 process_pixel(&data[i + jnx + knxy], array, matrix_size);
01799                         }
01800                 }
01801         }
01802 
01803         image->update();
01804 
01805         if( data2 )
01806         {
01807                 delete[]data2;
01808                 data2 = 0;
01809         }
01810 }
01811 
01812 void DiffBlockProcessor::process_inplace(EMData * image)
01813 {
01814         if (!image) {
01815                 LOGWARN("NULL Image");
01816                 return;
01817         }
01818 
01819         int nz = image->get_zsize();
01820 
01821         if (nz > 1) {
01822                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01823                 throw ImageDimensionException("3D model not supported");
01824         }
01825 
01826         int nx = image->get_xsize();
01827         int ny = image->get_ysize();
01828 
01829         int v1 = params["cal_half_width"];
01830         int v2 = params["fill_half_width"];
01831 
01832         int v0 = v1 > v2 ? v1 : v2;
01833 
01834         if (v2 <= 0) {
01835                 v2 = v1;
01836         }
01837 
01838         float *data = image->get_data();
01839 
01840         for (int y = v0; y <= ny - v0 - 1; y += v2) {
01841                 for (int x = v0; x <= nx - v0 - 1; x += v2) {
01842 
01843                         float sum = 0;
01844                         for (int y1 = y - v1; y1 <= y + v1; y1++) {
01845                                 for (int x1 = x - v1; x1 <= x + v1; x1++) {
01846                                         sum += data[x1 + y1 * nx];
01847                                 }
01848                         }
01849                         float mean = sum / ((v1 * 2 + 1) * (v1 * 2 + 1));
01850 
01851                         for (int j = y - v2; j <= y + v2; j++) {
01852                                 for (int i = x - v2; i <= x + v2; i++) {
01853                                         data[i + j * nx] = mean;
01854                                 }
01855                         }
01856                 }
01857         }
01858 
01859         image->update();
01860 }
01861 
01862 
01863 void CutoffBlockProcessor::process_inplace(EMData * image)
01864 {
01865         if (!image) {
01866                 LOGWARN("NULL Image");
01867                 return;
01868         }
01869         int nz = image->get_zsize();
01870 
01871         if (nz > 1) {
01872                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01873                 throw ImageDimensionException("3D model not supported");
01874         }
01875 
01876         int nx = image->get_xsize();
01877         int ny = image->get_ysize();
01878 
01879         float value1 = params["value1"];
01880         float value2 = params["value2"];
01881 
01882         int v1 = (int) value1;
01883         int v2 = (int) value2;
01884         if (v2 > v1 / 2) {
01885                 LOGERR("invalid value2 '%f' in CutoffBlockProcessor", value2);
01886                 return;
01887         }
01888 
01889         if (v2 <= 0) {
01890                 v2 = v1;
01891         }
01892 
01893         float *data = image->get_data();
01894         int y = 0, x = 0;
01895         for (y = 0; y <= ny - v1; y += v1) {
01896                 for (x = 0; x <= nx - v1; x += v1) {
01897 
01898                         EMData *clip = image->get_clip(Region(x, y, v1, v1));
01899                         EMData *fft = clip->do_fft();
01900 
01901                         float *fft_data = fft->get_data();
01902                         float sum = 0;
01903                         int nitems = 0;
01904 
01905                         for (int i = -v2; i < v2; i++) {
01906                                 for (int j = 0; j < v2; j++) {
01907                                         if (j == 0 && i == 0) {
01908                                                 continue;
01909                                         }
01910 
01911 #ifdef  _WIN32
01912                                         if (_hypot(j, i) < value2) {
01913 #else
01914                                         if (hypot(j, i) < value2) {
01915 #endif
01916                                                 int t = j * 2 + (i + v1 / 2) * (v1 + 2);
01917                                                 sum += (fft_data[t] * fft_data[t] + fft_data[t + 1] * fft_data[t + 1]);
01918                                                 nitems++;
01919                                         }
01920                                 }
01921                         }
01922 
01923                         if( clip )
01924                         {
01925                                 delete clip;
01926                                 clip = 0;
01927                         }
01928 
01929                         float mean = sum / nitems;
01930 
01931                         for (int i = y; i < y + v1; i++) {
01932                                 for (int j = x; j < x + v1; j++) {
01933                                         data[i * nx + j] = mean;
01934                                 }
01935                         }
01936                 }
01937         }
01938 
01939         memset(&data[y * nx], 0, (ny - y) * nx * sizeof(float));
01940 
01941         for (int i = 0; i < ny; i++) {
01942                 memset(&data[i * nx + x], 0, (nx - x) * sizeof(float));
01943         }
01944 
01945         image->update();
01946 }
01947 
01948 void MedianShrinkProcessor::process_inplace(EMData * image)
01949 {
01950         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
01951 
01952         int shrink_factor =  params.set_default("n",0);
01953         if (shrink_factor <= 1) {
01954                 throw InvalidValueException(shrink_factor,
01955                                                                         "median shrink: shrink factor must > 1");
01956         }
01957 
01958         int nx = image->get_xsize();
01959         int ny = image->get_ysize();
01960         int nz = image->get_zsize();
01961 
01962 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
01963 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
01964 //      }
01965 
01966 
01967         int shrunken_nx = nx / shrink_factor;
01968         int shrunken_ny = ny / shrink_factor;
01969         int shrunken_nz = 1;
01970         if (nz > 1) shrunken_nz = nz / shrink_factor;
01971 
01972         EMData* copy = image->copy();
01973         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
01974         accrue_median(image,copy,shrink_factor);
01975         image->update();
01976         if( copy )
01977         {
01978                 delete copy;
01979                 copy = 0;
01980         }
01981 }
01982 
01983 //
01984 EMData* MedianShrinkProcessor::process(const EMData *const image)
01985 {
01986         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
01987 
01988         int shrink_factor =  params.set_default("n",0);
01989         if (shrink_factor <= 1) {
01990                 throw InvalidValueException(shrink_factor,
01991                                                                         "median shrink: shrink factor must > 1");
01992         }
01993         int nx = image->get_xsize();
01994         int ny = image->get_ysize();
01995         int nz = image->get_zsize();
01996 
01997 
01998 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
01999 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
02000 //      }
02001 
02002 
02003         int shrunken_nx = nx / shrink_factor;
02004         int shrunken_ny = ny / shrink_factor;
02005         int shrunken_nz = 1;
02006         if (nz > 1) shrunken_nz = nz / shrink_factor;
02007 
02008 //      EMData* ret = new EMData(shrunken_nx, shrunken_ny, shrunken_nz);
02009         EMData *ret = image->copy_head();
02010         ret->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02011 
02012         accrue_median(ret,image,shrink_factor);
02013         ret->update();
02014         return ret;
02015 }
02016 
02017 void MedianShrinkProcessor::accrue_median(EMData* to, const EMData* const from,const int shrink_factor)
02018 {
02019 
02020         int nx_old = from->get_xsize();
02021         int ny_old = from->get_ysize();
02022 
02023         int threed_shrink_factor = shrink_factor * shrink_factor;
02024         int z_shrink_factor = 1;
02025         if (from->get_zsize() > 1) {
02026                 threed_shrink_factor *= shrink_factor;
02027                 z_shrink_factor = shrink_factor;
02028         }
02029 
02030         float *mbuf = new float[threed_shrink_factor];
02031 
02032 
02033         int nxy_old = nx_old * ny_old;
02034 
02035         int nx = to->get_xsize();
02036         int ny = to->get_ysize();
02037         int nz = to->get_zsize();
02038         int nxy_new = nx * ny;
02039 
02040         float * rdata = to->get_data();
02041         const float *const data_copy = from->get_const_data();
02042 
02043         for (int l = 0; l < nz; l++) {
02044                 int l_min = l * shrink_factor;
02045                 int l_max = l * shrink_factor + z_shrink_factor;
02046                 size_t cur_l = (size_t)l * nxy_new;
02047 
02048                 for (int j = 0; j < ny; j++) {
02049                         int j_min = j * shrink_factor;
02050                         int j_max = (j + 1) * shrink_factor;
02051                         size_t cur_j = j * nx + cur_l;
02052 
02053                         for (int i = 0; i < nx; i++) {
02054                                 int i_min = i * shrink_factor;
02055                                 int i_max = (i + 1) * shrink_factor;
02056 
02057                                 size_t k = 0;
02058                                 for (int l2 = l_min; l2 < l_max; l2++) {
02059                                         size_t cur_l2 = l2 * nxy_old;
02060 
02061                                         for (int j2 = j_min; j2 < j_max; j2++) {
02062                                                 size_t cur_j2 = j2 * nx_old + cur_l2;
02063 
02064                                                 for (int i2 = i_min; i2 < i_max; i2++) {
02065                                                         mbuf[k] = data_copy[i2 + cur_j2];
02066                                                         ++k;
02067                                                 }
02068                                         }
02069                                 }
02070 
02071                                 for (k = 0; k < size_t(threed_shrink_factor / 2 + 1); k++) {
02072                                         for (int i2 = k + 1; i2 < threed_shrink_factor; i2++) {
02073                                                 if (mbuf[i2] < mbuf[k]) {
02074                                                         float f = mbuf[i2];
02075                                                         mbuf[i2] = mbuf[k];
02076                                                         mbuf[k] = f;
02077                                                 }
02078                                         }
02079                                 }
02080 
02081                                 rdata[i + cur_j] = mbuf[threed_shrink_factor / 2];
02082                         }
02083                 }
02084         }
02085 
02086         if( mbuf )
02087         {
02088                 delete[]mbuf;
02089                 mbuf = 0;
02090         }
02091 
02092         to->scale_pixel((float)shrink_factor);
02093 }
02094 
02095 EMData* FFTResampleProcessor::process(const EMData *const image)
02096 {
02097         float sample_rate = params.set_default("n",0.0f);
02098         if (sample_rate <= 0.0F  )  {
02099                 throw InvalidValueException(sample_rate,        "sample rate must be >0 ");
02100         }
02101 
02102         EMData* result;
02103         if (image->is_complex()) result = image->copy();
02104         else result = image->do_fft();
02105         fft_resample(result,image,sample_rate);
02106         // The image may have been padded - we should shift it so that the phase origin is where FFTW expects it
02107         result->update();
02108         result->scale_pixel(sample_rate);
02109         return result;
02110 }
02111 
02112 void FFTResampleProcessor::process_inplace(EMData * image)
02113 {
02114         if (image->is_complex()) throw ImageFormatException("Error, the fft resampling processor does not work on complex images");
02115 
02116 
02117         float sample_rate = params.set_default("n",0.0f);
02118         if (sample_rate <= 0.0F  )  {
02119                 throw InvalidValueException(sample_rate,        "sample rate (n) must be >0 ");
02120         }
02121 
02122         fft_resample(image,image,sample_rate);
02123 
02124         image->scale_pixel(sample_rate);
02125         image->update();
02126 
02127 
02128 }
02129 
02130 void FFTResampleProcessor::fft_resample(EMData* to, const EMData *const from, const float& sample_rate) {
02131         int nx = from->get_xsize();
02132         int ny = from->get_ysize();
02133         int nz = from->get_zsize();
02134 
02135         int new_nx = static_cast<int>( static_cast<float> (nx) / sample_rate);
02136         int new_ny = static_cast<int>( static_cast<float> (ny) / sample_rate);
02137         int new_nz = static_cast<int>( static_cast<float> (nz) / sample_rate);
02138 
02139         if (new_nx == 0) throw UnexpectedBehaviorException("The resample rate causes the pixel dimensions in the x direction to go to zero");
02140         if (new_ny == 0) new_ny = 1;
02141         if (new_nz == 0) new_nz = 1;
02142 
02143         int ndim = from->get_ndim();
02144         if ( ndim < 3 ) {
02145                 new_nz = 1;
02146         }
02147         if ( ndim < 2 ) {
02148                 new_ny = 1;
02149         }
02150 
02151         int fft_x_correction = 1;
02152         if (new_nx % 2 == 0) fft_x_correction = 2;
02153 
02154         int fft_y_correction = 0;
02155         if (ny != 1 && new_ny % 2 == 0 && ny % 2 == 1) fft_y_correction = 1;
02156         else if (ny != 1 && new_ny % 2 == 1 && ny % 2 == 0) fft_y_correction = -1;
02157 
02158         int fft_z_correction = 0;
02159         if (nz != 1 && new_nz % 2 == 0 && nz % 2 == 1) fft_z_correction = 1;
02160         else if (nz != 1 && new_nz % 2 == 1 && nz % 2 == 0) fft_z_correction = -1;
02161 
02162         if ( ! to->is_complex()) to->do_fft_inplace();
02163 
02164         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocenter");
02165 
02166         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);
02167         to->clip_inplace(clip);
02168 
02169         if (fft_x_correction == 1) to->set_fftodd(true);
02170         else to->set_fftodd(false);
02171 
02172         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocorner");
02173 
02174         to->do_ift_inplace();
02175         to->depad_corner();
02176 
02177 }
02178 
02179 
02180 EMData* MeanShrinkProcessor::process(const EMData *const image)
02181 {
02182         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02183 
02184         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02185 
02186         float shrink_factor0 = params.set_default("n",0.0f);
02187         int shrink_factor = int(shrink_factor0);
02188         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02189                 throw InvalidValueException(shrink_factor0,
02190                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02191         }
02192 
02193         int nx = image->get_xsize();
02194         int ny = image->get_ysize();
02195         int nz = image->get_zsize();
02196 
02197 
02198         // here handle the special averaging by 1.5 for 2D case
02199         if (shrink_factor0==1.5 ) {
02200                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02201 
02202                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02203                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02204                 EMData* result = new EMData(shrunken_nx,shrunken_ny,1);
02205 
02206                 accrue_mean_one_p_five(result,image);
02207                 result->update();
02208 
02209                 return result;
02210         }
02211 
02212         int shrunken_nx = nx / shrink_factor;
02213         int shrunken_ny = ny / shrink_factor;
02214         int shrunken_nz = 1;
02215 
02216         if (nz > 1) {
02217                 shrunken_nz = nz / shrink_factor;
02218         }
02219 
02220 //      EMData* result = new EMData(shrunken_nx,shrunken_ny,shrunken_nz);
02221         EMData* result = image->copy_head();
02222         result->set_size(shrunken_nx,shrunken_ny,shrunken_nz);
02223         accrue_mean(result,image,shrink_factor);
02224 
02225         result->update();
02226 
02227         return result;
02228 }
02229 
02230 void MeanShrinkProcessor::process_inplace(EMData * image)
02231 {
02232         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02233 
02234         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02235 
02236         float shrink_factor0 = params.set_default("n",0.0f);
02237         int shrink_factor = int(shrink_factor0);
02238         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02239                 throw InvalidValueException(shrink_factor0,
02240                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02241         }
02242 
02243 /*      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) ||
02244         (nz > 1 && (nz % shrink_factor != 0))) {
02245         throw InvalidValueException(shrink_factor,
02246         "Image size not divisible by shrink factor");
02247 }*/
02248 
02249         int nx = image->get_xsize();
02250         int ny = image->get_ysize();
02251         int nz = image->get_zsize();
02252         // here handle the special averaging by 1.5 for 2D case
02253         if (shrink_factor0==1.5 ) {
02254                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02255 
02256                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02257                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02258 
02259                 EMData* orig = image->copy();
02260                 image->set_size(shrunken_nx, shrunken_ny, 1);   // now nx = shrunken_nx, ny = shrunken_ny
02261                 image->to_zero();
02262 
02263                 accrue_mean_one_p_five(image,orig);
02264 
02265                 if( orig ) {
02266                         delete orig;
02267                         orig = 0;
02268                 }
02269                 image->update();
02270 
02271                 return;
02272         }
02273 
02274         accrue_mean(image,image,shrink_factor);
02275 
02276         int shrunken_nx = nx / shrink_factor;
02277         int shrunken_ny = ny / shrink_factor;
02278         int shrunken_nz = 1;
02279         if (nz > 1) shrunken_nz = nz / shrink_factor;
02280 
02281         image->update();
02282         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02283 }
02284 
02285 void MeanShrinkProcessor::accrue_mean(EMData* to, const EMData* const from,const int shrink_factor)
02286 {
02287         const float * const data = from->get_const_data();
02288         float* rdata = to->get_data();
02289 
02290         size_t nx = from->get_xsize();
02291         size_t ny = from->get_ysize();
02292         size_t nz = from->get_zsize();
02293         size_t nxy = nx*ny;
02294 
02295 
02296         size_t shrunken_nx = nx / shrink_factor;
02297         size_t shrunken_ny = ny / shrink_factor;
02298         size_t shrunken_nz = 1;
02299         size_t shrunken_nxy = shrunken_nx * shrunken_ny;
02300 
02301         int normalize_shrink_factor = shrink_factor * shrink_factor;
02302         int z_shrink_factor = 1;
02303 
02304         if (nz > 1) {
02305                 shrunken_nz = nz / shrink_factor;
02306                 normalize_shrink_factor *= shrink_factor;
02307                 z_shrink_factor = shrink_factor;
02308         }
02309 
02310         float invnormfactor = 1.0f/(float)normalize_shrink_factor;
02311 
02312         for (size_t k = 0; k < shrunken_nz; k++) {
02313                 size_t k_min = k * shrink_factor;
02314                 size_t k_max = k * shrink_factor + z_shrink_factor;
02315                 size_t cur_k = k * shrunken_nxy;
02316 
02317                 for (size_t j = 0; j < shrunken_ny; j++) {
02318                         size_t j_min = j * shrink_factor;
02319                         size_t j_max = j * shrink_factor + shrink_factor;
02320                         size_t cur_j = j * shrunken_nx + cur_k;
02321 
02322                         for (size_t i = 0; i < shrunken_nx; i++) {
02323                                 size_t i_min = i * shrink_factor;
02324                                 size_t i_max = i * shrink_factor + shrink_factor;
02325 
02326                                 float sum = 0;
02327                                 for (size_t kk = k_min; kk < k_max; kk++) {
02328                                         size_t cur_kk = kk * nxy;
02329 
02330                                         for (size_t jj = j_min; jj < j_max; jj++) {
02331                                                 size_t cur_jj = jj * nx + cur_kk;
02332                                                 for (size_t ii = i_min; ii < i_max; ii++) {
02333                                                         sum += data[ii + cur_jj];
02334                                                 }
02335                                         }
02336                                 }
02337                                 rdata[i + cur_j] = sum * invnormfactor;
02338                         }
02339                 }
02340         }
02341         to->scale_pixel((float)shrink_factor);
02342 }
02343 
02344 
02345 void MeanShrinkProcessor::accrue_mean_one_p_five(EMData* to, const EMData * const from)
02346 {
02347         int nx0 = from->get_xsize(), ny0 = from->get_ysize();   // the original size
02348 
02349         int nx = to->get_xsize(), ny = to->get_ysize();
02350 
02351         float *data = to->get_data();
02352         const float * const data0 = from->get_const_data();
02353 
02354         for (int j = 0; j < ny; j++) {
02355                 int jj = int(j * 1.5);
02356                 float jw0 = 1.0F, jw1 = 0.5F;   // 3x3 -> 2x2, so each new pixel should have 2.25 of the old pixels
02357                 if ( j%2 ) {
02358                         jw0 = 0.5F;
02359                         jw1 = 1.0F;
02360                 }
02361                 for (int i = 0; i < nx; i++) {
02362                         int ii = int(i * 1.5);
02363                         float iw0 = 1.0F, iw1 = 0.5F;
02364                         float w = 0.0F;
02365 
02366                         if ( i%2 ) {
02367                                 iw0 = 0.5F;
02368                                 iw1 = 1.0F;
02369                         }
02370                         if ( jj < ny0 ) {
02371                                 if ( ii < nx0 ) {
02372                                         data[j * nx + i] = data0[ jj * nx0 + ii ] * jw0 * iw0 ;
02373                                         w += jw0 * iw0 ;
02374                                         if ( ii+1 < nx0 ) {
02375                                                 data[j * nx + i] += data0[ jj * nx0 + ii + 1] * jw0 * iw1;
02376                                                 w += jw0 * iw1;
02377                                         }
02378                                 }
02379                                 if ( jj +1 < ny0 ) {
02380                                         if ( ii < nx0 ) {
02381                                                 data[j * nx + i] += data0[ (jj+1) * nx0 + ii ] * jw1 * iw0;
02382                                                 w += jw1 * iw0;
02383                                                 if ( ii+1 < nx0 ) {
02384                                                         data[j * nx + i] += data0[ (jj+1) * nx0 + ii + 1] * jw1 * iw1;
02385                                                         w += jw1 * iw1;
02386                                                 }
02387                                         }
02388                                 }
02389                         }
02390                         if ( w>0 ) data[j * nx + i] /= w;
02391                 }
02392         }
02393 
02394         to->update();
02395         to->scale_pixel((float)1.5);
02396 }
02397 
02398 // This would have to be moved into the header if it were required in other source files
02399 template<class LogicOp>
02400 EMData* BooleanShrinkProcessor::process(const EMData *const image, Dict& params)
02401 {
02402         // The basic idea of this code is to iterate through each pixel in the output image
02403         // determining its value by investigation a region of the input image
02404 
02405         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02406 
02407         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02408 
02409 
02410         int shrink = params.set_default("n",2);
02411         int search = params.set_default("search",2);
02412 
02413         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02414 
02415 
02416         int nz = image->get_zsize();
02417         int ny = image->get_ysize();
02418         int nx = image->get_xsize();
02419 
02420         if (nx == 1 && ny == 1 && nz == 1 ) return image->copy();
02421 
02422         LogicOp op;
02423         EMData* return_image = new EMData();
02424 
02425         int shrinkx = shrink;
02426         int shrinky = shrink;
02427         int shrinkz = shrink;
02428 
02429         int searchx = search;
02430         int searchy = search;
02431         int searchz = search;
02432 
02433         // Clamping the shrink values to the dimension lengths
02434         // ensures that the return image has non zero dimensions
02435         if ( shrinkx > nx ) shrinkx = nx;
02436         if ( shrinky > ny ) shrinky = ny;
02437         if ( shrinkz > nz ) shrinkz = nz;
02438 
02439         if ( nz == 1 && ny == 1 )
02440         {
02441                 return_image->set_size(nx/shrinkx);
02442                 for(int i = 0; i < nx/shrinkx; ++i)
02443                 {
02444                         float tmp = op.get_start_val();
02445                         for(int s=0; s < searchx; ++s)
02446                         {
02447                                 int idx = shrinkx*i+s;
02448                                 // Don't ask for memory beyond limits
02449                                 if ( idx > nx ) break;
02450                                 else
02451                                 {
02452                                         float val = image->get_value_at(idx);
02453                                         if ( op( val,tmp) ) tmp = val;
02454                                 }
02455                         }
02456                         return_image->set_value_at(i,tmp);
02457                 }
02458         }
02459         else if ( nz == 1 )
02460         {
02461                 int ty = ny/shrinky;
02462                 int tx = nx/shrinkx;
02463                 return_image->set_size(tx,ty);
02464                 for(int y = 0; y < ty; ++y) {
02465                         for(int x = 0; x < tx; ++x) {
02466                                 float tmp = op.get_start_val();
02467                                 for(int sy=0; sy < searchy; ++sy) {
02468                                         int yidx = shrinky*y+sy;
02469                                         if ( yidx >= ny) break;
02470                                         for(int sx=0; sx < searchx; ++sx) {
02471                                                 int xidx = shrinkx*x+sx;
02472                                                 if ( xidx >= nx) break;
02473 
02474                                                 float val = image->get_value_at(xidx,yidx);
02475                                                 if ( op( val,tmp) ) tmp = val;
02476                                         }
02477                                 }
02478                                 return_image->set_value_at(x,y,tmp);
02479                         }
02480                 }
02481         }
02482         else
02483         {
02484                 int tz = nz/shrinkz;
02485                 int ty = ny/shrinky;
02486                 int tx = nx/shrinkx;
02487 
02488                 return_image->set_size(tx,ty,tz);
02489                 for(int z = 0; z < tz; ++z) {
02490                         for(int y = 0; y < ty; ++y) {
02491                                 for(int x = 0; x < tx; ++x) {
02492                                         float tmp = op.get_start_val();
02493 
02494                                         for(int sz=0; sz < searchz; ++sz) {
02495                                                 int zidx = shrinkz*z+sz;
02496                                                 if ( zidx >= nz) break;
02497 
02498                                                 for(int sy=0; sy < searchy; ++sy) {
02499                                                         int yidx = shrinky*y+sy;
02500                                                         if ( yidx >= ny) break;
02501 
02502                                                         for(int sx=0; sx < searchx; ++sx) {
02503                                                                 int xidx = shrinkx*x+sx;
02504                                                                 if ( xidx >= nx) break;
02505                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02506                                                                 if ( op( val,tmp) ) tmp = val;
02507                                                         }
02508                                                 }
02509                                         }
02510                                         return_image->set_value_at(x,y,z,tmp);
02511                                 }
02512                         }
02513                 }
02514         }
02515         return_image->update();
02516 
02517         return return_image;
02518 }
02519 
02520 template<class LogicOp>
02521 void BooleanShrinkProcessor::process_inplace(EMData * image, Dict& params)
02522 {
02523         // The basic idea of this code is to iterate through each pixel in the output image
02524         // determining its value by investigation a region of the input image
02525         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02526 
02527         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02528 
02529 
02530         int shrink = params.set_default("shrink",2);
02531         int search = params.set_default("search",2);
02532 
02533         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02534 
02535 
02536         int nz = image->get_zsize();
02537         int ny = image->get_ysize();
02538         int nx = image->get_xsize();
02539 
02540         LogicOp op;
02541 
02542         int shrinkx = shrink;
02543         int shrinky = shrink;
02544         int shrinkz = shrink;
02545 
02546         int searchx = search;
02547         int searchy = search;
02548         int searchz = search;
02549 
02550         // Clamping the shrink values to the dimension lengths
02551         // ensures that the return image has non zero dimensions
02552         if ( shrinkx > nx ) shrinkx = nx;
02553         if ( shrinky > ny ) shrinkx = ny;
02554         if ( shrinkz > nz ) shrinkx = nz;
02555 
02556         if (nx == 1 && ny == 1 && nz == 1 ) return;
02557 
02558         if ( nz == 1 && ny == 1 )
02559         {
02560                 for(int i = 0; i < nx/shrink; ++i)
02561                 {
02562                         float tmp = op.get_start_val();
02563                         for(int s=0; s < searchx; ++s)
02564                         {
02565                                 int idx = shrinkx*i+s;
02566                                 if ( idx > nx ) break;
02567                                 else
02568                                 {
02569                                         float val = image->get_value_at(idx);
02570                                         if ( op( val,tmp) ) tmp = val;
02571                                 }
02572                         }
02573                         image->set_value_at(i,tmp);
02574                 }
02575 
02576                 image->set_size(nx/shrinkx);
02577         }
02578         else if ( nz == 1 )
02579         {
02580                 int ty = ny/shrinky;
02581                 int tx = nx/shrinkx;
02582                 for(int y = 0; y < ty; ++y) {
02583                         for(int x = 0; x < tx; ++x) {
02584                                 float tmp = op.get_start_val();
02585                                 for(int sy=0; sy < searchy; ++sy) {
02586                                         int yidx = shrinky*y+sy;
02587                                         if ( yidx >= ny) break;
02588                                         for(int sx=0; sx < searchx; ++sx) {
02589                                                 int xidx = shrinkx*x+sx;
02590                                                 if ( xidx >= nx) break;
02591 
02592                                                 float val = image->get_value_at(xidx,yidx);
02593                                                 if ( op( val,tmp) ) tmp = val;
02594                                         }
02595                                 }
02596                                 (*image)(x+tx*y) = tmp;
02597                         }
02598                 }
02599                 image->set_size(tx,ty);
02600         }
02601         else
02602         {
02603                 int tnxy = nx/shrinkx*ny/shrinky;
02604                 int tz = nz/shrinkz;
02605                 int ty = ny/shrinky;
02606                 int tx = nx/shrinkx;
02607 
02608                 for(int z = 0; z < tz; ++z) {
02609                         for(int y = 0; y < ty; ++y) {
02610                                 for(int x = 0; x < tx; ++x) {
02611                                         float tmp = op.get_start_val();
02612                                         for(int sz=0; sz < searchz; ++sz) {
02613                                                 int zidx = shrinkz*z+sz;
02614                                                 if ( zidx >= nz) break;
02615                                                 for(int sy=0; sy < searchy; ++sy) {
02616                                                         int yidx = shrinky*y+sy;
02617                                                         if ( yidx >= ny) break;
02618                                                         for(int sx=0; sx < shrinkx; ++sx) {
02619                                                                 int xidx = shrinkx*x+sx;
02620                                                                 if ( xidx >= nx) break;
02621 
02622                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02623                                                                 if ( op( val,tmp) ) tmp = val;
02624                                                         }
02625                                                 }
02626                                         }
02627                                         (*image)(x+tx*y+tnxy*z) = tmp;
02628                                 }
02629                         }
02630                 }
02631                 image->set_size(tx,ty,tz);
02632         }
02633         image->update();
02634 }
02635 
02636 
02637 
02638 void GradientRemoverProcessor::process_inplace(EMData * image)
02639 {
02640         if (!image) {
02641                 LOGWARN("NULL Image");
02642                 return;
02643         }
02644 
02645         int nz = image->get_zsize();
02646         if (nz > 1) {
02647                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02648                 throw ImageDimensionException("3D model not supported");
02649         }
02650 
02651         int nx = image->get_xsize();
02652         int ny = image->get_ysize();
02653         float *dy = new float[ny];
02654         float m = 0;
02655         float b = 0;
02656         float sum_y = 0;
02657         float *data = image->get_data();
02658 
02659         for (int i = 0; i < ny; i++) {
02660                 Util::calc_least_square_fit(nx, 0, data + i * nx, &m, &b, false);
02661                 dy[i] = b;
02662                 sum_y += m;
02663         }
02664 
02665         float mean_y = sum_y / ny;
02666         float sum_x = 0;
02667         Util::calc_least_square_fit(ny, 0, dy, &sum_x, &b, false);
02668 
02669         for (int j = 0; j < ny; j++) {
02670                 for (int i = 0; i < nx; i++) {
02671                         data[i + j * nx] -= i * sum_x + j * mean_y + b;
02672                 }
02673         }
02674 
02675         image->update();
02676 }
02677 
02678 void FlattenBackgroundProcessor::process_inplace(EMData * image)
02679 {
02680 
02681         EMData* mask = params.set_default("mask",(EMData*)0);
02682         int radius = params.set_default("radius",0);
02683 
02684         if (radius != 0 && mask != 0) throw InvalidParameterException("Error - the mask and radius parameters are mutually exclusive.");
02685 
02686         if (mask == 0 && radius == 0) throw InvalidParameterException("Error - you must specify either the mask or the radius parameter.");
02687 
02688         // If the radius isn't 0, then turn the mask into the thing we want...
02689         bool deletemask = false;
02690         if (radius != 0) {
02691                 mask = new EMData;
02692                 int n = image->get_ndim();
02693                 if (n==1){
02694                         mask->set_size(2*radius+1);
02695                 } else if (n==2) {
02696                         mask->set_size(2*radius+1,2*radius+1);
02697                 }
02698                 else /*n==3*/ {
02699                         mask->set_size(2*radius+1,2*radius+1,2*radius+1);
02700                 }
02701                 // assuming default behavior is to make a circle/sphere with using the radius of the mask
02702                 mask->process_inplace("testimage.circlesphere");
02703         }
02704 
02705         // Double check that that mask isn't too big
02706         int mnx = mask->get_xsize(); int mny = mask->get_ysize(); int mnz = mask->get_zsize();
02707         int nx = image->get_xsize(); int ny = image->get_ysize(); int nz = image->get_zsize();
02708         int nxc = nx+mnx; int nyc = ny+mny; int nzc = nz+mnz;
02709         if (nz == 1) nzc = 1; // Sanity check
02710         if (ny == 1) nyc = 1; // Sanity check
02711 
02712         if ( mnx > nx || mny > ny || mnz > nz)
02713                 throw ImageDimensionException("Can not flatten using a mask that is larger than the image.");
02714 
02715         // Get the normalization factor
02716         float normfac = 0.0;
02717         for (int i=0; i<mask->get_xsize()*mask->get_ysize()*mask->get_zsize(); ++i){
02718                 normfac += mask->get_value_at(i);
02719         }
02720         // If the sum is zero the user probably doesn't understand that determining a measure of the mean requires
02721         // strictly positive numbers. The user has specified a mask that consists entirely of zeros, or the mask
02722         // has a mean of zero.
02723         if (normfac == 0) throw InvalidParameterException("Error - the pixels in the mask sum to zero. This breaks the flattening procedure");
02724         normfac = 1.0f/normfac;
02725 
02726         // The mask can now be automatically resized to the dimensions of the image
02727 //      bool undoclip = false;
02728 
02729         Region r;
02730         if (ny == 1) r = Region((mnx-nxc)/2,nxc);
02731         else if (nz == 1) r = Region((mnx-nxc)/2, (mny-nyc)/2,nxc,nyc);
02732         else r = Region((mnx-nxc)/2, (mny-nyc)/2,(mnz-nzc)/2,nxc,nyc,nzc);
02733         mask->clip_inplace(r,0);
02734 //      undoclip = true;
02735 //      if ( mnx < nx || mny < ny || mnz < nz) {
02736 //              Region r((mnx-nx)/2, (mny-ny)/2,(mnz-nz)/2,nx,ny,nz);
02737 //              mask->clip_inplace(r);
02738 //              undoclip = true;
02739 //      }
02740 
02741         Region r2;
02742         if (ny == 1) r2 = Region((nx-nxc)/2,nxc);
02743         else if (nz == 1) r2 = Region((nx-nxc)/2, (ny-nyc)/2,nxc,nyc);
02744         else r2 = Region((nx-nxc)/2, (ny-nyc)/2,(nz-nzc)/2,nxc,nyc,nzc);
02745         image->clip_inplace(r2,image->get_edge_mean());
02746         // Finally do the convolution
02747         EMData* m = image->convolute(mask);
02748         // Normalize so that m is truly the local mean
02749         m->mult(normfac);
02750         // Before we can subtract, the mean must be phase shifted
02751         m->process_inplace("xform.phaseorigin.tocenter");
02752         // Subtract the local mean
02753 //      image->write_image("a.mrc");
02754 //      m->write_image("b.mrc");
02755         image->sub(*m); // WE'RE DONE!
02756         delete m;
02757 
02758         if (deletemask) {
02759                 delete mask;
02760         } else { // I clipped it inplace, so undo this clipping so the user gets back what the put in
02761                 Region r;
02762                 if (ny == 1) r = Region((nxc-mnx)/2,mnx);
02763                 else if (nz == 1) r = Region((nxc-mnx)/2, (nyc-mny)/2,mnx,mny);
02764                 else r = Region((nxc-mnx)/2, (nyc-mny)/2,(nzc-mnz)/2,mnx,mny,mnz);
02765                 mask->clip_inplace(r);
02766         }
02767 
02768         Region r3;
02769         if (ny == 1) r3 = Region((nxc-nx)/2,nx);
02770         else if (nz == 1) r3 = Region((nxc-nx)/2, (nyc-ny)/2,nx,ny);
02771         else r3 = Region((nxc-nx)/2, (nyc-ny)/2,(nzc-nz)/2,nx,ny,nz);
02772         image->clip_inplace(r3);
02773 //      if ( undoclip ) {
02774 //              Region r((nx-mnx)/2, (ny-mny)/2, (nz-mnz)/2,mnx,mny,mnz);
02775 //              mask->clip_inplace(r);
02776 //      }
02777 
02778 }
02779 
02780 void NonConvexProcessor::process_inplace(EMData * image) {
02781         if (!image) { LOGWARN("NULL IMAGE"); return; }
02782         //int isinten=image->get_attr_default("is_intensity",0);
02783         
02784         // 1-D
02785         if (image->get_ysize()==1) {
02786                 
02787         }
02788         // 2-D
02789         else if (image->get_zsize()==1) {
02790 //              if (!isinten) throw ImageDimensionException("Only complex intensity images currently supported by NonConvexProcessor");
02791                 int nx2=image->get_xsize()/2;
02792                 int ny2=image->get_ysize()/2;
02793                 vector<float> rdist = image->calc_radial_dist(nx2*1.5,0,1,false);               // radial distribution to make sure nonconvex values decrease radially
02794                 // Make sure rdist is decreasing (or flat)
02795                 for (int i=1; i<nx2; i++) {
02796                         if (rdist[i]>rdist[i-1]) rdist[i]=rdist[i-1];
02797                 }
02798                 
02799                 image->process_inplace("xform.fourierorigin.tocenter");
02800                 EMData* binary=image->copy();
02801                 
02802                 // First we eliminate convex points from the input image (set to zero)
02803                 for (int x=0; x<image->get_xsize(); x+=2) {
02804                         for (int y=1; y<image->get_ysize()-1; y++) {
02805                                 int r=(int)hypot((float)(x/2),(float)(y-ny2));
02806                                 float cen=(*binary)(x,y);
02807                                 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
02808                                         image->set_value_at_fast(x/2+nx2,y,0.0);        // we are turning image into a full real-space intensity image for now
02809                                         image->set_value_at_fast(nx2-x/2,ny2*2-y-1,0.0);
02810                                 }
02811                                 else {
02812                                         image->set_value_at_fast(x/2+nx2,y,cen);        // we are turning image into a full real-space intensity image for now
02813                                         image->set_value_at_fast(nx2-x/2,ny2*2-y-1,cen);        // It will contain non-zero values only for nonconvex points
02814                                 }
02815                         }
02816                 }
02817                 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
02818                 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
02819                 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
02820                 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
02821                 for (int y=0; y<ny2*2; y++) image->set_value_at_fast(0,y,0.0f);
02822                 
02823                 // Now make a binary version of the convex points
02824                 float *idat=image->get_data();
02825                 float *bdat=binary->get_data();
02826                 int nxy=(nx2*ny2*4);
02827                 for (int i=0; i<nxy; i++) {
02828                         bdat[i]=idat[i]==0?0:1.0f;              // binary version of the convex points in image
02829                 }
02830                 binary->update();
02831                 
02832                 // We now use a Gaussian filter on both images, to use Gaussian interpolation to fill in zero values
02833                 image->set_complex(false);              // so we can use a Gaussian filter on it 
02834                 binary->set_complex(false);
02835 
02836 /*              image->write_image("con.hdf",0);*/
02837                 image->set_fftpad(false);
02838                 binary->set_fftpad(false);
02839                 
02840                 // Gaussian blur of both images
02841                 image->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02842                 binary->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02843 
02844 /*              image->write_image("con.hdf",1);
02845                 binary->write_image("con.hdf",2);*/
02846                 
02847                 for (int x=0; x<image->get_xsize(); x+=2) {
02848                         for (int y=0; y<image->get_ysize(); y++) {
02849                                 float bv=binary->get_value_at(x/2+nx2,y);
02850                                 image->set_value_at_fast(x,y,image->get_value_at(x/2+nx2,y)/(bv<=0?1.0f:bv));
02851                                 image->set_value_at_fast(x+1,y,0.0);
02852                         }
02853                 }
02854                 image->set_complex(true);
02855                 image->set_fftpad(true);
02856                 image->process_inplace("xform.fourierorigin.tocorner");
02857                 delete binary;
02858         }
02859         else throw ImageDimensionException("3D maps not yet supported by NonConvexProcessor");
02860         
02861 }
02862 
02863 
02864 #include <gsl/gsl_linalg.h>
02865 void GradientPlaneRemoverProcessor::process_inplace(EMData * image)
02866 {
02867         if (!image) {
02868                 LOGWARN("NULL Image");
02869                 return;
02870         }
02871 
02872         int nz = image->get_zsize();
02873         if (nz > 1) {
02874                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02875                 throw ImageDimensionException("3D map not supported");
02876         }
02877 
02878         int nx = image->get_xsize();
02879         int ny = image->get_ysize();
02880         float *d = image->get_data();
02881         EMData *mask = 0;
02882         float *dm = 0;
02883         if (params.has_key("mask")) {
02884                 mask = params["mask"];
02885                 if (nx!=mask->get_xsize() || ny!=mask->get_ysize()) {
02886                         LOGERR("%s Processor requires same size mask image", get_name().c_str());
02887                         throw ImageDimensionException("wrong size mask image");
02888                 }
02889                 dm = mask->get_data();
02890         }
02891         int count = 0;
02892         if (dm) {
02893                 for(int i=0; i<nx*ny; i++) {
02894                         if(dm[i]) count++;
02895                 }
02896         }
02897         else {
02898                 count = nx * ny;
02899         }
02900         if(count<3) {
02901                 LOGERR("%s Processor requires at least 3 pixels to fit a plane", get_name().c_str());
02902                 throw ImageDimensionException("too few usable pixels to fit a plane");
02903         }
02904         // Allocate the working space
02905         gsl_vector *S=gsl_vector_calloc(3);
02906         gsl_matrix *A=gsl_matrix_calloc(count,3);
02907         gsl_matrix *V=gsl_matrix_calloc(3,3);
02908 
02909         double m[3] = {0, 0, 0};
02910         int index=0;
02911         if (dm) {
02912                 for(int j=0; j<ny; j++){
02913                         for(int i=0; i<nx; i++){
02914                                 int ij=j*nx+i;
02915                                 if(dm[ij]) {
02916                                         m[0]+=i;        // x
02917                                         m[1]+=j;        // y
02918                                         m[2]+=d[ij];    // z
02919                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02920                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02921                                         index++;
02922                                 }
02923                         }
02924                 }
02925         }
02926         else {
02927                 for(int j=0; j<ny; j++){
02928                         for(int i=0; i<nx; i++){
02929                                 int ij=j*nx+i;
02930                                         m[0]+=i;        // x
02931                                         m[1]+=j;        // y
02932                                         m[2]+=d[ij];    // z
02933                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02934                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02935                                         index++;
02936                         }
02937                 }
02938         }
02939 
02940         for(int i=0; i<3; i++) m[i]/=count;     // compute center of the plane
02941 
02942         index=0;
02943         if (dm) {
02944                 for(int j=0; j<ny; j++){
02945                         for(int i=0; i<nx; i++){
02946                                 int ij=j*nx+i;
02947                                 if(dm[ij]) {
02948                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02949                                         gsl_matrix_set(A,index,0,i-m[0]);
02950                                         gsl_matrix_set(A,index,1,j-m[1]);
02951                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02952                                         index++;
02953                                 }
02954                         }
02955                 }
02956                 mask->update();
02957         }
02958         else {
02959                 for(int j=0; j<ny; j++){
02960                         for(int i=0; i<nx; i++){
02961                                 int ij=j*nx+i;
02962                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02963                                         gsl_matrix_set(A,index,0,i-m[0]);
02964                                         gsl_matrix_set(A,index,1,j-m[1]);
02965                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02966                                         index++;
02967                         }
02968                 }
02969         }
02970 
02971         // SVD decomposition and use the V vector associated with smallest singular value as the plan normal
02972         gsl_linalg_SV_decomp_jacobi(A, V, S);
02973 
02974         double n[3];
02975         for(int i=0; i<3; i++) n[i] = gsl_matrix_get(V, i, 2);
02976 
02977         #ifdef DEBUG
02978         printf("S=%g,%g,%g\n",gsl_vector_get(S,0), gsl_vector_get(S,1), gsl_vector_get(S,2));
02979         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));
02980         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));
02981         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));
02982         printf("Fitted plane: p0=%g,%g,%g\tn=%g,%g,%g\n",m[0],m[1],m[2],n[0],n[1],n[2]);
02983         #endif
02984 
02985         int changeZero = 0;
02986         if (params.has_key("changeZero")) changeZero = params["changeZero"];
02987         if (changeZero) {
02988                 for(int j=0; j<nx; j++){
02989                         for(int i=0; i<ny; i++){
02990                                 int ij = j*nx+i;
02991                                 d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
02992                         }
02993                 }
02994         }
02995         else {
02996                 for(int j=0; j<nx; j++){
02997                         for(int i=0; i<ny; i++){
02998                                 int ij = j*nx+i;
02999                                 if(d[ij]) d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
03000                         }
03001                 }
03002         }
03003         image->update();
03004         // set return plane parameters
03005         vector< float > planeParam;
03006         planeParam.resize(6);
03007         for(int i=0; i<3; i++) planeParam[i] = static_cast<float>(n[i]);
03008         for(int i=0; i<3; i++) planeParam[i+3] = static_cast<float>(m[i]);
03009         params["planeParam"]=EMObject(planeParam);
03010 }
03011 
03012 void VerticalStripeProcessor::process_inplace(EMData * image)
03013 {
03014         if (!image) {
03015                 LOGWARN("NULL Image");
03016                 return;
03017         }
03018 
03019         int nx = image->get_xsize();
03020         int ny = image->get_ysize();
03021         int nz = image->get_zsize();
03022 
03023         float *data = image->get_data();
03024         float sigma = image->get_attr("sigma");
03025 
03026         for (int k = 0; k < nz; k++) {
03027                 for (int i = 0; i < nx; i++) {
03028                         double sum = 0;
03029                         for (int j = ny / 4; j < 3 * ny / 4; j++) {
03030                                 sum += data[i + j * nx];
03031                         }
03032 
03033                         float mean = (float)sum / (ny / 2);
03034                         for (int j = 0; j < ny; j++) {
03035                                 data[i + j * nx] = (data[i + j * nx] - mean) / sigma;
03036                         }
03037                 }
03038         }
03039 
03040         image->update();
03041 }
03042 
03043 void RealToFFTProcessor::process_inplace(EMData *image)
03044 {
03045         if (!image) {
03046                 LOGWARN("NULL Image");
03047                 return;
03048         }
03049 
03050         //Note : real image only!
03051         if(image->is_complex()) {
03052                 LOGERR("%s Processor only operates on real images", get_name().c_str());
03053                 throw ImageFormatException("apply to real image only");
03054         }
03055 
03056         // Note : 2D only!
03057         int nz = image->get_zsize();
03058         if (nz > 1) {
03059                 LOGERR("%s Processor doesn't support 3D models", get_name().c_str());
03060                 throw ImageDimensionException("3D model not supported");
03061         }
03062 
03063         EMData *ff=image->do_fft();
03064         ff->ri2ap();
03065 
03066         int nx=image->get_xsize();
03067         int ny=image->get_ysize();
03068 
03069         int x,y;
03070         float norm=static_cast<float>(nx*ny);
03071 
03072         for (y=0; y<ny; y++) image->set_value_at(0,y,0);
03073 
03074         for (x=1; x<nx/2; x++) {
03075                 for (y=0; y<ny; y++) {
03076                         int y2;
03077                         if (y<ny/2) y2=y+ny/2;
03078                         else if (y==ny/2) y2=ny;
03079                         else y2=y-ny/2;
03080                         image->set_value_at(x,y,ff->get_value_at(nx-x*2,ny-y2)/norm);
03081                 }
03082         }
03083 
03084         for (x=nx/2; x<nx; x++) {
03085                 for (y=0; y<ny; y++) {
03086                         int y2;
03087                         if (y<ny/2) y2=y+ny/2;
03088                         else y2=y-ny/2;
03089                         image->set_value_at(x,y,ff->get_value_at(x*2-nx,y2)/norm);
03090                 }
03091         }
03092 
03093         image->update();
03094         if( ff )
03095         {
03096                 delete ff;
03097                 ff = 0;
03098         }
03099 }
03100 
03101 void SigmaZeroEdgeProcessor::process_inplace(EMData * image)
03102 {
03103         if (!image) {
03104                 LOGWARN("NULL Image");
03105                 return;
03106         }
03107 
03108         if (image->get_zsize() > 1) {
03109                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
03110                 throw ImageDimensionException("3D model not supported");
03111         }
03112         float *d = image->get_data();
03113         int i = 0;
03114         int j = 0;
03115 
03116         int nx = image->get_xsize();
03117         int ny = image->get_ysize();
03118 
03119         for (j = 0; j < ny; j++) {
03120                 for (i = 0; i < nx - 1; i++) {
03121                         if (d[i + j * nx] != 0) {
03122                                 break;
03123                         }
03124                 }
03125 
03126                 float v = d[i + j * nx];
03127                 while (i >= 0) {
03128                         d[i + j * nx] = v;
03129                         i--;
03130                 }
03131 
03132                 for (i = nx - 1; i > 0; i--) {
03133                         if (d[i + j * nx] != 0)
03134                                 break;
03135                 }
03136                 v = d[i + j * nx];
03137                 while (i < nx) {
03138                         d[i + j * nx] = v;
03139                         i++;
03140                 }
03141         }
03142 
03143         for (i = 0; i < nx; i++) {
03144                 for (j = 0; j < ny; j++) {
03145                         if (d[i + j * nx] != 0)
03146                                 break;
03147                 }
03148 
03149                 float v = d[i + j * nx];
03150                 while (j >= 0) {
03151                         d[i + j * nx] = v;
03152                         j--;
03153                 }
03154 
03155                 for (j = ny - 1; j > 0; j--) {
03156                         if (d[i + j * nx] != 0)
03157                                 break;
03158                 }
03159                 v = d[i + j * nx];
03160                 while (j < ny) {
03161                         d[i + j * nx] = v;
03162                         j++;
03163                 }
03164         }
03165 
03166 
03167         image->update();
03168 }
03169 
03170 
03171 
03172 void BeamstopProcessor::process_inplace(EMData * image)
03173 {
03174         if (!image) {
03175                 LOGWARN("NULL Image");
03176                 return;
03177         }
03178         if (image->get_zsize() > 1) {
03179                 LOGERR("BeamstopProcessor doesn't support 3D model");
03180                 throw ImageDimensionException("3D model not supported");
03181         }
03182 
03183         float value1 = params["value1"];
03184         float value2 = params["value2"];
03185         float value3 = params["value3"];
03186 
03187         float thr = fabs(value1);
03188         float *data = image->get_data();
03189         int cenx = (int) value2;
03190         int ceny = (int) value3;
03191 
03192         int nx = image->get_xsize();
03193         int ny = image->get_ysize();
03194 
03195         if (cenx <= 0) {
03196                 cenx = nx / 2;
03197         }
03198 
03199         if (ceny <= 0) {
03200                 ceny = ny / 2;
03201         }
03202 
03203         int mxr = (int) floor(sqrt(2.0f) * nx / 2);
03204 
03205         float *mean_values = new float[mxr];
03206         float *sigma_values = new float[mxr];
03207         double sum = 0;
03208         int count = 0;
03209         double square_sum = 0;
03210 
03211         for (int i = 0; i < mxr; i++) {
03212                 sum = 0;
03213                 count = 0;
03214                 square_sum = 0;
03215                 int nitems = 6 * i + 2;
03216 
03217                 for (int j = 0; j < nitems; j++) {
03218                         float ang = j * 2 * M_PI / nitems;
03219                         int x0 = (int) floor(cos(ang) * i + cenx);
03220                         int y0 = (int) floor(sin(ang) * i + ceny);
03221 
03222                         if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny) {
03223                                 continue;
03224                         }
03225 
03226                         float f = data[x0 + y0 * nx];
03227                         sum += f;
03228                         square_sum += f * f;
03229                         count++;
03230                 }
03231 
03232                 mean_values[i] = (float)sum / count;
03233                 sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03234         }
03235 
03236 
03237         for (int k = 0; k < 5; k++) {
03238                 for (int i = 0; i < mxr; i++) {
03239                         sum = 0;
03240                         count = 0;
03241                         square_sum = 0;
03242                         int nitems = 6 * i + 2;
03243                         double thr1 = mean_values[i] - sigma_values[i] * thr;
03244                         double thr2 = mean_values[i] + sigma_values[i];
03245 
03246                         for (int j = 0; j < nitems; j++) {
03247                                 float ang = j * 2 * M_PI / nitems;
03248                                 int x0 = (int) floor(cos(ang) * i + cenx);
03249                                 int y0 = (int) floor(sin(ang) * i + ceny);
03250 
03251                                 if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny ||
03252                                         data[x0 + y0 * nx] < thr1 || data[x0 + y0 * nx] > thr2) {
03253                                         continue;
03254                                 }
03255 
03256                                 sum += data[x0 + y0 * nx];
03257                                 square_sum += data[x0 + y0 * nx] * data[x0 + y0 * nx];
03258                                 count++;
03259                         }
03260 
03261                         mean_values[i] = (float) sum / count;
03262                         sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03263                 }
03264         }
03265 
03266         for (int i = 0; i < nx; i++) {
03267                 for (int j = 0; j < ny; j++) {
03268 
03269 #ifdef  _WIN32
03270                         int r = Util::round(_hypot((float) i - cenx, (float) j - ceny));
03271 #else
03272                         int r = Util::round(hypot((float) i - cenx, (float) j - ceny));
03273 #endif  //_WIN32
03274 
03275                         if (value1 < 0) {
03276                                 if (data[i + j * nx] < (mean_values[r] - sigma_values[r] * thr)) {
03277                                         data[i + j * nx] = 0;
03278                                 }
03279                                 else {
03280                                         data[i + j * nx] -= mean_values[r];
03281                                 }
03282                                 continue;
03283                         }
03284                         if (data[i + j * nx] > (mean_values[r] - sigma_values[r] * thr)) {
03285                                 continue;
03286                         }
03287                         data[i + j * nx] = mean_values[r];
03288                 }
03289         }
03290 
03291         if( mean_values )
03292         {
03293                 delete[]mean_values;
03294                 mean_values = 0;
03295         }
03296 
03297         if( sigma_values )
03298         {
03299                 delete[]sigma_values;
03300                 sigma_values = 0;
03301         }
03302 
03303         image->update();
03304 }
03305 
03306 
03307 
03308 void MeanZeroEdgeProcessor::process_inplace(EMData * image)
03309 {
03310         if (!image) {
03311                 LOGWARN("NULL Image");
03312                 return;
03313         }
03314         if (image->get_zsize() > 1) {
03315                 LOGERR("MeanZeroEdgeProcessor doesn't support 3D model");
03316                 throw ImageDimensionException("3D model not supported");
03317         }
03318 
03319         int nx = image->get_xsize();
03320         int ny = image->get_ysize();
03321         Dict dict = image->get_attr_dict();
03322         float mean_nonzero = dict.get("mean_nonzero");
03323 
03324         float *d = image->get_data();
03325         int i = 0;
03326         int j = 0;
03327 
03328         for (j = 0; j < ny; j++) {
03329                 for (i = 0; i < nx - 1; i++) {
03330                         if (d[i + j * nx] != 0) {
03331                                 break;
03332                         }
03333                 }
03334 
03335                 if (i == nx - 1) {
03336                         i = -1;
03337                 }
03338 
03339                 float v = d[i + j * nx] - mean_nonzero;
03340 
03341                 while (i >= 0) {
03342                         v *= 0.9f;
03343                         d[i + j * nx] = v + mean_nonzero;
03344                         i--;
03345                 }
03346 
03347 
03348                 for (i = nx - 1; i > 0; i--) {
03349                         if (d[i + j * nx] != 0) {
03350                                 break;
03351                         }
03352                 }
03353 
03354                 if (i == 0) {
03355                         i = nx;
03356                 }
03357 
03358                 v = d[i + j * nx] - mean_nonzero;
03359 
03360                 while (i < nx) {
03361                         v *= .9f;
03362                         d[i + j * nx] = v + mean_nonzero;
03363                         i++;
03364                 }
03365         }
03366 
03367 
03368         for (i = 0; i < nx; i++) {
03369                 for (j = 0; j < ny; j++) {
03370                         if (d[i + j * nx] != 0)
03371                                 break;
03372                 }
03373 
03374                 float v = d[i + j * nx] - mean_nonzero;
03375 
03376                 while (j >= 0) {
03377                         v *= .9f;
03378                         d[i + j * nx] = v + mean_nonzero;
03379                         j--;
03380                 }
03381 
03382                 for (j = ny - 1; j > 0; j--) {
03383                         if (d[i + j * nx] != 0)
03384                                 break;
03385                 }
03386 
03387                 v = d[i + j * nx] - mean_nonzero;
03388 
03389                 while (j < ny) {
03390                         v *= .9f;
03391                         d[i + j * nx] = v + mean_nonzero;
03392                         j++;
03393                 }
03394         }
03395 
03396         image->update();
03397 }
03398 
03399 
03400 
03401 void AverageXProcessor::process_inplace(EMData * image)
03402 {
03403         if (!image) {
03404                 LOGWARN("NULL Image");
03405                 return;
03406         }
03407 
03408         float *data = image->get_data();
03409         int nx = image->get_xsize();
03410         int ny = image->get_ysize();
03411         int nz = image->get_zsize();
03412         size_t nxy = (size_t)nx * ny;
03413 
03414         size_t idx;
03415         for (int z = 0; z < nz; z++) {
03416                 for (int x = 0; x < nx; x++) {
03417                         double sum = 0;
03418                         for (int y = 0; y < ny; y++) {
03419                                 idx = x + y * nx + z * nxy;
03420                                 sum += data[idx];
03421                         }
03422                         float mean = (float) sum / ny;
03423 
03424                         for (int y = 0; y < ny; y++) {
03425                                 idx = x + y * nx + z * nxy;
03426                                 data[idx] = mean;
03427                         }
03428                 }
03429         }
03430 
03431         image->update();
03432 }
03433 
03434 void DecayEdgeProcessor::process_inplace(EMData * image)
03435 {
03436         if (!image) {
03437                 LOGWARN("NULL Image");
03438                 return;
03439         }
03440 
03441         if (image->get_zsize() > 1) throw ImageDimensionException("3D model not supported");
03442 
03443         int nx = image->get_xsize();
03444         int ny = image->get_ysize();
03445 
03446         float *d = image->get_data();
03447         int width = params["width"];
03448 
03449         for (int i=0; i<width; i++) {
03450                 float frac=i/(float)width;
03451                 for (int j=0; j<nx; j++) {
03452                         d[j+i*nx]*=frac;
03453                         d[nx*ny-j-i*nx-1]*=frac;
03454                 }
03455                 for (int j=0; j<ny; j++) {
03456                         d[j*nx+i]*=frac;
03457                         d[nx*ny-j*nx-i-1]*=frac;
03458                 }
03459         }
03460 
03461         image->update();
03462 }
03463 
03464 void ZeroEdgeRowProcessor::process_inplace(EMData * image)
03465 {
03466         if (!image) {
03467                 LOGWARN("NULL Image");
03468                 return;
03469         }
03470 
03471         if (image->get_zsize() > 1) {
03472                 LOGERR("ZeroEdgeRowProcessor is not supported in 3D models");
03473                 throw ImageDimensionException("3D model not supported");
03474         }
03475 
03476         int nx = image->get_xsize();
03477         int ny = image->get_ysize();
03478 
03479         float *d = image->get_data();
03480         int top_nrows = params["y0"];
03481         int bottom_nrows = params["y1"];
03482 
03483         int left_ncols = params["x0"];
03484         int right_ncols = params["x1"];
03485 
03486         size_t row_size = nx * sizeof(float);
03487 
03488         memset(d, 0, top_nrows * row_size);
03489         memset(d + (ny - bottom_nrows) * nx, 0, bottom_nrows * row_size);
03490 
03491         for (int i = top_nrows; i < ny - bottom_nrows; i++) {
03492                 memset(d + i * nx, 0, left_ncols * sizeof(float));
03493                 memset(d + i * nx + nx - right_ncols, 0, right_ncols * sizeof(float));
03494         }
03495         image->update();
03496 }
03497 
03498 void ZeroEdgePlaneProcessor::process_inplace(EMData * image)
03499 {
03500         if (!image) {
03501                 LOGWARN("NULL Image");
03502                 return;
03503         }
03504 
03505         if (image->get_zsize() <= 1) {
03506                 LOGERR("ZeroEdgePlaneProcessor only support 3D models");
03507                 throw ImageDimensionException("3D model only");
03508         }
03509 
03510         int nx = image->get_xsize();
03511         int ny = image->get_ysize();
03512         int nz = image->get_zsize();
03513 
03514         float *d = image->get_data();
03515 
03516         int x0=params["x0"];
03517         int x1=params["x1"];
03518         int y0=params["y0"];
03519         int y1=params["y1"];
03520         int z0=params["z0"];
03521         int z1=params["z1"];
03522 
03523         size_t row_size = nx * sizeof(float);
03524         size_t nxy = nx * ny;
03525         size_t sec_size = nxy * sizeof(float);
03526         size_t y0row = y0 * row_size;
03527         size_t y1row = y1 * row_size;
03528         int max_y = ny-y1;
03529         size_t x0size = x0*sizeof(float);
03530         size_t x1size = x1*sizeof(float);
03531 
03532         memset(d,0,z0*sec_size);                                        // zero -z
03533         memset(d+(nxy*(nz-z1)),0,sec_size*z1);      // zero +z
03534 
03535         for (int z=z0; z<nz-z1; z++) {
03536                 memset(d+z*nxy,0,y0row);                        // zero -y
03537                 memset(d+z*nxy+(ny-y1)*nx,0,y1row);     // zero +y
03538 
03539                 int znxy = z * nxy;
03540                 int znxy2 = znxy + nx - x1;
03541 
03542                 for (int y=y0; y<max_y; y++) {
03543                         memset(d+znxy+y*nx,0,x0size);   // zero -x
03544                         memset(d+znxy2+y*nx,0,x1size);  // zero +x
03545                 }
03546         }
03547 
03548         image->update();
03549 }
03550 
03551 
03552 float NormalizeProcessor::calc_sigma(EMData * image) const
03553 {
03554         return image->get_attr("sigma");
03555 }
03556 
03557 void NormalizeProcessor::process_inplace(EMData * image)
03558 {
03559         if (!image) {
03560                 LOGWARN("cannot do normalization on NULL image");
03561                 return;
03562         }
03563 
03564         if (image->is_complex()) {
03565                 LOGWARN("cannot do normalization on complex image");
03566                 return;
03567         }
03568 
03569         float sigma = calc_sigma(image);
03570         if (sigma == 0 || !Util::goodf(&sigma)) {
03571                 LOGWARN("cannot do normalization on image with sigma = 0");
03572                 return;
03573         }
03574 
03575         float mean = calc_mean(image);
03576 
03577         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03578         float *data = image->get_data();
03579 
03580         for (size_t i = 0; i < size; ++i) {
03581                 data[i] = (data[i] - mean) / sigma;
03582         }
03583 
03584         image->update();
03585 }
03586 
03587 float NormalizeUnitProcessor::calc_sigma(EMData * image) const
03588 {
03589         if (!image) {
03590                 LOGWARN("NULL Image");
03591                 return 0;
03592         }
03593         float ret=sqrt((float)image->get_attr("square_sum"));
03594         return ret==0.0f?1.0f:ret;
03595 }
03596 
03597 float NormalizeUnitSumProcessor::calc_sigma(EMData * image) const
03598 {
03599         if (!image) {
03600                 LOGWARN("NULL Image");
03601                 return 0;
03602         }
03603         float ret=(float)image->get_attr("mean")*image->get_xsize()*image->get_ysize()*image->get_zsize();
03604         return ret==0.0f?1.0f:ret;
03605 }
03606 
03607 float NormalizeMaskProcessor::calc_sigma(EMData * image) const
03608 {
03609         if (!image) {
03610                 LOGWARN("NULL Image");
03611                 return 0;
03612         }
03613         EMData *mask = params["mask"];
03614         int no_sigma = params["no_sigma"];
03615 
03616         if(no_sigma == 0) {
03617                 return 1;
03618         }
03619         else {
03620                 if (!EMUtil::is_same_size(mask, image)) {
03621                         LOGERR("normalize.maskProcessor: mask and image must be the same size");
03622                         throw ImageDimensionException("mask and image must be the same size");
03623                 }
03624 
03625                 float *data = image->get_data();
03626                 float *mask_data = mask->get_data();
03627                 size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03628                 double sum = 0;
03629                 double sq2 = 0;
03630                 size_t n_norm = 0;
03631 
03632                 for (size_t i = 0; i < size; ++i) {
03633                         if (mask_data[i] > 0.5f) {
03634                                 sum += data[i];
03635                                 sq2 += data[i]*double (data[i]);
03636                                 n_norm++;
03637                         }
03638                 }
03639                 return sqrt(static_cast<float>((sq2 - sum * sum /n_norm)/(n_norm -1))) ;
03640         }
03641 }
03642 
03643 float NormalizeMaskProcessor::calc_mean(EMData * image) const
03644 {
03645         if (!image) {
03646                 LOGWARN("NULL Image");
03647                 return 0;
03648         }
03649         EMData *mask = params["mask"];
03650 
03651         if (!EMUtil::is_same_size(mask, image)) {
03652                 LOGERR("normalize.maskProcessor: mask and image must be the same size");
03653                 throw ImageDimensionException("mask and image must be the same size");
03654         }
03655 
03656         float *data = image->get_data();
03657         float *mask_data = mask->get_data();
03658         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03659         double sum = 0;
03660         size_t n_norm = 0;
03661 
03662         for (size_t i = 0; i < size; ++i) {
03663                 if (mask_data[i] > 0.5f) {
03664                         sum += data[i];
03665                         n_norm++;
03666                 }
03667         }
03668 
03669         float mean = 0;
03670         if (n_norm == 0) {
03671                 mean = image->get_edge_mean();
03672         }
03673         else {
03674                 mean = (float) sum / n_norm;
03675         }
03676 
03677         return mean;
03678 }
03679 
03680 void NormalizeRampNormVar::process_inplace(EMData * image)
03681 {
03682         if (!image) {
03683                 LOGWARN("cannot do normalization on NULL image");
03684                 return;
03685         }
03686 
03687         if (image->is_complex()) {
03688                 LOGWARN("cannot do normalization on complex image");
03689                 return;
03690         }
03691 
03692         image->process_inplace( "filter.ramp" );
03693         int nx = image->get_xsize();
03694         EMData mask(nx,nx);
03695         mask.process_inplace("testimage.circlesphere", Dict("radius",nx/2-2,"fill",1));
03696 
03697         vector<float> rstls = Util::infomask( image, &mask, false);
03698         image->add((float)-rstls[0]);
03699         image->mult((float)1.0/rstls[1]);
03700         image->update();
03701 }
03702 
03703 void NormalizeByMassProcessor::process_inplace(EMData * image)
03704 {
03705         float mass = params.set_default("mass",-1.0f);
03706 
03707         if (mass <= 0) throw InvalidParameterException("You must specify a positive non zero mass");
03708 
03709         float thr = params.set_default("thr",(float)image->get_attr("mean")+(float)image->get_attr("sigma"));
03710 
03711         float apix = image->get_attr_default("apix_x",1.0f);
03712         apix = params.set_default("apix",apix);
03713 
03714         if (apix <= 0) throw InvalidParameterException("You must specify a positive non zero apix");
03715 
03716         float step = ((float)image->get_attr("sigma"))/2.0f;
03717 
03718         int count=0;
03719         size_t n = image->get_size();
03720         float* d = image->get_data();
03721 
03722         for (size_t i=0; i<n; ++i) {
03723                 if (d[i]>=thr) ++count;
03724         }
03725 
03726         float max = image->get_attr("maximum");
03727         float min = image->get_attr("minimum");
03728         for (int j=0; j<4; j++) {
03729                 while (thr<max && count*apix*apix*apix*.81/1000.0>mass) {
03730                         thr+=step;
03731                         count=0;
03732                         for (size_t i=0; i<n; ++i) {
03733                                 if (d[i]>=thr) ++count;
03734                         }
03735                 }
03736 
03737                 step/=4.0;
03738 
03739                 while (thr>min && count*apix*apix*apix*.81/1000.0<mass) {
03740                         thr-=step;
03741                         count=0;
03742                         for (size_t i=0; i<n; ++i) {
03743                                 if (d[i]>=thr) ++count;
03744                         }
03745                 }
03746 
03747                 step/=4.0;
03748         }
03749 
03750         image->mult((float)1.0/thr);
03751         image->update();
03752 }
03753 
03754 float NormalizeEdgeMeanProcessor::calc_mean(EMData * image) const
03755 {
03756         if (!image) {
03757                 LOGWARN("NULL Image");
03758                 return 0;
03759         }
03760         return image->get_edge_mean();
03761 }
03762 
03763 float NormalizeCircleMeanProcessor::calc_mean(EMData * image) const
03764 {
03765         if (!image) {
03766                 LOGWARN("NULL Image");
03767                 return 0;
03768         }
03769         return image->get_circle_mean();
03770 }
03771 
03772 
03773 float NormalizeMaxMinProcessor::calc_sigma(EMData * image) const
03774 {
03775         if (!image) {
03776                 LOGWARN("NULL Image");
03777                 return 0;
03778         }
03779         float maxval = image->get_attr("maximum");
03780         float minval = image->get_attr("minimum");
03781         return (maxval + minval) / 2;
03782 }
03783 
03784 float NormalizeMaxMinProcessor::calc_mean(EMData * image) const
03785 {
03786         if (!image) {
03787                 LOGWARN("NULL Image");
03788                 return 0;
03789         }
03790         float maxval = image->get_attr("maximum");
03791         float minval = image->get_attr("minimum");
03792         return (maxval - minval) / 2;
03793 }
03794 
03795 float NormalizeLREdgeMeanProcessor::calc_mean(EMData * image) const
03796 {
03797         if (!image) {
03798                 LOGWARN("NULL Image");
03799                 return 0;
03800         }
03801         double sum = 0;
03802         int nx = image->get_xsize();
03803         int ny = image->get_ysize();
03804         int nz = image->get_zsize();
03805         float *d = image->get_data();
03806         size_t nyz = ny * nz;
03807 
03808         for (size_t i = 0; i < nyz; i++) {
03809                 size_t l = i * nx;
03810                 size_t r = l + nx - 2;
03811                 sum += d[l] + d[l + 1] + d[r] + d[r + 1];
03812         }
03813         float mean = (float) sum / (4 * nyz);
03814         return mean;
03815 }
03816 
03817 void NormalizeRowProcessor::process_inplace(EMData * image)
03818 {
03819         if (!image) {
03820                 LOGWARN("NULL Image");
03821                 return;
03822         }
03823 
03824         if (image->get_zsize() > 1) {
03825                 LOGERR("row normalize only works for 2D image");
03826                 return;
03827         }
03828 
03829         float *rdata = image->get_data();
03830         int nx = image->get_xsize();
03831         int ny = image->get_ysize();
03832 
03833         for (int y = 0; y < ny; y++) {
03834                 double row_sum = 0;
03835                 for (int x = 0; x < nx; x++) {
03836                         row_sum += rdata[x + y * nx];
03837                 }
03838 
03839                 double row_mean = row_sum / nx;
03840                 if (row_mean <= 0) {
03841                         row_mean = 1;
03842                 }
03843 
03844                 for (int x = 0; x < nx; x++) {
03845                         rdata[x + y * nx] /= (float)row_mean;
03846                 }
03847         }
03848 
03849         image->update();
03850 }
03851 
03852 float NormalizeStdProcessor::calc_mean(EMData * image) const
03853 {
03854         if (!image) {
03855                 LOGWARN("NULL Image");
03856                 return 0;
03857         }
03858         return image->get_attr("mean");
03859 }
03860 
03861 
03862 
03863 void NormalizeToLeastSquareProcessor::process_inplace(EMData * image)
03864 {
03865         if (!image) {
03866                 LOGWARN("NULL Image");
03867                 return;
03868         }
03869 
03870         EMData *to = params["to"];
03871 
03872         bool ignore_zero = params.set_default("ignore_zero",true);
03873 
03874         float low_threshold = FLT_MIN;
03875         string low_thr_name = "low_threshold";
03876         if (params.has_key(low_thr_name)) {
03877                 low_threshold = params[low_thr_name];
03878         }
03879 
03880         float high_threshold = FLT_MAX;
03881         string high_thr_name = "high_threshold";
03882         if (params.has_key(high_thr_name)) {
03883                 high_threshold = params[high_thr_name];
03884         }
03885 
03886         float *rawp = image->get_data();
03887         float *refp = to->get_data();
03888 
03889         int nx = image->get_xsize();
03890         int ny = image->get_ysize();
03891         int nz = image->get_zsize();
03892         size_t size = (size_t)nx * ny * nz;
03893 
03894         float sum_x = 0;
03895         float sum_y = 0;
03896         size_t count = 0;
03897 
03898         float sum_x_mean = 0;
03899         float sum_tt = 0;
03900         float b = 0;
03901 
03902         // This is really inefficient, who coded it ?   --steve
03903         if (ignore_zero) {
03904                 for (size_t i = 0; i < size; ++i) {
03905                         if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0f && rawp[i] != 0.0f) {
03906                                 count++;
03907                                 sum_x += refp[i];
03908                                 sum_y += rawp[i];
03909                         }
03910                 }
03911 
03912                 sum_x_mean = sum_x / count;
03913                 sum_tt = 0;
03914                 b = 0;
03915 
03916                 float t;
03917                 for (size_t i = 0; i < size; ++i) {
03918                         if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0f && rawp[i] != 0.0f) {
03919                                 t = refp[i] - sum_x_mean;
03920                                 sum_tt += t * t;
03921                                 b += t * rawp[i];
03922                         }
03923                 }
03924         }
03925         else {
03926                         for (size_t i = 0; i < size; ++i) {
03927                         if (refp[i] >= low_threshold && refp[i] <= high_threshold) {
03928                                 count++;
03929                                 sum_x += refp[i];
03930                                 sum_y += rawp[i];
03931                         }
03932                 }
03933 
03934                 sum_x_mean = sum_x / count;
03935                 sum_tt = 0;
03936                 b = 0;
03937 
03938                 float t;
03939                 for (size_t i = 0; i < size; ++i) {
03940                         if (refp[i] >= low_threshold && refp[i] <= high_threshold) {
03941                                 t = refp[i] - sum_x_mean;
03942                                 sum_tt += t * t;
03943                                 b += t * rawp[i];
03944                         }
03945                 }
03946         }
03947 
03948         b /= sum_tt;
03949 
03950         float a = (sum_y - sum_x * b) / count;
03951         float scale = 1 / b;
03952         float shift = -a / b;
03953 
03954         for (size_t i = 0; i < size; ++i) {
03955                 rawp[i] = (rawp[i] - a) / b;
03956         }
03957 
03958         image->update();
03959 
03960         params["scale"] = scale;
03961         params["shift"] = shift;
03962 
03963         image->set_attr("norm_mult",scale);
03964         image->set_attr("norm_add",shift);
03965 
03966 }
03967 
03968 void BinarizeFourierProcessor::process_inplace(EMData* image) {
03969         ENTERFUNC;
03970         if (!image->is_complex()) throw ImageFormatException("Fourier binary thresholding processor only works for complex images");
03971 
03972         float threshold = params.set_default("value",0.0f);
03973         image->ri2ap(); //  works for cuda
03974 
03975         float* d = image->get_data();
03976         for( size_t i = 0; i < image->get_size()/2; ++i, d+=2) {
03977                 if ( *d < threshold ) {
03978                         *d = 0;
03979                         *(d+1) = 0;
03980                 } 
03981         }
03982         image->ap2ri();
03983         image->set_ri(true); // So it can be used for fourier multiplaction, for example
03984         image->update();
03985         EXITFUNC;
03986 } 
03987   
03988 void BilateralProcessor::process_inplace(EMData * image)
03989 {
03990         if (!image) {
03991                 LOGWARN("NULL Image");
03992                 return;
03993         }
03994 
03995         float distance_sigma = params["distance_sigma"];
03996         float value_sigma = params["value_sigma"];
03997         int max_iter = params["niter"];
03998         int half_width = params["half_width"];
03999 
04000         if (half_width < distance_sigma) {
04001                 LOGWARN("localwidth(=%d) should be larger than distance_sigma=(%f)\n",
04002                                                         half_width, distance_sigma);
04003         }
04004 
04005         distance_sigma *= distance_sigma;
04006 
04007         float image_sigma = image->get_attr("sigma");
04008         if (image_sigma > value_sigma) {
04009                 LOGWARN("image sigma(=%f) should be smaller than value_sigma=(%f)\n",
04010                                                         image_sigma, value_sigma);
04011         }
04012         value_sigma *= value_sigma;
04013 
04014         int nx = image->get_xsize();
04015         int ny = image->get_ysize();
04016         int nz = image->get_zsize();
04017 
04018         if(nz==1) {     //for 2D image
04019                 int width=nx, height=ny;
04020 
04021                 int i,j,m,n;
04022 
04023                 float tempfloat1,tempfloat2,tempfloat3;
04024                 int   index1,index2,index;
04025                 int   Iter;
04026                 int   tempint1,tempint3;
04027 
04028                 tempint1=width;
04029                 tempint3=width+2*half_width;
04030 
04031                 float* mask=(float*)calloc((2*half_width+1)*(2*half_width+1),sizeof(float));
04032                 float* OrgImg=(float*)calloc((2*half_width+width)*(2*half_width+height),sizeof(float));
04033                 float* NewImg=image->get_data();
04034 
04035                 for(m=-(half_width);m<=half_width;m++)
04036                         for(n=-(half_width);n<=half_width;n++) {
04037                    index=(m+half_width)*(2*half_width+1)+(n+half_width);
04038                    mask[index]=exp((float)(-(m*m+n*n)/distance_sigma/2.0));
04039                 }
04040 
04041                 //printf("entering bilateral filtering process \n");
04042 
04043                 Iter=0;
04044                 while(Iter<max_iter) {
04045                         for(i=0;i<height;i++)
04046                         for(j=0;j<width;j++) {
04047                                 index1=(i+half_width)*tempint3+(j+half_width);
04048                                         index2=i*tempint1+j;
04049                                 OrgImg[index1]=NewImg[index2];
04050                         }
04051 
04052                         // Mirror Padding
04053                         for(i=0;i<height;i++){
04054                                 for(j=0;j<half_width;j++) OrgImg[(i+half_width)*tempint3+(j)]=OrgImg[(i+half_width)*tempint3+(2*half_width-j)];
04055                                 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)];
04056                         }
04057                         for(i=0;i<half_width;i++){
04058                                 for(j=0;j<(width+2*half_width);j++) OrgImg[i*tempint3+j]=OrgImg[(2*half_width-i)*tempint3+j];
04059                                 for(j=0;j<(width+2*half_width);j++) OrgImg[(i+height+half_width)*tempint3+j]=OrgImg[(height+half_width-2-i)*tempint3+j];
04060                         }
04061 
04062                         //printf("finish mirror padding process \n");
04063                         //now mirror padding have been done
04064 
04065                         for(i=0;i<height;i++){
04066                                 //printf("now processing the %d th row \n",i);
04067                                 for(j=0;j<width;j++){
04068                                         tempfloat1=0.0; tempfloat2=0.0;
04069                                         for(m=-(half_width);m<=half_width;m++)
04070                                                 for(n=-(half_width);n<=half_width;n++){
04071                                                         index =(m+half_width)*(2*half_width+1)+(n+half_width);
04072                                                         index1=(i+half_width)*tempint3+(j+half_width);
04073                                                         index2=(i+half_width+m)*tempint3+(j+half_width+n);
04074                                                         tempfloat3=(OrgImg[index1]-OrgImg[index2])*(OrgImg[index1]-OrgImg[index2]);
04075 
04076                                                         tempfloat3=mask[index]*(1.0f/(1+tempfloat3/value_sigma));       // Lorentz kernel
04077                                                         //tempfloat3=mask[index]*exp(tempfloat3/Sigma2/(-2.0)); // Guassian kernel
04078                                                         tempfloat1+=tempfloat3;
04079 
04080                                                         tempfloat2+=tempfloat3*OrgImg[(i+half_width+m)*tempint3+(j+half_width+n)];
04081                                         }
04082                                         NewImg[i*width+j]=tempfloat2/tempfloat1;
04083                                 }
04084                         }
04085                         Iter++;
04086             }
04087 
04088             //printf("have finished %d  th iteration\n ",Iter);
04089 //              doneData();
04090                 free(mask);
04091                 free(OrgImg);
04092                 // end of BilaFilter routine
04093 
04094         }
04095         else {  //3D case
04096                 int width = nx;
04097                 int height = ny;
04098                 int slicenum = nz;
04099 
04100                 int slice_size = width * height;
04101                 int new_width = width + 2 * half_width;
04102                 int new_slice_size = (width + 2 * half_width) * (height + 2 * half_width);
04103 
04104                 int width1 = 2 * half_width + 1;
04105                 int mask_size = width1 * width1;
04106                 int old_img_size = (2 * half_width + width) * (2 * half_width + height);
04107 
04108                 int zstart = -half_width;
04109                 int zend = -half_width;
04110                 int is_3d = 0;
04111                 if (nz > 1) {
04112                         mask_size *= width1;
04113                         old_img_size *= (2 * half_width + slicenum);
04114                         zend = half_width;
04115                         is_3d = 1;
04116                 }
04117 
04118                 float *mask = (float *) calloc(mask_size, sizeof(float));
04119                 float *old_img = (float *) calloc(old_img_size, sizeof(float));
04120 
04121                 float *new_img = image->get_data();
04122 
04123                 for (int p = zstart; p <= zend; p++) {
04124                         int cur_p = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04125 
04126                         for (int m = -half_width; m <= half_width; m++) {
04127                                 int cur_m = (m + half_width) * (2 * half_width + 1) + half_width;
04128 
04129                                 for (int n = -half_width; n <= half_width; n++) {
04130                                         int l = cur_p + cur_m + n;
04131                                         mask[l] = exp((float) (-(m * m + n * n + p * p * is_3d) / distance_sigma / 2.0f));
04132                                 }
04133                         }
04134                 }
04135 
04136                 int iter = 0;
04137                 while (iter < max_iter) {
04138                         for (int k = 0; k < slicenum; k++) {
04139                                 size_t cur_k1 = (size_t)(k + half_width) * new_slice_size * is_3d;
04140                                 int cur_k2 = k * slice_size;
04141 
04142                                 for (int i = 0; i < height; i++) {
04143                                         int cur_i1 = (i + half_width) * new_width;
04144                                         int cur_i2 = i * width;
04145 
04146                                         for (int j = 0; j < width; j++) {
04147                                                 size_t k1 = cur_k1 + cur_i1 + (j + half_width);
04148                                                 int k2 = cur_k2 + cur_i2 + j;
04149                                                 old_img[k1] = new_img[k2];
04150                                         }
04151                                 }
04152                         }
04153 
04154                         for (int k = 0; k < slicenum; k++) {
04155                                 size_t cur_k = (k + half_width) * new_slice_size * is_3d;
04156 
04157                                 for (int i = 0; i < height; i++) {
04158                                         int cur_i = (i + half_width) * new_width;
04159 
04160                                         for (int j = 0; j < half_width; j++) {
04161                                                 size_t k1 = cur_k + cur_i + j;
04162                                                 size_t k2 = cur_k + cur_i + (2 * half_width - j);
04163                                                 old_img[k1] = old_img[k2];
04164                                         }
04165 
04166                                         for (int j = 0; j < half_width; j++) {
04167                                                 size_t k1 = cur_k + cur_i + (width + half_width + j);
04168                                                 size_t k2 = cur_k + cur_i + (width + half_width - j - 2);
04169                                                 old_img[k1] = old_img[k2];
04170                                         }
04171                                 }
04172 
04173 
04174                                 for (int i = 0; i < half_width; i++) {
04175                                         int i2 = i * new_width;
04176                                         int i3 = (2 * half_width - i) * new_width;
04177                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04178                                                 size_t k1 = cur_k + i2 + j;
04179                                                 size_t k2 = cur_k + i3 + j;
04180                                                 old_img[k1] = old_img[k2];
04181                                         }
04182 
04183                                         i2 = (height + half_width + i) * new_width;
04184                                         i3 = (height + half_width - 2 - i) * new_width;
04185                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04186                                                 size_t k1 = cur_k + i2 + j;
04187                                                 size_t k2 = cur_k + i3 + j;
04188                                                 old_img[k1] = old_img[k2];
04189                                         }
04190                                 }
04191                         }
04192 
04193                         size_t idx;
04194                         for (int k = 0; k < slicenum; k++) {
04195                                 size_t cur_k = (k + half_width) * new_slice_size;
04196 
04197                                 for (int i = 0; i < height; i++) {
04198                                         int cur_i = (i + half_width) * new_width;
04199 
04200                                         for (int j = 0; j < width; j++) {
04201                                                 float f1 = 0;
04202                                                 float f2 = 0;
04203                                                 size_t k1 = cur_k + cur_i + (j + half_width);
04204 
04205                                                 for (int p = zstart; p <= zend; p++) {
04206                                                         size_t cur_p1 = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04207                                                         size_t cur_p2 = (k + half_width + p) * new_slice_size;
04208 
04209                                                         for (int m = -half_width; m <= half_width; m++) {
04210                                                                 size_t cur_m1 = (m + half_width) * (2 * half_width + 1);
04211                                                                 size_t cur_m2 = cur_p2 + cur_i + m * new_width + j + half_width;
04212 
04213                                                                 for (int n = -half_width; n <= half_width; n++) {
04214                                                                         size_t k = cur_p1 + cur_m1 + (n + half_width);
04215                                                                         size_t k2 = cur_m2 + n;
04216                                                                         float f3 = Util::square(old_img[k1] - old_img[k2]);
04217 
04218                                                                         f3 = mask[k] * (1.0f / (1 + f3 / value_sigma));
04219                                                                         f1 += f3;
04220                                                                         size_t l1 = cur_m2 + n;
04221                                                                         f2 += f3 * old_img[l1];
04222                                                                 }
04223 
04224                                                                 idx = (size_t)k * height * width + i * width + j;
04225                                                                 new_img[idx] = f2 / f1;
04226                                                         }
04227                                                 }
04228                                         }
04229                                 }
04230                         }
04231                         iter++;
04232                 }
04233                 if( mask ) {
04234                         free(mask);
04235                         mask = 0;
04236                 }
04237 
04238                 if( old_img ) {
04239                         free(old_img);
04240                         old_img = 0;
04241                 }
04242         }
04243 
04244         image->update();
04245 }
04246 
04247 void RotationalAverageProcessor::process_inplace(EMData * image)
04248 {
04249         if (!image || image->is_complex()) {
04250                 LOGWARN("only works on real image. do nothing.");
04251                 return;
04252         }
04253 
04254         if (image->get_ndim() <= 0 || image->get_ndim() > 3)    throw ImageDimensionException("radial average processor only works for 2D and 3D images");
04255 
04256         float *rdata = image->get_data();
04257         int nx = image->get_xsize();
04258         int ny = image->get_ysize();
04259 
04260         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04261 
04262         float midx = (float)((int)nx/2);
04263         float midy = (float)((int)ny/2);
04264 
04265         size_t c = 0;
04266         if (image->get_ndim() == 2) {
04267                 for (int y = 0; y < ny; y++) {
04268                         for (int x = 0; x < nx; x++, c++) {
04269         #ifdef  _WIN32
04270                                 float r = (float) _hypot(x - midx, y - midy);
04271         #else
04272                                 float r = (float) hypot(x - midx, y - midy);
04273         #endif  //_WIN32
04274 
04275 
04276                                 int i = (int) floor(r);
04277                                 r -= i;
04278                                 if (i >= 0 && i < nx / 2 - 1) {
04279                                         rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04280                                 }
04281                                 else if (i < 0) {
04282                                         rdata[c] = dist[0];
04283                                 }
04284                                 else {
04285                                         rdata[c] = 0;
04286                                 }
04287                         }
04288                 }
04289         }
04290         else if (image->get_ndim() == 3) {
04291                 int nz = image->get_zsize();
04292                 float midz = (float)((int)nz/2);
04293                 float r;
04294                 int i;
04295                 for (int z = 0; z < nz; ++z) {
04296                         for (int y = 0; y < ny; ++y) {
04297                                 for (int x = 0; x < nx; ++x, ++c) {
04298 
04299                                         r = (float) Util::hypot3(x - midx, y - midy, z - midz);
04300 
04301                                         i = Util::fast_floor(r);
04302                                         r -= i;
04303                                         if (i >= 0 && i < nx / 2 - 1) {
04304                                                 rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04305                                         }
04306                                         else if (i < 0) {
04307                                                 rdata[c] = dist[0];
04308                                         }
04309                                         else {
04310                                                 rdata[c] = 0;
04311                                         }
04312                                 }
04313                         }
04314                 }
04315         }
04316 
04317         image->update();
04318 }
04319 
04320 
04321 
04322 void RotationalSubstractProcessor::process_inplace(EMData * image)
04323 {
04324         if (!image || image->is_complex()) {
04325                 LOGWARN("only works on real image. do nothing.");
04326                 return;
04327         }
04328 
04329         if (image->get_ndim() != 2) throw ImageDimensionException("This processor works only for 2D images");
04330 
04331         float *rdata = image->get_data();
04332         int nx = image->get_xsize();
04333         int ny = image->get_ysize();
04334 
04335         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04336 
04337         int c = 0;
04338         for (int y = 0; y < ny; y++) {
04339                 for (int x = 0; x < nx; x++, c++) {
04340 #ifdef  _WIN32
04341                         float r = (float) _hypot(x - nx / 2, y - ny / 2);
04342 #else
04343                         float r = (float) hypot(x - nx / 2, y - ny / 2);
04344 #endif
04345                         int i = (int) floor(r);
04346                         r -= i;
04347                         if (i >= 0 && i < nx / 2 - 1) {
04348                                 rdata[c] -= dist[i] * (1.0f - r) + dist[i + 1] * r;
04349                         }
04350                         else {
04351                                 rdata[c] = 0;
04352                         }
04353                 }
04354         }
04355 
04356         image->update();
04357 }
04358 
04359 
04360 EMData* TransposeProcessor::process(const EMData* const image) {
04361         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04362         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04363 
04364         EMData* ret = new EMData(image->get_ysize(),image->get_xsize(),1); // transpose dimensions
04365 
04366         for(int j = 0; j< image->get_ysize();++j) {
04367                 for(int i = 0; i< image->get_xsize();++i) {
04368                         ret->set_value_at(j,i,image->get_value_at(i,j));
04369                 }
04370         }
04371 
04372         return ret;
04373 
04374 }
04375 
04376 void TransposeProcessor::process_inplace(EMData* image) {
04377         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04378         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04379 
04380         float* data = (float*)malloc(image->get_ysize()*image->get_xsize()*sizeof(float));
04381 
04382         int nx = image->get_ysize(); // note tranpose
04383         for(int j = 0; j< image->get_ysize();++j) {
04384                 for(int i = 0; i< image->get_xsize();++i) {
04385                         data[i*nx+j] = image->get_value_at(i,j);
04386                 }
04387         }
04388 
04389         image->set_data(data,image->get_ysize(),image->get_xsize(),1);
04390 
04391 }
04392 
04393 void FlipProcessor::process_inplace(EMData * image)
04394 {
04395         ENTERFUNC;
04396         if (!image) {
04397                 LOGWARN("NULL Image");
04398                 return;
04399         }
04400         string axis = (const char*)params["axis"];
04401         
04402 #ifdef EMAN2_USING_CUDA
04403         if (EMData::usecuda == 1 && image->getcudarwdata()) {
04404                 //cout << "flip processor" << endl;
04405                 float array[12] = {1.0, 0.0, 0.0, 0.0,
04406                                                    0.0, 1.0, 0.0, 0.0,
04407                                                    0.0, 0.0, 1.0, 0.0};
04408                 if (axis == "x" || axis == "X") {               // horizontal flip
04409                         array[0] = -1.0;
04410                 }else if (axis == "y" || axis == "Y") {         // vertical flip
04411                         array[5] = -1.0;
04412                 }
04413                 else if (axis == "z" || axis == "Z") {          // vertical flip
04414                         array[10] = -1.0;
04415                 }
04416                 Transform t(array);
04417                 Dict params("transform",(Transform*)&t);
04418                 image->process_inplace("xform",params);
04419 
04420                 EXITFUNC;
04421                 return;
04422         }
04423 #endif
04424 
04425 
04426         float *d = image->get_data();
04427         int nx = image->get_xsize();
04428         int ny = image->get_ysize();
04429         int nz = image->get_zsize();
04430 
04431         size_t nxy = nx * ny;
04432 
04433 
04434         // Note in all cases the origin is nx/2, ny/2 and nz/2
04435         // This means when flipping even sized dimensions that some pixels are redundant.
04436         // Here redundant pixels are set to zero, however, should this change to something
04437         // like the mean.
04438         if (axis == "x" || axis == "X") {               // Horizontal flip
04439                 int offset = (nx%2 == 0);
04440                 size_t idx1, idx2;
04441                 for(int z = 0; z < nz; ++z) {
04442                         for(int y = 0; y < ny; ++y) {
04443                                 if (offset != 0 ) {
04444                                         idx1 = z*nxy + y*nx;
04445                                         d[idx1] = 0; // Here's where you'd make it the mean
04446                                 }
04447                                 for(int x = offset; x < nx / 2; ++x) {
04448                                         idx1 = z*nxy + y*nx + x;
04449                                         idx2 = z*nxy + y*nx + (nx-x-1+offset);
04450                                         std::swap(d[idx1], d[idx2]);
04451                                 }
04452 
04453                         }
04454                 }
04455         }
04456 
04457         else if (axis == "y" || axis == "Y") {          // vertical flip
04458                 int offset = (ny%2 == 0);
04459                 for(int z=0; z<nz; ++z) {
04460                         if (offset != 0) {
04461                                 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)
04462                         }
04463                         for(int y=offset; y<ny/2; ++y) {
04464                                 for(int x=0; x<nx; ++x) {
04465                                         std::swap(d[(size_t)z*nxy + y*nx +x], d[(size_t)z*nxy + (ny -y -1+offset)*nx +x]);
04466                                 }
04467                         }
04468                 }
04469         }
04470         else if (axis == "z" || axis == "Z") {          //z axis flip
04471                 int offset = (nz%2 == 0);
04472                 if (offset != 0) {
04473                         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)
04474                 }
04475                 size_t idx1, idx2;
04476                 for(int z=offset; z<nz/2; ++z) {
04477                         for(int y=0; y<ny; ++y) {
04478                                 for(int x=0; x<nx; ++x) {
04479                                         idx1 = (size_t)z*nxy + y*nx + x;
04480                                         idx2 = (size_t)(nz-z-1+offset)*nxy + y*nx + x;
04481                                         std::swap(d[idx1], d[idx2]);
04482                                 }
04483                         }
04484                 }
04485         }
04486 
04487         image->update();
04488         EXITFUNC;
04489 }
04490 
04491 void AddNoiseProcessor::process_inplace(EMData * image)
04492 {
04493         if (!image) {
04494                 LOGWARN("NULL Image");
04495                 return;
04496         }
04497 
04498         Randnum * randnum = Randnum::Instance();
04499         if(params.has_key("seed")) {
04500                 randnum->set_seed((int)params["seed"]);
04501         }
04502 
04503         float addnoise = params["noise"];
04504         addnoise *= get_sigma(image);
04505         float *dat = image->get_data();
04506 
04507         for (size_t j = 0; j < image->get_size(); ++j) {
04508                 dat[j] += randnum->get_gauss_rand(addnoise, addnoise / 2);
04509         }
04510 
04511         image->update();
04512 }
04513 
04514 float AddSigmaNoiseProcessor::get_sigma(EMData * image)
04515 {
04516         if (!image) {
04517                 LOGWARN("NULL Image");
04518                 return 0;
04519         }
04520         return image->get_attr("sigma");
04521 }
04522 
04523 void FourierToCornerProcessor::process_inplace(EMData * image)
04524 {
04525         if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04526 
04527         int nx=image->get_xsize();
04528         int ny=image->get_ysize();
04529         int nz=image->get_zsize();
04530 
04531         int nxy = nx*ny;
04532 
04533         if ( ny == 1 && nz == 1 ){
04534                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04535                 return;
04536         }
04537         int yodd = (ny%2==1);
04538         int zodd = (nz%2==1);
04539 
04540         float* rdata = image->get_data();
04541 
04542         float tmp[2];
04543         float* p1;
04544         float* p2;
04545 
04546         if (yodd){
04547                 // Swap the middle slice (with respect to the y direction) with the bottom slice
04548                 // shifting all slices above the middles slice upwards by one pixel, stopping
04549                 // at the middle slice, not if nz = 1 we are not talking about slices, we are
04550                 // talking about rows
04551                 float prev[2];
04552                 size_t idx;
04553                 for( int s = 0; s < nz; s++ ) {
04554                         for( int c =0; c < nx; c += 2 ) {
04555                                 idx = (size_t)s*nxy+ny/2*nx+c;
04556                                 prev[0] = rdata[idx];
04557                                 prev[1] = rdata[idx+1];
04558                                 for( int r = 0; r <= ny/2; ++r ) {
04559                                         idx = (size_t)s*nxy+r*nx+c;
04560                                         float* p1 = &rdata[idx];
04561                                         tmp[0] = p1[0];
04562                                         tmp[1] = p1[1];
04563 
04564                                         p1[0] = prev[0];
04565                                         p1[1] = prev[1];
04566 
04567                                         prev[0] = tmp[0];
04568                                         prev[1] = tmp[1];
04569                                 }
04570                         }
04571                 }
04572         }
04573 
04574         // Shift slices (3D) or rows (2D) correctly in the y direction
04575         size_t idx1, idx2;
04576         for( int s = 0; s < nz; ++s ) {
04577                 for( int r = 0 + yodd; r < ny/2+yodd; ++r ) {
04578                         for( int c =0; c < nx; c += 2 ) {
04579                                 idx1 = (size_t)s*nxy+r*nx+c;
04580                                 idx2 = (size_t)s*nxy+(r+ny/2)*nx+c;
04581                                 p1 = &rdata[idx1];
04582                                 p2 = &rdata[idx2];
04583 
04584                                 tmp[0] = p1[0];
04585                                 tmp[1] = p1[1];
04586 
04587                                 p1[0] = p2[0];
04588                                 p1[1] = p2[1];
04589 
04590                                 p2[0] = tmp[0];
04591                                 p2[1] = tmp[1];
04592                         }
04593                 }
04594         }
04595 
04596         if ( nz != 1 )
04597         {
04598 
04599                 if (zodd){
04600                         // Swap the middle slice (with respect to the z direction) and the front slice
04601                         // shifting all behind the front slice towards the middle a distance of 1 voxel,
04602                         // stopping at the middle slice.
04603                         float prev[2];
04604                         size_t idx;
04605                         for( int r = 0; r < ny; ++r ) {
04606                                 for( int c =0; c < nx; c += 2 ) {
04607                                         idx = (size_t)nz/2*nxy+r*nx+c;
04608                                         prev[0] = rdata[idx];
04609                                         prev[1] = rdata[idx+1];
04610                                         for( int s = 0; s <= nz/2; ++s ) {
04611                                                 idx = (size_t)s*nxy+r*nx+c;
04612                                                 float* p1 = &rdata[idx];
04613                                                 tmp[0] = p1[0];
04614                                                 tmp[1] = p1[1];
04615 
04616                                                 p1[0] = prev[0];
04617                                                 p1[1] = prev[1];
04618 
04619                                                 prev[0] = tmp[0];
04620                                                 prev[1] = tmp[1];
04621                                         }
04622                                 }
04623                         }
04624                 }
04625 
04626                 // Shift slices correctly in the z direction
04627                 size_t idx1, idx2;
04628                 for( int s = 0+zodd; s < nz/2 + zodd; ++s ) {
04629                         for( int r = 0; r < ny; ++r ) {
04630                                 for( int c =0; c < nx; c += 2 ) {
04631                                         idx1 = (size_t)s*nxy+r*nx+c;
04632                                         idx2 = (size_t)(s+nz/2)*nxy+r*nx+c;
04633                                         p1 = &rdata[idx1];
04634                                         p2 = &rdata[idx2];
04635 
04636                                         tmp[0] = p1[0];
04637                                         tmp[1] = p1[1];
04638 
04639                                         p1[0] = p2[0];
04640                                         p1[1] = p2[1];
04641 
04642                                         p2[0] = tmp[0];
04643                                         p2[1] = tmp[1];
04644                                 }
04645                         }
04646                 }
04647         }
04648         image->set_shuffled(false);
04649 }
04650 
04651 void FourierToCenterProcessor::process_inplace(EMData * image)
04652 {
04653 //      if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04654 
04655         int nx=image->get_xsize();
04656         int ny=image->get_ysize();
04657         int nz=image->get_zsize();
04658 
04659         int nxy = nx*ny;
04660 
04661         if ( ny == 1 && nz == 1 ){
04662                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04663                 return;
04664         }
04665 
04666         int yodd = (ny%2==1);
04667         int zodd = (nz%2==1);
04668 
04669         float* rdata = image->get_data();
04670 
04671         float tmp[2];
04672         float* p1;
04673         float* p2;
04674 
04675         // This will tackle the 'normalization' images which come out of the Fourier reconstructor.
04676         // ie- real-space 1/2 FFt images centered on the corner
04677         if ( !image->is_complex() ) {
04678                 if (nz!=1 && !yodd && !zodd) {
04679                         for (int x=0; x<nx; x++) {
04680                                 for (int y=0; y<ny; y++) {
04681                                         for (int z=0; z<nz/2; z++) {
04682                                                 int y2=(y+ny/2)%ny;
04683                                                 int z2=(z+nz/2)%nz;             // %nz should be redundant here
04684                                                 size_t i=x+y*nx+(size_t)z*nxy;
04685                                                 size_t i2=x+y2*nx+(size_t)z2*nxy;
04686                                                 float swp=rdata[i];
04687                                                 rdata[i]=rdata[i2];
04688                                                 rdata[i2]=swp;
04689                                         }
04690                                 }
04691                         }
04692 
04693                         return;
04694                 }
04695                 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");
04696         }
04697 
04698         if (yodd){
04699                 // In 3D this is swapping the bottom slice (with respect to the y direction) and the middle slice,
04700                 // shifting all slices below the middle slice down one. In 2D it is equivalent, but in terms of rows.
04701                 float prev[2];
04702                 size_t idx;
04703                 for( int s = 0; s < nz; s++ ) {
04704                         for( int c =0; c < nx; c += 2 ) {
04705                                 idx = (size_t)s*nxy+c;
04706                                 prev[0] = rdata[idx];
04707                                 prev[1] = rdata[idx+1];
04708                                 for( int r = ny/2; r >= 0; --r ) {
04709                                         idx = (size_t)s*nxy+r*nx+c;
04710                                         float* p1 = &rdata[idx];
04711                                         tmp[0] = p1[0];
04712                                         tmp[1] = p1[1];
04713 
04714                                         p1[0] = prev[0];
04715                                         p1[1] = prev[1];
04716 
04717                                         prev[0] = tmp[0];
04718                                         prev[1] = tmp[1];
04719                                 }
04720                         }
04721                 }
04722         }
04723 
04724         // 3D - Shift slices correctly in the y direction, 2D - shift rows
04725         size_t idx1, idx2;
04726         for( int s = 0; s < nz; ++s ) {
04727                 for( int r = 0; r < ny/2; ++r ) {
04728                         for( int c =0; c < nx; c += 2 ) {
04729                                 idx1 = (size_t)s*nxy+r*nx+c;
04730                                 idx2 = (size_t)s*nxy+(r+ny/2+yodd)*nx+c;
04731                                 p1 = &rdata[idx1];
04732                                 p2 = &rdata[idx2];
04733 
04734                                 tmp[0] = p1[0];
04735                                 tmp[1] = p1[1];
04736 
04737                                 p1[0] = p2[0];
04738                                 p1[1] = p2[1];
04739 
04740                                 p2[0] = tmp[0];
04741                                 p2[1] = tmp[1];
04742                         }
04743                 }
04744         }
04745 
04746         if ( nz != 1 )  {
04747                 if (zodd){
04748                         // Swap the front slice (with respect to the z direction) and the middle slice
04749                         // shifting all slices behind the middles slice towards the front slice 1 voxel.
04750                         float prev[2];
04751                         size_t idx;
04752                         for( int r = 0; r < ny; ++r ) {
04753                                 for( int c =0; c < nx; c += 2 ) {
04754                                         prev[0] = rdata[r*nx+c];
04755                                         prev[1] = rdata[r*nx+c+1];
04756                                         for( int s = nz/2; s >= 0; --s ) {
04757                                                 idx = (size_t)s*nxy+r*nx+c;
04758                                                 float* p1 = &rdata[idx];
04759                                                 tmp[0] = p1[0];
04760                                                 tmp[1] = p1[1];
04761 
04762                                                 p1[0] = prev[0];
04763                                                 p1[1] = prev[1];
04764 
04765                                                 prev[0] = tmp[0];
04766                                                 prev[1] = tmp[1];
04767                                         }
04768                                 }
04769                         }
04770                 }
04771 
04772                 // Shift slices correctly in the y direction
04773                 size_t idx1, idx2;
04774                 for( int s = 0; s < nz/2; ++s ) {
04775                         for( int r = 0; r < ny; ++r ) {
04776                                 for( int c =0; c < nx; c += 2 ) {
04777                                         idx1 = (size_t)s*nxy+r*nx+c;
04778                                         idx2 = (size_t)(s+nz/2+zodd)*nxy+r*nx+c;
04779                                         p1 = &rdata[idx1];
04780                                         p2 = &rdata[idx2];
04781 
04782                                         tmp[0] = p1[0];
04783                                         tmp[1] = p1[1];
04784 
04785                                         p1[0] = p2[0];
04786                                         p1[1] = p2[1];
04787 
04788                                         p2[0] = tmp[0];
04789                                         p2[1] = tmp[1];
04790                                 }
04791                         }
04792                 }
04793         }
04794         image->set_shuffled(true);
04795 }
04796 
04797 void Phase180Processor::fourier_phaseshift180(EMData * image)
04798 {
04799         if ( !image->is_complex() ) throw ImageFormatException("Can not handle images that are not complex in fourier phase shift 180");
04800 
04801         int nx = image->get_xsize();
04802         int ny = image->get_ysize();
04803         int nz = image->get_zsize();
04804 
04805         int nxy = nx * ny;
04806 
04807         float *rdata = image->get_data();
04808 
04809         // Who uses this function? It doesn't work for odd images, and it will give incorrect results for some even images
04810         // d.woolford, March 15 2009
04811         int of=0;
04812         if (((ny/2)%2)+((nz/2)%2)==1) of=1;
04813 
04814         for (int k = 0; k < nz; k++) {
04815                 size_t k2 = (size_t)k * nxy;
04816 
04817                 for (int j = 0; j < ny; j++) {
04818                         int i = ((k+j)%2==of?2:0);
04819                         size_t j2 = j * nx + k2;
04820 
04821                         for (; i < nx; i += 4) {
04822                                 rdata[i + j2] *= -1.0f;
04823                                 rdata[i + j2 + 1] *= -1.0f;
04824                         }
04825                 }
04826         }
04827 }
04828 
04829 void Phase180Processor::swap_corners_180(EMData * image)
04830 {
04831         int nx = image->get_xsize();
04832         int ny = image->get_ysize();
04833         int nz = image->get_zsize();
04834 
04835         int xodd = (nx % 2) == 1;
04836         int yodd = (ny % 2) == 1;
04837         int zodd = (nz % 2) == 1;
04838 
04839         int nxy = nx * ny;
04840 
04841         float *rdata = image->get_data();
04842 
04843         if ( ny == 1 && nz == 1 ){
04844                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04845         }
04846         else if ( nz == 1 ) {
04847 
04848                 // Swap the bottom left and top right corners
04849                 for ( int r = 0; r < ny/2; ++r ) {
04850                         for ( int c = 0; c < nx/2; ++c) {
04851                                 int idx1 = r*nx + c;
04852                                 int idx2 = (r+ny/2+yodd)*nx + c + nx/2+xodd;
04853                                 float tmp = rdata[idx1];
04854                                 rdata[idx1] = rdata[idx2];
04855                                 rdata[idx2] = tmp;
04856                         }
04857                 }
04858 
04859                 // Swap the top left and bottom right corners
04860                 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04861                         for ( int c = 0; c < nx/2; ++c) {
04862                                 int idx1 = r*nx + c;
04863                                 int idx2 = (r-ny/2-yodd)*nx + c + nx/2+xodd;
04864                                 float tmp = rdata[idx1];
04865                                 rdata[idx1] = rdata[idx2];
04866                                 rdata[idx2] = tmp;
04867                         }
04868                 }
04869         }
04870         else // nx && ny && nz are greater than 1
04871         {
04872                 float tmp;
04873                 // Swap the bottom left front and back right top quadrants
04874                 size_t idx1, idx2;
04875 
04876                 for ( int s = 0; s < nz/2; ++s ) {
04877                         for ( int r = 0; r < ny/2; ++r ) {
04878                                 for ( int c = 0; c < nx/2; ++ c) {
04879                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04880                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
04881                                         tmp = rdata[idx1];
04882                                         rdata[idx1] = rdata[idx2];
04883                                         rdata[idx2] = tmp;
04884                                 }
04885                         }
04886                 }
04887                 // Swap the bottom right front and back left top quadrants
04888                 for ( int s = 0; s < nz/2; ++s ) {
04889                         for ( int r = 0; r < ny/2; ++r ) {
04890                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04891                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04892                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c-nx/2-xodd;
04893                                         tmp = rdata[idx1];
04894                                         rdata[idx1] = rdata[idx2];
04895                                         rdata[idx2] = tmp;
04896                                 }
04897                         }
04898                 }
04899                 // Swap the top right front and back left bottom quadrants
04900                 for ( int s = 0; s < nz/2; ++s ) {
04901                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04902                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04903                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04904                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c-nx/2-xodd;
04905                                         tmp = rdata[idx1];
04906                                         rdata[idx1] = rdata[idx2];
04907                                         rdata[idx2] = tmp;
04908                                 }
04909                         }
04910                 }
04911                 // Swap the top left front and back right bottom quadrants
04912                 for ( int s = 0; s < nz/2; ++s ) {
04913                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04914                                 for ( int c = 0; c < nx/2; ++c) {
04915                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04916                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
04917                                         tmp = rdata[idx1];
04918                                         rdata[idx1] = rdata[idx2];
04919                                         rdata[idx2] = tmp;
04920                                 }
04921                         }
04922                 }
04923         }
04924 }
04925 
04926 void Phase180Processor::swap_central_slices_180(EMData * image)
04927 {
04928         int nx = image->get_xsize();
04929         int ny = image->get_ysize();
04930         int nz = image->get_zsize();
04931 
04932         int xodd = (nx % 2) == 1;
04933         int yodd = (ny % 2) == 1;
04934         int zodd = (nz % 2) == 1;
04935 
04936         int nxy = nx * ny;
04937 
04938         float *rdata = image->get_data();
04939 
04940         if ( ny == 1 && nz == 1 ){
04941                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04942         }
04943         else if ( nz == 1 ) {
04944                 float tmp;
04945                 if ( yodd ) {
04946                         // Iterate along middle row, swapping values where appropriate
04947                         int r = ny/2;
04948                         for ( int c = 0; c < nx/2; ++c ) {
04949                                 int idx1 = r*nx + c;
04950                                 int idx2 = r*nx + c + nx/2+ xodd;
04951                                 tmp = rdata[idx1];
04952                                 rdata[idx1] = rdata[idx2];
04953                                 rdata[idx2] = tmp;
04954                         }
04955                 }
04956 
04957                 if ( xodd )     {
04958                         // Iterate along the central column, swapping values where appropriate
04959                         int c = nx/2;
04960                         for (  int r = 0; r < ny/2; ++r ) {
04961                                 int idx1 = r*nx + c;
04962                                 int idx2 = (r+ny/2+yodd)*nx + c;
04963                                 tmp = rdata[idx1];
04964                                 rdata[idx1] = rdata[idx2];
04965                                 rdata[idx2] = tmp;
04966                         }
04967                 }
04968         }
04969         else // nx && ny && nz are greater than 1
04970         {
04971                 float tmp;
04972                 if ( xodd ) {
04973                         // Iterate along the x = nx/2 slice, swapping values where appropriate
04974                         int c = nx/2;
04975                         size_t idx1, idx2;
04976                         for( int s = 0; s < nz/2; ++s ) {
04977                                 for ( int r = 0; r < ny/2; ++r ) {
04978                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04979                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
04980                                         tmp = rdata[idx1];
04981                                         rdata[idx1] = rdata[idx2];
04982                                         rdata[idx2] = tmp;
04983                                 }
04984                         }
04985 
04986                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
04987                                 for ( int r = 0; r < ny/2; ++r ) {
04988                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04989                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
04990                                         tmp = rdata[idx1];
04991                                         rdata[idx1] = rdata[idx2];
04992                                         rdata[idx2] = tmp;
04993                                 }
04994                         }
04995                 }
04996                 if ( yodd ) {
04997                         // Iterate along the y = ny/2 slice, swapping values where appropriate
04998                         int r = ny/2;
04999                         size_t idx1, idx2;
05000                         for( int s = 0; s < nz/2; ++s ) {
05001                                 for ( int c = 0; c < nx/2; ++c ) {
05002                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05003                                         idx2 =(s+nz/2+zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
05004                                         tmp = rdata[idx1];
05005                                         rdata[idx1] = rdata[idx2];
05006                                         rdata[idx2] = tmp;
05007                                 }
05008                         }
05009 
05010                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
05011                                 for ( int c = 0; c < nx/2; ++c ) {
05012                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05013                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
05014                                         tmp = rdata[idx1];
05015                                         rdata[idx1] = rdata[idx2];
05016                                         rdata[idx2] = tmp;
05017                                 }
05018                         }
05019                 }
05020                 if ( zodd ) {
05021                         // Iterate along the z = nz/2 slice, swapping values where appropriate
05022                         int s = nz/2;
05023                         size_t idx1, idx2;
05024                         for( int r = 0; r < ny/2; ++r ) {
05025                                 for ( int c = 0; c < nx/2; ++c ) {
05026                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05027                                         idx2 = (size_t)s*nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
05028                                         tmp = rdata[idx1];
05029                                         rdata[idx1] = rdata[idx2];
05030                                         rdata[idx2] = tmp;
05031                                 }
05032                         }
05033 
05034                         for( int r = ny-1; r >= (ny/2+yodd); --r ) {
05035                                 for ( int c = 0; c < nx/2; ++c ) {
05036                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05037                                         idx2 = (size_t)s*nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
05038                                         tmp = rdata[idx1];
05039                                         rdata[idx1] = rdata[idx2];
05040                                         rdata[idx2] = tmp;
05041                                 }
05042                         }
05043                 }
05044         }
05045 }
05046 
05047 void PhaseToCornerProcessor::process_inplace(EMData * image)
05048 {
05049         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05050 
05051 #ifdef EMAN2_USING_CUDA
05052         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05053                 //cout << "CUDA tocorner " << image->getcudarwdata() << endl;
05054                 emdata_phaseorigin_to_corner(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05055                 return;
05056         }
05057 #endif // EMAN2_USING_CUDA
05058 
05059         if (image->is_complex()) {
05060                 fourier_phaseshift180(image);
05061                 return;
05062         }
05063 
05064         int nx = image->get_xsize();
05065         int ny = image->get_ysize();
05066         int nz = image->get_zsize();
05067 
05068         if ( ny == 1 && nz == 1 && nx == 1) return;
05069 
05070         int nxy = nx * ny;
05071 
05072         float *rdata = image->get_data();
05073 
05074         bool xodd = (nx % 2) == 1;
05075         bool yodd = (ny % 2) == 1;
05076         bool zodd = (nz % 2) == 1;
05077 
05078         if ( ny == 1 && nz == 1 ){
05079                 if (xodd){
05080                         // Put the last pixel in the center, shifting the contents
05081                         // to right of the center one step to the right
05082                         float in_x = rdata[nx-1];
05083                         float tmp;
05084                         for ( int i = nx/2; i < nx; ++i ) {
05085                                 tmp = rdata[i];
05086                                 rdata[i] = in_x;
05087                                 in_x = tmp;
05088                         }
05089                 }
05090                 // now the operation is straight forward
05091                 for ( int i = 0; i < nx/2; ++i ) {
05092                         int idx = i+nx/2+xodd;
05093                         float tmp = rdata[i];
05094                         rdata[i] = rdata[idx];
05095                         rdata[idx] = tmp;
05096                 }
05097 
05098         }
05099         else if ( nz == 1 ) {
05100                 if (yodd) {
05101                         // Tranfer the top row into the middle row,
05102                         // shifting all pixels above and including the current middle up one.
05103                         for ( int c = 0; c < nx; ++c ) {
05104                                 // Get the value in the top row
05105                                 float last_val = rdata[(ny-1)*nx + c];
05106                                 float tmp;
05107                                 for ( int r = ny/2; r < ny; ++r ){
05108                                         int idx =r*nx+c;
05109                                         tmp = rdata[idx];
05110                                         rdata[idx] = last_val;
05111                                         last_val = tmp;
05112                                 }
05113                         }
05114                 }
05115 
05116                 if (xodd) {
05117                         // Transfer the right most column into the center column
05118                         // Shift all columns right of and including center to the right one pixel
05119                         for ( int r  = 0; r < ny; ++r ) {
05120                                 float last_val = rdata[(r+1)*nx -1];
05121                                 float tmp;
05122                                 for ( int c = nx/2; c < nx; ++c ){
05123                                         int idx =r*nx+c;
05124                                         tmp = rdata[idx];
05125                                         rdata[idx] = last_val;
05126                                         last_val = tmp;
05127                                 }
05128                         }
05129                 }
05130                 // It is important central slice shifting come after the previous two operations
05131                 swap_central_slices_180(image);
05132                 // Now the corners of the image can be shifted...
05133                 swap_corners_180(image);
05134 
05135         }
05136         else
05137         {
05138                 float tmp;
05139                 if (zodd) {
05140                         // Tranfer the back slice into the middle slice,
05141                         // shifting all pixels beyond and including the middle slice back one.
05142                         size_t idx = 0;
05143                         for (int r = 0; r < ny; ++r){
05144                                 for (int c = 0; c < nx; ++c) {
05145                                         float last_val = rdata[(nz-1)*nxy+r*nx+c];
05146                                         for (int s = nz/2; s < nz; ++s) {
05147                                                 idx = (size_t)s*nxy+r*nx+c;
05148                                                 tmp = rdata[idx];
05149                                                 rdata[idx] = last_val;
05150                                                 last_val = tmp;
05151                                         }
05152                                 }
05153                         }
05154                 }
05155                 if (yodd) {
05156                         // Tranfer the top slice into the middle slice,
05157                         // shifting all pixels above and including the middle slice up one.
05158                         size_t idx = 0;
05159                         for (int s = 0; s < nz; ++s) {
05160                                 for (int c = 0; c < nx; ++c) {
05161                                 float last_val = rdata[s*nxy+(ny-1)*nx+c];
05162                                         for (int r = ny/2; r < ny; ++r){
05163                                                 idx = (size_t)s*nxy+r*nx+c;
05164                                                 tmp = rdata[idx];
05165                                                 rdata[idx] = last_val;
05166                                                 last_val = tmp;
05167                                         }
05168                                 }
05169                         }
05170                 }
05171                 if (xodd) {
05172                         // Transfer the right most slice into the central slice
05173                         // Shift all pixels to right of and including center slice to the right one pixel
05174                         size_t idx = 0;
05175                         for (int s = 0; s < nz; ++s) {
05176                                 for (int r = 0; r < ny; ++r) {
05177                                         float last_val = rdata[s*nxy+r*nx+nx-1];
05178                                         for (int c = nx/2; c < nx; ++c){
05179                                                 idx = (size_t)s*nxy+r*nx+c;
05180                                                 tmp = rdata[idx];
05181                                                 rdata[idx] = last_val;
05182                                                 last_val = tmp;
05183                                         }
05184                                 }
05185                         }
05186                 }
05187                 // Now swap the various parts in the central slices
05188                 swap_central_slices_180(image);
05189                 // Now shift the corners
05190                 swap_corners_180(image);
05191         }
05192 }
05193 
05194 
05195 void PhaseToCenterProcessor::process_inplace(EMData * image)
05196 {
05197         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05198 
05199 #ifdef EMAN2_USING_CUDA
05200         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05201                 //cout << "CUDA tocenter" << endl;
05202                 emdata_phaseorigin_to_center(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05203                 return;
05204         }
05205 #endif // EMAN2_USING_CUDA
05206 
05207         if (image->is_complex()) {
05208                 fourier_phaseshift180(image);
05209                 return;
05210         }
05211 
05212         int nx = image->get_xsize();
05213         int ny = image->get_ysize();
05214         int nz = image->get_zsize();
05215 
05216         if ( ny == 1 && nz == 1 && nx == 1) return;
05217 
05218         int nxy = nx * ny;
05219 
05220         float *rdata = image->get_data();
05221 
05222         bool xodd = (nx % 2) == 1;
05223         bool yodd = (ny % 2) == 1;
05224         bool zodd = (nz % 2) == 1;
05225 
05226         if ( ny == 1 && nz == 1 ){
05227                 if (xodd) {
05228                         // Put the center pixel at the end, shifting the contents
05229                         // to right of the center one step to the left
05230                         float in_x = rdata[nx/2];
05231                         float tmp;
05232                         for ( int i = nx-1; i >= nx/2; --i ) {
05233                                 tmp = rdata[i];
05234                                 rdata[i] = in_x;
05235                                 in_x = tmp;
05236                         }
05237                 }
05238                 // now the operation is straight forward
05239                 for ( int i = 0; i < nx/2; ++i ) {
05240                         int idx = i + nx/2;
05241                         float tmp = rdata[i];
05242                         rdata[i] = rdata[idx];
05243                         rdata[idx] = tmp;
05244                 }
05245         }
05246         else if ( nz == 1 ){
05247                 // The order in which these operations occur literally undoes what the
05248                 // PhaseToCornerProcessor did to the image.
05249                 // First, the corners sections of the image are swapped appropriately
05250                 swap_corners_180(image);
05251                 // Second, central pixel lines are swapped
05252                 swap_central_slices_180(image);
05253 
05254                 float tmp;
05255                 // Third, appropriate sections of the image are cyclically shifted by one pixel
05256                 if (xodd) {
05257                         // Transfer the middle column to the far right
05258                         // Shift all from the far right to (but not including the) middle one to the left
05259                         for ( int r  = 0; r < ny; ++r ) {
05260                                 float last_val = rdata[r*nx+nx/2];
05261                                 for ( int c = nx-1; c >=  nx/2; --c ){
05262                                         int idx = r*nx+c;
05263                                         tmp = rdata[idx];
05264                                         rdata[idx] = last_val;
05265                                         last_val = tmp;
05266                                 }
05267                         }
05268                 }
05269                 if (yodd) {
05270                         // Tranfer the middle row to the top,
05271                         // shifting all pixels from the top row down one, until  but not including the) middle
05272                         for ( int c = 0; c < nx; ++c ) {
05273                                 // Get the value in the top row
05274                                 float last_val = rdata[ny/2*nx + c];
05275                                 for ( int r = ny-1; r >= ny/2; --r ){
05276                                         int idx = r*nx+c;
05277                                         tmp = rdata[idx];
05278                                         rdata[idx] = last_val;
05279                                         last_val = tmp;
05280                                 }
05281                         }
05282                 }
05283         }
05284         else
05285         {
05286                 // The order in which these operations occur literally undoes the
05287                 // PhaseToCornerProcessor operation - in 3D.
05288                 // First, the corner quadrants of the voxel volume are swapped
05289                 swap_corners_180(image);
05290                 // Second, appropriate parts of the central slices are swapped
05291                 swap_central_slices_180(image);
05292 
05293                 float tmp;
05294                 // Third, appropriate sections of the image are cyclically shifted by one voxel
05295                 if (xodd) {
05296                         // Transfer the central slice in the x direction to the far right
05297                         // moving all slices on the far right toward the center one pixel, until
05298                         // the center x slice is ecountered
05299                         size_t idx = 0;
05300                         for (int s = 0; s < nz; ++s) {
05301                                 for (int r = 0; r < ny; ++r) {
05302                                         float last_val = rdata[s*nxy+r*nx+nx/2];
05303                                         for (int c = nx-1; c >= nx/2; --c){
05304                                                 idx = (size_t)s*nxy+r*nx+c;
05305                                                 tmp = rdata[idx];
05306                                                 rdata[idx] = last_val;
05307                                                 last_val = tmp;
05308                                         }
05309                                 }
05310                         }
05311                 }
05312                 if (yodd) {
05313                         // Tranfer the central slice in the y direction to the top
05314                         // shifting all pixels below it down on, until the center y slice is encountered.
05315                         size_t idx = 0;
05316                         for (int s = 0; s < nz; ++s) {
05317                                 for (int c = 0; c < nx; ++c) {
05318                                         float last_val = rdata[s*nxy+ny/2*nx+c];
05319                                         for (int r = ny-1; r >= ny/2; --r){
05320                                                 idx = (size_t)s*nxy+r*nx+c;
05321                                                 tmp = rdata[idx];
05322                                                 rdata[idx] = last_val;
05323                                                 last_val = tmp;
05324                                         }
05325                                 }
05326                         }
05327                 }
05328                 if (zodd) {
05329                         // Tranfer the central slice in the z direction to the back
05330                         // shifting all pixels beyond and including the middle slice back one.
05331                         size_t idx = 0;
05332                         for (int r = 0; r < ny; ++r){
05333                                 for (int c = 0; c < nx; ++c) {
05334                                         float last_val = rdata[nz/2*nxy+r*nx+c];
05335                                         for (int s = nz-1; s >= nz/2; --s) {
05336                                                 idx = (size_t)s*nxy+r*nx+c;
05337                                                 tmp = rdata[idx];
05338                                                 rdata[idx] = last_val;
05339                                                 last_val = tmp;
05340                                         }
05341                                 }
05342                         }
05343                 }
05344 
05345 
05346         }
05347 }
05348 
05349 void AutoMaskAsymUnit::process_inplace(EMData* image) {
05350         if (!image) {
05351                 LOGWARN("NULL Image");
05352                 return;
05353         }
05354 
05355         int nx = image->get_xsize();
05356         int ny = image->get_ysize();
05357         int nz = image->get_zsize();
05358 
05359         int ox = nx/2;
05360         int oy = ny/2;
05361         int oz = nz/2;
05362 
05363         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
05364         int au = params.set_default("au",0);
05365 
05366         float *d = image->get_data();
05367         for(int k = 0; k < nz; ++k ) {
05368                 for(int j = 0; j < ny; ++j ) {
05369                         for (int i = 0; i< nx; ++i, ++d) {
05370                                 //cout << i << " " << j << " " << k << endl;
05371                                 Vec3f v(i-ox,j-oy,k-oz);
05372 //                              v.normalize();
05373                                 int a = sym->point_in_which_asym_unit(v);
05374                                 if (au == -1) {
05375                                         *d = (float)a;
05376                                 } else {
05377                                         if ( a == au ) *d = 1;
05378                                         else *d = 0;
05379                                 }
05380                         }
05381                 }
05382         }
05383 
05384         delete sym;
05385 
05386 }
05387 
05388 void AutoMask2DProcessor::process_inplace(EMData * image)
05389 {
05390         if (!image) {
05391                 LOGWARN("NULL Image");
05392                 return;
05393         }
05394 
05395         if (image->get_ndim() != 2) {
05396                 throw ImageDimensionException("This processor only supports 2D images.");
05397         }
05398 
05399         /*
05400          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
05401          To get around this just use the return_mask parameter.
05402         string mask_output = params.set_default("write_mask", "");
05403         if ( mask_output != "") {
05404                 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.");
05405                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
05406         }
05407         */
05408 
05409         int radius=0;
05410         if (params.has_key("radius")) {
05411                 radius = params["radius"];
05412         }
05413         int nmaxseed=0;
05414         if (params.has_key("nmaxseed")) {
05415                 nmaxseed = params["nmaxseed"];
05416         }
05417 
05418         float threshold=0.0;
05419         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
05420         else threshold=params["threshold"];
05421 
05422 
05423         int nshells = params["nshells"];
05424         int nshellsgauss = params["nshellsgauss"];
05425         int verbose=params.set_default("verbose",0);
05426 
05427         int nx = image->get_xsize();
05428         int ny = image->get_ysize();
05429 
05430         EMData *amask = new EMData();
05431         amask->set_size(nx, ny);
05432 
05433         float *dat = image->get_data();
05434         float *dat2 = amask->get_data();
05435         int i,j;
05436         size_t l = 0;
05437 
05438         if (verbose) printf("%f\t%f\t%f\n",(float)image->get_attr("mean"),(float)image->get_attr("sigma"),threshold);
05439 
05440         // Seeds with the highest valued pixels
05441         if (nmaxseed>0) {
05442                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
05443 
05444                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
05445                         amask->set_value_at((*i).x,(*i).y,0,1.0);
05446                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
05447                 }
05448         }
05449 
05450         // Seeds with a circle
05451         if (radius>0) {
05452                 // start with an initial circle
05453                 l=0;
05454                 for (j = -ny / 2; j < ny / 2; ++j) {
05455                         for (i = -nx / 2; i < nx / 2; ++i,++l) {
05456                                 if ( abs(j) > radius || abs(i) > radius) continue;
05457 //                              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
05458                                 if ( (j * j + i * i) > (radius*radius) ) continue;
05459                                 dat2[l] = 1.0f;
05460                         }
05461                 }
05462         }
05463 
05464         // iteratively 'flood fills' the map... recursion would be better
05465         int done=0;
05466         int iter=0;
05467         while (!done) {
05468                 iter++;
05469                 done=1;
05470                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
05471                 for (j=1; j<ny-1; ++j) {
05472                         for (i=1; i<nx-1; ++i) {
05473                                 l=i+j*nx;
05474                                 if (dat2[l]) continue;
05475                                 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx])) {
05476                                         dat2[l]=1.0;
05477                                         done=0;
05478                                 }
05479                         }
05480                 }
05481         }
05482 
05483         amask->update();
05484 
05485         if (verbose) printf("extending mask\n");
05486         amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
05487 
05488         bool return_mask = params.set_default("return_mask",false);
05489         if (return_mask) {
05490                 // 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.
05491                 memcpy(dat,dat2,image->get_size()*sizeof(float));
05492         } else {
05493                 image->mult(*amask);
05494         }
05495 
05496         // EMAN2 policy is not to allow file io from with a processor
05497         //if (mask_output != "") {
05498         //      amask->write_image(mask_output);
05499         //}
05500 
05501 
05502         delete amask;
05503 }
05504 
05505 void CtfSimProcessor::process_inplace(EMData *image) {
05506         EMData *tmp=process(image);
05507         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
05508         delete tmp;
05509         image->update();
05510         return;
05511 }
05512 
05513 EMData* CtfSimProcessor::process(const EMData * const image) {
05514         if (!image) {
05515                 LOGWARN("NULL Image");
05516                 return NULL;
05517         }
05518 
05519         EMData *fft;
05520         if (!image->is_complex()) fft=image->do_fft();
05521         else fft=image->copy();
05522 
05523         EMAN2Ctf ctf;
05524         ctf.defocus=params["defocus"];
05525         ctf.bfactor=params["bfactor"];
05526         ctf.ampcont=params.set_default("ampcont",10.0f);
05527         ctf.voltage=params.set_default("voltage",200.0f);
05528         ctf.cs=params.set_default("cs",2.0);
05529         ctf.apix=params.set_default("apix",image->get_attr_default("apix_x",1.0));
05530         ctf.dsbg=1.0/(ctf.apix*fft->get_ysize()*4.0);           //4x oversampling
05531         
05532         float noiseamp=params.set_default("noiseamp",0.0f);
05533         float noiseampwhite=params.set_default("noiseampwhite",0.0f);
05534         
05535         // compute and apply the CTF
05536         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
05537 
05538 //      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());
05539 //      FILE *out=fopen("x.txt","w");
05540 //      for (int i=0; i<ctfc.size(); i++) fprintf(out,"%f\t%1.3g\n",0.25*i/(float)fft->get_ysize(),ctfc[i]);
05541 //      fclose(out);
05542         
05543         fft->apply_radial_func(0,0.25f/fft->get_ysize(),ctfc,1);
05544         
05545         // Add noise
05546         if (noiseamp!=0 || noiseampwhite!=0) {
05547                 EMData *noise = new EMData(image->get_ysize(),image->get_ysize(),1);
05548                 noise->process_inplace("testimage.noise.gauss");
05549                 noise->do_fft_inplace();
05550         
05551                 // White noise
05552                 if (noiseampwhite!=0) {
05553                         noise->mult((float)noiseampwhite*15.0f);                // The 15.0 is to roughly compensate for the stronger pink noise curve
05554                         fft->add(*noise);
05555                         noise->mult((float)1.0/(noiseampwhite*15.0f));
05556                 }
05557                 
05558                 // Pink noise
05559                 if (noiseamp!=0) {
05560                         vector <float> pinkbg;
05561                         pinkbg.resize(500);
05562                         float nyimg=0.5f/ctf.apix;      // image nyquist
05563                         // This pink curve came from a typical image in the GroEL 4A data set
05564                         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
05565                         noise->apply_radial_func(0,.002f,pinkbg,1);             // Image nyquist is at 250 -> 0.5
05566                         fft->add(*noise);
05567                 }
05568                 
05569         }
05570         
05571         EMData *ret=fft->do_ift();
05572         delete fft;
05573         
05574         return ret;
05575 }
05576 
05577 void AddRandomNoiseProcessor::process_inplace(EMData * image)
05578 {
05579         if (!image) {
05580                 LOGWARN("NULL Image");
05581                 return;
05582         }
05583 
05584         if (!image->is_complex()) {
05585                 LOGERR("AddRandomNoise Processor only works for complex image");
05586                 throw ImageFormatException("only work for complex image");
05587         }
05588 
05589         int n = params["n"];
05590         float x0 = params["x0"];
05591         float dx = params["dx"];
05592         vector < float >y = params["y"];
05593 
05594         int interpolation = 1;
05595         if (params.has_key("interpolation")) {
05596                 interpolation = params["interpolation"];
05597         }
05598 
05599         Randnum * randnum = Randnum::Instance();
05600         if(params.has_key("seed")) {
05601                 randnum->set_seed((int)params["seed"]);
05602         }
05603 
05604         int nx = image->get_xsize();
05605         int ny = image->get_ysize();
05606         int nz = image->get_zsize();
05607 
05608         image->ap2ri();
05609         float *rdata = image->get_data();
05610 
05611         size_t k = 0;
05612         float half_nz = 0;
05613         if (nz > 1) {
05614                 half_nz = nz / 2.0f;
05615         }
05616 
05617         const float sqrt_2 = sqrt((float) 2);
05618 
05619         float r;
05620         for (int h = 0; h < nz; h++) {
05621                 for (int j = 0; j < ny; j++) {
05622                         for (int i = 0; i < nx; i += 2, k += 2) {
05623                                 r = (Util::hypot3(i / 2.0f, j - ny / 2.0f, h - half_nz));
05624 //                              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
05625                                 r = (r - x0) / dx;
05626                                 int l = 0;
05627                                 if (interpolation) {
05628                                         l = Util::fast_floor(r);
05629                                 }
05630                                 else {
05631                                         l = Util::fast_floor(r + 0.5f);
05632                                 }
05633                                 r -= l;
05634                                 float f = 0;
05635                                 if (l >= n - 2) {
05636                                         f = y[n - 1];
05637                                 }
05638                                 else if (l < 0) {
05639                                         l = 0;
05640                                 }
05641                                 else {
05642                                         if (interpolation) {
05643                                                 f = (y[l] * (1 - r) + y[l + 1] * r);
05644                                         }
05645                                         else {
05646                                                 f = y[l];
05647                                         }
05648                                 }
05649                                 f = randnum->get_gauss_rand(sqrt(f), sqrt(f) / 3);
05650                                 float a = randnum->get_frand(0.0f, (float)(2 * M_PI));
05651                                 if (i == 0) {
05652                                         f *= sqrt_2;
05653                                 }
05654                                 rdata[k] += f * cos(a);
05655                                 rdata[k + 1] += f * sin(a);
05656                         }
05657                 }
05658         }
05659 
05660         image->update();
05661 }
05662 
05663 void AddMaskShellProcessor::process_inplace(EMData * image)
05664 {
05665         if (!image) {
05666                 LOGWARN("NULL Image");
05667                 return;
05668         }
05669 
05670         int nx = image->get_xsize();
05671         int ny = image->get_ysize();
05672         int nz = image->get_zsize();
05673 
05674         if (ny == 1) {
05675                 LOGERR("Tried to add mask shell to 1d image");
05676                 return;
05677         }
05678 
05679         int num_shells = params["nshells"];
05680 
05681         float *d = image->get_data();
05682         float k = 0.99999f;
05683         int nxy = nx * ny;
05684 
05685         if (nz == 1) {
05686                 for (int i = 0; i < num_shells; i++) {
05687                         for (int y = 1; y < ny - 1; y++) {
05688                                 int cur_y = y * nx;
05689 
05690                                 for (int x = 1; x < nx - 1; x++) {
05691                                         int j = x + cur_y;
05692                                         if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k || d[j - nx] > k)) {
05693                                                 d[j] = k;
05694                                         }
05695                                 }
05696                         }
05697                         k -= 0.00001f;
05698                 }
05699         }
05700         else {
05701                 for (int i = 0; i < num_shells; i++) {
05702                         for (int z = 1; z < nz - 1; z++) {
05703                                 size_t cur_z = (size_t)z * nx * ny;
05704 
05705                                 for (int y = 1; y < ny - 1; y++) {
05706                                         size_t cur_y = y * nx + cur_z;
05707 
05708                                         for (int x = 1; x < nx - 1; x++) {
05709                                                 size_t j = x + cur_y;
05710 
05711                                                 if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k ||
05712                                                                           d[j - nx] > k || d[j - nxy] > k || d[j + nxy] > k)) {
05713                                                         d[j] = k;
05714                                                 }
05715                                         }
05716                                 }
05717                         }
05718 
05719                         k -= 0.00001f;
05720                 }
05721         }
05722 
05723         size_t size = (size_t)nx * ny * nz;
05724         for (size_t i = 0; i < size; ++i) {
05725                 if (d[i]) {
05726                         d[i] = 1;
05727                 }
05728                 else {
05729                         d[i] = 0;
05730                 }
05731         }
05732 
05733         image->update();
05734 }
05735 
05736 void ToMassCenterProcessor::process_inplace(EMData * image)
05737 {
05738         if (!image) {
05739                 LOGWARN("NULL Image");
05740                 return;
05741         }
05742 
05743         int int_shift_only = params.set_default("int_shift_only",1);
05744         float threshold = params.set_default("threshold",0.0f);
05745 //      int positive = params.set_default("positive",0);
05746 
05747         if ((float)image->get_attr("sigma")==0.0f) return;              // Can't center a constant valued image
05748         if (threshold>(float)image->get_attr("maximum")) {
05749                 printf("Warning, centering threshold %1.2f, but image max %1.2f. Adjusting.",threshold,(float)image->get_attr("maximum"));
05750                 threshold=(float)image->get_attr("mean")+(float)image->get_attr("sigma");
05751         }
05752 
05753         FloatPoint com = image->calc_center_of_mass(threshold);
05754 
05755         int nx = image->get_xsize();
05756         int ny = image->get_ysize();
05757         int nz = image->get_zsize();
05758 
05759         if (int_shift_only) {
05760                 int dx = -(int)(floor(com[0] + 0.5f) - nx / 2);
05761                 int dy = -(int)(floor(com[1] + 0.5f) - ny / 2);
05762                 int dz = 0;
05763                 if (nz > 1) {
05764                         dz = -(int)(floor(com[2] + 0.5f) - nz / 2);
05765                 }
05766                 if (abs(dx)>=nx-1 || abs(dy)>=ny-1 || abs(dz)>=nz) {
05767                         printf("ERROR, center of mass outside image\n");
05768                 }
05769                 else {
05770                         image->translate(dx, dy, dz);
05771 
05772                         Transform t;
05773                         t.set_trans((float)dx,(float)dy,(float)dz);
05774 
05775                         if (nz > 1) {
05776                                 image->set_attr("xform.align3d",&t);
05777                         } else {
05778                                 image->set_attr("xform.align2d",&t);
05779                         }
05780                 }
05781         }
05782         else {
05783                 float dx = -(com[0] - nx / 2);
05784                 float dy = -(com[1] - ny / 2);
05785                 float dz = 0;
05786                 if (nz > 1) {
05787                         dz = -(com[2] - nz / 2);
05788                 }
05789                 if (fabs(dx)>=nx-1 || fabs(dy)>=ny-2 || fabs(dz)>=nz) {
05790                         printf("ERROR, center of mass outside image\n");
05791                 }
05792                 else {
05793                         image->translate(dx, dy, dz);
05794 
05795                         Transform t;
05796                         t.set_trans(dx,dy,dz);
05797 
05798                         if (nz > 1) {
05799                                 image->set_attr("xform.align3d",&t);
05800                         } else {
05801                                 image->set_attr("xform.align2d",&t);
05802                         }
05803                 }
05804         }
05805 }
05806 
05807 void PhaseToMassCenterProcessor::process_inplace(EMData * image)
05808 {
05809         if (!image) {
05810                 LOGWARN("NULL Image");
05811                 return;
05812         }
05813 
05814         int int_shift_only = params.set_default("int_shift_only",1);
05815 
05816         vector<float> pcog = image->phase_cog();
05817 
05818         int dims = image->get_ndim();
05819 
05820         if (int_shift_only) {
05821                 int dx=-int(pcog[0]+0.5f),dy=0,dz=0;
05822                 if ( dims >= 2 ) dy = -int(pcog[1]+0.5);
05823                 if ( dims == 3 ) dz = -int(pcog[2]+0.5);
05824 
05825                 Transform t;
05826                 t.set_trans((float)dx,(float)dy,(float)dz);
05827                 if (dims == 3) image->set_attr("xform.align3d",&t);
05828                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05829 
05830                 image->translate(dx,dy,dz);
05831         } else  {
05832                 float dx=-pcog[0],dy=0.0,dz=0.0;
05833                 if ( dims >= 2 ) dy = -pcog[1];
05834                 if ( dims == 3 ) dz = -pcog[2];
05835                 image->translate(dx,dy,dz);
05836 
05837                 Transform t;
05838                 t.set_trans(dx,dy,dz);
05839                 if (dims == 3) image->set_attr("xform.align3d",&t);
05840                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05841         }
05842 }
05843 
05844 void ACFCenterProcessor::process_inplace(EMData * image)
05845 {
05846         if (!image) {
05847                 LOGWARN("NULL Image");
05848                 return;
05849         }
05850 
05851         Dict params1;
05852         params1["intonly"] = 1;
05853         params1["maxshift"] = image->get_xsize() / 4;
05854         EMData* aligned = image->align("translational", 0, params1);
05855         if ( image->get_ndim() == 3 ) {
05856                 Transform* t = aligned->get_attr("xform.align3d");
05857                 image->translate(t->get_trans());
05858                 image->set_attr("xform.align3d",t);
05859                 delete t;
05860         }
05861         else {
05862                 // assumption is the image is 2D which may be  false
05863                 Transform* t = aligned->get_attr("xform.align2d");
05864                 image->translate(t->get_trans());
05865                 image->set_attr("xform.align2d",t);
05866                 delete t;
05867         }
05868 
05869         delete aligned;
05870 
05871 }
05872 
05873 void SNRProcessor::process_inplace(EMData * image)
05874 {
05875         if (!image) {
05876                 return;
05877         }
05878 
05879         int wiener = params["wiener"];
05880         const char *snrfile = params["snrfile"];
05881 
05882         XYData sf;
05883         int err = sf.read_file(snrfile);
05884         if (err) {
05885                 LOGERR("couldn't read structure factor file!");
05886                 return;
05887         }
05888 
05889 
05890         for (size_t i = 0; i < sf.get_size(); i++) {
05891                 if (sf.get_y(i) <= 0) {
05892                         sf.set_y(i, -4.0f);
05893                 }
05894                 else {
05895                         sf.set_y(i, log10(sf.get_y(i)));
05896                 }
05897         }
05898         sf.update();
05899 
05900         Ctf *image_ctf = image->get_ctf();
05901 
05902         vector < float >ctf;
05903         if (wiener) {
05904                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_WIENER_FILTER, &sf);
05905         }
05906         else {
05907                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR, &sf);
05908         }
05909 
05910         if(image_ctf) {delete image_ctf; image_ctf=0;}
05911 
05912         image->process_inplace("normalize.circlemean");
05913 
05914         int nx = image->get_xsize();
05915         int ny = image->get_ysize();
05916 
05917         Region clip_r(-nx / 2, -ny / 2, nx * 2, ny * 2);
05918         EMData *d3 = image->get_clip(clip_r);
05919         EMData *d2 = d3->do_fft();
05920 
05921         d2->apply_radial_func(0, 2.0f / Ctf::CTFOS, ctf, 0);
05922 
05923         if( d3 )
05924         {
05925                 delete d3;
05926                 d3 = 0;
05927         }
05928 
05929         if( image )
05930         {
05931                 delete image;
05932                 image = 0;
05933         }
05934 
05935         EMData *d1 = d2->do_ift();
05936         int d1_nx = d1->get_xsize();
05937         int d1_ny = d1->get_ysize();
05938         Region d1_r(d1_nx / 4, d1_ny / 4, d1_nx / 2, d1_ny / 2);
05939 
05940         image = d1->get_clip(d1_r);
05941 
05942         if( d1 )
05943         {
05944                 delete d1;
05945                 d1 = 0;
05946         }
05947 
05948         if( d2 )
05949         {
05950                 delete d2;
05951                 d2 = 0;
05952         }
05953 }
05954 
05955 void FileFourierProcessor::process_inplace(EMData * image)
05956 {
05957         if (!image) {
05958                 LOGWARN("NULL Image");
05959                 return;
05960         }
05961         const char *filename = params["filename"];
05962         float apix = params["apix"];
05963 
05964         FILE *in = fopen(filename, "rb");
05965         if (!in) {
05966                 LOGERR("FileFourierProcessor: cannot open file '%s'", filename);
05967                 return;
05968         }
05969 
05970         float f = 0;
05971         int n = 0;
05972         while (fscanf(in, " %f %f", &f, &f) == 2) {
05973                 n++;
05974         }
05975         rewind(in);
05976 
05977         vector < float >xd(n);
05978         vector < float >yd(n);
05979 
05980         float sf = apix * image->get_xsize();
05981 
05982         for (int i = 0; fscanf(in, " %f %f", &xd[i], &yd[i]) == 2; i++) {
05983                 xd[i] *= sf;
05984         }
05985 
05986         if (xd[2] - xd[1] != xd[1] - xd[0]) {
05987                 LOGWARN("Warning, x spacing appears nonuniform %g!=%g\n",
05988                                 xd[2] - xd[1], xd[1] - xd[0]);
05989         }
05990 
05991         EMData *d2 = image->do_fft();
05992         if( image )
05993         {
05994                 delete image;
05995                 image = 0;
05996         }
05997 
05998         d2->apply_radial_func(xd[0], xd[1] - xd[0], yd, 1);
05999         image = d2->do_ift();
06000 }
06001 
06002 void StripeXYProcessor::process_inplace(EMData * image)
06003 {
06004         if (!image) {
06005                 LOGWARN("NULL Image");
06006                 return;
06007         }
06008         int xlen = params.set_default("xlen",10);
06009         int ylen = params.set_default("ylen",10);
06010 
06011         int nx=image->get_attr("nx");
06012         int ny=image->get_attr("ny");
06013         EMData *tmp=new EMData(nx,ny,1);
06014         
06015         // we do this in real-space, since the integration size is small, and we don't want Fourier edge effects
06016         // we use a 'moving window' to avoid summing the same points multiple times 
06017         // start with y
06018         if (ylen>0) {
06019                 for (int x=0; x<nx; x++) {
06020                         float sum=0.0;
06021                         float sumn=0.0;
06022                         for (int y=0; y<(ylen<ny?ylen:ny); y++) { sum+=image->get_value_at(x,y); sumn+=1.0; } // we seed the process with a 1/2 stripe
06023                         // now loop over each final pixel
06024                         for (int y=0; y<ny; y++) {
06025                                 if (y+ylen<ny) { sum+=image->get_value_at(x,y+ylen); sumn+=1.0; }
06026                                 if (y-ylen-1>=0) { sum-=image->get_value_at(x,y-ylen-1); sumn-=1.0; }
06027                                 tmp->set_value_at_fast(x,y,sum/sumn);
06028                         }
06029                 }
06030                 tmp->write_image("tmp.hdf",0);
06031                 image->sub(*tmp);
06032         }
06033         
06034         // now x
06035         if (xlen>0) {
06036                 for (int y=0; y<ny; y++) {
06037                         float sum=0.0;
06038                         float sumn=0.0;
06039                         for (int x=0; x<(xlen<nx?xlen:nx); x++) { sum+=image->get_value_at(x,y); sumn+=1.0; } // we seed the process with a 1/2 stripe
06040                         // now loop over each final pixel
06041                         for (int x=0; x<nx; x++) {
06042                                 if (x+xlen<nx) { sum+=image->get_value_at(x+xlen,y); sumn+=1.0; }
06043                                 if (x-xlen-1>=0) { sum-=image->get_value_at(x-xlen-1,y); sumn-=1.0; }
06044                                 tmp->set_value_at_fast(x,y,sum/sumn);
06045                         }
06046                 }
06047                 tmp->write_image("tmp.hdf",1);
06048                 image->sub(*tmp);
06049         }
06050         
06051         delete tmp;
06052 }
06053 
06054 
06055 void LocalNormProcessor::process_inplace(EMData * image)
06056 {
06057         if (!image) {
06058                 LOGWARN("NULL Image");
06059                 return;
06060         }
06061         float apix = params["apix"];
06062         float threshold = params["threshold"];
06063         float radius = params["radius"];
06064 
06065         if (apix > 0) {
06066                 int ny = image->get_ysize();
06067                 radius = ny * apix / radius;
06068                 //printf("Norm filter radius=%1.1f\n", radius);
06069         }
06070 
06071         EMData *blur = image->copy();
06072         EMData *maskblur = image->copy();
06073 
06074         maskblur->process_inplace("threshold.binary", Dict("value", threshold));
06075         maskblur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06076 //      maskblur->process_inplace("filter.highpass.tanh", Dict("highpass", -10.0f));
06077         maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06078 //      maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06079 
06080 
06081         blur->process_inplace("threshold.belowtozero", Dict("minval", threshold));
06082         blur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06083 //      blur->process_inplace("filter.highpass.tanh", Dict("cutoff_abs", -10.0f));
06084 
06085         maskblur->div(*blur);
06086         image->mult(*maskblur);
06087 //      maskblur->write_image("norm.mrc", 0, EMUtil::IMAGE_MRC);
06088 
06089         if( maskblur )
06090         {
06091                 delete maskblur;
06092                 maskblur = 0;
06093         }
06094 
06095         if( blur )
06096         {
06097                 delete blur;
06098                 blur = 0;
06099         }
06100 }
06101 
06102 
06103 void SymSearchProcessor::process_inplace(EMData * image)
06104 {
06105         if (!image) {
06106                 LOGWARN("NULL Image");
06107                 return;
06108         }
06109         float thresh = params["thresh"];
06110         int output_symlabel = params["output_symlabel"];
06111 
06112         // set up all the symmetry transforms for all the searched symmetries
06113         const vector<string> sym_list = params["sym"];
06114         int sym_num = sym_list.size();
06115         vector< vector< Transform > > transforms(sym_num);
06116         vector< float* > symvals(sym_num);
06117         for (int i =0; i < sym_num; i++) {
06118                 vector<Transform> sym_transform =  Symmetry3D::get_symmetries(sym_list[i]);
06119                 transforms[i] = sym_transform;
06120                 symvals[i] = new float[sym_transform.size()]; // new float(nsym);
06121         }
06122 
06123         EMData *orig = image->copy();
06124 
06125         image->to_zero();
06126 
06127         int nx= image->get_xsize();
06128         int ny= image->get_ysize();
06129         int nz= image->get_zsize();
06130         int xy = nx * ny;
06131         float * data = image->get_data();
06132         float * sdata = orig->get_data();
06133 
06134         EMData *symlabel = 0;
06135         float * ldata = symlabel->get_data();
06136         if (output_symlabel) {
06137                 symlabel = image->copy();
06138                 symlabel->to_zero();
06139                 ldata = symlabel->get_data();
06140         }
06141 
06142         for (int k = 0; k < nz; k++) {
06143                 for (int j = 0; j < ny; j++) {
06144                         for(int i = 0; i < nx; i++) {
06145                                 size_t index = (size_t)k * nx * ny + j * nx + i;
06146                                 float val = sdata[ index ];
06147                                 float bestmean = val, bestsymlevel = FLT_MAX;
06148                                 int bestsym = 0;
06149                                 for( int sym = 0; sym< sym_num; sym++) {
06150                                         int cur_sym_num = transforms[sym].size();
06151                                         float *symval = symvals[sym];
06152                                         // first find out all the symmetry related location values
06153                                         for( int s = 0; s < cur_sym_num; s++){
06154                                                 Transform r = transforms[sym][s];
06155                                                 float x2 = (float)(r[0][0] * (i-nx/2) + r[0][1] * (j-ny/2) + r[0][2] * (k-nz/2) + nx / 2);
06156                                                 float y2 = (float)(r[1][0] * (i-nx/2) + r[1][1] * (j-ny/2) + r[1][2] * (k-nz/2) + ny / 2);
06157                                                 float z2 = (float)(r[2][0] * (i-nx/2) + r[2][1] * (j-ny/2) + r[2][2] * (k-nz/2) + nz / 2);
06158 
06159                                                 if (x2 >= 0 && y2 >= 0 && z2 >= 0 && x2 < (nx - 1) && y2 < (ny - 1)
06160                                                         && z2 < (nz - 1)) {
06161                                                         float x = (float)Util::fast_floor(x2);
06162                                                         float y = (float)Util::fast_floor(y2);
06163                                                         float z = (float)Util::fast_floor(z2);
06164 
06165                                                         float t = x2 - x;
06166                                                         float u = y2 - y;
06167                                                         float v = z2 - z;
06168 
06169                                                         size_t ii = x + y * nx + z * (size_t)xy;
06170 
06171                                                         symval[s]=
06172                                                                 Util::trilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],
06173                                                                                                                         sdata[ii + nx + 1], sdata[ii + nx * ny],
06174                                                                                                                         sdata[ii + xy + 1], sdata[ii + xy + nx],
06175                                                                                                                         sdata[ii + xy + nx + 1], t, u, v);
06176                                                 }
06177                                                 else {
06178                                                         symval[s] = 0.0 ;
06179                                                 }
06180                                         }
06181                                         float tmean=0, tsigma=0;
06182                                         for( int s = 0; s < cur_sym_num; s++) {
06183                                                 tmean += symval[s];
06184                                                 tsigma += symval[s] * symval[s];
06185                                         }
06186                                         tmean /= cur_sym_num;
06187                                         tsigma = tsigma/cur_sym_num - tmean*tmean;
06188                                         if (tsigma < bestsymlevel ) {
06189                                                 bestsymlevel = tsigma;
06190                                                 bestmean = tmean;
06191                                                 bestsym = sym;
06192                                         }
06193                                 }
06194                                 if ( bestsymlevel > thresh) {
06195                                         if (output_symlabel) ldata[index] = (float)bestsym;
06196                                         data[index] = bestmean;
06197                                 }
06198                                 else {
06199                                         if (output_symlabel) ldata[index] = -1;
06200                                         data[index] = val;
06201                                 }
06202                         }
06203                 }
06204         }
06205         if( orig )
06206         {
06207                 delete orig;
06208                 orig = 0;
06209         }
06210         for (int i =0; i < sym_num; i++) {
06211                 if( symvals[i] )
06212                 {
06213                         delete symvals[i];
06214                         symvals[i] = 0;
06215                 }
06216         }
06217         if (symlabel) params.put("symlabel_map", EMObject(symlabel));
06218 }
06219 
06220 
06221 void IndexMaskFileProcessor::process_inplace(EMData * image)
06222 {
06223         if (!image) {
06224                 LOGWARN("NULL Image");
06225                 return;
06226         }
06227 
06228         const char *filename = params["filename"];
06229         EMData *msk = new EMData();
06230         msk->read_image(filename);
06231         if (!EMUtil::is_same_size(image, msk)) {
06232                 LOGERR("IndexMaskFileProcessor: Mask size different than image");
06233                 return;
06234         }
06235 
06236         if ((int) params["ismaskset"] != 0) {
06237                 msk->process_inplace("threshold.binaryrange", Dict("low", 0.5f, "high", 1.5f));
06238         }
06239 
06240         image->mult(*msk);
06241         if( msk )
06242         {
06243                 delete msk;
06244                 msk = 0;
06245         }
06246 }
06247 
06248 
06249 void CoordinateMaskFileProcessor::process_inplace(EMData * image)
06250 {
06251         if (!image) {
06252                 LOGWARN("NULL Image");
06253                 return;
06254         }
06255 
06256         const char *filename = params["filename"];
06257         EMData *msk = new EMData();
06258         msk->read_image(filename);
06259 
06260         int nx = image->get_xsize();
06261         int ny = image->get_ysize();
06262         int nz = image->get_zsize();
06263 
06264         int xm = msk->get_xsize();
06265         int ym = msk->get_ysize();
06266         int zm = msk->get_zsize();
06267 
06268         float apix = image->get_attr("apix_x");
06269         float apixm = msk->get_attr("apix_x");
06270 
06271         float xo = image->get_attr_default("origin_x",0.0);
06272         float yo = image->get_attr_default("origin_y",0.0);
06273         float zo = image->get_attr_default("origin_z",0.0);
06274 
06275         float xom = msk->get_attr_default("origin_x",0.0);
06276         float yom = msk->get_attr_default("origin_y",0.0);
06277         float zom = msk->get_attr_default("origin_z",0.0);
06278 
06279         float *dp = image->get_data();
06280         float *dpm = msk->get_data();
06281         int nxy = nx * ny;
06282 
06283         for (int k = 0; k < nz; k++) {
06284                 float zc = zo + k * apix;
06285                 if (zc <= zom || zc >= zom + zm * apixm) {
06286                         memset(&(dp[k * nxy]), 0, sizeof(float) * nxy);
06287                 }
06288                 else {
06289                         int km = (int) ((zc - zom) / apixm);
06290 
06291                         for (int j = 0; j < ny; j++) {
06292                                 float yc = yo + j * apix;
06293                                 if (yc <= yom || yc >= yom + ym * apixm) {
06294                                         memset(&(dp[k * nxy + j * nx]), 0, sizeof(float) * nx);
06295                                 }
06296                                 else {
06297                                         int jm = (int) ((yc - yom) / apixm);
06298                                         size_t idx = 0;
06299                                         float xc;
06300                                         int im;
06301                                         for (int i = 0; i < nx; i++) {
06302                                                 xc = xo + i * apix;
06303                                                 idx = (size_t)k * nxy + j * nx + i;
06304                                                 if (xc <= xom || xc >= xom + xm * apixm) {
06305                                                         dp[idx] = 0;
06306                                                 }
06307                                                 else {
06308                                                         im = (int) ((xc - xom) / apixm);
06309                                                         if (dpm[km * xm * ym + jm * xm + im] <= 0) {
06310                                                                 dp[idx] = 0;
06311                                                         }
06312                                                 }
06313                                         }
06314                                 }
06315                         }
06316                 }
06317         }
06318 
06319         image->update();
06320         msk->update();
06321         if( msk )
06322         {
06323                 delete msk;
06324                 msk = 0;
06325         }
06326 }
06327 
06328 void MatchSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06329         // The radial mask comes in with the existing radial image profile
06330         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06331 
06332         EMData *to = params["to"];
06333         XYData *sf = new XYData();
06334         float apixto = to->get_attr("apix_x");
06335 
06336 
06337         if (to->is_complex()) {
06338                 vector<float> rd=to->calc_radial_dist(to->get_ysize()/2.0f,0,1.0f,1);
06339                 for (size_t i=0; i<rd.size(); ++i) {
06340                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06341                         sf->set_y(i,rd[i]);
06342                 }
06343         }
06344         else {
06345                 EMData *tmp=to->do_fft();
06346                 vector<float> rd=tmp->calc_radial_dist(to->get_ysize()/2,0,1.0,1);
06347                 for (size_t i=0; i<rd.size(); ++i) {
06348                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06349                         sf->set_y(i,rd[i]);
06350                 }
06351                 delete tmp;
06352         }
06353 
06354         float apix=image->get_attr("apix_x");
06355 
06356 //      sf->write_file("a.txt");
06357 //      Util::save_data(0,sf->get_x(1),radial_mask,"b.txt");
06358 
06359         int n = radial_mask.size();
06360         for (int i=0; i<n; i++) {
06361                 if (radial_mask[i]>0) radial_mask[i]= sqrt(sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06362                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06363         }
06364 
06365 //      Util::save_data(0,sf->get_x(1),radial_mask,"c.txt");
06366 
06367         delete sf;
06368 }
06369 
06370 void SetSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06371         // The radial mask comes in with the existing radial image profile
06372         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06373 
06374         XYData *sf = params["strucfac"];
06375         if(params.has_key("apix")) {
06376                 image->set_attr("apix_x", (float)params["apix"]);
06377                 image->set_attr("apix_y", (float)params["apix"]);
06378                 image->set_attr("apix_z", (float)params["apix"]);
06379         }
06380 
06381         float apix=image->get_attr("apix_x");
06382         
06383         int n = radial_mask.size();
06384         for (int i=0; i<n; i++) {
06385 //              if (radial_mask[i]>0)
06386 //              {
06387 //                      radial_mask[i]= sqrt(n*sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06388 //              }
06389                 if (radial_mask[i]>0) {
06390                         radial_mask[i]= sqrt((n*n*n)*sf->get_yatx(i/(apix*2.0f*n))/radial_mask[i]);
06391                 }
06392                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06393         }
06394 
06395 }
06396 
06397 void SmartMaskProcessor::process_inplace(EMData * image)
06398 {
06399         if (!image) {
06400                 LOGWARN("NULL Image");
06401                 return;
06402         }
06403 
06404         float mask = params["mask"];
06405 
06406         int nx = image->get_xsize();
06407         int ny = image->get_ysize();
06408         int nz = image->get_zsize();
06409 
06410         float *dat = image->get_data();
06411         double sma = 0;
06412         size_t smn = 0;
06413         float r = 0.0f;
06414         for (int k = 0; k < nz; ++k) {
06415                 for (int j = 0; j < ny; ++j) {
06416                         for (int i = 0; i < nx; ++i, ++dat) {
06417                                 r =
06418                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06419                                                  Util::square(k - nz / 2));
06420                                 if (r > mask - 1.5f && r < mask - 0.5f) {
06421                                         sma += *dat;
06422                                         smn++;
06423                                 }
06424                         }
06425                 }
06426         }
06427 
06428         float smask = (float) (sma / smn);
06429         image->update();
06430 
06431         dat = image->get_data();
06432         for (int k = 0; k < nz; ++k) {
06433                 for (int j = 0; j < ny; ++j) {
06434                         for (int i = 0; i < nx; ++i, ++dat) {
06435                                 r =
06436                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06437                                                  Util::square(k - nz / 2));
06438                                 if (r > mask - .5) {
06439                                         *dat = 0;
06440                                 }
06441                                 else {
06442                                         *dat -= smask;
06443                                 }
06444                         }
06445                 }
06446         }
06447 
06448         image->update();
06449 }
06450 
06451 void AutoMask3DProcessor::search_nearby(float *dat, float *dat2, int nx, int ny, int nz, float threshold)
06452 {
06453         Assert(dat != 0);
06454         Assert(dat2 != 0);
06455         Assert(nx > 0);
06456         Assert(ny > 0);
06457 
06458         bool done = false;
06459         int nxy = nx * ny;
06460 
06461         while (!done) {
06462                 done = true;
06463                 for (int k = 1; k < nz - 1; k++) {
06464                         size_t k2 = (size_t)k * nxy;
06465                         for (int j = 1; j < ny - 1; j++) {
06466                                 size_t l = j * nx + k2 + 1;
06467 
06468                                 for (int i = 1; i < nx - 1; i++) {
06469                                         if (dat[l] >= threshold || dat2[l]) {
06470                                                 if (dat2[l - 1] || dat2[l + 1] ||
06471                                                         dat2[l - nx] || dat2[l + nx] || dat2[l - nxy] || dat2[l + nxy]) {
06472                                                         dat2[l] = 1.0f;
06473                                                         done = false;
06474                                                 }
06475                                         }
06476                                         ++l;
06477                                 }
06478                         }
06479                 }
06480         }
06481 }
06482 
06483 void AutoMask3DProcessor::fill_nearby(float *dat2, int nx, int ny, int nz)
06484 {
06485         Assert(dat2 != 0);
06486         Assert(nx > 0);
06487         Assert(ny > 0);
06488         Assert(nz >= 0);
06489 
06490         int nxy = nx * ny;
06491         size_t idx;
06492         for (int i = 0; i < nx; ++i) {
06493                 for (int j = 0; j < ny; ++j) {
06494                         int j2 = j * nx + i;
06495                         int k0 = 0;
06496                         for (int k = 0; k < nz; ++k) {
06497                                 idx = j2 + (size_t)k * nxy;
06498                                 if (dat2[idx]) {
06499                                         k0 = k;
06500                                         break;
06501                                 }
06502                         }
06503 
06504                         if (k0 != nz) {
06505                                 int k1 = nz - 1;
06506                                 for (int k = nz - 1; k >= 0; --k) {
06507                                         idx = j2 + (size_t)k * nxy;
06508                                         if (dat2[idx]) {
06509                                                 k1 = k;
06510                                                 break;
06511                                         }
06512                                 }
06513 
06514                                 for (int k = k0 + 1; k < k1; ++k) {
06515                                         idx = j2 + (size_t)k * nxy;
06516                                         dat2[idx] = 1.0f;
06517                                 }
06518                         }
06519                 }
06520         }
06521 
06522         for (int i = 0; i < nx; ++i) {
06523                 for (int j = 0; j < nz; ++j) {
06524                         size_t j2 = (size_t)j * nxy + i;
06525                         int k0 = 0;
06526                         for (int k = 0; k < ny; ++k) {
06527                                 idx = (size_t)k * nx + j2;
06528                                 if (dat2[idx]) {
06529                                         k0 = k;
06530                                         break;
06531                                 }
06532                         }
06533 
06534                         if (k0 != ny) {
06535                                 int k1 = ny - 1;
06536                                 for (int k = ny - 1; k >= 0; --k) {
06537                                         idx = (size_t)k * nx + j2;
06538                                         if (dat2[idx]) {
06539                                                 k1 = k;
06540                                                 break;
06541                                         }
06542                                 }
06543 
06544                                 for (int k = k0 + 1; k < k1; ++k) {
06545                                         idx = (size_t)k * nx + j2;
06546                                         dat2[idx] = 1.0f;
06547                                 }
06548                         }
06549                 }
06550         }
06551 
06552         for (int i = 0; i < ny; ++i) {
06553                 for (int j = 0; j < nz; ++j) {
06554                         size_t j2 = i * nx + (size_t)j * nxy;
06555                         int k0 = 0;
06556                         for (int k = 0; k < nx; ++k) {
06557                                 if (dat2[k + j2]) {
06558                                         k0 = k;
06559                                         break;
06560                                 }
06561                         }
06562                         if (k0 != nx) {
06563                                 int k1 = nx - 1;
06564                                 for (int k = nx - 1; k >= 0; --k) {
06565                                         if (dat2[k + j2]) {
06566                                                 k1 = k;
06567                                                 break;
06568                                         }
06569                                 }
06570 
06571                                 for (int k = k0 + 1; k < k1; ++k) {
06572                                         dat2[k + j2] = 1.0f;
06573                                 }
06574                         }
06575                 }
06576         }
06577 
06578 }
06579 
06580 void AutoMask3DProcessor::process_inplace(EMData * image)
06581 {
06582         if (!image) {
06583                 LOGWARN("NULL Image");
06584                 return;
06585         }
06586 
06587         int nx = image->get_xsize();
06588         int ny = image->get_ysize();
06589         int nz = image->get_zsize();
06590 
06591         EMData *amask = new EMData();
06592         amask->set_size(nx, ny, nz);
06593 
06594         float sig = 0;
06595         float mean = 0;
06596 
06597         if (params.has_key("threshold1") && params.has_key("threshold2")) {
06598                 sig = image->get_attr("sigma");
06599                 mean = image->get_attr("mean");
06600         }
06601 
06602         float *dat = image->get_data();
06603         float *dat2 = amask->get_data();
06604 
06605         float t = 0;
06606         if (params.has_key("threshold1")) {
06607                 t = params["threshold1"];
06608         }
06609         else {
06610                 t = mean + sig * 2.5f;
06611         }
06612 
06613         size_t l = 0;
06614         for (int k = 0; k < nz; ++k) {
06615                 for (int j = 0; j < ny; ++j) {
06616                         for (int i = 0; i < nx; ++i) {
06617                                 if (dat[l] > t) {
06618                                         dat2[l] = 1.0f;
06619                                 }
06620                                 ++l;
06621                         }
06622                 }
06623         }
06624 
06625 
06626         if (params.has_key("threshold2")) {
06627                 t = params["threshold2"];
06628         }
06629         else {
06630                 t = mean + sig * 0.5f;
06631         }
06632 
06633         search_nearby(dat, dat2, nx, ny, nz, t);
06634 
06635         int nxy = nx * ny;
06636 
06637         for (int k = 1; k < nz - 1; ++k) {
06638                 for (int j = 1; j < ny - 1; ++j) {
06639                         size_t l = j * nx + (size_t)k * nxy + 1;
06640                         for (int i = 1; i < nx - 1; ++i, ++l) {
06641                                 if (dat2[l - 1] == 1.0f || dat2[l + 1] == 1.0f ||
06642                                         dat2[l - nx] == 1.0f || dat2[l + nx] == 1.0f ||
06643                                         dat2[l - nxy] == 1.0f || dat2[l + nxy] == 1.0f) {
06644                                         dat2[l] = 2.0f;
06645                                 }
06646                         }
06647                 }
06648         }
06649 
06650         size_t size = (size_t)nx * ny * nz;
06651         for (size_t i = 0; i < size; ++i) {
06652                 if (dat2[i] == 2.0f) {
06653                         dat2[i] = 1.0f;
06654                 }
06655         }
06656 
06657         fill_nearby(dat2, nx, ny, nz);
06658 
06659         image->update();
06660         amask->update();
06661 
06662         image->mult(*amask);
06663         amask->write_image("mask.mrc", 0, EMUtil::IMAGE_MRC);
06664         if( amask )
06665         {
06666                 delete amask;
06667                 amask = 0;
06668         }
06669 }
06670 
06671 
06672 void AutoMask3D2Processor::process_inplace(EMData * image)
06673 {
06674         if (!image) {
06675                 LOGWARN("NULL Image");
06676                 return;
06677         }
06678 
06679         if (image->get_ndim() != 3) {
06680                 throw ImageDimensionException("This processor was only ever designed to work on 3D images.");
06681         }
06682 
06683         /*
06684          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
06685          To get around this just use the return_mask parameter.
06686         string mask_output = params.set_default("write_mask", "");
06687         if ( mask_output != "") {
06688                 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.");
06689                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
06690         }
06691         */
06692 
06693         int radius=0;
06694         if (params.has_key("radius")) {
06695                 radius = params["radius"];
06696         }
06697         int nmaxseed=0;
06698         if (params.has_key("nmaxseed")) {
06699                 nmaxseed = params["nmaxseed"];
06700         }
06701 
06702         float threshold=0.0;
06703         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
06704         else threshold=params["threshold"];
06705 
06706         int nshells = params["nshells"];
06707         int nshellsgauss = params["nshellsgauss"];
06708         int verbose=params.set_default("verbose",0);
06709 
06710         int nx = image->get_xsize();
06711         int ny = image->get_ysize();
06712         int nz = image->get_zsize();
06713         int nxy=nx*ny;
06714 
06715         EMData *amask = new EMData();
06716         amask->set_size(nx, ny, nz);
06717 
06718         float *dat = image->get_data();
06719         float *dat2 = amask->get_data();
06720         int i,j,k;
06721         size_t l = 0;
06722 
06723         // Seeds with the highest valued pixels
06724         if (nmaxseed>0) {
06725                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
06726 
06727                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
06728                         amask->set_value_at((*i).x,(*i).y,(*i).z,1.0);
06729                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
06730                 }
06731         }
06732 
06733         // Seeds with a sphere
06734         if (radius>0) {
06735                 // start with an initial sphere
06736                 for (k = -nz / 2; k < nz / 2; ++k) {
06737                         for (j = -ny / 2; j < ny / 2; ++j) {
06738                                 for (i = -nx / 2; i < nx / 2; ++i,++l) {
06739                                         if (abs(k) > radius || abs(j) > radius || abs(i) > radius) continue;
06740                                         if ( (k * k + j * j + i * i) > (radius*radius) || dat[l] < threshold) continue;
06741                                         dat2[l] = 1.0f;
06742                                 }
06743                         }
06744                 }
06745         }
06746 
06747 
06748         // iteratively 'flood fills' the map... recursion would be better
06749         int done=0;
06750         int iter=0;
06751         while (!done) {
06752                 iter++;
06753                 done=1;
06754                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
06755                 for (k=1; k<nz-1; ++k) {
06756                         for (j=1; j<ny-1; ++j) {
06757                                 for (i=1; i<nx-1; ++i) {
06758                                         l=i+j*nx+k*nx*ny;
06759                                         if (dat2[l]) continue;
06760                                         if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx]||dat2[l-nxy]||dat2[l+nxy])) {
06761                                                 dat2[l]=1.0;
06762                                                 done=0;
06763                                         }
06764                                 }
06765                         }
06766                 }
06767         }
06768 
06769         amask->update();
06770 
06771         if (verbose) printf("expanding mask\n");
06772         amask->process_inplace("mask.addshells.gauss", Dict("val1", (int)(nshells+nshellsgauss/2),"val2",0));
06773         if (verbose) printf("filtering mask\n");
06774         amask->process_inplace("filter.lowpass.gauss", Dict("cutoff_abs", (float)(1.0f/(float)nshellsgauss)));
06775         amask->process_inplace("threshold.belowtozero", Dict("minval",(float)0.002));   // this makes the value exactly 0 beyond ~2.5 sigma
06776 
06777         bool return_mask = params.set_default("return_mask",false);
06778         if (return_mask) {
06779                 // 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.
06780                 dat = image->get_data();
06781                 dat2 = amask->get_data();
06782                 memcpy(dat,dat2,image->get_size()*sizeof(float));
06783         } else {
06784                 image->mult(*amask);
06785         }
06786 
06787         // EMAN2 policy is not to allow file io from with a processor
06788         //if (mask_output != "") {
06789         //      amask->write_image(mask_output);
06790         //}
06791 
06792 
06793         delete amask;
06794 }
06795 
06796 void IterBinMaskProcessor::process_inplace(EMData * image)
06797 {
06798         if (!image) {
06799                 LOGWARN("NULL Image");
06800                 return;
06801         }
06802 
06803         float val1 = params["val1"];
06804         float val2 = params["val2"];
06805 
06806         int nx = image->get_xsize();
06807         int ny = image->get_ysize();
06808         int nz = image->get_zsize();
06809         EMData *image2 = new EMData(nx,ny,nz);
06810 
06811         // Got a compile warning complaining that these things were never used. Hope I didn't break anything - apologies if so (d.woolford)
06812 //      float *dat = image->get_data();
06813 //      float *dat2 = image2->get_data();
06814 
06815 
06816         float *d = image->get_data();
06817         float *d2 = image2->get_data();
06818 
06819         const int nxy = nx * ny;
06820         size_t size = (size_t)nx * ny * nz;
06821 
06822         // TODO: THIS IS EXTREMELY INEFFICIENT
06823         if (nz != 1) {
06824                 for (int l = 1; l <= (int) val1+val2; ++l) {
06825                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06826                         for (int k = 1; k < nz - 1; ++k) {
06827                                 for (int j = 1; j < ny - 1; ++j) {
06828                                         for (int i = 1; i < nx - 1; ++i) {
06829                                                 size_t t = i + j*nx+(size_t)k*nx*ny;
06830                                                 if (d[t]) continue;
06831                                                 if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx] || d2[t + nxy] || d2[t - nxy]) d[t] = (float) l + 1;
06832                                         }
06833                                 }
06834                         }
06835                 }
06836         }
06837         else {
06838                 for (int l = 1; l <= (int) val1+val2; ++l) {
06839                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06840                         for (int j = 1; j < ny - 1; ++j) {
06841                                 for (int i = 1; i < nx - 1; ++i) {
06842                                         size_t t = i + j * nx;
06843                                         if (d[t]) continue;
06844                                         if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx]) d[t] = (float) l + 1;
06845                                 }
06846                         }
06847                 }
06848         }
06849 
06850         vector<float> vec;
06851         for (int i=0; i<val1+2; i++) vec.push_back(1.0);
06852         for (int i=0; i<val2; i++) {
06853                 vec.push_back(exp(-pow(2.0f*i/(val2),2.0f)));
06854 //              printf("%f\n",exp(-pow(2.0*i/(val1-val2),2.0)));
06855         }
06856         for (size_t i = 0; i < size; ++i) if (d[i]) d[i]=vec[(int)d[i]];
06857 
06858         image->update();
06859         delete image2;
06860 }
06861 
06862 EMData* DirectionalSumProcessor::process(const EMData* const image ) {
06863         string dir = params.set_default("axis", "");
06864         if ( dir == "" || ( dir != "x" && dir != "y" && dir != "z" ) )
06865                 throw InvalidParameterException("The direction parameter must be either x, y, or z");
06866 
06867         int nx = image->get_xsize();
06868         int ny = image->get_ysize();
06869         int nz = image->get_zsize();
06870 
06871         int a0 = params.set_default("first", 0);
06872         int a1 = params.set_default("last", -1);
06873 
06874         EMData* ret = new EMData;
06875         // compress one of the dimensions
06876         if ( dir == "x" ) {
06877                 ret->set_size(nz,ny);
06878 
06879                 // bounds checks
06880                 if (a0<0) a0+=nx;
06881                 if (a1<0) a1+=nx;
06882                 if (a0<0) a0=0;
06883                 if (a1<0) a1=0;
06884                 if (a0>=nx) a0=nx-1;
06885                 if (a1>=nx) a1=nx-1;
06886 
06887                 for (int y=0; y<ny; y++) {
06888                         for (int z=0; z<nz; z++) {
06889                                 double sum=0.0;
06890                                 for (int x=a0; x<=a1; x++) sum+=image->get_value_at(x,y,z);
06891                                 ret->set_value_at(z,y,(float)sum);
06892                         }
06893                 }
06894         }
06895         else if ( dir == "y" ) {
06896                 ret->set_size(nx,nz);
06897 
06898                 // bounds checks
06899                 if (a0<0) a0+=ny;
06900                 if (a1<0) a1+=ny;
06901                 if (a0<0) a0=0;
06902                 if (a1<0) a1=0;
06903                 if (a0>=ny) a0=ny-1;
06904                 if (a1>=ny) a1=ny-1;
06905 
06906                 for (int x=0; x<nx; x++) {
06907                         for (int z=0; z<nz; z++) {
06908                                 double sum=0.0;
06909                                 for (int y=a0; y<=a1; y++) sum+=image->get_value_at(x,y,z);
06910                                 ret->set_value_at(x,z,(float)sum);
06911                         }
06912                 }
06913         }
06914         else if ( dir == "z" ) {
06915                 ret->set_size(nx,ny);
06916 
06917                 // bounds checks
06918                 if (a0<0) a0+=nz;
06919                 if (a1<0) a1+=nz;
06920                 if (a0<0) a0=0;
06921                 if (a1<0) a1=0;
06922                 if (a0>=nz) a0=nz-1;
06923                 if (a1>=nz) a1=nz-1;
06924 
06925                 for (int y=0; y<ny; y++) {
06926                         for (int x=0; x<nx; x++) {
06927                                 double sum=0.0;
06928                                 for (int z=a0; z<=a1; z++) sum+=image->get_value_at(x,y,z);
06929                                 ret->set_value_at(x,y,(float)sum);
06930                         }
06931                 }
06932         }
06933 
06934         ret->update();
06935         return ret;
06936 }
06937 
06938 void TestImageProcessor::preprocess(EMData * image)
06939 {
06940         if (!image) {
06941                 LOGWARN("NULL Image");
06942                 return;
06943         }
06944 
06945         nx = image->get_xsize();
06946         ny = image->get_ysize();
06947         nz = image->get_zsize();
06948 }
06949 
06950 
06951 void TestImageFourierNoiseGaussian::process_inplace(EMData* image)
06952 {
06953         if (!image->is_complex()) {
06954                 int nx = image->get_xsize();
06955                 int offset = 2 - nx%2;
06956 
06957                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
06958                 image->set_complex(true);
06959                 if (1 == offset) image->set_fftodd(true);
06960                 else image->set_fftodd(false);
06961                 image->set_fftpad(true);
06962         }
06963         image->ri2ap();
06964 
06965         float sigma = params.set_default("sigma",.25f);
06966 
06967         float * d = image->get_data();
06968         int nx = image->get_xsize();
06969         int ny = image->get_ysize();
06970         int nxy = image->get_ysize()*nx;
06971         int nzon2 = image->get_zsize()/2;
06972         int nyon2 = image->get_ysize()/2;
06973         float rx, ry, rz, length, amp, phase;
06974         int twox;
06975         for (int z = 0; z< image->get_zsize(); ++z) {
06976                 for (int y = 0; y < image->get_ysize(); ++y) {
06977                         for (int x = 0; x < image->get_xsize()/2; ++x) {
06978                                 rx = (float)x;
06979                                 ry = (float)nyon2 - (float)y;
06980                                 rz = (float)nzon2 - (float)z;
06981                                 length = sqrt(rx*rx + ry*ry + rz*rz);
06982                                 amp = exp(-sigma*length);
06983                                 phase = Util::get_frand(0,1)*2*M_PI;
06984 
06985                                 twox = 2*x;
06986                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
06987                                 size_t idx2 = idx1 + 1;
06988                                 d[idx1] = amp;
06989                                 d[idx2] = phase;
06990 
06991                         }
06992                 }
06993         }
06994 
06995         image->ap2ri();
06996         if (image->get_ndim() == 2) {
06997                 bool yodd = image->get_ysize() % 2 == 1;
06998 
06999                 int yit = image->get_ysize()/2-1;
07000                 int offset = 1;
07001                 if (yodd) {
07002                         offset = 0;
07003                 }
07004                 for (int y = 0; y < yit; ++y) {
07005                         int bot_idx = (y+offset)*nx;
07006                         int top_idx = (ny-1-y)*nx;
07007                         float r1 = d[bot_idx];
07008                         float i1 = d[bot_idx+1];
07009                         float r2 = d[top_idx];
07010                         float i2 = d[top_idx+1];
07011                         float r = (r1 + r2)/2.0f;
07012                         float i = (i1 + i2)/2.0f;
07013                         d[bot_idx] = r;
07014                         d[top_idx] = r;
07015                         d[bot_idx+1] = i;
07016                         d[top_idx+1] = -i;
07017 
07018                         bot_idx = (y+offset)*nx+nx-2;
07019                         top_idx = (ny-1-y)*nx+nx-2;
07020                         r1 = d[bot_idx];
07021                         i1 = d[bot_idx+1];
07022                         r2 = d[top_idx];
07023                         i2 = d[top_idx+1];
07024                         r = (r1 + r2)/2.0f;
07025                         i = (i1 + i2)/2.0f;
07026                         d[bot_idx] = r;
07027                         d[top_idx] = r;
07028                         d[bot_idx+1] = i;
07029                         d[top_idx+1] = -i;
07030                 }
07031 
07032                 d[1] = 0; // 0 phase for this componenet
07033                 d[nx-1] = 0; // 0 phase for this component
07034                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
07035                 d[ny/2*nx+1] = 0;// 0 phase for this component
07036         }
07037 
07038         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
07039         image->do_ift_inplace();
07040         image->depad();
07041 }
07042 
07043 #include <iostream>
07044 using std::ostream_iterator;
07045 
07046 void CTFSNRWeightProcessor::process_inplace(EMData* image) {
07047         if (params.has_key("noise")==false) throw InvalidParameterException("You must supply the noise argument");
07048         if (params.has_key("snr")==false) throw InvalidParameterException("You must supply the snr argument");
07049 
07050         float boost = params.set_default("boost",1.0f);
07051 
07052         if (!image->is_complex()) {
07053                 image->do_fft_inplace();
07054         }
07055         EMData* cpy = image->copy();
07056         cpy->ri2inten();
07057         vector<float> sf = cpy->calc_radial_dist(cpy->get_ysize()/2,0.0,1.0,1);
07058         transform(sf.begin(),sf.end(),sf.begin(),sqrtf);
07059         delete cpy;
07060 
07061         image->ri2ap();
07062 
07063         vector<float> noise = params["noise"];
07064         vector<float> snr = params["snr"];
07065 
07066 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
07067 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
07068 
07069         for(vector<float>::iterator it = noise.begin(); it != noise.end(); ++it){
07070                 if ((*it) == 0) *it = 1;
07071         }
07072         for(vector<float>::iterator it = snr.begin(); it != snr.end(); ++it){
07073                 if ((*it) < 0) *it = 0;
07074         }
07075         // Subtract the mean from the data and store it in data_mm
07076         transform(snr.begin(),snr.end(),noise.begin(),snr.begin(),std::multiplies<float>());
07077         transform(snr.begin(),snr.end(),snr.begin(),sqrtf);
07078 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
07079 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
07080 
07081         int i = static_cast<int>(snr.size());
07082 
07083         float * d = image->get_data();
07084         int nx = image->get_xsize();
07085 //      int ny = image->get_ysize();
07086         int nxy = image->get_ysize()*nx;
07087         int nzon2 = image->get_zsize()/2;
07088         int nyon2 = image->get_ysize()/2;
07089         float rx, ry, rz, amp;
07090         int length;
07091         int twox;
07092         image->process_inplace("xform.fourierorigin.tocenter");
07093         for (int z = 0; z< image->get_zsize(); ++z) {
07094                 for (int y = 0; y < image->get_ysize(); ++y) {
07095                         for (int x = 0; x < image->get_xsize()/2; ++x) {
07096                                 rx = (float)x;
07097                                 ry = (float)nyon2 - (float)y;
07098                                 rz = (float)nzon2 - (float)z;
07099                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
07100 
07101                                 twox = 2*x;
07102                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
07103                                 if (length >= i || length >= (int)sf.size()) {
07104                                         d[idx1] = 0;
07105                                         continue;
07106                                 } else {
07107                                         amp = boost*snr[length];
07108 //                                      if (amp > 0) amp =sqrtf(amp);
07109 //                                      else amp = 0;
07110                                 }
07111 
07112                                 if (sf[length] == 0) {
07113                                         d[idx1] = 0;
07114                                         continue;
07115                                 }
07116 
07117 //                              size_t idx2 = idx1 + 1;
07118 //                              cout << d[idx1] << " " << sf[length] << endl;
07119                                 d[idx1] /= sf[length];
07120                                 if (d[idx1] < 0) {
07121                                         d[idx1] *= amp;
07122                                 }else {
07123                                         d[idx1] *= -amp;
07124                                 }
07125 //                              d[idx2] = phase;
07126 
07127                         }
07128                 }
07129         }
07130 
07131         image->ap2ri();
07132         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
07133         image->do_ift_inplace();
07134         image->depad();
07135 }
07136 
07137 void TestImageFourierNoiseProfile::process_inplace(EMData * image) {
07138 
07139         if (params.has_key("profile")==false) throw InvalidParameterException("You must supply the profile argument");
07140 
07141         if (!image->is_complex()) {
07142                 int nx = image->get_xsize();
07143                 int offset = 2 - nx%2;
07144 
07145                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
07146                 image->set_complex(true);
07147                 if (1 == offset) image->set_fftodd(true);
07148                 else image->set_fftodd(false);
07149                 image->set_fftpad(true);
07150         }
07151         image->to_zero();
07152         image->ri2ap();
07153 
07154         vector<float> profile = params["profile"];
07155         transform(profile.begin(),profile.end(),profile.begin(),sqrtf);
07156 
07157         int i = static_cast<int>(profile.size());
07158 
07159         float * d = image->get_data();
07160         int nx = image->get_xsize();
07161         int ny = image->get_ysize();
07162         int nxy = image->get_ysize()*nx;
07163         int nzon2 = image->get_zsize()/2;
07164         int nyon2 = image->get_ysize()/2;
07165         float rx, ry, rz, amp, phase;
07166         int length;
07167         int twox;
07168         for (int z = 0; z< image->get_zsize(); ++z) {
07169                 for (int y = 0; y < image->get_ysize(); ++y) {
07170                         for (int x = 0; x < image->get_xsize()/2; ++x) {
07171                                 rx = (float)x;
07172                                 ry = (float)nyon2 - (float)y;
07173                                 rz = (float)nzon2 - (float)z;
07174                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
07175 
07176                                 twox = 2*x;
07177                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
07178                                 size_t idx2 = idx1 + 1;
07179 
07180 
07181                                 if (length >= i) {
07182                                         d[idx1] = 0;
07183                                         d[idx2] = 0;
07184                                         continue;
07185                                 }
07186                                 amp = profile[length];
07187                                 phase = Util::get_frand(0,1)*2*M_PI;
07188 
07189 
07190                                 d[idx1] = amp;
07191                                 d[idx2] = phase;
07192 
07193                         }
07194                 }
07195         }
07196 
07197         image->ap2ri();
07198         if (image->get_ndim() == 2) {
07199                 bool yodd = image->get_ysize() % 2 == 1;
07200 
07201                 int yit = image->get_ysize()/2-1;
07202                 int offset = 1;
07203                 if (yodd) {
07204                         offset = 0;
07205                 }
07206                 for (int y = 0; y < yit; ++y) {
07207                         int bot_idx = (y+offset)*nx;
07208                         int top_idx = (ny-1-y)*nx;
07209                         float r1 = d[bot_idx];
07210                         float i1 = d[bot_idx+1];
07211                         float r2 = d[top_idx];
07212                         float i2 = d[top_idx+1];
07213                         float r = (r1 + r2)/2.0f;
07214                         float i = (i1 + i2)/2.0f;
07215                         d[bot_idx] = r;
07216                         d[top_idx] = r;
07217                         d[bot_idx+1] = i;
07218                         d[top_idx+1] = -i;
07219 
07220                         bot_idx = (y+offset)*nx+nx-2;
07221                         top_idx = (ny-1-y)*nx+nx-2;
07222                         r1 = d[bot_idx];
07223                         i1 = d[bot_idx+1];
07224                         r2 = d[top_idx];
07225                         i2 = d[top_idx+1];
07226                         r = (r1 + r2)/2.0f;
07227                         i = (i1 + i2)/2.0f;
07228                         d[bot_idx] = r;
07229                         d[top_idx] = r;
07230                         d[bot_idx+1] = i;
07231                         d[top_idx+1] = -i;
07232                 }
07233 
07234                 d[1] = 0; // 0 phase for this componenet
07235                 d[nx-1] = 0; // 0 phase for this component
07236                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
07237                 d[ny/2*nx+1] = 0;// 0 phase for this component
07238         }
07239 
07240         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
07241         image->do_ift_inplace();
07242         image->depad();
07243 }
07244 
07245 void TestImageLineWave::process_inplace(EMData * image)
07246 {
07247         preprocess(image);
07248 
07249         float period = params.set_default("period",10.0f);
07250         size_t n = (size_t)image->get_xsize()*image->get_ysize()*image->get_zsize();
07251 
07252         for(size_t i = 0; i < n; ++i) {
07253                 float x = fmod((float)i,period);
07254                 x /= period;
07255                 x = (float)sin(x*EMConsts::pi*2.0);
07256                 image->set_value_at_fast(i,x);
07257         }
07258 }
07259 
07260 void TestImageGaussian::process_inplace(EMData * image)
07261 {
07262         preprocess(image);
07263 
07264         float sigma = params["sigma"];
07265         string axis = (const char*)params["axis"];
07266         float c = params["c"];
07267 
07268         float *dat = image->get_data();
07269         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
07270         float x2, y2, z2; //this is the coordinates of this pixel from image center
07271         for (int k = 0; k < nz; ++k) {
07272                 for (int j = 0; j < ny; ++j) {
07273                         for (int i = 0; i < nx; ++i, ++dat) {
07274                                 x2 = (float)( i - nx/2 );
07275                                 y2 = (float)( j - ny/2 );
07276                                 z2 = (float)( k - nz/2 );
07277 
07278                                 if(axis==""){
07279                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
07280                                 }
07281                                 else if(axis == "x"){
07282                                         float lc = -c;
07283                                         float rc = c;
07284                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
07285                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
07286                                 }
07287                                 else if(axis == "y"){
07288                                         float lc = -c;
07289                                         float rc = c;
07290                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
07291                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
07292                                 }
07293                                 else if(axis == "z"){
07294                                         if( nz == 1 ){
07295                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07296                                         }
07297                                         float lc = -c;
07298                                         float rc = c;
07299                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
07300                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
07301                                 }
07302                                 else{
07303                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07304                                 }
07305                                 //the amplitude of the pixel is proportional to the distance of this pixel from the center
07306                                 *dat = (float)gsl_ran_gaussian_pdf((double)r,(double)sigma);
07307                         }
07308                 }
07309         }
07310 
07311         image->update();
07312 }
07313 
07314 void TestImageGradient::process_inplace(EMData * image)
07315 {
07316         string axis = params.set_default("axis", "x");
07317 
07318         float m = params.set_default("m", 1.0f);
07319         float b = params.set_default("b", 0.0f);
07320 
07321         if ( axis != "z" && axis != "y" && axis != "x") throw InvalidParameterException("Axis must be x,y or z");
07322 
07323         preprocess(image);
07324 
07325         if ( axis == "x")
07326         {
07327                 for(int k=0; k<nz;++k) {
07328                         for(int j=0; j<ny; ++j) {
07329                                 for(int i=0; i <nx; ++i) {
07330                                         image->set_value_at(i,j,k,m*i+b);
07331                                 }
07332                         }
07333                 }
07334         }
07335         else if ( axis == "y")
07336         {
07337                 for(int k=0; k<nz;++k) {
07338                         for(int j=0; j<ny; ++j) {
07339                                 for(int i=0; i <nx; ++i) {
07340                                         image->set_value_at(i,j,k,m*j+b);
07341                                 }
07342                         }
07343                 }
07344         }
07345         else if ( axis == "z")
07346         {
07347                 for(int k=0; k<nz;++k) {
07348                         for(int j=0; j<ny; ++j) {
07349                                 for(int i=0; i <nx; ++i) {
07350                                         image->set_value_at(i,j,k,m*k+b);
07351                                 }
07352                         }
07353                 }
07354         }
07355         image->update();
07356 }
07357 
07358 void TestImageAxes::process_inplace(EMData * image)
07359 {
07360         preprocess(image);
07361 
07362         float fill = params.set_default("fill", 1.0f);
07363         // get the central coordinates
07364         int cx = nx/2;
07365         int cy = ny/2;
07366         int cz = nz/2;
07367 
07368         // Offsets are used to detect when "the extra pixel" needs to be filled in
07369         // They are implemented on the assumption that for odd dimensions
07370         // the "center pixel" is the center pixel, but for even dimensions the "center
07371         // pixel" is displaced in the positive direction by 1
07372         int xoffset = (nx % 2 == 0? 1:0);
07373         int yoffset = (ny % 2 == 0? 1:0);
07374         int zoffset = (nz % 2 == 0? 1:0);
07375 
07376         // This should never occur - but if indeed it did occur, the code in this function
07377         // would break - the function would proceed into the final "else" and seg fault
07378         // It is commented out but left for clarity
07379 //      if ( nx < 1 || ny < 1 || nz < 1 ) throw ImageDimensionException("Error: one of the image dimensions was less than zero");
07380 
07381         if ( nx == 1 && ny == 1 && nz == 1 )
07382         {
07383                 (*image)(0) = fill;
07384         }
07385         else if ( ny == 1 && nz == 1 )
07386         {
07387                 int radius = params.set_default("radius", cx );
07388                 if ( radius > cx ) radius = cx;
07389 
07390                 (*image)(cx) = fill;
07391                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i) = fill;
07392                 for ( int i = 1; i <= radius; ++i ) (*image)(cx-i) = fill;
07393         }
07394         else if ( nz == 1 )
07395         {
07396                 int min = ( nx < ny ? nx : ny );
07397                 min /= 2;
07398 
07399                 int radius = params.set_default("radius", min );
07400                 if ( radius > min ) radius = min;
07401 
07402                 (*image)(cx,cy) = fill;
07403 
07404                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i,cy) = fill;
07405                 for ( int i = 1; i <= radius-yoffset; ++i )(*image)(cx,cy+i) = fill;
07406 
07407                 for ( int i = 1; i <= radius; ++i )
07408                 {
07409                         (*image)(cx-i,cy) = fill;
07410                         (*image)(cx,cy-i) = fill;
07411                 }
07412 
07413         }
07414         else
07415         {
07416                 // nx > 1 && ny > 1 && nz > 1
07417                 int min = ( nx < ny ? nx : ny );
07418                 if (nz < min ) min = nz;
07419                 min /= 2;
07420 
07421                 int radius = params.set_default("radius", min);
07422                 if ( radius > min ) radius = min;
07423 
07424 
07425                 (*image)(cx,cy,cz) = fill;
07426                 for ( int i = 1; i <=radius-xoffset; ++i ) (*image)(cx+i,cy,cz) = fill;
07427                 for ( int i = 1; i <=radius-yoffset; ++i ) (*image)(cx,cy+i,cz) = fill;
07428                 for ( int i = 1; i <=radius-zoffset; ++i ) (*image)(cx,cy,cz+i) = fill;
07429                 for ( int i = 1; i <= radius; ++i )
07430                 {
07431                         (*image)(cx-i,cy,cz) = fill;
07432                         (*image)(cx,cy-i,cz) = fill;
07433                         (*image)(cx,cy,cz-i) = fill;
07434                 }
07435         }
07436 
07437         image->update();
07438 }
07439 
07440 void TestImageScurve::process_inplace(EMData * image)
07441 {
07442         preprocess(image);
07443 
07444         int dim_size = image->get_ndim();
07445         if( 2 != dim_size ) {
07446                 throw ImageDimensionException("works for 2D images only");
07447         }
07448 
07449         int nx = image->get_xsize();
07450         int ny = image->get_ysize();
07451         image->to_zero();
07452 
07453         for (int i=0; i<100; i++) {
07454                 int x=static_cast<int>( nx/2+nx/6.0*sin(i*2.0*3.14159/100.0) );
07455                 int y=ny/4+i*ny/200;
07456                 for (int xx=x-nx/10; xx<x+nx/10; xx++) {
07457                         for (int yy=y-ny/10; yy<y+ny/10; yy++) {
07458 #ifdef  _WIN32
07459                                 (*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);
07460 #else
07461                                 (*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);
07462 #endif
07463                         }
07464                 }
07465         }
07466 
07467         image->update();
07468 }
07469 
07470 void TestImagePureGaussian::process_inplace(EMData * image)
07471 {
07472         preprocess(image);
07473 
07474         float x_sigma = params["x_sigma"];
07475         float y_sigma = params["y_sigma"];
07476         float z_sigma = params["z_sigma"];
07477 
07478         float x_center = params["x_center"];
07479         float y_center = params["y_center"];
07480         float z_center = params["z_center"];
07481 
07482         int nx = image->get_xsize();
07483         int ny = image->get_ysize();
07484         int nz = image->get_zsize();
07485 
07486         float x_twosig2 = 2*x_sigma*x_sigma;
07487         float y_twosig2 = 2*y_sigma*y_sigma;
07488         float z_twosig2 = 2*z_sigma*z_sigma;
07489 
07490         float sr2pi = sqrt( 2.0f*(float)pi );
07491         float norm  = 1.0f/ ( x_sigma*sr2pi );
07492         if (ny > 1) {
07493                 norm *= 1.0f/ ( y_sigma*sr2pi );
07494                 if (nz > 1) norm  *= 1.0f/ ( z_sigma*sr2pi );
07495         }
07496 
07497         float z, y, x, sum, val;
07498         for (int iz=0; iz < nz; ++iz) {
07499                 z = static_cast<float>(iz) - z_center;
07500                 for (int iy=0; iy < ny; ++iy) {
07501                         y = static_cast<float>(iy) - y_center;
07502                         for (int ix=0; ix < nx; ++ix) {
07503                                 x = static_cast<float>(ix) - x_center;
07504                                 sum = x*x/x_twosig2 + y*y/y_twosig2 + z*z/z_twosig2;
07505                                 val = norm*exp(-sum);
07506                                 (*image)(ix,iy,iz) = val;
07507                         }
07508                 }
07509         }
07510         image->update();
07511 }
07512 
07513 void TestImageSphericalWave::process_inplace(EMData * image)
07514 {
07515         preprocess(image);
07516 
07517         if(!params.has_key("wavelength")) {
07518                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07519                 throw InvalidParameterException("wavelength parameter is required.");
07520         }
07521         float wavelength = params["wavelength"];
07522 
07523         float phase = 0;
07524         if(params.has_key("phase")) {
07525                 phase = params["phase"];
07526         }
07527 
07528         float x = (float)(nx/2);
07529         if (params.has_key("x")) x=params["x"];
07530         float y = (float)(ny/2);
07531         if (params.has_key("y")) y=params["y"];
07532         float z = (float)(nz/2);
07533         if (params.has_key("z")) z=params["z"];
07534 
07535         int ndim = image->get_ndim();
07536 
07537         if(ndim==2) {   //2D
07538                 for(int j=0; j<ny; ++j) {
07539                         for(int i=0; i<nx; ++i) {
07540 #ifdef _WIN32
07541                                 float r=_hypotf(x-(float)i,y-(float)j);
07542 #else
07543                                 float r=hypot(x-(float)i,y-(float)j);
07544 #endif  //_WIN32
07545                                 if (r<.5) continue;
07546                                 image->set_value_at(i,j,cos(2*(float)pi*r/wavelength+phase)/r);
07547                         }
07548                 }
07549         }
07550         else {  //3D
07551                 for(int k=0; k<nz; ++k) {
07552                         for(int j=0; j<ny; ++j) {
07553                                 for(int i=0; i<nx; ++i) {
07554                                         float r=Util::hypot3(x-(float)i,y-(float)j,z-(float)k);
07555                                         if (r<.5) continue;
07556                                         image->set_value_at(i,j,k,cos(2*(float)pi*r/wavelength+phase)/(r*r));
07557                                 }
07558                         }
07559                 }
07560         }
07561 
07562         image->update();
07563 }
07564 
07565 
07566 void TestImageSinewave::process_inplace(EMData * image)
07567 {
07568         preprocess(image);
07569 
07570         if(!params.has_key("wavelength")) {
07571                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07572                 throw InvalidParameterException("wavelength parameter is required.");
07573         }
07574         float wavelength = params["wavelength"];
07575 
07576         string axis = "";
07577         if(params.has_key("axis")) {
07578                 axis = (const char*)params["axis"];
07579         }
07580 
07581         float phase = 0;
07582         if(params.has_key("phase")) {
07583                 phase = params["phase"];
07584         }
07585 
07586         int ndim = image->get_ndim();
07587         float * dat = image->get_data();
07588 
07589         if(ndim==1) {   //1D
07590                 for(int i=0; i<nx; ++i, ++dat) {
07591                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07592                 }
07593         }
07594         else if(ndim==2) {      //2D
07595                 float alpha = 0;
07596                 if(params.has_key("az")) {
07597                         alpha = params["az"];
07598                 }
07599                 for(int j=0; j<ny; ++j) {
07600                         for(int i=0; i<nx; ++i, ++dat) {
07601                                 if(alpha != 0) {
07602                                         *dat = sin((i*sin((180-alpha)*M_PI/180)+j*cos((180-alpha)*M_PI/180))*(2.0f*M_PI/wavelength) + phase);
07603                                 }
07604                                 else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07605                                         *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07606                                 }
07607                                 else {
07608                                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07609                                 }
07610                         }
07611                 }
07612         }
07613         else {  //3D
07614                 float az = 0;
07615                 if(params.has_key("az")) {
07616                         az = params["az"];
07617                 }
07618                 float alt = 0;
07619                 if(params.has_key("alt")) {
07620                         alt = params["alt"];
07621                 }
07622                 float phi = 0;
07623                 if(params.has_key("phi")) {
07624                         phi = params["phi"];
07625                 }
07626 
07627                 for(int k=0; k<nz; ++k) {
07628                         for(int j=0; j<ny; ++j) {
07629                                 for(int i=0; i<nx; ++i, ++dat) {
07630                                         if(axis.compare("z")==0 || axis.compare("Z")==0) {
07631                                                 *dat = sin(k*(2.0f*M_PI/wavelength) + phase);
07632                                         }
07633                                         else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07634                                                 *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07635                                         }
07636                                         else {
07637                                                 *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07638                                         }
07639                                 }
07640                         }
07641                 }
07642 
07643                 if(az != 0 || alt != 0 || phi != 0) {
07644                         Dict d("type","eman");
07645                         d["az"] = az; d["phi"] = phi; d["alt"] = alt;
07646                         image->transform(Transform(d));
07647                 }
07648         }
07649 
07650         image->update();
07651 }
07652 
07653 void TestImageSinewaveCircular::process_inplace(EMData * image)
07654 {
07655         preprocess(image);
07656 
07657         float wavelength = params["wavelength"];
07658         string axis = (const char*)params["axis"];
07659         float c = params["c"];
07660         float phase = params["phase"];
07661 
07662         float *dat = image->get_data();
07663         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
07664         float x2, y2, z2; //this is the coordinates of this pixel from image center
07665         for (int k = 0; k < nz; ++k) {
07666                 for (int j = 0; j < ny; ++j) {
07667                         for (int i = 0; i < nx; ++i, ++dat) {
07668                                 x2 = (float)( i - nx/2 );
07669                                 y2 = (float)( j - ny/2 );
07670                                 z2 = (float)( k - nz/2 );
07671                                 if(axis == ""){
07672                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
07673                                 }
07674                                 else if(axis == "x"){
07675                                         float lc = -c;
07676                                         float rc = c;
07677                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
07678                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
07679                                 }
07680                                 else if(axis == "y"){
07681                                         float lc = -c;
07682                                         float rc = c;
07683                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
07684                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
07685                                 }
07686                                 else if(axis == "z"){
07687                                         if( nz == 1 ){
07688                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07689                                         }
07690                                         float lc = -c;
07691                                         float rc = c;
07692                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
07693                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
07694                                 }
07695                                 else{
07696                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07697                                 }
07698                                 *dat = sin( r * (2.0f*M_PI/wavelength) - phase*180/M_PI);
07699                         }
07700                 }
07701         }
07702 
07703         image->update();
07704 }
07705 
07706 void TestImageSquarecube::process_inplace(EMData * image)
07707 {
07708         preprocess(image);
07709 
07710         float edge_length = params["edge_length"];
07711         string axis = (const char*)params["axis"];
07712         float odd_edge = params["odd_edge"];
07713         int fill = 1;
07714         if(params.has_key("fill")) {
07715                 fill = (int)params["fill"];
07716         }
07717 
07718         float *dat = image->get_data();
07719         float x2, y2, z2; //this coordinates of this pixel from center
07720         float xEdge, yEdge, zEdge; //half of edge length for this cube
07721         if(axis == ""){
07722                 xEdge = edge_length/2.0f;
07723                 yEdge = edge_length/2.0f;
07724                 zEdge = edge_length/2.0f;
07725         }
07726         else if(axis == "x"){
07727                 xEdge = odd_edge/2.0f;
07728                 yEdge = edge_length/2.0f;
07729                 zEdge = edge_length/2.0f;
07730         }
07731         else if(axis == "y"){
07732                 xEdge = edge_length/2.0f;
07733                 yEdge = odd_edge/2.0f;
07734                 zEdge = edge_length/2.0f;
07735         }
07736         else if(axis == "z"){
07737                 if( nz == 1 ){
07738                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07739                 }
07740                 xEdge = edge_length/2.0f;
07741                 yEdge = edge_length/2.0f;
07742                 zEdge = odd_edge/2.0f;
07743         }
07744         else{
07745                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07746         }
07747         for (int k = 0; k < nz; ++k) {
07748                 for (int j = 0; j < ny; ++j) {
07749                         for (int i = 0; i < nx; ++i, ++dat) {
07750                                 x2 = (float)fabs((float)i - nx/2);
07751                                 y2 = (float)fabs((float)j - ny/2);
07752                                 z2 = (float)fabs((float)k - nz/2);
07753                                 if( x2<=xEdge && y2<=yEdge && z2<=zEdge ) {
07754                                         if( !fill) {
07755                                                 *dat = 0;
07756                                         }
07757                                         else {
07758                                                 *dat = 1;
07759                                         }
07760                                 }
07761                                 else {
07762                                         if( !fill ) {
07763                                                 *dat = 1;
07764                                         }
07765                                         else {
07766                                                 *dat = 0;
07767                                         }
07768                                 }
07769                         }
07770                 }
07771         }
07772 
07773         image->update();
07774 }
07775 
07776 void TestImageCirclesphere::process_inplace(EMData * image)
07777 {
07778         preprocess(image);
07779 
07780         float radius = params.set_default("radius",nx/2.0f);
07781         string axis = (const char*)params["axis"];
07782         float c =  params.set_default("c",nx/2.0f);
07783         int fill = params.set_default("fill",1);
07784 
07785         float *dat = image->get_data();
07786         float x2, y2, z2; //this is coordinates of this pixel from center
07787         float r = 0.0f;
07788         float asy = 0.0f;
07789         if(axis == ""){
07790                 asy = radius;
07791         }
07792         else if(axis == "x" || axis == "y"){
07793                 asy = c;
07794         }
07795         else if(axis=="z"){
07796                 if( nz == 1 ){
07797                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07798                 }
07799                 asy = c;
07800         }
07801         else{
07802                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07803         }
07804 
07805         for (int k = 0; k < nz; ++k) {
07806                 for (int j = 0; j < ny; ++j) {
07807                         for (int i = 0; i < nx; ++i, ++dat) {
07808                                 x2 = fabs((float)i - nx/2);
07809                                 y2 = fabs((float)j - ny/2);
07810                                 z2 = fabs((float)k - nz/2);
07811                                 if( axis == "" ){
07812                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07813                                 }
07814                                 else if (axis == "x"){
07815                                         r = (x2*x2)/(asy*asy) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07816                                 }
07817                                 else if(axis == "y"){
07818                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(asy*asy) + (z2*z2)/(radius*radius);
07819                                 }
07820                                 else if(axis=="z"){
07821                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(asy*asy);
07822                                 }
07823                                 if( r<=1 ) {
07824                                         if( !fill) {
07825                                                 *dat = 0;
07826                                         }
07827                                         else {
07828                                                 *dat = 1;
07829                                         }
07830                                 }
07831                                 else {
07832                                         if( !fill ) {
07833                                                 *dat = 1;
07834                                         }
07835                                         else {
07836                                                 *dat = 0;
07837                                         }
07838                                 }
07839                         }
07840                 }
07841         }
07842 
07843         image->update();
07844 }
07845 
07846 void TestImageHollowEllipse::process_inplace(EMData * image)
07847 {
07848         preprocess(image);
07849 
07850         float width = params.set_default("width",2.0f);
07851 
07852         float a2 = params.set_default("a",nx/2.0f-1.0f);
07853         float b2 = params.set_default("b",ny/2.0f-1.0f);
07854         float c2 = params.set_default("c",nz/2.0f-1.0f);
07855 
07856         float a1 = params.set_default("xwidth",a2-width);
07857         float b1 = params.set_default("ywidth",b2-width);
07858         float c1 = params.set_default("zwidth",c2-width);
07859 
07860         float fill = params.set_default("fill",1.0f);
07861         Transform* t;
07862         if (params.has_key("transform")) {
07863                 t = params["transform"];
07864         } else {
07865                 t = new Transform;
07866         }
07867 
07868 
07869         int mz = 2*(int)c2+1;
07870         if ( nz < mz ) mz = nz;
07871         int my = 2*(int)b2+1;
07872         if ( ny < my ) my = ny;
07873         int mx = 2*(int)a2+1;
07874         if ( nx < mx ) mx = nx;
07875 
07876         float ai1 = 1/(a1*a1);
07877         float bi1 = 1/(b1*b1);
07878         float ci1 = 1/(c1*c1);
07879 
07880         float ai2 = 1/(a2*a2);
07881         float bi2 = 1/(b2*b2);
07882         float ci2 = 1/(c2*c2);
07883 
07884         Vec3f origin(nx/2,ny/2,nz/2);
07885 
07886         float x2, y2, z2, r1,r2;
07887         int xl, yl, zl;
07888         for (int k = 0; k < mz; ++k) {
07889                 for (int j = 0; j < my; ++j) {
07890                         for (int i = 0; i < mx; ++i) {
07891                                 x2 = (float)(i - mx/2);
07892                                 y2 = (float)(j - my/2);
07893                                 z2 = (float)(k - mz/2);
07894                                 r1 = (x2*x2)*ai1 + (y2*y2)*bi1 + (z2*z2)*ci1;
07895                                 r2 = (x2*x2)*ai2 + (y2*y2)*bi2 + (z2*z2)*ci2;
07896                                 if (r2 <= 1 && r1 >= 1) {
07897 
07898                                         if (t != 0) {
07899                                                 Vec3f v(x2,y2,z2);
07900                                                 v = (*t)*v;
07901                                                 v += origin;
07902 
07903                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07904                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07905 
07906                                                 for( int kk = -1; kk <= 1; ++kk)
07907                                                         for( int jj = -1; jj <= 1; ++jj)
07908                                                                 for( int ii = -1; ii <= 1; ++ii) {
07909                                                                         xl = (int)v[0]+ii;
07910                                                                         yl = (int)v[1]+jj;
07911                                                                         zl = (int)v[2]+kk;
07912                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07913                                                                                 image->set_value_at(xl,yl,zl,1.0);
07914                                                                 }
07915                                         } else {
07916                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07917                                         }
07918                                 }
07919                         }
07920                 }
07921         }
07922 
07923         delete t;
07924 
07925         image->update();
07926 }
07927 
07928 void TestImageEllipse::process_inplace(EMData * image)
07929 {
07930         preprocess(image);
07931 
07932 
07933         float a = params.set_default("a",nx/2.0f-1.0f);
07934         float b = params.set_default("b",ny/2.0f-1.0f);
07935         float c = params.set_default("c",nz/2.0f-1.0f);
07936         float fill = params.set_default("fill",1.0f);
07937         //bool hollow = params.set_default("hollow",false);
07938         Transform* t;
07939         if (params.has_key("transform")) {
07940                 t = params["transform"];
07941         } else {
07942                 t = new Transform;
07943         }
07944 
07945 
07946         int mz = 2*(int)c+1;
07947         if ( nz < mz ) mz = nz;
07948         int my = 2*(int)b+1;
07949         if ( ny < my ) my = ny;
07950         int mx = 2*(int)a+1;
07951         if ( nx < mx ) mx = nx;
07952 
07953 
07954         float ai = 1/(a*a);
07955         float bi = 1/(b*b);
07956         float ci = 1/(c*c);
07957 
07958         Vec3f origin(nx/2,ny/2,nz/2);
07959 
07960         float x2, y2, z2, r;
07961         int xl, yl, zl;
07962         for (int k = 0; k < mz; ++k) {
07963                 for (int j = 0; j < my; ++j) {
07964                         for (int i = 0; i < mx; ++i) {
07965                                 x2 = (float)(i - mx/2);
07966                                 y2 = (float)(j - my/2);
07967                                 z2 = (float)(k - mz/2);
07968                                 r = (x2*x2)*ai + (y2*y2)*bi + (z2*z2)*ci;
07969                                 if (r <= 1) {
07970 
07971                                         if (t != 0) {
07972                                                 Vec3f v(x2,y2,z2);
07973                                                 v = (*t)*v;
07974                                                 v += origin;
07975 
07976                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07977                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07978 
07979                                                 for( int kk = -1; kk <= 1; ++kk)
07980                                                         for( int jj = -1; jj <= 1; ++jj)
07981                                                                 for( int ii = -1; ii <= 1; ++ii) {
07982                                                                         xl = (int)v[0]+ii;
07983                                                                         yl = (int)v[1]+jj;
07984                                                                         zl = (int)v[2]+kk;
07985                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07986                                                                                 image->set_value_at(xl,yl,zl,fill);
07987                                                                 }
07988                                         } else {
07989                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07990                                         }
07991                                 }
07992                         }
07993                 }
07994         }
07995 
07996         delete t;
07997 
07998         image->update();
07999 }
08000 
08001 void TestImageNoiseUniformRand::process_inplace(EMData * image)
08002 {
08003         preprocess(image);
08004 
08005         Randnum * r = Randnum::Instance();
08006         if(params.has_key("seed")) {
08007                 r->set_seed((int)params["seed"]);
08008         }
08009 
08010         float *dat = image->get_data();
08011         size_t size = (size_t)nx*ny*nz;
08012         for (size_t i=0; i<size; ++i) {
08013                 dat[i] = r->get_frand();
08014         }
08015 
08016         image->update();
08017 }
08018 
08019 void TestImageNoiseGauss::process_inplace(EMData * image)
08020 {
08021         preprocess(image);
08022 
08023         float sigma = params["sigma"];
08024         if (sigma<=0) { sigma = 1.0; }
08025         float mean = params["mean"];
08026 
08027         Randnum * r = Randnum::Instance();
08028         if (params.has_key("seed")) {
08029                 r->set_seed((int)params["seed"]);
08030         }
08031 
08032         float *dat = image->get_data();
08033         size_t size = (size_t)nx*ny*nz;
08034         for (size_t i=0; i<size; ++i) {
08035                 dat[i] = r->get_gauss_rand(mean, sigma);
08036         }
08037 
08038         image->update();
08039 }
08040 
08041 void TestImageCylinder::process_inplace(EMData * image)
08042 {
08043         preprocess(image);
08044 
08045         int nx = image->get_xsize();
08046         int ny = image->get_ysize();
08047         int nz = image->get_zsize();
08048 
08049         if(nz == 1) {
08050                 throw ImageDimensionException("This processor only apply to 3D image");
08051         }
08052 
08053         float radius = params["radius"];
08054 #ifdef _WIN32
08055         if(radius > _cpp_min(nx, ny)/2.0) {
08056 #else
08057         if(radius > std::min(nx, ny)/2.0) {
08058 #endif
08059                 throw InvalidValueException(radius, "radius must be <= min(nx, ny)/2");
08060         }
08061 
08062         float height;
08063         if(params.has_key("height")) {
08064                 height = params["height"];
08065                 if(height > nz) {
08066                         throw InvalidValueException(radius, "height must be <= nz");
08067                 }
08068         }
08069         else {
08070                 height = static_cast<float>(nz);
08071         }
08072 
08073         float *dat = image->get_data();
08074         float x2, y2; //this is coordinates of this pixel from center axle
08075         float r = 0.0f;
08076         for (int k = 0; k < nz; ++k) {
08077                 for (int j = 0; j < ny; ++j) {
08078                         for (int i = 0; i < nx; ++i, ++dat) {
08079                                 x2 = fabs((float)i - nx/2);
08080                                 y2 = fabs((float)j - ny/2);
08081                                 r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius);
08082 
08083                                 if(r<=1 && k>=(nz-height)/2 && k<=(nz+height)/2) {
08084                                         *dat = 1;
08085                                 }
08086                                 else {
08087                                         *dat = 0;
08088                                 }
08089                         }
08090                 }
08091         }
08092 
08093         image->update();
08094 }
08095 
08096 void RampProcessor::process_inplace(EMData * image)
08097 {
08098         if (!image) {
08099                 return;
08100         }
08101 
08102         int nz = image->get_zsize();
08103         if (nz > 1) {
08104                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
08105                 throw ImageDimensionException("3D model not supported");
08106         }
08107 
08108         int nsam = image->get_xsize();
08109         int nrow = image->get_ysize();
08110         int n1 = nsam / 2;
08111         double sx1 = double(n1)*double(nsam+1);
08112         if ( nsam % 2 == 1 )
08113                 sx1 += 1 + n1;
08114         sx1 *= nrow;
08115         int n2 = nrow / 2;
08116         double sx2 = double(n2)*double(nrow+1);
08117         if ( nrow % 2 == 1 )
08118                 sx2 += 1 + n2;
08119         sx2 *= nsam;
08120         float *data = image->get_data();
08121         float *row = NULL; // handy pointer for values in a specific row of the data
08122         // statistical sums
08123         double syx1 = 0, syx2 = 0, sy = 0, sx1q = 0, sx2q = 0, syq = 0;
08124         for (int j=1; j <= nrow; j++) {
08125                 row = data + (j-1)*nsam - 1; // "-1" so that we can start counting at 1
08126                 for (int i=1; i<=nsam; i++) {
08127                         syx1 += row[i]*i;
08128                         syx2 += row[i]*j;
08129                         sy += row[i];
08130                         sx1q += i*i;
08131                         sx2q += j*j;
08132                         syq += row[i]*double(row[i]);
08133                 }
08134         }
08135         // least-squares
08136         float dn = float(nsam)*float(nrow);
08137         double qyx1 = syx1 - sx1*sy / dn;
08138         double qyx2 = syx2 - sx2*sy / dn;
08139         double qx1x2 = 0.0;
08140         double qx1 = sx1q - sx1*sx1 / dn;
08141         double qx2 = sx2q - sx2*sx2 / dn;
08142         double qy = syq - sy*sy / dn;
08143         double c = qx1*qx2 - qx1x2*qx1x2;
08144         if ( c > FLT_EPSILON ) {
08145                 double b1 = (qyx1*qx2 - qyx2*qx1x2) / c;
08146                 double b2 = (qyx2*qx1 - qyx1*qx1x2) / c;
08147                 double a = (sy - b1*sx1 - b2*sx2) / dn;
08148                 double d = a + b1 + b2;
08149                 for (int i=1; i<=nrow; i++) {
08150                         qy = d;
08151                         row = data + (i-1)*nsam - 1;
08152                         for (int k=1; k<=nsam; k++) {
08153                                 row[k] -= static_cast<float>(qy);
08154                                 qy += b1;
08155                         }
08156                         d += b2;
08157                 }
08158         } // image not altered if c is zero
08159 
08160         image->update();
08161 }
08162 
08163 
08164 void CCDNormProcessor::process_inplace(EMData * image)
08165 {
08166         if (!image) {
08167           Log::logger()->set_level(Log::ERROR_LOG);
08168           Log::logger()->error("Null image during call to CCDNorm\n");
08169           return;
08170         }
08171         if (image->get_zsize() > 1) {
08172           Log::logger()->set_level(Log::ERROR_LOG);
08173           Log::logger()->error("CCDNorm does not support 3d images\n");
08174           return;
08175         }
08176 
08177         int xs = image->get_xsize();
08178         int ys = image->get_ysize();
08179 
08180         // width of sample area on either side of the seams
08181         int width = params["width"];
08182 
08183         width%=(xs > ys ? xs/2 : ys/2);  // make sure width is a valid value
08184         if (width==0) {
08185           width=1;
08186         }
08187 
08188         // get the 4 "seams" of the image
08189         float *left, *right, *top, *bottom;
08190 
08191         double *temp;
08192         temp= (double*)malloc((xs > ys ? xs*width : ys*width)*sizeof(double));
08193         if (temp==NULL) {
08194           Log::logger()->set_level(Log::ERROR_LOG);
08195           Log::logger()->error("Could not allocate enough memory during call to CCDNorm\n");
08196           return;
08197         }
08198 
08199         int x, y, z;
08200 
08201         // the mean values of each seam and the average
08202         double mL,mR,mT,mB;
08203 
08204         // how much to shift each seam
08205         double nl,nr,nt,nb;
08206 
08207         // quad. shifting amount
08208         double q1,q2,q3,q4;
08209 
08210         // calc. the mean for each quadrant
08211         for (z=0; z<width; z++) {
08212           left = image->get_col(xs/2 -1-z)->get_data();
08213           for (y=0; y<ys; y++)
08214             temp[z*ys+y]=left[y];
08215         }
08216         mL=gsl_stats_mean(temp,1,ys*width);
08217 
08218         for (z=0; z<width; z++) {
08219           right = image->get_col(xs/2 +z)->get_data();
08220           for (y=0; y<ys; y++)
08221             temp[z*ys+y]=right[y];
08222         }
08223         mR=gsl_stats_mean(temp,1,ys*width);
08224 
08225         for (z=0; z<width; z++) {
08226           top = image->get_row(ys/2 -1-z)->get_data();
08227           for (x=0; x<xs; x++)
08228             temp[z*xs+x]=top[x];
08229         }
08230         mT=gsl_stats_mean(temp,1,xs*width);
08231 
08232         for (z=0; z<width; z++) {
08233           bottom = image->get_row(ys/2 +z)->get_data();
08234           for (x=0; x<xs; x++)
08235             temp[z*xs+x]=bottom[x];
08236         }
08237         mB=gsl_stats_mean(temp,1,xs*width);
08238 
08239         free(temp);
08240 
08241         nl=(mL+mR)/2-mL;
08242         nr=(mL+mR)/2-mR;
08243         nt=(mT+mB)/2-mT;
08244         nb=(mT+mB)/2-mB;
08245 
08246         q1=nl+nt;
08247         q2=nr+nt;
08248         q3=nr+nb;
08249         q4=nl+nb;
08250 
08251         // change the pixel values
08252         for (x = 0; x < xs / 2; x++)
08253           for (y = 0; y < ys / 2; y++) {
08254             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q1));
08255           }
08256         for (x = xs / 2; x < xs; x++)
08257           for (y = 0; y < ys / 2; y++) {
08258             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q2));
08259           }
08260         for (x = xs / 2; x < xs; x++)
08261           for (y = ys / 2; y < ys; y++) {
08262             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q3));
08263           }
08264         for (x = 0; x < xs / 2; x++)
08265           for (y = ys / 2; y < ys; y++) {
08266             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q4));
08267           }
08268 
08269 }
08270 
08271 void WaveletProcessor::process_inplace(EMData *image)
08272 {
08273         if (image->get_zsize() != 1) {
08274                         LOGERR("%s Processor doesn't support 3D", get_name().c_str());
08275                         throw ImageDimensionException("3D model not supported");
08276         }
08277 
08278         int i,nx,ny;
08279         const gsl_wavelet_type * T;
08280         nx=image->get_xsize();
08281         ny=image->get_ysize();
08282 
08283         if (nx != ny && ny!=1) throw ImageDimensionException("Wavelet transform only supports square images");
08284 //      float l=log((float)nx)/log(2.0f);
08285 //      if (l!=floor(l)) throw ImageDimensionException("Wavelet transform size must be power of 2");
08286         if( !Util::IsPower2(nx) )  throw ImageDimensionException("Wavelet transform size must be power of 2");
08287 
08288         // Unfortunately GSL works only on double() arrays
08289         // eventually we should put our own wavelet code in here
08290         // but this will work for now
08291         double *cpy = (double *)malloc(nx*ny*sizeof(double));
08292 
08293         for (i=0; i<nx*ny; i++) cpy[i]=image->get_value_at(i,0,0);
08294 
08295         string tp = (const char*)params["type"];
08296         if (tp=="daub") T=gsl_wavelet_daubechies;
08297         else if (tp=="harr") T=gsl_wavelet_haar;
08298         else if (tp=="bspl") T=gsl_wavelet_bspline;
08299         else throw InvalidStringException(tp,"Invalid wavelet name, 'daub', 'harr' or 'bspl'");
08300 
08301         int K=(int)params["ord"];
08302         gsl_wavelet_direction dir;
08303         if ((int)params["dir"]==1) dir=forward;
08304         else dir=backward;
08305 
08306         gsl_wavelet *w = gsl_wavelet_alloc(T, K);
08307         gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(nx);
08308 
08309         if (ny==1) gsl_wavelet_transform (w,cpy, 1, nx, dir, work);
08310         else gsl_wavelet2d_transform (w, cpy, nx,nx,ny, dir, work);
08311 
08312         gsl_wavelet_workspace_free (work);
08313         gsl_wavelet_free (w);
08314 
08315         for (i=0; i<nx*ny; i++) image->set_value_at_fast(i,0,0,static_cast<float>(cpy[i]));
08316 
08317         free(cpy);
08318 }
08319 
08320 void FFTProcessor::process_inplace(EMData* image)
08321 {
08322         if( params.has_key("dir") ) {
08323                 if ((int)params["dir"]==-1) {
08324                         image->do_ift_inplace();
08325                 }
08326                 else {
08327                         image->do_fft_inplace();
08328                 }
08329         }
08330 }
08331 
08332 void RadialProcessor::process_inplace(EMData * image)
08333 {
08334         if (!image) {
08335                 LOGWARN("NULL Image");
08336                 return;
08337         }
08338 
08339         //Note : real image only!
08340         if(image->is_complex()) {
08341                 LOGERR("%s Processor only operates on real images", get_name().c_str());
08342                 throw ImageFormatException("apply to real image only");
08343         }
08344 
08345         vector<float> table = params["table"];
08346         vector<float>::size_type tsize = table.size();
08347 
08348         int nx = image->get_xsize();
08349         int ny = image->get_ysize();
08350         int nz = image->get_zsize();
08351 
08352         int nx2 = nx / 2;
08353         int ny2 = ny / 2;
08354         int nz2 = nz / 2;
08355         float sz[3];
08356         sz[0] = static_cast<float>(nx2);
08357         sz[1] = static_cast<float>(ny2);
08358         sz[2] = static_cast<float>(nz2);
08359         float szmax = *std::max_element(&sz[0], &sz[3]);
08360         float maxsize;
08361         if(nz>1) {
08362                 maxsize = (float)(1.8f * szmax);
08363         }
08364         else{
08365                 maxsize = (float)(1.5f * szmax);
08366         }
08367         for(int i=tsize+1; i<maxsize; i++) {
08368                 table.push_back(0.0f);
08369         }
08370 
08371         float dx = 1.0f / (float)nx;
08372         float dy = 1.0f / (float)ny;
08373         float dz = 1.0f / (float)nz;
08374         float dx2 = dx * dx;
08375         float dy2 = dy * dy;
08376         float dz2 = dz * dz;
08377         int iz, iy, ix, jz, jy, jx;
08378         float argx, argy, argz;
08379         float rf, df, f;
08380         int ir;
08381         for(iz=1; iz<=nz; iz++) {
08382                 jz = iz - 1;
08383                 if(jz > nz2) {
08384                         jz -= nz;
08385                 }
08386                 argz = float(jz*jz) * dz2;
08387 
08388                 for(iy=1; iy<=ny; iy++) {
08389                         jy = iy - 1;
08390                         if(jy > ny2) {
08391                                 jy -= ny;
08392                         }
08393                         argy = argz + float(jy*jy) * dy2;
08394 
08395                         for(ix=1; ix<=nx; ix++) {
08396                                 jx = ix -1;
08397                                 argx = argy + float(jx*jx)*dx2;
08398 
08399                                 rf = sqrt(argx)*2.0f*nx2;
08400                                 ir = int(rf);
08401                                 df = rf - float(ir);
08402                                 f = table[ir] + df*(table[ir+1]-table[ir]);
08403 
08404                                 (*image)(ix-1,iy-1,iz-1) *= f;
08405                         }
08406                 }
08407         }
08408 
08409         image->update();
08410 }
08411 
08412 void MirrorProcessor::process_inplace(EMData *image)
08413 {
08414         if (!image) {
08415                 LOGWARN("NULL Image");
08416                 return;
08417         }
08418 
08419         string axis = (const char*)params["axis"];
08420 
08421         float* data = image->EMData::get_data();
08422 
08423         int nx = image->get_xsize();
08424         int ny = image->get_ysize();
08425         int nz = image->get_zsize();
08426         size_t nxy = nx*ny;
08427 
08428         int x_start = 1-nx%2;
08429         int y_start = 1-ny%2;
08430         int z_start = 1-nz%2;
08431 
08432         if (axis == "x" || axis == "X") {
08433                 for (int iz = 0; iz < nz; iz++)
08434                         for (int iy = 0; iy < ny; iy++) {
08435                                 int offset = nx*iy + nxy*iz;
08436                                 reverse(&data[offset+x_start],&data[offset+nx]);
08437                         }
08438         } else if (axis == "y" || axis == "Y") {
08439                 float *tmp = new float[nx];
08440                 int nhalf   = ny/2;
08441                 size_t beg     = 0;
08442                 for (int iz = 0; iz < nz; iz++) {
08443                         beg = iz*nxy;
08444                         for (int iy = y_start; iy < nhalf; iy++) {
08445                                 memcpy(tmp, &data[beg+iy*nx], nx*sizeof(float));
08446                                 memcpy(&data[beg+iy*nx], &data[beg+(ny-iy-1+y_start)*nx], nx*sizeof(float));
08447                                 memcpy(&data[beg+(ny-iy-1+y_start)*nx], tmp, nx*sizeof(float));
08448                         }
08449                 }
08450                 delete[] tmp;
08451         } else if (axis == "z" || axis == "Z") {
08452                 if(1-z_start) {
08453                         int nhalf = nz/2;
08454                         float *tmp = new float[nxy];
08455                         for(int iz = 0;iz<nhalf;iz++){
08456                                 memcpy(tmp,&data[iz*nxy],nxy*sizeof(float));
08457                                 memcpy(&data[iz*nxy],&data[(nz-iz-1)*nxy],nxy*sizeof(float));
08458                                 memcpy(&data[(nz-iz-1)*nxy],tmp,nxy*sizeof(float));
08459                         }
08460                         delete[] tmp;
08461                 } else {
08462                         float *tmp = new float[nx];
08463                         int nhalf   = nz/2;
08464                         size_t beg     = 0;
08465                         for (int iy = 0; iy < ny; iy++) {
08466                                 beg = iy*nx;
08467                                 for (int iz = z_start; iz < nhalf; iz++) {
08468                                         memcpy(tmp, &data[beg+ iz*nxy], nx*sizeof(float));
08469                                         memcpy(&data[beg+iz*nxy], &data[beg+(nz-iz-1+z_start)*nxy], nx*sizeof(float));
08470                                         memcpy(&data[beg+(nz-iz-1+z_start)*nxy], tmp, nx*sizeof(float));
08471                                 }
08472                         }
08473                         delete[] tmp;
08474                 }
08475         }
08476 
08477         image->update();
08478 }
08479 
08480 
08481 int EMAN::multi_processors(EMData * image, vector < string > processornames)
08482 {
08483         Assert(image != 0);
08484         Assert(processornames.size() > 0);
08485 
08486         for (size_t i = 0; i < processornames.size(); i++) {
08487                 image->process_inplace(processornames[i]);
08488         }
08489         return 0;
08490 }
08491 
08492 
08493 float* TransformProcessor::transform(const EMData* const image, const Transform& t) const {
08494 
08495         ENTERFUNC;
08496 
08497         Transform inv = t.inverse();
08498         int nx = image->get_xsize();
08499         int ny = image->get_ysize();
08500         int nz = image->get_zsize();
08501         int nxy = nx*ny;
08502 
08503         const float * const src_data = image->get_const_data();
08504         float *des_data = (float *) EMUtil::em_malloc(nx*ny*nz* sizeof(float));
08505 
08506         if (nz == 1) {
08507                 Vec2f offset(nx/2,ny/2);
08508                 for (int j = 0; j < ny; j++) {
08509                         for (int i = 0; i < nx; i++) {
08510                                 Vec2f coord(i-nx/2,j-ny/2);
08511                                 Vec2f soln = inv*coord;
08512                                 soln += offset;
08513 
08514                                 float x2 = soln[0];
08515                                 float y2 = soln[1];
08516 
08517                                 if (x2 < 0 || x2 >= nx || y2 < 0 || y2 >= ny ) {
08518                                         des_data[i + j * nx] = 0; // It may be tempting to set this value to the
08519                                         // mean but in fact this is not a good thing to do. Talk to S.Ludtke about it.
08520                                 }
08521                                 else {
08522                                         int ii = Util::fast_floor(x2);
08523                                         int jj = Util::fast_floor(y2);
08524                                         int k0 = ii + jj * nx;
08525                                         int k1 = k0 + 1;
08526                                         int k2 = k0 + nx;
08527                                         int k3 = k0 + nx + 1;
08528 
08529                                         if (ii == nx - 1) {
08530                                                 k1--;
08531                                                 k3--;
08532                                         }
08533                                         if (jj == ny - 1) {
08534                                                 k2 -= nx;
08535                                                 k3 -= nx;
08536                                         }
08537 
08538                                         float t = x2 - ii;
08539                                         float u = y2 - jj;
08540 
08541                                         des_data[i + j * nx] = Util::bilinear_interpolate(src_data[k0],src_data[k1], src_data[k2], src_data[k3],t,u);
08542                                 }
08543                         }
08544                 }
08545         }
08546         else {
08547                 size_t l=0, ii, k0, k1, k2, k3, k4, k5, k6, k7;
08548                 Vec3f offset(nx/2,ny/2,nz/2);
08549                 float x2, y2, z2, tuvx, tuvy, tuvz;
08550                 int ix, iy, iz;
08551                 for (int k = 0; k < nz; ++k) {
08552                         for (int j = 0; j < ny; ++j) {
08553                                 for (int i = 0; i < nx; ++i,++l) {
08554                                         Vec3f coord(i-nx/2,j-ny/2,k-nz/2);
08555                                         Vec3f soln = inv*coord;
08556                                         soln += offset;
08557 
08558                                         x2 = soln[0];
08559                                         y2 = soln[1];
08560                                         z2 = soln[2];
08561 
08562                                         if (x2 < 0 || y2 < 0 || z2 < 0 || x2 >= nx  || y2 >= ny  || z2>= nz ) {
08563                                                 des_data[l] = 0;
08564                                         }
08565                                         else {
08566                                                 ix = Util::fast_floor(x2);
08567                                                 iy = Util::fast_floor(y2);
08568                                                 iz = Util::fast_floor(z2);
08569                                                 tuvx = x2-ix;
08570                                                 tuvy = y2-iy;
08571                                                 tuvz = z2-iz;
08572                                                 ii = ix + iy * nx + iz * nxy;
08573 
08574                                                 k0 = ii;
08575                                                 k1 = k0 + 1;
08576                                                 k2 = k0 + nx;
08577                                                 k3 = k0 + nx+1;
08578                                                 k4 = k0 + nxy;
08579                                                 k5 = k1 + nxy;
08580                                                 k6 = k2 + nxy;
08581                                                 k7 = k3 + nxy;
08582 
08583                                                 if (ix == nx - 1) {
08584                                                         k1--;
08585                                                         k3--;
08586                                                         k5--;
08587                                                         k7--;
08588                                                 }
08589                                                 if (iy == ny - 1) {
08590                                                         k2 -= nx;
08591                                                         k3 -= nx;
08592                                                         k6 -= nx;
08593                                                         k7 -= nx;
08594                                                 }
08595                                                 if (iz == nz - 1) {
08596                                                         k4 -= nxy;
08597                                                         k5 -= nxy;
08598                                                         k6 -= nxy;
08599                                                         k7 -= nxy;
08600                                                 }
08601 
08602                                                 des_data[l] = Util::trilinear_interpolate(src_data[k0],
08603                                                                 src_data[k1], src_data[k2], src_data[k3], src_data[k4],
08604                                                                 src_data[k5], src_data[k6],     src_data[k7], tuvx, tuvy, tuvz);
08605                                         }
08606                                 }
08607                         }
08608                 }
08609         }
08610 
08611         EXITFUNC;
08612         return des_data;
08613 }
08614 
08615 void TransformProcessor::assert_valid_aspect(const EMData* const image) const {
08616         int ndim = image->get_ndim();
08617         if (ndim != 2 && ndim != 3) throw ImageDimensionException("Transforming an EMData only works if it's 2D or 3D");
08618 
08619         if (! params.has_key("transform") ) throw InvalidParameterException("You must specify a Transform in order to perform this operation");
08620 }
08621 
08622 //void TransformProcessor::update_emdata_attributes(EMData* const p, const Dict& attr_dict, const float& scale) const {
08623 //
08624 //      float inv_scale = 1.0f/scale;
08625 //
08626 //      p->scale_pixel(1.0f/scale);
08627 //
08628 //      // According to Baker the origin attributes remain unchanged
08639 //
08640 //      vector<string> scale_attrs;
08641 //      scale_attrs.push_back("apix_x");
08642 //      scale_attrs.push_back("apix_y");
08643 //      scale_attrs.push_back("apix_z");
08644 //
08645 //
08646 //      for(vector<string>::const_iterator it = scale_attrs.begin(); it != scale_attrs.end(); ++it) {
08647 //              if (attr_dict.has_key(*it)) {
08648 //                      p->set_attr(*it,(float) attr_dict[*it] * inv_scale);
08649 //              }
08650 //      }
08651 //
08652 //}
08653 
08654 EMData* TransformProcessor::process(const EMData* const image) {
08655         ENTERFUNC;
08656 
08657         assert_valid_aspect(image);
08658 
08659         Transform* t = params["transform"];
08660 
08661         EMData* p  = 0;
08662 #ifdef EMAN2_USING_CUDA
08663         if(EMData::usecuda == 1 && image->isrodataongpu()){     
08664                 //cout << "using CUDA xform" << endl;
08665                 p = new EMData(0,0,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict()); 
08666                 float * m = new float[12];
08667                 Transform inv = t->inverse();
08668                 inv.copy_matrix_into_array(m);
08669                 image->bindcudaarrayA(true);
08670                 p->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
08671                 image->unbindcudaarryA();
08672                 delete [] m;
08673                 p->update();
08674         }
08675 #endif
08676 
08677         if ( p == 0 ) {
08678                 float* des_data = transform(image,*t);
08679                 p = new EMData(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict());
08680         }
08681 
08682         //      all_translation += transform.get_trans();
08683 
08684         float scale = t->get_scale();
08685         if (scale != 1.0) {
08686                 p->scale_pixel(1.0f/scale);
08687 //              update_emdata_attributes(p,image->get_attr_dict(),scale);
08688         }
08689 
08690         if(t) {delete t; t=0;}
08691         EXITFUNC;
08692         return p;
08693 }
08694 
08695 void TransformProcessor::process_inplace(EMData* image) {
08696         ENTERFUNC;
08697 
08698         assert_valid_aspect(image);
08699 
08700         Transform* t = params["transform"];
08701 
08702         //      all_translation += transform.get_trans();
08703         bool use_cpu = true;
08704         
08705 #ifdef EMAN2_USING_CUDA
08706         if(EMData::usecuda == 1 && image->isrodataongpu()){
08707                 //cout << "CUDA xform inplace" << endl;
08708                 image->bindcudaarrayA(false);   
08709                 float * m = new float[12];
08710                 Transform inv = t->inverse();
08711                 inv.copy_matrix_into_array(m);  
08712                 image->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
08713                 image->unbindcudaarryA();
08714                 delete [] m;
08715                 use_cpu = false;
08716                 image->update();
08717         }
08718 #endif
08719         if ( use_cpu ) {
08720                 float* des_data = transform(image,*t);
08721                 image->set_data(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize());
08722                 image->update();
08723         }
08724         float scale = t->get_scale();
08725         if (scale != 1.0f) {
08726                 image->scale_pixel(1.0f/scale);
08727 //              update_emdata_attributes(image,image->get_attr_dict(),scale);
08728         }
08729 
08730         if(t) {delete t; t=0;}
08731 
08732         EXITFUNC;
08733 }
08734 
08735 
08736 void IntTranslateProcessor::assert_valid_aspect(const vector<int>& translation, const EMData* const) const {
08737         if (translation.size() == 0 ) throw InvalidParameterException("You must specify the trans argument");
08738 }
08739 
08740 Region IntTranslateProcessor::get_clip_region(vector<int>& translation, const EMData* const image) const {
08741         unsigned int dim = static_cast<unsigned int> (image->get_ndim());
08742 
08743         if ( translation.size() != dim ) {
08744                 for(unsigned int i = translation.size(); i < dim; ++i ) translation.push_back(0);
08745         }
08746 
08747         Region clip_region;
08748         if (dim == 1) {
08749                 clip_region = Region(-translation[0],image->get_xsize());
08750         } else if ( dim == 2 ) {
08751                 clip_region = Region(-translation[0],-translation[1],image->get_xsize(),image->get_ysize());
08752         } else if ( dim == 3 ) {
08753                 clip_region = Region(-translation[0],-translation[1],-translation[2],image->get_xsize(),image->get_ysize(),image->get_zsize());
08754         } else throw ImageDimensionException("Only 1,2 and 3D images are supported");
08755 
08756         return clip_region;
08757 }
08758 
08759 void IntTranslateProcessor::process_inplace(EMData* image) {
08760 
08761         vector<int> translation = params.set_default("trans",vector<int>() );
08762 
08763 
08764         assert_valid_aspect(translation,image);
08765 
08766         Region clip_region = get_clip_region(translation,image);
08767 
08768         image->clip_inplace(clip_region,0);
08769         // clip_inplace does the update!
08770 }
08771 
08772 EMData* IntTranslateProcessor::process(const EMData* const image) {
08773 
08774         vector<int> translation = params.set_default("trans",vector<int>() );
08775 
08776         assert_valid_aspect(translation,image);
08777 
08778         Region clip_region = get_clip_region(translation,image);
08779 
08780         return image->get_clip(clip_region,0);
08781         // clip_inplace does the update!
08782 }
08783 
08784 
08785 void ScaleTransformProcessor::process_inplace(EMData* image) {
08786         int ndim = image->get_ndim();
08787         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08788 
08789         if ( image->get_xsize() != image->get_ysize()) {
08790                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08791         }
08792         if ( ndim == 3 ) {
08793                 if ( image->get_xsize() != image->get_zsize()) {
08794                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08795                 }
08796         }
08797 
08798         float scale = params.set_default("scale",0.0f);
08799         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08800 
08801         int clip = 0;
08802 
08803         if(params.has_key("clip"))
08804         {
08805                 clip = params["clip"];
08806                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08807         }
08808         else
08809         {
08810                 clip = (int)(scale*image->get_xsize());
08811         }
08812 
08813         Region r;
08814         if (ndim == 3) {
08815                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08816         } else { // ndim == 2 guaranteed by check at beginning of function
08817                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08818         }
08819 
08820         if (scale > 1) {
08821                 if ( clip != 0) {
08822                         image->clip_inplace(r);
08823                 }
08824                 Transform t;
08825                 t.set_scale(scale);
08826                 image->process_inplace("xform",Dict("transform",&t));
08827         } else if (scale < 1) {
08828                 Transform t;
08829                 t.set_scale(scale);
08830                 image->process_inplace("xform",Dict("transform",&t));
08831                 if ( clip != 0) {
08832                         image->clip_inplace(r);
08833                 }
08834         } else {
08835                 if ( clip != 0) {
08836                         image->clip_inplace(r);
08837                 }
08838         }
08839 }
08840 
08841 EMData* ScaleTransformProcessor::process(const EMData* const image) {
08842         int ndim = image->get_ndim();
08843         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08844 
08845         if ( image->get_xsize() != image->get_ysize()) {
08846                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08847         }
08848         if ( ndim == 3 ) {
08849                 if ( image->get_xsize() != image->get_zsize()) {
08850                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08851                 }
08852         }
08853 
08854         float scale = params.set_default("scale",0.0f);
08855         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08856 
08857         int clip = 0;
08858 
08859         if(params.has_key("clip"))
08860         {
08861                 clip = params["clip"];
08862                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08863         }
08864         else
08865         {
08866                 clip = (int)(scale*image->get_xsize());
08867         }
08868 
08869         Region r;
08870         if (ndim == 3) {
08871                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08872         } else { // ndim == 2 guaranteed by check at beginning of function
08873                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08874         }
08875 
08876         EMData* ret = 0;
08877         if (scale > 1) {
08878                 if ( clip != 0) {
08879                         ret = image->get_clip(r);
08880                 }
08881                 Transform t;
08882                 t.set_scale(scale);
08883                 if (ret != 0) {
08884                         ret->process_inplace("xform",Dict("transform",&t));
08885                 } else {
08886                         ret = image->process("xform",Dict("transform",&t));
08887                 }
08888         } else if (scale < 1) {
08889                 Transform t;
08890                 t.set_scale(scale);
08891                 ret = image->process("xform",Dict("transform",&t));
08892                 if ( clip != 0) {
08893                         ret->clip_inplace(r);
08894                 }
08895         } else {
08896                 if ( clip != 0) {
08897                         ret = image->get_clip(r);
08898                 } else {
08899                         ret = image->copy();
08900                 }
08901         }
08902         return ret;
08903 
08904 }
08905 
08906 void Rotate180Processor::process_inplace(EMData* image) {
08907         ENTERFUNC;
08908 
08909 
08910         if (image->get_ndim() != 2) {
08911                 throw ImageDimensionException("2D only");
08912         }
08913 
08914 #ifdef EMAN2_USING_CUDA
08915         if (EMData::usecuda == 1 && image->getcudarwdata()) {
08916                 //cout << "CUDA rotate 180" << endl;
08917                 emdata_rotate_180(image->getcudarwdata(), image->get_xsize(), image->get_ysize());
08918                 EXITFUNC;
08919                 return;
08920         }
08921 #endif
08922 
08923         float *d = image->get_data();
08924         int nx = image->get_xsize();
08925         int ny = image->get_ysize();
08926 
08927         // x and y offsets are used to handle even vs odd cases
08928         int x_offset = 0;
08929         if (nx % 2 == 1) x_offset=1;
08930         int y_offset = 0;
08931         if (ny % 2 == 1) y_offset=1;
08932 
08933         bool stop = false;
08934         for (int x = 1; x <= (nx/2+x_offset); x++) {
08935                 int y = 0;
08936                 for (y = 1; y < (ny+y_offset); y++) {
08937                         if (x == (nx / 2+x_offset) && y == (ny / 2+y_offset)) {
08938                                 stop = true;
08939                                 break;
08940                         }
08941                         int i = (x-x_offset) + (y-y_offset) * nx;
08942                         int k = nx - x + (ny - y) * nx;
08943 
08944                         float t = d[i];
08945                         d[i] = d[k];
08946                         d[k] = t;
08947                 }
08948                 if (stop) break;
08949         }
08950 
08951         /* Here we guard against irregularites that occur at the boundaries
08952          * of even dimensioned images. The basic policy is to replace the pixel
08953          * in row 0 and/or column 0 with those in row 1 and/or column 1, respectively.
08954          * The pixel at 0,0 is replaced with the pixel at 1,1 if both image dimensions
08955          * are even. FIXME - it may be better to use an average at the corner, in
08956          * this latter case, using pixels (1,1), (0,1) and (1,0). I am not sure. (dsawoolford)
08957         */
08958         if (x_offset == 0) {
08959                 for (int y = 0; y < ny; y++) {
08960                         image->set_value_at_fast(0,y,image->get_value_at(1,y));
08961                 }
08962         }
08963 
08964         if (y_offset == 0) {
08965                 for (int x = 0; x < nx; x++) {
08966                         image->set_value_at_fast(x,0,image->get_value_at(x,1));
08967                 }
08968         }
08969 
08970         if (y_offset == 0 && x_offset == 0) {
08971                 image->set_value_at_fast(0,0,image->get_value_at(1,1));
08972         }
08973 
08974         image->update();
08975         EXITFUNC;
08976 }
08977 
08978 
08979 void ClampingProcessor::process_inplace( EMData* image )
08980 {
08981 
08982         if ( image->is_complex() ) throw ImageFormatException("Error: clamping processor does not work on complex images");
08983 
08984         float min = params.set_default("minval",default_min);
08985         float max = params.set_default("maxval",default_max);
08986         bool tomean = params.set_default("tomean",false);
08987         bool tozero = params.set_default("tozero",false);
08988         float new_min_vals = min;
08989         float new_max_vals = max;
08990         if (tomean) new_min_vals = new_max_vals = image->get_attr("mean");
08991         if (tozero) new_min_vals = new_max_vals = 0.0;
08992 
08993         // Okay, throwing such an error is probably overkill - but atleast the user will get a loud message
08994         // saying what went wrong.
08995         if ( max < min ) throw InvalidParameterException("Error: minval was greater than maxval, aborting");
08996 
08997         size_t size = image->get_size();
08998         for(size_t i = 0; i < size; ++i )
08999         {
09000                 float * data = &image->get_data()[i];
09001                 if ( *data < min ) *data = new_min_vals;
09002                 else if ( *data > max ) *data = new_max_vals;
09003         }
09004         image->update();
09005 }
09006 
09007 void TestTomoImage::insert_rectangle( EMData* image, const Region& region, const float& value, const Transform& t3d )
09008 {
09009         int startx = (int)region.origin[0] - (int)region.size[0]/2;
09010         int starty = (int)region.origin[1] - (int)region.size[1]/2;
09011         int startz = (int)region.origin[2] - (int)region.size[2]/2;
09012 
09013         int endx  = (int)region.origin[0] + (int)region.size[0]/2;
09014         int endy  = (int)region.origin[1] + (int)region.size[1]/2;
09015         int endz  = (int)region.origin[2] + (int)region.size[2]/2;
09016 
09017         if ( ! t3d.is_identity() ) {
09018                 float xt, yt, zt;
09019                 for ( float z = (float)startz; z < (float)endz; z += 0.25f ) {
09020                         for ( float y = (float)starty; y < (float)endy; y += 0.25f ) {
09021                                 for ( float x = (float)startx; x < (float)endx; x += 0.25f ) {
09022                                         xt = (float) x - region.origin[0];
09023                                         yt = (float) y - region.origin[1];
09024                                         zt = (float) z - region.origin[2];
09025                                         Vec3f v((float)xt,(float)yt,(float)zt);
09026                                         v = t3d*v;
09027                                         image->set_value_at((int)(v[0]+region.origin[0]),(int)(v[1]+region.origin[1]),(int)(v[2]+region.origin[2]), value);
09028                                 }
09029                         }
09030                 }
09031         } else {
09032                 for ( int z = startz; z < endz; ++z ) {
09033                         for ( int y = starty; y < endy; ++y ) {
09034                                 for ( int x = startx; x < endx; ++x ) {
09035                                         image->set_value_at(x,y,z, value);
09036                                 }
09037                         }
09038                 }
09039         }
09040 }
09041 
09042 void TestTomoImage::process_inplace( EMData* image )
09043 {
09044         //float nx = 240;
09045         //float ny = 240;
09046         //float nz = 60;
09047 
09048         //image->set_size((int)nx,(int)ny,(int)nz);
09049         float nx = (float) image->get_xsize();
09050         float ny = (float) image->get_ysize();
09051         float nz = (float) image->get_zsize();
09052 
09053         // This increment is used to simplified positioning
09054         // It's an incremental factor that matches the grid size of the paper
09055         // that I drew this design on before implementing it in code
09056         float inc = 1.0f/22.0f;
09057         float xinc = inc;
09058         float yinc = inc;
09059         float zinc = inc;
09060 
09061         Dict d;
09062         d["a"] = (float) .4*nx+3;
09063         d["b"] = (float) .4*ny+3;
09064         d["c"] = (float) .4*nz+3;
09065         d["fill"] = 0.2;
09066         image->process_inplace("testimage.ellipsoid",d);
09067 
09068         d["a"] = (float) .4*nx;
09069         d["b"] = (float) .4*ny;
09070         d["c"] = (float) .4*nz;
09071         d["fill"] = 0.1;
09072         image->process_inplace("testimage.ellipsoid",d);
09073 
09074         // Center x, center z, bottom y ellipsoids that grow progessively smaller
09075         {
09076                 Transform t;
09077                 t.set_trans(0.,ny*4.0f*yinc-ny/2,0);
09078                 Dict d;
09079                 d["transform"] = &t;
09080                 d["a"] = (float) 2.*xinc*nx;
09081                 d["b"] = (float)0.5*yinc*ny;
09082                 d["c"] = (float) 1.*zinc*nz;
09083                 d["fill"] = 0.3;
09084                 image->process_inplace("testimage.ellipsoid",d);
09085         }
09086 
09087         {
09088                 Transform t;
09089                 t.set_trans(0.,ny*5.5f*yinc-ny/2,0);
09090                 Dict d;
09091                 d["transform"] = &t;
09092                 d["a"] = (float) 1.5*xinc*nx;
09093                 d["b"] = (float)0.5*yinc*ny;
09094                 d["c"] = (float) 1.*zinc*nz;
09095                 d["fill"] = 0.0;
09096                 image->process_inplace("testimage.ellipsoid",d);
09097         }
09098         {
09099                 Transform t;
09100                 t.set_trans(0.,ny*7*yinc-ny/2,0);
09101                 Dict d;
09102                 d["transform"] = &t;
09103                 d["a"] = (float) 1.*xinc*nx;
09104                 d["b"] = (float)0.5*yinc*ny;
09105                 d["c"] = (float) 1.*zinc*nz;
09106                 d["fill"] = 0.3;
09107                 image->process_inplace("testimage.ellipsoid",d);
09108         }
09109 
09110 
09111         {
09112                 Transform t;
09113                 t.set_trans(0.,ny*8.5f*yinc-ny/2,0);
09114                 Dict d;
09115                 d["transform"] = &t;
09116                 d["a"] = (float) .75*xinc*nx;
09117                 d["b"] = (float)0.5*yinc*ny;
09118                 d["c"] = (float) 1.*zinc*nz;
09119                 d["fill"] = 0.0;
09120                 image->process_inplace("testimage.ellipsoid",d);
09121         }
09122 
09123         // Center x, center z, bottom y ellipsoids that grow progessively smaller
09124         {
09125                 Transform t;
09126                 t.set_trans(0.,ny*18*yinc-ny/2,0);
09127                 Dict d;
09128                 d["transform"] = &t;
09129                 d["a"] = (float) 2*xinc*nx;
09130                 d["b"] = (float)0.5*yinc*ny;
09131                 d["c"] = (float) 1.*zinc*nz;
09132                 d["fill"] = 0.3;
09133                 image->process_inplace("testimage.ellipsoid",d);
09134         }
09135 
09136         {
09137                 Transform t;
09138                 t.set_trans(0.,ny*16.5f*yinc-ny/2,0);
09139                 Dict d;
09140                 d["transform"] = &t;
09141                 d["a"] = (float) 1.5*xinc*nx;
09142                 d["b"] = (float)0.5*yinc*ny;
09143                 d["c"] = (float) 1.*zinc*nz;
09144                 d["fill"] = 0.3;
09145                 image->process_inplace("testimage.ellipsoid",d);
09146         }
09147 
09148         {
09149                 Transform t;
09150                 t.set_trans(0.,ny*15*yinc-ny/2,0);
09151                 Dict d;
09152                 d["transform"] = &t;
09153                 d["a"] = (float) 1*xinc*nx;
09154                 d["b"] = (float)0.5*yinc*ny;
09155                 d["c"] = (float) 1.*zinc*nz;
09156                 d["fill"] = 0.3f;
09157                 image->process_inplace("testimage.ellipsoid",d);
09158         }
09159 
09160         {
09161                 Transform t;
09162                 t.set_trans(0.,ny*13.5f*yinc-ny/2,0);
09163                 Dict d;
09164                 d["transform"] = &t;
09165                 d["a"] = (float).75*xinc*nx;
09166                 d["b"] = (float)0.5*yinc*ny;
09167                 d["c"] = (float) 1.*zinc*nz;
09168                 d["fill"] = 0.3;
09169                 image->process_inplace("testimage.ellipsoid",d);
09170         }
09171 
09172         // Left ellipsoids from the bottom up
09173         {
09174 
09175                 Transform t;
09176                 t.set_trans(nx*6*xinc-nx/2,ny*5*yinc-ny/2,0);
09177                 Dict d;
09178                 d["transform"] = &t;
09179                 d["a"] = (float)1*xinc*nx;
09180                 d["b"] = (float).75*yinc*ny;
09181                 d["c"] = (float) .75*zinc*nz;
09182                 d["fill"] = 0.25;
09183                 image->process_inplace("testimage.ellipsoid",d);
09184         }
09185 
09186         {
09187                 Transform t;
09188                 t.set_trans(nx*6*xinc-nx/2,ny*7*yinc-ny/2,0);
09189                 Dict d;
09190                 d["transform"] = &t;
09191                 d["a"] = (float)1.5*xinc*nx;
09192                 d["b"] = (float).75*yinc*ny;
09193                 d["c"] = (float) .75*zinc*nz;
09194                 d["fill"] = 0.25;
09195                 image->process_inplace("testimage.ellipsoid",d);
09196         }
09197 
09198         {
09199                 Transform t;
09200                 t.set_trans(nx*6*xinc-nx/2,ny*9*yinc-ny/2,0);
09201                 Dict d;
09202                 d["transform"] = &t;
09203                 d["a"] = (float)2*xinc*nx;
09204                 d["b"] = (float).75*yinc*ny;
09205                 d["c"] = (float) .75*zinc*nz;
09206                 d["fill"] = 0.25;
09207                 image->process_inplace("testimage.ellipsoid",d);
09208         }
09209 
09210         {
09211                 Transform t;
09212                 t.set_trans(nx*6*xinc-nx/2,ny*11*yinc-ny/2,0);
09213                 Dict d;
09214                 d["transform"] = &t;
09215                 d["a"] = (float)2.5*xinc*nx;
09216                 d["b"] = (float).75*yinc*ny;
09217                 d["c"] = (float) 1*zinc*nz;
09218                 d["fill"] = 0.25;
09219                 image->process_inplace("testimage.ellipsoid",d);
09220         }
09221 
09222         {
09223                 Transform t;
09224                 t.set_trans(nx*6*xinc-nx/2,ny*13*yinc-ny/2,0);
09225                 Dict d;
09226                 d["transform"] = &t;
09227                 d["a"] = (float) 3*xinc*nx;
09228                 d["b"] = (float).75*yinc*ny;
09229                 d["c"] = (float) 1*zinc*nz;
09230                 d["fill"] = 0.25;
09231                 image->process_inplace("testimage.ellipsoid",d);
09232         }
09233 
09234         // Right rectangle from the top down
09235         {
09236                 Region region(nx*15.*inc,ny*17.*inc,nz/2.,1.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09237                 insert_rectangle(image, region, 0.25);
09238         }
09239         {
09240                 Region region(nx*15.*inc,ny*15.*inc,nz/2.,1.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
09241                 insert_rectangle(image, region, 0.25);
09242         }
09243         {
09244                 Region region(nx*15.*inc,ny*13.*inc,nz/2.,2.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09245                 insert_rectangle(image, region, 0.25);
09246         }
09247         {
09248                 Region region(nx*15.*inc,ny*11.*inc,nz/2.,2.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
09249                 insert_rectangle(image, region, 0.25);
09250         }
09251         {
09252                 Region region(nx*15.*inc,ny*9.*inc,nz/2.,3.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09253                 insert_rectangle(image, region, 0.25);
09254         }
09255 
09256         // Center rotated rectangle
09257         {
09258                 Region region(nx/2.,ny/2.,nz/2.,2.*inc*nx,2.5*inc*ny,1.*inc*nz);
09259                 Transform t3d(Dict("type","eman","az",(float)-25.0));
09260                 insert_rectangle(image, region, 0.4f, t3d);
09261         }
09262 
09263         // Rotated ellipsoids
09264         {
09265                 Transform t;
09266                 t.set_trans(nx*6.8f*xinc-nx/2,ny*16*yinc-ny/2,0);
09267                 Dict rot;
09268                 rot["type"] = "eman";
09269                 rot["az"] = 43.0f;
09270                 t.set_rotation(rot);
09271                 Dict d;
09272                 d["transform"] = &t;
09273                 d["a"] = (float) 1.5*xinc*nx;
09274                 d["b"] = (float) .5*yinc*ny;
09275                 d["c"] = (float) .5*zinc*nz;
09276                 d["fill"] = 0.2;
09277                 image->process_inplace("testimage.ellipsoid",d);
09278         }
09279         {
09280                 Transform t;
09281                 t.set_trans(nx*7.2f*xinc-nx/2,ny*16*yinc-ny/2,0);
09282                 Dict rot;
09283                 rot["type"] = "eman";
09284                 rot["az"] = 135.0f;
09285                 t.set_rotation(rot);
09286                 Dict d;
09287                 d["transform"] = &t;
09288                 d["a"] = (float) 1.5*xinc*nx;
09289                 d["b"] = (float) .5*yinc*ny;
09290                 d["c"] = (float) .5*zinc*nz;
09291                 d["fill"] = 0.3;
09292                 image->process_inplace("testimage.ellipsoid",d);
09293         }
09294 
09295         // Dense small ellipsoids
09296         {
09297                 Transform t;
09298                 t.set_trans(nx*3.5f*xinc-nx/2,ny*8*yinc-ny/2,0);
09299                 Dict d;
09300                 d["transform"] = &t;
09301                 d["a"] = (float) .5*xinc*nx;
09302                 d["b"] = (float) .5*yinc*ny;
09303                 d["c"] = (float) .5*zinc*nz;
09304                 d["fill"] = 2.05;
09305                 image->process_inplace("testimage.ellipsoid",d);
09306 
09307                 t.set_trans(nx*8*xinc-nx/2,ny*18*yinc-ny/2,0);
09308                 image->process_inplace("testimage.ellipsoid",d);
09309 
09310                 t.set_trans(nx*14*xinc-nx/2,ny*18.2f*yinc-ny/2,0);
09311                 image->process_inplace("testimage.ellipsoid",d);
09312 
09313                 t.set_trans(nx*18*xinc-nx/2,ny*14*yinc-ny/2,0);
09314                 image->process_inplace("testimage.ellipsoid",d);
09315 
09316                 t.set_trans(nx*17*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09317                 image->process_inplace("testimage.ellipsoid",d);
09318         }
09319 
09320 
09321         // Dense small rectangles
09322         {
09323                 Region region(nx*18.*inc,ny*11.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
09324                 Transform t3d(Dict("type","eman","az",(float)45.0));
09325                 insert_rectangle(image, region, 1.45f, t3d);
09326         }
09327         {
09328                 Region region(nx*3.*inc,ny*10.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
09329                 Transform t3d(Dict("type","eman","az",(float)45.0));
09330                 insert_rectangle(image, region, 1.45f, t3d);
09331         }
09332 
09333         // Insert small cluster of spheres
09334         {
09335                 Transform t;
09336                 t.set_trans(nx*14*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09337                 Dict d;
09338                 d["transform"] = &t;
09339                 d["a"] = (float) .5*xinc*nx;
09340                 d["b"] = (float) .5*yinc*ny;
09341                 d["c"] = (float) .5*zinc*nz;
09342                 d["fill"] = .35;
09343                 image->process_inplace("testimage.ellipsoid",d);
09344         }
09345         {
09346                 Transform t;
09347                 t.set_trans(nx*15*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09348                 Dict d;
09349                 d["transform"] = &t;
09350                 d["a"] = (float) .25*xinc*nx;
09351                 d["b"] = (float) .25*yinc*ny;
09352                 d["c"] = (float) .25*zinc*nz;
09353                 d["fill"] = .35;
09354                 image->process_inplace("testimage.ellipsoid",d);
09355 
09356                 t.set_trans(nx*13.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09357                 image->process_inplace("testimage.ellipsoid",d);
09358 
09359                 t.set_trans(nx*14.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09360                 image->process_inplace("testimage.ellipsoid",d);
09361 
09362                 t.set_trans(nx*15.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09363                 image->process_inplace("testimage.ellipsoid",d);
09364 
09365                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09366                 image->process_inplace("testimage.ellipsoid",d);
09367 
09368                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09369                 image->process_inplace("testimage.ellipsoid",d);
09370 
09371                 t.set_trans(nx*15*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09372                 image->process_inplace("testimage.ellipsoid",d);
09373 
09374                 t.set_trans(nx*16*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09375                 image->process_inplace("testimage.ellipsoid",d);
09376 
09377                 t.set_trans(nx*14.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09378                 image->process_inplace("testimage.ellipsoid",d);
09379 
09380                 t.set_trans(nx*15.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09381                 image->process_inplace("testimage.ellipsoid",d);
09382         }
09383         // Insert feducials around the outside of the "cell"
09384 //      for ( float i = 0.; i < 3.; i += 1. ) {
09385 //              for ( float j = 0.; j < 3.; j += 1. ) {
09386 //                      Region region(nx*2.+i*inc,ny*2.+j*inc,nz/2.,0.05*inc*nx,0.05*inc*ny,0.05*inc*nz);
09387 //                      insert_solid_ellipse(image, region, 2.0);
09388 //              }
09389 //      }
09390 
09391 }
09392 
09393 void NSigmaClampingProcessor::process_inplace(EMData *image)
09394 {
09395         float nsigma = params.set_default("nsigma",default_sigma);
09396         float sigma = image->get_attr("sigma");
09397         float mean = image->get_attr("mean");
09398         params.set_default("minval",mean - nsigma*sigma);
09399         params.set_default("maxval",mean + nsigma*sigma);
09400 
09401         ClampingProcessor::process_inplace(image);
09402 }
09403 
09404 void HistogramBin::process_inplace(EMData *image)
09405 {
09406         float min = image->get_attr("minimum");
09407         float max = image->get_attr("maximum");
09408         float nbins = (float)params.set_default("nbins",default_bins);
09409         bool debug = params.set_default("debug",false);
09410 
09411         vector<int> debugscores;
09412         if ( debug ) {
09413                 debugscores = vector<int>((int)nbins, 0);
09414         }
09415 
09416         if ( nbins < 0 ) throw InvalidParameterException("nbins must be greater than 0");
09417 
09418         float bin_width = (max-min)/nbins;
09419         float bin_val_offset = bin_width/2.0f;
09420 
09421         size_t size = image->get_size();
09422         float* dat = image->get_data();
09423 
09424         for(size_t i = 0; i < size; ++i ) {
09425                 float val = dat[i];
09426                 val -= min;
09427                 int bin = (int) (val/bin_width);
09428 
09429                 // This makes the last interval [] and not [)
09430                 if (bin == nbins) bin -= 1;
09431 
09432                 dat[i] = min + bin*bin_width + bin_val_offset;
09433                 if ( debug ) {
09434                         debugscores[bin]++;
09435                 }
09436         }
09437 
09438         if ( debug ) {
09439                 int i = 0;
09440                 for( vector<int>::const_iterator it = debugscores.begin(); it != debugscores.end(); ++it, ++i)
09441                         cout << "Bin " << i << " has " << *it << " pixels in it" << endl;
09442         }
09443 
09444 }
09445 void ConvolutionProcessor::process_inplace(EMData* image)
09446 {
09447         //bool complexflag = false;
09448         EMData* null = 0;
09449         EMData* with = params.set_default("with", null);
09450         if ( with == NULL ) throw InvalidParameterException("Error - the image required for the convolution is null");
09451 
09452         EMData* newimage = fourierproduct(image, with, CIRCULANT, CONVOLUTION, false);
09453 
09454         float* orig = image->get_data();
09455         float* work = newimage->get_data();
09456         int nx  = image->get_xsize();
09457         int ny  = image->get_ysize();
09458         int nz  = image->get_zsize();
09459         memcpy(orig,work,nx*ny*nz*sizeof(float));
09460         image->update();
09461 
09462         delete newimage;
09463 }
09464 
09465 void XGradientProcessor::process_inplace( EMData* image )
09466 {
09467         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09468 
09469         EMData* e = new EMData();
09470         int nx = image->get_xsize();
09471         int ny = image->get_ysize();
09472         int nz = image->get_zsize();
09473 
09474         if ( nz == 1 && ny == 1 ) {
09475                 if ( nx < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09476 
09477                 e->set_size(3,1,1);
09478                 e->set_value_at(0,-1);
09479                 e->set_value_at(2, 1);
09480 
09481                 Region r = Region(-nx/2+1,nx);
09482                 e->clip_inplace(r);
09483         } else if ( nz == 1 ) {
09484                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09485                 e->set_size(3,3,1);
09486                 e->set_value_at(0,0,-1);
09487                 e->set_value_at(0,1,-2);
09488                 e->set_value_at(0,2,-1);
09489 
09490                 e->set_value_at(2,0,1);
09491                 e->set_value_at(2,1,2);
09492                 e->set_value_at(2,2,1);
09493                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09494                 e->clip_inplace(r);
09495         } else {
09496                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09497                 e->set_size(3,3,3);
09498                 e->set_value_at(0,0,0,-1);
09499                 e->set_value_at(0,1,0,-1);
09500                 e->set_value_at(0,2,0,-1);
09501                 e->set_value_at(0,0,1,-1);
09502                 e->set_value_at(0,1,1,-8);
09503                 e->set_value_at(0,2,1,-1);
09504                 e->set_value_at(0,0,2,-1);
09505                 e->set_value_at(0,1,2,-1);
09506                 e->set_value_at(0,2,2,-1);
09507 
09508                 e->set_value_at(2,0,0,1);
09509                 e->set_value_at(2,1,0,1);
09510                 e->set_value_at(2,2,0,1);
09511                 e->set_value_at(2,0,1,1);
09512                 e->set_value_at(2,1,1,8);
09513                 e->set_value_at(2,2,1,1);
09514                 e->set_value_at(2,0,2,1);
09515                 e->set_value_at(2,1,2,1);
09516                 e->set_value_at(2,2,2,1);
09517 
09518                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09519                 e->clip_inplace(r);
09520         }
09521 
09522         Dict conv_parms;
09523         conv_parms["with"] = e;
09524         image->process_inplace("math.convolution", conv_parms);
09525         image->process_inplace("xform.phaseorigin.tocenter");
09526 
09527         delete e;
09528 }
09529 
09530 
09531 void TomoTiltAngleWeightProcessor::process_inplace( EMData* image )
09532 {
09533         bool fim = params.set_default("angle_fim", false);
09534         float alt;
09535         if ( fim ) {
09536                 alt = image->get_attr("euler_alt");
09537         }
09538         else alt = params.set_default("angle", 0.0f);
09539 
09540         float cosine = cos(alt*M_PI/180.0f);
09541         float mult_fac =  1.0f/(cosine);
09542         image->mult( mult_fac );
09543 }
09544 
09545 void TomoTiltEdgeMaskProcessor::process_inplace( EMData* image )
09546 {
09547         bool biedgemean = params.set_default("biedgemean", false);
09548         bool edgemean = params.set_default("edgemean", false);
09549         // You can only do one of these - so if someone specifies them both the code complains loudly
09550         if (biedgemean && edgemean) throw InvalidParameterException("The edgemean and biedgemean options are mutually exclusive");
09551 
09552         bool fim = params.set_default("angle_fim", false);
09553         float alt;
09554         if ( fim ) {
09555                 Transform* t = (Transform*)image->get_attr("xform.projection");
09556                 Dict d = t->get_params("eman");
09557                 alt = (float) d["alt"];
09558                 if(t) {delete t; t=0;}
09559         }
09560         else alt = params.set_default("angle", 0.0f);
09561 
09562 
09563         float cosine = cos(alt*M_PI/180.0f);
09564 
09565         // Zero the edges
09566         int nx = image->get_xsize();
09567         int ny = image->get_ysize();
09568         int x_clip = static_cast<int>( (float) nx * ( 1.0 - cosine ) / 2.0);
09569 
09570         float x1_edge_mean = 0.0;
09571         float x2_edge_mean = 0.0;
09572 
09573         if ( biedgemean )
09574         {
09575                 float edge_mean = 0.0;
09576 
09577                 // Accrue the pixel densities on the side strips
09578                 for ( int i = 0; i < ny; ++i ) {
09579                         edge_mean += image->get_value_at(x_clip, i );
09580                         edge_mean += image->get_value_at(nx - x_clip-1, i );
09581                 }
09582                 // Now make it so the mean is stored
09583                 edge_mean /= 2*ny;
09584 
09585                 // Now shift pixel values accordingly
09586                 for ( int i = 0; i < ny; ++i ) {
09587                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09588                                 image->set_value_at(j,i,edge_mean);
09589                         }
09590                         for ( int j = 0; j < x_clip; ++j) {
09591                                 image->set_value_at(j,i,edge_mean);
09592                         }
09593                 }
09594                 x1_edge_mean = edge_mean;
09595                 x2_edge_mean = edge_mean;
09596         }
09597         else if (edgemean)
09598         {
09599                 for ( int i = 0; i < ny; ++i ) {
09600                         x1_edge_mean += image->get_value_at(x_clip, i );
09601                         x2_edge_mean += image->get_value_at(nx - x_clip-1, i );
09602                 }
09603                 x1_edge_mean /= ny;
09604                 x2_edge_mean /= ny;
09605 
09606                 for ( int i = 0; i < ny; ++i ) {
09607                         for ( int j = 0; j < x_clip; ++j) {
09608                                 image->set_value_at(j,i,x1_edge_mean);
09609                         }
09610                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09611                                 image->set_value_at(j,i,x2_edge_mean);
09612                         }
09613                 }
09614         }
09615         else
09616         {
09617                 // The edges are just zeroed -
09618                 Dict zero_dict;
09619                 zero_dict["x0"] = x_clip;
09620                 zero_dict["x1"] = x_clip;
09621                 zero_dict["y0"] = 0;
09622                 zero_dict["y1"] = 0;
09623                 image->process_inplace( "mask.zeroedge2d", zero_dict );
09624         }
09625 
09626         int gauss_rad = params.set_default("gauss_falloff", 0);
09627         if ( gauss_rad != 0)
09628         {
09629                 // If the gaussian falloff distance is greater than x_clip, it will technically
09630                 // go beyond the image boundaries. Thus we clamp gauss_rad so this cannot happen.
09631                 // Therefore, there is potential here for (benevolent) unexpected behavior.
09632                 if ( gauss_rad > x_clip ) gauss_rad = x_clip;
09633 
09634                 float gauss_sigma = params.set_default("gauss_sigma", 3.0f);
09635                 if ( gauss_sigma < 0 ) throw InvalidParameterException("Error - you must specify a positive, non-zero gauss_sigma");
09636                 float sigma = (float) gauss_rad/gauss_sigma;
09637 
09638                 GaussianFunctoid gf(sigma);
09639 
09640                 for ( int i = 0; i < ny; ++i ) {
09641 
09642                         float left_value = image->get_value_at(x_clip, i );
09643                         float scale1 = left_value-x1_edge_mean;
09644 
09645                         float right_value = image->get_value_at(nx - x_clip - 1, i );
09646                         float scale2 = right_value-x2_edge_mean;
09647 
09648                         for ( int j = 1; j < gauss_rad; ++j )
09649                         {
09650                                 image->set_value_at(x_clip-j, i, scale1*gf((float)j)+x1_edge_mean );
09651                                 image->set_value_at(nx - x_clip + j-1, i, scale2*gf((float)j)+x2_edge_mean);
09652                         }
09653                 }
09654         }
09655 
09656         image->update();
09657 }
09658 
09659 void YGradientProcessor::process_inplace( EMData* image )
09660 {
09661         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09662 
09663         EMData* e = new EMData();
09664         int nx = image->get_xsize();
09665         int ny = image->get_ysize();
09666         int nz = image->get_zsize();
09667 
09668         if ( nz == 1 && ny == 1 ) {
09669                 throw ImageDimensionException("Error - cannot detect Y edges for an image that that is 1D!");
09670         } else if ( nz == 1 ) {
09671                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09672                 e->set_size(3,3,1);
09673                 e->set_value_at(0,0,-1);
09674                 e->set_value_at(1,0,-2);
09675                 e->set_value_at(2,0,-1);
09676 
09677                 e->set_value_at(0,2,1);
09678                 e->set_value_at(1,2,2);
09679                 e->set_value_at(2,2,1);
09680                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09681                 e->clip_inplace(r);
09682         } else {
09683                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09684                 e->set_size(3,3,3);
09685                 e->set_value_at(0,0,0,-1);
09686                 e->set_value_at(1,0,0,-1);
09687                 e->set_value_at(2,0,0,-1);
09688                 e->set_value_at(0,0,1,-1);
09689                 e->set_value_at(1,0,1,-8);
09690                 e->set_value_at(2,0,1,-1);
09691                 e->set_value_at(0,0,2,-1);
09692                 e->set_value_at(1,0,2,-1);
09693                 e->set_value_at(2,0,2,-1);
09694 
09695                 e->set_value_at(0,2,0,1);
09696                 e->set_value_at(1,2,0,1);
09697                 e->set_value_at(2,2,0,1);
09698                 e->set_value_at(0,2,1,1);
09699                 e->set_value_at(1,2,1,8);
09700                 e->set_value_at(2,2,1,1);
09701                 e->set_value_at(0,2,2,1);
09702                 e->set_value_at(1,2,2,1);
09703                 e->set_value_at(2,2,2,1);
09704 
09705                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09706                 e->clip_inplace(r);
09707         }
09708 
09709         Dict conv_parms;
09710         conv_parms["with"] = e;
09711         image->process_inplace("math.convolution", conv_parms);
09712 
09713         delete e;
09714 }
09715 
09716 
09717 void ZGradientProcessor::process_inplace( EMData* image )
09718 {
09719         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09720 
09721         EMData* e = new EMData();
09722         int nx = image->get_xsize();
09723         int ny = image->get_ysize();
09724         int nz = image->get_zsize();
09725 
09726         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");
09727 
09728         e->set_size(3,3,3);
09729         e->set_value_at(0,0,0,-1);
09730         e->set_value_at(1,0,0,-1);
09731         e->set_value_at(2,0,0,-1);
09732         e->set_value_at(0,1,0,-1);
09733         e->set_value_at(1,1,0,-8);
09734         e->set_value_at(2,1,0,-1);
09735         e->set_value_at(0,2,0,-1);
09736         e->set_value_at(1,2,0,-1);
09737         e->set_value_at(2,2,0,-1);
09738 
09739         e->set_value_at(0,0,2,1);
09740         e->set_value_at(1,0,2,1);
09741         e->set_value_at(2,0,2,1);
09742         e->set_value_at(0,1,2,1);
09743         e->set_value_at(1,1,2,8);
09744         e->set_value_at(2,1,2,1);
09745         e->set_value_at(0,2,2,1);
09746         e->set_value_at(1,2,2,1);
09747         e->set_value_at(2,2,2,1);
09748 
09749         Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09750         e->clip_inplace(r);
09751 
09752         Dict conv_parms;
09753         conv_parms["with"] = e;
09754         image->process_inplace("math.convolution", conv_parms);
09755 
09756         delete e;
09757 }
09758 
09759 void EMAN::dump_processors()
09760 {
09761         dump_factory < Processor > ();
09762 }
09763 
09764 map<string, vector<string> > EMAN::dump_processors_list()
09765 {
09766         return dump_factory_list < Processor > ();
09767 }
09768 
09769 map<string, vector<string> > EMAN::group_processors()
09770 {
09771         map<string, vector<string> > processor_groups;
09772 
09773         vector <string> processornames = Factory<Processor>::get_list();
09774 
09775         for (size_t i = 0; i < processornames.size(); i++) {
09776                 Processor * f = Factory<Processor>::get(processornames[i]);
09777                 if (dynamic_cast<RealPixelProcessor*>(f) != 0) {
09778                         processor_groups["RealPixelProcessor"].push_back(f->get_name());
09779                 }
09780                 else if (dynamic_cast<BoxStatProcessor*>(f)  != 0) {
09781                         processor_groups["BoxStatProcessor"].push_back(f->get_name());
09782                 }
09783                 else if (dynamic_cast<ComplexPixelProcessor*>(f)  != 0) {
09784                         processor_groups["ComplexPixelProcessor"].push_back(f->get_name());
09785                 }
09786                 else if (dynamic_cast<CoordinateProcessor*>(f)  != 0) {
09787                         processor_groups["CoordinateProcessor"].push_back(f->get_name());
09788                 }
09789                 else if (dynamic_cast<FourierProcessor*>(f)  != 0) {
09790                         processor_groups["FourierProcessor"].push_back(f->get_name());
09791                 }
09792                 else if (dynamic_cast<NewFourierProcessor*>(f)  != 0) {
09793                         processor_groups["FourierProcessor"].push_back(f->get_name());
09794                 }
09795                 else if (dynamic_cast<NormalizeProcessor*>(f)  != 0) {
09796                         processor_groups["NormalizeProcessor"].push_back(f->get_name());
09797                 }
09798                 else {
09799                         processor_groups["Others"].push_back(f->get_name());
09800                 }
09801         }
09802 
09803         return processor_groups;
09804 }
09805 
09806 
09807 
09808 /* vim: set ts=4 noet: */
09809 
09810 float ModelHelixProcessor::radprofile(float r, int type)
09811 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09812 {
09813         // r in angstrom
09814         double ret = 0;//iterations ==> rounding is problematic with float types if 15 < r < 20 and really bad if 20 < r < 30
09815         if (type == 0) { // pure Gaussian falloff
09816                 r /= 2;
09817                 ret = exp(-r * r);
09818         } else if (type == 1) { // pure Gaussian falloff + negative dip, so mean is 0
09819                 r /= 2;
09820                 ret = (1 - r * r / 4) * exp(-r * r / 4);
09821         } else if (type == 2) {
09822                 // polynomial fitting to the radial profile of real helix density
09823                 // f=a0*x^n+a1+x^(n-1)+ ... +a[n-1]*x+an
09824                 //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};
09825 
09826                 // now the fitting to the original profile
09827                 if (r >= 12.2)
09828                         return 0; //We don't want that part of the polynomial --> goes way below zero
09829                 static float an[15] = { -3.9185246832229140e-16f,
09830                                 3.3957205298900993e-14f, 2.0343351971222658e-12f,
09831                                 -4.4935965816879751e-10f, 3.0668169835080933e-08f,
09832                                 -1.1904544689091790e-06f, 2.9753088549414953e-05f,
09833                                 -4.9802112876220150e-04f, 5.5900917825309360e-03f,
09834                                 -4.0823714462925299e-02f, 1.8021733669148599e-01f,
09835                                 -4.0992557296268717e-01f, 3.3980328566901458e-01f,
09836                                 -3.6062024812411908e-01f, 1.0000000000000000e+00f };
09837 
09838                 ret = an[0];
09839                 for (int i = 1; i < 15; i++) {
09840                         ret = ret * r + an[i];
09841                 }
09842         }
09843         return (float)ret;
09844 }
09845 
09846 void ModelEMCylinderProcessor::process_inplace(EMData * in)
09847 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09848 {
09849         // synthesize model alpha helix, len is Angstrom, default to 2 turns
09850         //The helical axis is parallel to the z axis.
09851         EMData * cyl = in;
09852         int nx = cyl->get_xsize();
09853         int ny = cyl->get_ysize();
09854         int nz = cyl->get_zsize();
09855 
09856         int type = params.set_default("type", 2);
09857         float len = params.set_default("length", 16.2f); //in angstroms
09858         int x0 = params.set_default("x0", -1); //in voxels -- default value changed a few lines down
09859         int y0 = params.set_default("y0", -1); //in voxels
09860         int z0 = params.set_default("z0", -1); //in voxels
09861         //TODO: check with Matt about default values
09862 
09863         if (x0 < 0 || x0 >= nx)
09864                 x0 = nx / 2;
09865         if (y0 < 0 || y0 >= ny)
09866                 y0 = ny / 2;
09867         if (z0 < 0 || z0 >= nz)
09868                 z0 = nz / 2;
09869 
09870         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
09871         float apix_y = cyl->get_attr("apix_y");
09872         float apix_z = cyl->get_attr("apix_z");
09873 
09874         float * dat = cyl->get_data();
09875         int cyl_voxel_len = (int) (len / apix_z);
09876         int cyl_k_min = z0 - cyl_voxel_len / 2;
09877         int cyl_k_max = z0 + cyl_voxel_len / 2;
09878 
09879         int x, y;
09880         for (int k = 0; k < nz; ++k) {
09881                 for (int j = 0; j < ny; ++j) {
09882                         for (int i = 0; i < nx; ++i, ++dat) {
09883                                 x = i - x0;//coordinate sys centered on cylinder
09884                                 y = j - y0;//coordinate sys centered on cylinder
09885                                 float radius = (float)hypot(x * apix_x, y * apix_y);
09886                                 if ((k > cyl_k_min) && (k < cyl_k_max))
09887                                         *dat += radprofile(radius, type); //pointer arithmetic for array done in loop
09888                                 //else
09889                                         //continue;
09890 
09891                         }
09892                 }
09893         }
09894 }
09895 
09896 void ApplyPolynomialProfileToHelix::process_inplace(EMData * in)
09897 {
09898         EMData * cyl = in;
09899         int nx = cyl->get_xsize();
09900         int ny = cyl->get_ysize();
09901         int nz = cyl->get_zsize();
09902         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
09903         float apix_y = cyl->get_attr("apix_y");
09904         float apix_z = cyl->get_attr("apix_z");
09905         float lengthAngstroms = params["length"];
09906         int z0 = params.set_default("z0", -1); //in voxels
09907 
09908         if (z0 < 0 || z0 >= nz)
09909                 z0 = nz / 2;
09910 
09911         int z_start = Util::round( z0 - 0.5*lengthAngstroms/apix_z );
09912         int z_stop = Util::round( z0 + 0.5*lengthAngstroms/apix_z );
09913 
09914         float * dat = cyl->get_data();
09915         double rho_x_sum, rho_y_sum, rho_sum, x_cm, y_cm, radius;
09916 
09917         for (int k = 0; k < nz; ++k) //taking slices along z axis
09918         {
09919                 rho_x_sum = rho_y_sum = rho_sum = 0; //Set to zero for a new slice
09920 
09921                 if (k >= z_start && k <= z_stop)
09922                 //Apply the radial profile only between z_start and z_stop on the z axis
09923                 {
09924                         //Calculating CM for the slice...
09925                         for (int j = 0; j < ny; ++j)
09926                         {
09927                                 for (int i = 0; i < nx; ++i, ++dat)
09928                                 {
09929                                         rho_x_sum += (*dat)*i;
09930                                         rho_y_sum += (*dat)*j;
09931                                         rho_sum += *dat;
09932                                 }
09933                         }
09934                         if (rho_sum != 0)
09935                         {
09936                                 dat -= nx*ny;//going back to the beginning of the dat array
09937                                 x_cm = rho_x_sum/rho_sum;
09938                                 y_cm = rho_y_sum/rho_sum;
09939 
09940                                 //Applying radial profile...
09941                                 for (int j=0; j<ny;++j)
09942                                 {
09943                                         for (int i=0;i<nx;++i,++dat)
09944                                         {
09945                                                 radius = hypot( (i-x_cm)*apix_x, (j-y_cm)*apix_y );
09946                                                 *dat = radprofile((float)radius, 2);//Type 2 is the polynomial radial profile.
09947                                         }
09948                                 }
09949                         }
09950                 }
09951                 else
09952                 //Clear the map, setting the density to zero everywhere else.
09953                 {
09954                         for (int j=0; j<ny; j++)
09955                                 for(int i=0; i<nx; i++)
09956                                 {
09957                                         *dat = 0;
09958                                         dat++;
09959                                 }
09960                 }
09961 
09962         }
09963 }
09964 
09965 //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!
09966 EMData* BinarySkeletonizerProcessor::process(EMData * image)
09967 {
09968         using namespace wustl_mm::GraySkeletonCPP;
09969         using namespace wustl_mm::SkeletonMaker;
09970 
09971         Volume * vimage = new Volume(image);
09972         float threshold = params["threshold"];
09973         int min_curvew = params.set_default("min_curve_width", 4);
09974         int min_srfcw = params.set_default("min_surface_width", 4);
09975         bool mark_surfaces = params.set_default("mark_surfaces", true);
09976         Volume* vskel = VolumeSkeletonizer::PerformPureJuSkeletonization(vimage, "unused", static_cast<double>(threshold), min_curvew, min_srfcw);
09977         //VolumeSkeletonizer::CleanUpSkeleton(vskel, 4, 0.01f);
09978         if (mark_surfaces) {
09979                 VolumeSkeletonizer::MarkSurfaces(vskel);
09980         }
09981 
09982         vskel->getVolumeData()->owns_emdata = false; //ensure the EMData object will remain when the Volume and its VolumeData object are freed
09983         EMData* skel = vskel->get_emdata();
09984         skel->update();
09985         return skel;
09986 }
09987 
09988 void BinarySkeletonizerProcessor::process_inplace(EMData * image)
09989 {
09990         EMData* em_skel = this->process(image);
09991         //TODO: use memcpy and copy metadata explicitly
09992         *image = *em_skel; //Deep copy performed by EMData::operator=
09993         image->update();
09994         delete em_skel;
09995         em_skel = NULL;
09996         return;
09997 }
09998 
09999 EMData* ConvolutionKernelProcessor::process(const EMData* const image) 
10000 {
10001         if (image->get_zsize()!=1) throw ImageDimensionException("Only 2-D images supported");
10002         
10003         EMData* conv = new EMData(image->get_xsize(),image->get_ysize(),1);
10004         vector<float>kernel = params["kernel"];
10005 
10006         if (fmod(sqrt((float)kernel.size()), 1.0f) != 0) throw InvalidParameterException("Convolution kernel must be square!!");
10007         
10008         float* data = image->get_data();
10009         float* cdata = conv->get_data();        // Yes I could use set_value_at_fast, but is still slower than this....
10010         
10011         //I could do the edges by wrapping around, but this is not necessary(such functionality can be iplemented later)
10012         int ks = int(sqrt(float(kernel.size())));
10013         int n = (ks - 1)/2;
10014         int nx = image->get_xsize();
10015         int ny = image->get_ysize();
10016         for (int i = n; i < (nx - n); i++) {
10017                 for (int j = n; j < (ny - n); j++) {
10018                         //now do the convolution
10019                         float cpixel = 0;
10020                         int idx = 0;
10021                         // Perahps I could use some ofrm of Caching to speed things up?
10022                         for (int cx = -n; cx <= n; cx++) {
10023                                 for (int cy = -n; cy <= n; cy++) {
10024                                         cpixel += data[(i+cx) + (j+cy) * nx]*kernel[idx];
10025                                         idx++;
10026                                 }
10027                         }
10028                         cdata[i + j * nx] = cpixel;
10029                 }
10030         }
10031           
10032         return conv;
10033 }
10034 
10035 void ConvolutionKernelProcessor::process_inplace(EMData * image )
10036 {
10037         throw UnexpectedBehaviorException("Not implemented yet");
10038         
10039         return;
10040 }
10041 
10042 
10043 EMData* RotateInFSProcessor::process(const EMData* const image) // 
10044 {
10045 
10046     EMData* imageCp        = image -> copy(); // This is the rotated image
10047     process_inplace(imageCp);
10048     
10049     return imageCp;
10050 }
10051 
10052 
10053 void RotateInFSProcessor::process_inplace(EMData * image) // right now for 2d images
10054 {
10055 //      float angle = params["angle"];
10056         
10057 
10058 //      Transform *rotNow  = params.set_default("transform",&Transform());
10059         Transform *rotNow  = params["transform"];
10060         float interpCutoff = params.set_default("interpCutoff",0.8f);   // JFF, can you move this to input parameter? 
10061 //      float interpCutoff = params["interpCutoff"];   // JFF, can you move this to input parameter? 
10062 //      float interpCutoff =.8;   // JFF, can you move this to input parameter? 
10063         
10064         
10065         int debug=0;
10066         
10067 //      error: conversion from ‘EMAN::EMObject’ to non-scalar type ‘EMAN::Transform’ requested
10068         
10069         
10070         // if 2N is size of image, then sizes of FFT are (2N+2,2N,2N) or  (2N+2,2N,1)
10071         // if 2N+1 is size of image, then sizes of FFT are (2N+2,2N+1,2N+1) or  (2N+2,2N+1,1)
10072         
10073         int x_size = image->get_xsize();  //16
10074         int y_size = image->get_ysize();  int y_odd=  (y_size%2);
10075         int z_size = image->get_zsize();
10076         
10077 //      float size_check = abs(y_size-z_size)+abs(x_size-y_size-2+y_odd);
10078 //      if (size_check!=0) throw ImageDimensionException("Only cubic images");
10079         int size_check = abs(x_size-y_size-2+y_odd)+ abs(z_size-1)*abs(z_size-y_size);
10080         int N = x_size/2-1;
10081         int Mid = N+1;
10082         if (size_check!=0) throw ImageDimensionException("Only square or cubic  images for now");
10083         if (image->is_real()) throw ImageDimensionException("Only for Fourier images");
10084 //      if (y_odd==0) throw ImageDimensionException("Only use odd images for now");
10085         
10086         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 );
10087         
10088         EMData* RotIm        = image -> copy(); // This is the rotated image
10089         EMData* WeightIm     = image -> copy(); WeightIm     ->to_zero();// This is the Weight image for rotated image
10090         EMData* PhaseOrigIm  = new EMData(N+1,2*N+1,z_size) ; PhaseOrigIm  ->to_zero();// This is the Weight image for rotated image
10091         EMData* PhaseFinalIm = PhaseOrigIm -> copy(); PhaseFinalIm ->to_zero();// This is the Weight image for rotated image
10092         EMData* MagFinalIm   = PhaseOrigIm -> copy(); MagFinalIm   ->to_zero();// This is the Weight image for rotated image
10093         
10094 //      float*   data      = image    -> get_data();
10095 //      float* Rotdata     = RotIm    -> get_data();  // This is the data of the rotated image
10096 //      float* WeightData  = WeightIm -> get_data();  //
10097         
10098         float  WeightNowX, WeightNowY, WeightNowZ ;
10099         int    kxMin,kxMax, kyMin, kyMax,  kzMin, kzMax, kxBefore, kyBefore, kzBefore ;
10100         float  kxRT, kyRT, kzRT ;
10101         
10102         Vec3f PosAfter;
10103         Vec3f PosBefore;
10104         Transform invRotNow;
10105         // Fill out real and imaginary full images
10106 
10107         //int kz=0;
10108 
10109         if (debug) {image -> write_image("OrigImageFFT.hdf");   
10110                     printf("Just wrote OrigImageFFT.hdf \n"); }
10111         
10112 
10113         for (kxBefore = 0; kxBefore <=  N      ; ++kxBefore) {  // These are the  kx, ky coordinates of the original image
10114            for (kyBefore = 0; kyBefore < y_size ; ++kyBefore)  {         //  We need to rephase
10115               for (kzBefore = 0; kzBefore < z_size ; ++kzBefore)  {         //  We need to rephase
10116 
10117             // Now we need a 
10118               float CurrentReal = RotIm -> get_value_at(2*kxBefore  ,kyBefore, kzBefore);
10119               float CurrentImag = RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
10120               
10121 //         fftOfxPRB3(1+mod(ik-Mid,N))=Grand*exp(-2*pi*1i*Mid*(ik-Mid)/x_size); % Phase to apply to centered version
10122               
10123 //            float Phase    = -2*pi*(kxBefore+kyBefore + kzBefore)*(Mid)/y_size;
10124               float Phase    = -pi*(kxBefore+kyBefore + kzBefore)*x_size/y_size;
10125               // Phase    = 0;
10126               float CosPhase = cos( Phase);
10127               float SinPhase = sin( Phase);
10128              
10129               float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
10130               float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
10131               
10132               RotIm ->set_value_at(2*kxBefore  ,kyBefore, kzBefore, NewRealValue);
10133               RotIm ->set_value_at(2*kxBefore+1,kyBefore, kzBefore, NewImagValue);
10134         }}}
10135         
10136         if (debug) {RotIm  -> write_image("OrigImageFFTAfterPhaseCorrection.hdf"); 
10137                     printf("  Just wrote OrigImageFFTAfterPhaseCorrection.hdf \n");}
10138         
10139         // RotIm ->set_value_at(2*Mid-1,0, 0, 0);
10140         if (debug) printf("  Just about to start second loop  \n");
10141         
10142         image ->to_zero();
10143         invRotNow = rotNow ->inverse(); //  no match for ‘operator=’ in ‘PosBefore = EMAN::operator*(const EMAN::Transform&, const EMAN::Transform&)((
10144          
10145         
10146         for (int kxAfter = 0; kxAfter <= N  ; ++kxAfter) {  // These are the  kx, ky, kz coordinates of the rotated image
10147           for (int kyAfter = -N; kyAfter < y_size-N     ; ++kyAfter)  {     // referring to a properly centered version
10148              for (int kzAfter = -z_size/2; kzAfter <= z_size/2  ; ++kzAfter)  {   
10149 
10150             // Now we need a 
10151 
10152               PosAfter = Vec3f(kxAfter, kyAfter, kzAfter);
10153               PosBefore = invRotNow*PosAfter;
10154               kxRT = PosBefore[0]; // This will be the off-lattice site, where the point was rotated from
10155               kyRT = PosBefore[1]; //  
10156               kzRT = PosBefore[2]; //  
10157               
10158               
10159               kxMin = ceil( kxRT-interpCutoff); kxMax = floor(kxRT+interpCutoff);
10160               kyMin = ceil( kyRT-interpCutoff); kyMax = floor(kyRT+interpCutoff);
10161               kzMin = ceil( kzRT-interpCutoff); kzMax = floor(kzRT+interpCutoff);
10162 
10163     
10164 //              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); 
10165               //continue; 
10166               for (int kxI= kxMin; kxI <= kxMax; ++kxI){  // go through this
10167                 for (int kyI= kyMin; kyI <= kyMax; ++kyI){  // and get values to interp
10168                    for (int kzI= kzMin; kzI <= kzMax; ++kzI){ //  
10169 
10170 // 
10171                      if (abs(kxI) >N) continue; // don't go off the lattice
10172                      if (abs(kyI) >N) continue;
10173                      if (abs(kzI) >z_size/2) continue;
10174                      
10175                      float distx= abs(kxI-kxRT);
10176                      float disty= abs(kyI-kyRT);
10177                      float distz= abs(kzI-kzRT);
10178 
10179                      // fold kxI, kyI back into lattice if possible
10180                      int IsComplexConj= 1;
10181                      
10182                      if (kxI<0) IsComplexConj=-1;
10183                      kxBefore= IsComplexConj*kxI; // The Proper coordinates will be
10184                      kyBefore= IsComplexConj*kyI; // where the original data is stored 
10185                      kzBefore= IsComplexConj*kzI; // At this point kxBefore >=0, but not necessarily kyBefore
10186                      
10187                      if ( kyBefore<0 ) kyBefore += y_size; // makes sure kyBefore is also >0
10188                      if ( kzBefore<0 ) kzBefore += y_size; // makes sure kzBefore is also >0
10189                      
10190                      WeightNowX  = (distx ==0)? 1: (sin(pi*distx) /(pi*distx)) ;
10191                      WeightNowY  = (disty ==0)? 1: (sin(pi*disty) /(pi*disty)) ;
10192                      WeightNowZ  = (distz ==0)? 1: (sin(pi*distz) /(pi*distz)) ;
10193                      
10194                      
10195                      float CurrentValue;
10196                      float ToAdd;
10197                      int kyAfterInd = (kyAfter+y_size)%(y_size);
10198                      int kzAfterInd = (kzAfter+z_size)%(z_size);
10199                      
10200                     // if (kxAfter==0) IsComplexConj*=-1;
10201                      
10202 //                   if ((kxI+kyI)%1 ==0)
10203 //                       printf("Block5,kx=%d, ky=%d,kxI=%d, kyI=%d, kxBefore=%d, kyBefore=%d  \n",kxAfter,kyAfter,kxI,kyI, kxBefore,kyBefore);
10204 //                       printf("  %d,     %d,  %d,  %d,        %d,  %d,       %d, %d \n",IsComplexConj,kxAfter,kyAfter, kyAfterInd,kxI,kyI, kxBefore,kyBefore);
10205                      
10206                      CurrentValue =   image -> get_value_at(2*kxAfter,kyAfterInd, kzAfterInd);  // Update real part of Image
10207                      ToAdd =   WeightNowX*WeightNowY*WeightNowZ*(RotIm -> get_value_at(2*kxBefore,kyBefore, kzBefore));
10208                      image -> set_value_at(2*kxAfter  ,kyAfterInd  , kzAfterInd,  ToAdd   + CurrentValue );
10209                      
10210                      
10211                      CurrentValue =   WeightIm -> get_value_at(kxAfter,kyAfterInd, kzAfterInd);    // Update real  part of Weight image
10212                      ToAdd =   WeightNowX*WeightNowY;
10213                      WeightIm -> set_value_at(kxAfter  , kyAfterInd , kzAfterInd,  abs(ToAdd)   + CurrentValue );
10214                      
10215                      CurrentValue = image -> get_value_at(2*kxAfter+1,kyAfterInd);    // Update imaginary   part of image
10216                      ToAdd =   IsComplexConj*WeightNowX*WeightNowY*RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore );
10217                      image -> set_value_at(2*kxAfter+1  , kyAfterInd , kzAfterInd,  ToAdd   + CurrentValue );
10218                      
10219                       
10220                 }}}
10221 
10222             
10223           }}}
10224 
10225 //        Set the image values to the rotated image, because we do it in place
10226 
10227 
10228         if (debug) { image        -> write_image("RotImageBeforeFinalPhaseCorrection.hdf"); 
10229                      printf("  Just wrote RotImageBeforeFinalPhaseCorrection.hdf \n");   }
10230 
10231 
10232         for (kxBefore = 0; kxBefore <= N     ; ++kxBefore) {      // This is  the normalization step
10233           for (kyBefore = 0; kyBefore < y_size   ; ++kyBefore)  {  // These are the  kx, ky, kz coordinates of the original image       
10234               for (kzBefore = 0; kzBefore < z_size   ; ++kzBefore)  {       
10235 
10236               float CurrentReal = image -> get_value_at(2*kxBefore   , kyBefore, kzBefore);
10237               float CurrentImag = image -> get_value_at(2*kxBefore+1 , kyBefore, kzBefore);
10238               
10239               PhaseFinalIm -> set_value_at(kxBefore,kyBefore, kzBefore, atan2(CurrentImag,CurrentReal));
10240               MagFinalIm   -> set_value_at(kxBefore,kyBefore, kzBefore, sqrt(CurrentImag*CurrentImag+CurrentReal*CurrentReal) );
10241               float WeightNow    = WeightIm -> get_value_at(kxBefore,kyBefore, kzBefore);
10242               if (WeightNow>0) {
10243                  float val =  (image->get_value_at(2*kxBefore   , kyBefore, kzBefore))/WeightNow;
10244                  image -> set_value_at(2*kxBefore   , kyBefore, kzBefore, val);
10245                  val      =  (image->get_value_at(2*kxBefore +1  , kyBefore, kzBefore))/WeightNow;
10246                  image -> set_value_at(2*kxBefore +1  , kyBefore, kzBefore,  val);
10247               }
10248         
10249         }}}
10250         
10251         if (debug) { printf("  Just did normalization step \n");}
10252         
10253 
10254         for ( kxBefore = 0; kxBefore < Mid     ; ++kxBefore) {     //  This is the rephase step
10255           for ( kyBefore = 0; kyBefore < y_size   ; ++kyBefore)  {     
10256             for ( kzBefore = 0; kzBefore < z_size   ; ++kzBefore)  {     
10257 
10258               float CurrentReal = image -> get_value_at(2*kxBefore  ,kyBefore, kzBefore);
10259               float CurrentImag = image -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
10260               
10261 //            float Phase    = +2*pi*(kxBefore+kyBefore+kzBefore)*(Mid)/y_size;
10262               float Phase    =  pi*(kxBefore + kyBefore + kzBefore)*x_size/y_size;
10263               // Phase    = 0; // Offset should be Mid-1
10264               float CosPhase = cos( Phase);
10265               float SinPhase = sin( Phase);
10266              
10267               float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
10268               float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
10269               
10270               image ->set_value_at(2*kxBefore,  kyBefore,  kzBefore, NewRealValue);
10271               image ->set_value_at(2*kxBefore+1,kyBefore,  kzBefore, NewImagValue);
10272         }}}
10273         
10274         if (debug) {
10275            image        -> write_image("RotatedImageFFT.hdf");
10276            PhaseFinalIm -> write_image("PhaseImInFS.hdf");   // These are the phases,mags of the image when properly centered
10277            MagFinalIm   -> write_image("MagFinalImInFS.hdf"); 
10278            WeightIm     -> write_image("WeightIm.hdf");
10279            printf("  Just wrote RotatedImageFFT.hdf \n");
10280         }
10281 
10282         image -> update();
10283         
10284 }
10285 
10286 
10287 #ifdef SPARX_USING_CUDA
10288 
10289 /* CLASS MPICUDA_kmeans processor
10290  *
10291  */
10292 #include "sparx/cuda/cuda_mpi_kmeans.h"
10293 MPICUDA_kmeans::MPICUDA_kmeans() {
10294     h_IM = NULL;
10295     h_AVE = NULL;
10296     h_ASG = NULL;
10297     h_dist = NULL;
10298     h_AVE2 = NULL;
10299     h_im2 = NULL;
10300     h_NC = NULL;
10301     params = NULL;
10302     d_im = NULL;
10303     d_AVE = NULL;
10304     d_dist = NULL;
10305 }
10306 
10307 MPICUDA_kmeans::~MPICUDA_kmeans() {
10308     if (h_IM) delete h_IM;
10309     if (h_ASG) delete h_ASG;
10310     if (h_AVE) delete h_AVE;
10311     if (h_dist) delete h_dist;
10312     if (h_AVE2) delete h_AVE2;
10313     if (h_im2) delete h_im2;
10314     if (h_NC) delete h_NC;
10315     if (params) delete params;
10316 }
10317 
10318 #include "sparx/cuda/cuda_mpi_kmeans.h"
10319 int MPICUDA_kmeans::setup(int extm, int extN, int extn, int extK, int extn_start) {
10320     m = extm;                           // number of pixels per image
10321     N = extN;                           // Total number of images
10322     n = extn;                           // Number of images used locally
10323     K = extK;                           // number of classes
10324     n_start = extn_start;               // Starting point to local images
10325     size_IM = m * N;                    // nb elements in IM
10326     size_im = m * n;                    // nb elements in im
10327     size_AVE = m * K;                   // nb elements in ave
10328     size_dist = n * K;                  // nb elements in dist
10329     ite = 0;                            // init nb of iterations
10330     BLOCK_SIZE = 512;
10331     NB = size_dist / BLOCK_SIZE;
10332     ins_BLOCK = NB * BLOCK_SIZE;
10333     // Host memory allocation for images
10334     h_IM = (float*)malloc(size_IM * sizeof(float));
10335     if (h_IM == 0) return 1;
10336     h_im = &h_IM[n_start * m]; // for local images
10337     // Host memory allocation for the averages
10338     h_AVE = (float*)malloc(size_AVE * sizeof(float));
10339     if (h_AVE == 0) return 1;
10340     // Host memory allocation for all assignment
10341     h_ASG = (unsigned short int*)malloc(N * sizeof(unsigned short int));
10342     if (h_ASG == 0) return 1;
10343     h_asg = &h_ASG[n_start]; // for local assignment
10344     // allocate the memory for the sum squared of averages
10345     h_AVE2 = (float*)malloc(K * sizeof(float));
10346     if (h_AVE2 == 0) return 1;
10347     // allocate the memory for the sum squared of images
10348     h_im2 = (float*)malloc(n * sizeof(float));
10349     if (h_im2 == 0) return 1;
10350     // allocate the memory for the distances
10351     h_dist = (float*)malloc(size_dist * sizeof(float));
10352     if (h_dist == 0) return 1;
10353     // allocate the memory for the number of images per class
10354     h_NC = (unsigned int*)malloc(K * sizeof(unsigned int));
10355     if (h_NC == 0) return 1;
10356     // allocate the memory to parameters
10357     params = (int*)malloc(8 * sizeof(int));
10358     if (params == 0) return 1;
10359     params[0] = n;
10360     params[1] = m;
10361     params[2] = K;
10362     params[3] = 0;          // Reserve for flag_stop_iteration
10363     params[4] = 0;          // Reserve for ct_im_mv (debug)
10364     params[5] = BLOCK_SIZE; // Size of threads block (512)
10365     params[6] = NB;         // Number of blocks which fit with BLOCK_SIZE
10366     params[7] = ins_BLOCK;  // Number of blocks remaining
10367     
10368 
10369     return 0;
10370 }
10371 
10372 // add image pre-process by Util.compress_image_mask
10373 void MPICUDA_kmeans::append_flat_image(EMData* im, int pos) {
10374    
10375     for (int i = 0; i < m ; ++i) h_IM[pos * m + i] = (*im)(i);
10376     
10377 }
10378 
10379 // cuda init mem device, cublas (get device ptr)
10380 int MPICUDA_kmeans::init_mem(int numdev) {
10381     int stat = 1;
10382     float** hd_AVE = NULL;
10383     float** hd_im = NULL;
10384     float** hd_dist = NULL;
10385     hd_AVE = &d_AVE;
10386     hd_im = &d_im;
10387     hd_dist = &d_dist;
10388     stat = cuda_mpi_init(h_im, hd_im, hd_AVE, hd_dist, size_im, size_AVE, size_dist, numdev);
10389     //printf("C++ get this pointer for d_AVE: %p\n", d_AVE);
10390     //printf("C++ get this pointer for d_im: %p\n", d_im);
10391     //printf("C++ get this pointer for d_dist: %p\n", d_dist);
10392     return stat;
10393 }
10394 
10395 // precalculate im2
10396 void MPICUDA_kmeans::compute_im2() {
10397     for (int i = 0; i < n; i++) {
10398         h_im2[i] = 0.0f;
10399         for (int j = 0; j < m; j++) h_im2[i] += (h_im[i * m + j] * h_im[i * m + j]);
10400     }
10401 }
10402 
10403 // init randomly the first assignment
10404 int MPICUDA_kmeans::random_ASG(long int rnd) {
10405     srand(rnd);
10406     int ret = 20;
10407     int flag = 0;
10408     int i, k;
10409     std::cout<<"111111111  number of image==="<<N<<"number cluster=="<<K<<"img size"<<m<<std::endl;
10410     for (k = 0; k < K; k++) h_NC[k] = 0;
10411     while (ret > 0) {
10412         ret--;
10413         for (i = 0; i < N; i++) {
10414             h_ASG[i] = rand() % K;
10415             h_NC[h_ASG[i]]++;
10416         }
10417         flag = 1;
10418         k = K;
10419         while (k > 0 && flag) {
10420             k--;
10421             if (h_NC[k] <= 1) {
10422                 flag = 0;
10423                 if (ret == 0) {
10424                     //printf("Erreur randomize assignment\n");
10425                     return -1;
10426                 }
10427                 for (k = 0; k < K; k++) h_NC[k] = 0;
10428             }
10429         if (flag == 1) ret = 0;
10430         }
10431     }
10432    
10433     return 0;
10434 }
10435 
10436 // get back the assignment
10437 vector <int> MPICUDA_kmeans::get_ASG() {
10438     vector <int> ASG(h_ASG, &h_ASG[N]);
10439     return ASG;
10440 }
10441 
10442 // get back the global assignment
10443 vector <int> MPICUDA_kmeans::get_asg() {
10444     vector <int> asg(h_asg, &h_asg[n]);
10445     return asg;
10446 }
10447 
10448 // compute NC from ASG
10449 void MPICUDA_kmeans::compute_NC() {
10450     for (int i = 0; i < K; ++i) h_NC[i] = 0;
10451     for (int i = 0; i < N; ++i) h_NC[h_ASG[i]]++;
10452 }
10453 
10454 // get NC
10455 vector <int> MPICUDA_kmeans::get_NC() {
10456     vector <int> NC(h_NC, &h_NC[K]);
10457     return NC;
10458 }
10459 
10460 // set a new global assignment
10461 void MPICUDA_kmeans::set_ASG(const vector <int>& ASG) {
10462     for (int i = 0; i < N ; ++i) h_ASG[i] = ASG[i];
10463 }
10464 
10465 // set number of objects per group
10466 void MPICUDA_kmeans::set_NC(const vector <int>& NC) {
10467     for (int i = 0; i < K; ++i) h_NC[i] = NC[i];
10468 }
10469 
10470 // get back some information (ite and T0)
10471 int MPICUDA_kmeans::get_ct_im_mv() {
10472     return params[4]; // ct_im_mov
10473 }
10474 
10475 // set the value of T
10476 void MPICUDA_kmeans::set_T(float extT) {
10477     T = extT;
10478 }
10479 
10480 // get the T value
10481 float MPICUDA_kmeans::get_T() {
10482     return T;
10483 }
10484 
10485 // compute ave and ave2
10486 void MPICUDA_kmeans::compute_AVE() {
10487     float buf = 0.0f;
10488     int i, j, c, d, ind;
10489     // compute the averages according ASG
10490     for (i = 0; i < size_AVE; ++i) h_AVE[i] = 0.0f;                          // set averages to zero
10491     for (i = 0; i < N; ++i) {
10492         c = h_ASG[i] * m;
10493         d = i * m;
10494         for (j = 0; j < m; ++j) h_AVE[c + j] += h_IM[d + j];                 // accumulate images
10495     }
10496     for (i = 0; i < K; i++) {
10497         buf = 0.0f;
10498         for (j = 0 ; j < m; j++) {
10499             ind = i * m + j;
10500             h_AVE[ind] /= (float)h_NC[i];                                    // compute average
10501             buf += (h_AVE[ind] * h_AVE[ind]);                                // do sum squared AVE
10502         }
10503         h_AVE2[i] = buf;
10504     }
10505     
10506     /*for (i = 0; i < K; i++) {
10507         std::cout<<"average image"<<std::endl;
10508         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;
10509     }*/
10510   
10511 }
10512 
10513 // set averages
10514 void MPICUDA_kmeans::set_AVE(EMData* im, int pos) {
10515     for (int i = 0; i < m ; ++i) h_AVE[pos * m + i] = (*im)(i);
10516 }
10517 
10518 // get back the averages
10519 vector<EMData*> MPICUDA_kmeans::get_AVE() {
10520     vector<EMData*> ave(K);
10521     for (int k = 0; k < K; ++k) {
10522         EMData* im = new EMData();
10523         im->set_size(m, 1, 1);
10524         float *ptr = im->get_data();
10525         for (int i = 0; i < m; ++i) {ptr[i] =  h_AVE[k * m + i];}
10526         ave[k] = im->copy();
10527         delete im;
10528     }
10529     return ave;
10530 }
10531 
10532 // k-means one iteration
10533 int MPICUDA_kmeans::one_iter() {
10534     int status = cuda_mpi_kmeans(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params);
10535     ite++;
10536     return status;
10537 }
10538 // k-means SSE one iteration help function
10539 /*int MPICUDA_kmeans::init_dist() {
10540    
10541     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);
10542    
10543     return status;
10544 }*/
10545 
10546 /*int MPICUDA_kmeans::AVE_to_host() {
10547    
10548     int status = cuda_mpi_kmeans_copy_ave_from_device(h_AVE, d_AVE, params);
10549    
10550     return status;
10551 }*/
10552 
10553 
10554 int one_iter_SA();
10555 // k-means SSE one iteration
10556 /*int MPICUDA_kmeans::one_iter_SSE() {
10557     //if ( ite == 0)
10558     
10559     if( ite ==0) {
10560          int status_init=init_dist();
10561          ttt = compute_tt();//int status = 0;
10562          printf("intial energy ===%f\n",ttt);
10563     }
10564     //std::cout<<bb<<BB<<std::endl;
10565     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);
10566     
10567     //float t = compute_tt();//int status = 0;
10568     //std::cout<<"engery at iteration"<<ite<<"==="<<t<<std::endl;
10569  
10570     ite++;
10571     return status;
10572 }*/
10573 // k-means SA one iteration
10574 int MPICUDA_kmeans::one_iter_SA() {
10575     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);
10576     ite++;
10577     return status;
10578 }
10579 
10580 // compute ji
10581 vector <float> MPICUDA_kmeans::compute_ji() {
10582     int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
10583     vector <float> ji(K);
10584     int i;
10585     if (status != 0) {
10586         for (i = 0; i < K; ++i) ji[i] = -1.0;
10587         return ji;
10588     }
10589     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]]);
10590     return ji;
10591 }
10592 
10593 
10594 float MPICUDA_kmeans::compute_tt() {
10595     /*int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
10596     vector <float> ji(K);
10597     int i;
10598     if (status != 0) {
10599         for (i = 0; i < K; ++i) ji[i] = -1.0;
10600         return -11111111;
10601     }
10602     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]]);
10603    float t =0.0; 
10604    for (i =0; i<K;i++)
10605        t +=ji[i];
10606     return t;*/
10607     
10608            
10609     vector <float> ji(K);
10610     int i,j;
10611     float dist, temp;
10612     for (i = 0; i < n; ++i) 
10613     {
10614         dist =0;
10615         for ( j=0; j<m; j++)     {
10616             temp = (h_im[i*m+j] -h_AVE[ h_asg[i]*m+j]);
10617             dist = dist + temp*temp;
10618          }
10619         ji[h_asg[i]] = ji[h_asg[i]]+ dist;
10620    }
10621         
10622    float t =0.0; 
10623    for (i =0; i<K;i++)
10624        t +=ji[i];
10625     return t;
10626 }
10627 
10628 
10629 //
10630 vector <float> MPICUDA_kmeans::compute_criterion(const vector <float>& Ji) {
10631     float buf = 0.0f;
10632     float Je = 0.0f;
10633     float Tr_AVE = 0.0f;
10634     float v_max = 0.0f;
10635     float* S_AVE2 = (float*)calloc(m, sizeof(float));
10636     float* S_AVE = (float*)calloc(m, sizeof(float));
10637     vector <float> crit(4);
10638     int i, j, k;
10639     // Je
10640     for (i = 0; i < K; ++i) Je += (Ji[i] / float(m));
10641     crit[0] = Je;
10642     // trace ave
10643     for (i = 0; i < K; ++i) {
10644         for (j = 0; j < m; ++j) {
10645             S_AVE[j] += h_AVE[i * m + j];
10646             S_AVE2[j] += (h_AVE[i * m + j] * h_AVE[i * m +j]);
10647         }
10648     }
10649     buf = 1 / (float)K;
10650     for (i = 0; i < m; ++i) Tr_AVE += (buf * (S_AVE2[i] - buf * S_AVE[i] * S_AVE[i]));
10651     // Coleman
10652     crit[1] = Tr_AVE * Je;
10653     // Harabasz
10654     crit[2] = (Tr_AVE * (float)(N - K)) / (Je * (float)(K - 1));
10655     // Davies-Bouldin
10656     for (i = 0; i < K; ++i) {
10657         v_max = 0.0f;
10658         for (j = 0; j < K; ++j) {
10659             if (j != i) {
10660                 buf = 0.0f;
10661                 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]));
10662                 buf = (Ji[i] / (float)h_NC[i] + Ji[j] / (float)h_NC[j]) * ((float)m / buf);
10663             }
10664             if (buf > v_max) v_max = buf;
10665         }
10666         crit[3] += v_max;
10667     }
10668     crit[3] /= (float)K;
10669     free(S_AVE);
10670     free(S_AVE2);
10671     return crit;
10672 }
10673 
10674 // shutdown cublas and release device mem
10675 int MPICUDA_kmeans::shutdown() {
10676     return cuda_mpi_shutdown(d_im, d_AVE, d_dist);
10677 }
10679 
10680 #endif //SPARX_USING_CUDA
10681 
10682 

Generated on Tue Jun 11 13:40:42 2013 for EMAN2 by  doxygen 1.3.9.1