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

Generated on Mon Jul 19 13:03:48 2010 for EMAN2 by  doxygen 1.4.4