processor.cpp

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

Generated on Mon May 2 13:26:54 2011 for EMAN2 by  doxygen 1.4.7