processor.cpp

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

Generated on Tue Jul 12 13:45:50 2011 for EMAN2 by  doxygen 1.4.7