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

processor.cpp

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

Generated on Tue May 25 17:34:13 2010 for EMAN2 by  doxygen 1.4.4