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

processor.cpp

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

Generated on Thu Nov 17 12:43:48 2011 for EMAN2 by  doxygen 1.3.9.1