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         float low_threshold = FLT_MIN;
03706         string low_thr_name = "low_threshold";
03707         if (params.has_key(low_thr_name)) {
03708                 low_threshold = params[low_thr_name];
03709         }
03710 
03711         float high_threshold = FLT_MAX;
03712         string high_thr_name = "high_threshold";
03713         if (params.has_key(high_thr_name)) {
03714                 high_threshold = params[high_thr_name];
03715         }
03716 
03717         float *rawp = image->get_data();
03718         float *refp = to->get_data();
03719 
03720         int nx = image->get_xsize();
03721         int ny = image->get_ysize();
03722         int nz = image->get_zsize();
03723         size_t size = nx * ny * nz;
03724 
03725         float sum_x = 0;
03726         float sum_y = 0;
03727         int count = 0;
03728 
03729         for (size_t i = 0; i < size; i++) {
03730                 if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0 && rawp[i] != 0.0) {
03731                         count++;
03732                         sum_x += refp[i];
03733                         sum_y += rawp[i];
03734                 }
03735         }
03736 
03737         float sum_x_mean = sum_x / count;
03738         float sum_tt = 0;
03739         float b = 0;
03740 
03741         float t;
03742         for (size_t i = 0; i < size; i++) {
03743                 if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0 && rawp[i] != 0.0) {
03744                         t = refp[i] - sum_x_mean;
03745                         sum_tt += t * t;
03746                         b += t * rawp[i];
03747                 }
03748         }
03749 
03750         b /= sum_tt;
03751 
03752         float a = (sum_y - sum_x * b) / count;
03753         float scale = 1 / b;
03754         float shift = -a / b;
03755 
03756         for (size_t i = 0; i < size; i++) {
03757                 rawp[i] = (rawp[i] - a) / b;
03758         }
03759 
03760         image->update();
03761 
03762         params["scale"] = scale;
03763         params["shift"] = shift;
03764 
03765         image->set_attr("norm_mult",scale);
03766         image->set_attr("norm_add",shift);
03767 
03768 }
03769 
03770 
03771 void BinarizeFourierProcessor::process_inplace(EMData* image) {
03772         ENTERFUNC;
03773         if (!image->is_complex()) throw ImageFormatException("Fourier binary thresholding processor only works for complex images");
03774 
03775         float threshold = params.set_default("value",-1.0f);
03776         if (threshold < 0) throw InvalidParameterException("For fourier amplitude-based thresholding, the threshold must be greater than or equal to 0.");
03777 
03778         image->ri2ap(); //  works for cuda
03779 
03780 #ifdef EMAN2_USING_CUDA
03781         if (image->gpu_operation_preferred()) {
03782                 EMDataForCuda tmp = image->get_data_struct_for_cuda();
03783                 binarize_fourier_amp_processor(&tmp,threshold);
03784                 image->set_ri(true); // So it can be used for fourier multiplaction, for example
03785                 image->gpu_update();
03786                 EXITFUNC;
03787                 return;
03788         }
03789 #endif
03790 
03791         float* d = image->get_data();
03792         for( size_t i = 0; i < image->get_size()/2; ++i, d+=2) {
03793                 float v = *d;
03794                 if ( v >= threshold ) {
03795                         *d = 1;
03796                         *(d+1) = 0;
03797                 } else {
03798                         *d = 0;
03799                         *(d+1) = 0;
03800                 }
03801         }
03802 
03803         // No need to run ap2ri, because 1+0i is the same in either notation
03804         image->set_ri(true); // So it can be used for fourier multiplaction, for example
03805         image->update();
03806         EXITFUNC;
03807 }
03808 
03809 
03810 void BilateralProcessor::process_inplace(EMData * image)
03811 {
03812         if (!image) {
03813                 LOGWARN("NULL Image");
03814                 return;
03815         }
03816 
03817         float distance_sigma = params["distance_sigma"];
03818         float value_sigma = params["value_sigma"];
03819         int max_iter = params["niter"];
03820         int half_width = params["half_width"];
03821 
03822         if (half_width < distance_sigma) {
03823                 LOGWARN("localwidth(=%d) should be larger than distance_sigma=(%f)\n",
03824                                                         half_width, distance_sigma);
03825         }
03826 
03827         distance_sigma *= distance_sigma;
03828 
03829         float image_sigma = image->get_attr("sigma");
03830         if (image_sigma > value_sigma) {
03831                 LOGWARN("image sigma(=%f) should be smaller than value_sigma=(%f)\n",
03832                                                         image_sigma, value_sigma);
03833         }
03834         value_sigma *= value_sigma;
03835 
03836         int nx = image->get_xsize();
03837         int ny = image->get_ysize();
03838         int nz = image->get_zsize();
03839 
03840         if(nz==1) {     //for 2D image
03841                 int width=nx, height=ny;
03842 
03843                 int i,j,m,n;
03844 
03845                 float tempfloat1,tempfloat2,tempfloat3;
03846                 int   index1,index2,index;
03847                 int   Iter;
03848                 int   tempint1,tempint3;
03849 
03850                 tempint1=width;
03851                 tempint3=width+2*half_width;
03852 
03853                 float* mask=(float*)calloc((2*half_width+1)*(2*half_width+1),sizeof(float));
03854                 float* OrgImg=(float*)calloc((2*half_width+width)*(2*half_width+height),sizeof(float));
03855                 float* NewImg=image->get_data();
03856 
03857                 for(m=-(half_width);m<=half_width;m++)
03858                         for(n=-(half_width);n<=half_width;n++) {
03859                    index=(m+half_width)*(2*half_width+1)+(n+half_width);
03860                    mask[index]=exp((float)(-(m*m+n*n)/distance_sigma/2.0));
03861                 }
03862 
03863                 //printf("entering bilateral filtering process \n");
03864 
03865                 Iter=0;
03866                 while(Iter<max_iter) {
03867                         for(i=0;i<height;i++)
03868                         for(j=0;j<width;j++) {
03869                                 index1=(i+half_width)*tempint3+(j+half_width);
03870                                         index2=i*tempint1+j;
03871                                 OrgImg[index1]=NewImg[index2];
03872                         }
03873 
03874                         // Mirror Padding
03875                         for(i=0;i<height;i++){
03876                                 for(j=0;j<half_width;j++) OrgImg[(i+half_width)*tempint3+(j)]=OrgImg[(i+half_width)*tempint3+(2*half_width-j)];
03877                                 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)];
03878                         }
03879                         for(i=0;i<half_width;i++){
03880                                 for(j=0;j<(width+2*half_width);j++) OrgImg[i*tempint3+j]=OrgImg[(2*half_width-i)*tempint3+j];
03881                                 for(j=0;j<(width+2*half_width);j++) OrgImg[(i+height+half_width)*tempint3+j]=OrgImg[(height+half_width-2-i)*tempint3+j];
03882                         }
03883 
03884                         //printf("finish mirror padding process \n");
03885                         //now mirror padding have been done
03886 
03887                         for(i=0;i<height;i++){
03888                                 //printf("now processing the %d th row \n",i);
03889                                 for(j=0;j<width;j++){
03890                                         tempfloat1=0.0; tempfloat2=0.0;
03891                                         for(m=-(half_width);m<=half_width;m++)
03892                                                 for(n=-(half_width);n<=half_width;n++){
03893                                                         index =(m+half_width)*(2*half_width+1)+(n+half_width);
03894                                                         index1=(i+half_width)*tempint3+(j+half_width);
03895                                                         index2=(i+half_width+m)*tempint3+(j+half_width+n);
03896                                                         tempfloat3=(OrgImg[index1]-OrgImg[index2])*(OrgImg[index1]-OrgImg[index2]);
03897 
03898                                                         tempfloat3=mask[index]*(1.0f/(1+tempfloat3/value_sigma));       // Lorentz kernel
03899                                                         //tempfloat3=mask[index]*exp(tempfloat3/Sigma2/(-2.0)); // Guassian kernel
03900                                                         tempfloat1+=tempfloat3;
03901 
03902                                                         tempfloat2+=tempfloat3*OrgImg[(i+half_width+m)*tempint3+(j+half_width+n)];
03903                                         }
03904                                         NewImg[i*width+j]=tempfloat2/tempfloat1;
03905                                 }
03906                         }
03907                         Iter++;
03908             }
03909 
03910             //printf("have finished %d  th iteration\n ",Iter);
03911 //              doneData();
03912                 free(mask);
03913                 free(OrgImg);
03914                 // end of BilaFilter routine
03915 
03916         }
03917         else {  //3D case
03918                 int width = nx;
03919                 int height = ny;
03920                 int slicenum = nz;
03921 
03922                 int slice_size = width * height;
03923                 int new_width = width + 2 * half_width;
03924                 int new_slice_size = (width + 2 * half_width) * (height + 2 * half_width);
03925 
03926                 int width1 = 2 * half_width + 1;
03927                 int mask_size = width1 * width1;
03928                 int old_img_size = (2 * half_width + width) * (2 * half_width + height);
03929 
03930                 int zstart = -half_width;
03931                 int zend = -half_width;
03932                 int is_3d = 0;
03933                 if (nz > 1) {
03934                         mask_size *= width1;
03935                         old_img_size *= (2 * half_width + slicenum);
03936                         zend = half_width;
03937                         is_3d = 1;
03938                 }
03939 
03940                 float *mask = (float *) calloc(mask_size, sizeof(float));
03941                 float *old_img = (float *) calloc(old_img_size, sizeof(float));
03942 
03943                 float *new_img = image->get_data();
03944 
03945                 for (int p = zstart; p <= zend; p++) {
03946                         int cur_p = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
03947 
03948                         for (int m = -half_width; m <= half_width; m++) {
03949                                 int cur_m = (m + half_width) * (2 * half_width + 1) + half_width;
03950 
03951                                 for (int n = -half_width; n <= half_width; n++) {
03952                                         int l = cur_p + cur_m + n;
03953                                         mask[l] = exp((float) (-(m * m + n * n + p * p * is_3d) / distance_sigma / 2.0f));
03954                                 }
03955                         }
03956                 }
03957 
03958                 int iter = 0;
03959                 while (iter < max_iter) {
03960                         for (int k = 0; k < slicenum; k++) {
03961                                 int cur_k1 = (k + half_width) * new_slice_size * is_3d;
03962                                 int cur_k2 = k * slice_size;
03963 
03964                                 for (int i = 0; i < height; i++) {
03965                                         int cur_i1 = (i + half_width) * new_width;
03966                                         int cur_i2 = i * width;
03967 
03968                                         for (int j = 0; j < width; j++) {
03969                                                 int k1 = cur_k1 + cur_i1 + (j + half_width);
03970                                                 int k2 = cur_k2 + cur_i2 + j;
03971                                                 old_img[k1] = new_img[k2];
03972                                         }
03973                                 }
03974                         }
03975 
03976                         for (int k = 0; k < slicenum; k++) {
03977                                 int cur_k = (k + half_width) * new_slice_size * is_3d;
03978 
03979                                 for (int i = 0; i < height; i++) {
03980                                         int cur_i = (i + half_width) * new_width;
03981 
03982                                         for (int j = 0; j < half_width; j++) {
03983                                                 int k1 = cur_k + cur_i + j;
03984                                                 int k2 = cur_k + cur_i + (2 * half_width - j);
03985                                                 old_img[k1] = old_img[k2];
03986                                         }
03987 
03988                                         for (int j = 0; j < half_width; j++) {
03989                                                 int k1 = cur_k + cur_i + (width + half_width + j);
03990                                                 int k2 = cur_k + cur_i + (width + half_width - j - 2);
03991                                                 old_img[k1] = old_img[k2];
03992                                         }
03993                                 }
03994 
03995 
03996                                 for (int i = 0; i < half_width; i++) {
03997                                         int i2 = i * new_width;
03998                                         int i3 = (2 * half_width - i) * new_width;
03999                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04000                                                 int k1 = cur_k + i2 + j;
04001                                                 int k2 = cur_k + i3 + j;
04002                                                 old_img[k1] = old_img[k2];
04003                                         }
04004 
04005                                         i2 = (height + half_width + i) * new_width;
04006                                         i3 = (height + half_width - 2 - i) * new_width;
04007                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04008                                                 int k1 = cur_k + i2 + j;
04009                                                 int k2 = cur_k + i3 + j;
04010                                                 old_img[k1] = old_img[k2];
04011                                         }
04012                                 }
04013                         }
04014 
04015                         size_t idx;
04016                         for (int k = 0; k < slicenum; k++) {
04017                                 int cur_k = (k + half_width) * new_slice_size;
04018 
04019                                 for (int i = 0; i < height; i++) {
04020                                         int cur_i = (i + half_width) * new_width;
04021 
04022                                         for (int j = 0; j < width; j++) {
04023                                                 float f1 = 0;
04024                                                 float f2 = 0;
04025                                                 int k1 = cur_k + cur_i + (j + half_width);
04026 
04027                                                 for (int p = zstart; p <= zend; p++) {
04028                                                         int cur_p1 = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04029                                                         int cur_p2 = (k + half_width + p) * new_slice_size;
04030 
04031                                                         for (int m = -half_width; m <= half_width; m++) {
04032                                                                 int cur_m1 = (m + half_width) * (2 * half_width + 1);
04033                                                                 int cur_m2 = cur_p2 + cur_i + m * new_width + j + half_width;
04034 
04035                                                                 for (int n = -half_width; n <= half_width; n++) {
04036                                                                         int k = cur_p1 + cur_m1 + (n + half_width);
04037                                                                         int k2 = cur_m2 + n;
04038                                                                         float f3 = Util::square(old_img[k1] - old_img[k2]);
04039 
04040                                                                         f3 = mask[k] * (1.0f / (1 + f3 / value_sigma));
04041                                                                         f1 += f3;
04042                                                                         int l1 = cur_m2 + n;
04043                                                                         f2 += f3 * old_img[l1];
04044                                                                 }
04045 
04046                                                                 idx = k * height * width + i * width + j;
04047                                                                 new_img[idx] = f2 / f1;
04048                                                         }
04049                                                 }
04050                                         }
04051                                 }
04052                         }
04053                         iter++;
04054                 }
04055                 if( mask ) {
04056                         free(mask);
04057                         mask = 0;
04058                 }
04059 
04060                 if( old_img ) {
04061                         free(old_img);
04062                         old_img = 0;
04063                 }
04064         }
04065 
04066         image->update();
04067 }
04068 
04069 void RotationalAverageProcessor::process_inplace(EMData * image)
04070 {
04071         if (!image || image->is_complex()) {
04072                 LOGWARN("only works on real image. do nothing.");
04073                 return;
04074         }
04075 
04076         if (image->get_ndim() <= 0 || image->get_ndim() > 3)    throw ImageDimensionException("radial average processor only works for 2D and 3D images");
04077 
04078         float *rdata = image->get_data();
04079         int nx = image->get_xsize();
04080         int ny = image->get_ysize();
04081 
04082         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04083 
04084         float midx = (float)((int)nx/2);
04085         float midy = (float)((int)ny/2);
04086 
04087         size_t c = 0;
04088         if (image->get_ndim() == 2) {
04089                 for (int y = 0; y < ny; y++) {
04090                         for (int x = 0; x < nx; x++, c++) {
04091         #ifdef  _WIN32
04092                                 float r = (float) _hypot(x - midx, y - midy);
04093         #else
04094                                 float r = (float) hypot(x - midx, y - midy);
04095         #endif  //_WIN32
04096 
04097 
04098                                 int i = (int) floor(r);
04099                                 r -= i;
04100                                 if (i >= 0 && i < nx / 2 - 1) {
04101                                         rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04102                                 }
04103                                 else if (i < 0) {
04104                                         rdata[c] = dist[0];
04105                                 }
04106                                 else {
04107                                         rdata[c] = 0;
04108                                 }
04109                         }
04110                 }
04111         }
04112         else if (image->get_ndim() == 3) {
04113                 int nz = image->get_zsize();
04114                 float midz = (float)((int)nz/2);
04115                 float r;
04116                 int i;
04117                 for (int z = 0; z < nz; ++z) {
04118                         for (int y = 0; y < ny; ++y) {
04119                                 for (int x = 0; x < nx; ++x, ++c) {
04120 
04121                                         r = (float) Util::hypot3(x - midx, y - midy, z - midz);
04122 
04123                                         i = Util::fast_floor(r);
04124                                         r -= i;
04125                                         if (i >= 0 && i < nx / 2 - 1) {
04126                                                 rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04127                                         }
04128                                         else if (i < 0) {
04129                                                 rdata[c] = dist[0];
04130                                         }
04131                                         else {
04132                                                 rdata[c] = 0;
04133                                         }
04134                                 }
04135                         }
04136                 }
04137         }
04138 
04139         image->update();
04140 }
04141 
04142 
04143 
04144 void RotationalSubstractProcessor::process_inplace(EMData * image)
04145 {
04146         if (!image || image->is_complex()) {
04147                 LOGWARN("only works on real image. do nothing.");
04148                 return;
04149         }
04150 
04151         if (image->get_ndim() != 2) throw ImageDimensionException("This processor works only for 2D images");
04152 
04153         float *rdata = image->get_data();
04154         int nx = image->get_xsize();
04155         int ny = image->get_ysize();
04156 
04157         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04158 
04159         int c = 0;
04160         for (int y = 0; y < ny; y++) {
04161                 for (int x = 0; x < nx; x++, c++) {
04162 #ifdef  _WIN32
04163                         float r = (float) _hypot(x - nx / 2, y - ny / 2);
04164 #else
04165                         float r = (float) hypot(x - nx / 2, y - ny / 2);
04166 #endif
04167                         int i = (int) floor(r);
04168                         r -= i;
04169                         if (i >= 0 && i < nx / 2 - 1) {
04170                                 rdata[c] -= dist[i] * (1.0f - r) + dist[i + 1] * r;
04171                         }
04172                         else {
04173                                 rdata[c] = 0;
04174                         }
04175                 }
04176         }
04177 
04178         image->update();
04179 }
04180 
04181 
04182 EMData* TransposeProcessor::process(const EMData* const image) {
04183         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04184         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04185 
04186         EMData* ret = new EMData(image->get_ysize(),image->get_xsize(),1); // transpose dimensions
04187 
04188         for(int j = 0; j< image->get_ysize();++j) {
04189                 for(int i = 0; i< image->get_xsize();++i) {
04190                         ret->set_value_at(j,i,image->get_value_at(i,j));
04191                 }
04192         }
04193 
04194         return ret;
04195 
04196 }
04197 
04198 void TransposeProcessor::process_inplace(EMData* image) {
04199         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04200         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04201 
04202         float* data = (float*)malloc(image->get_ysize()*image->get_xsize()*sizeof(float));
04203 
04204         int nx = image->get_ysize(); // note tranpose
04205         for(int j = 0; j< image->get_ysize();++j) {
04206                 for(int i = 0; i< image->get_xsize();++i) {
04207                         data[i*nx+j] = image->get_value_at(i,j);
04208                 }
04209         }
04210 
04211         image->set_data(data,image->get_ysize(),image->get_xsize(),1);
04212 
04213 }
04214 
04215 void FlipProcessor::process_inplace(EMData * image)
04216 {
04217         ENTERFUNC;
04218         if (!image) {
04219                 LOGWARN("NULL Image");
04220                 return;
04221         }
04222         string axis = (const char*)params["axis"];
04223 #ifdef EMAN2_USING_CUDA
04224         if (image->gpu_operation_preferred()) {
04225                 float array[12] = {1.0, 0.0, 0.0, 0.0,
04226                                                    0.0, 1.0, 0.0, 0.0,
04227                                                    0.0, 0.0, 1.0, 0.0};
04228                 if (axis == "x" || axis == "X") {               // horizontal flip
04229                         array[0] = -1.0;
04230                 }else if (axis == "y" || axis == "Y") {         // vertical flip
04231                         array[5] = -1.0;
04232                 }
04233                 else if (axis == "z" || axis == "Z") {          // vertical flip
04234                         array[10] = -1.0;
04235                 }
04236                 Transform t(array);
04237                 Dict params("transform",(Transform*)&t);
04238                 image->process_inplace("xform",params);
04239                 EXITFUNC;
04240                 return;
04241         }
04242 #endif
04243 
04244 
04245         float *d = image->get_data();
04246         int nx = image->get_xsize();
04247         int ny = image->get_ysize();
04248         int nz = image->get_zsize();
04249 
04250         size_t nxy = nx * ny;
04251 
04252 
04253         // Note in all cases the origin is nx/2, ny/2 and nz/2
04254         // This means when flipping even sized dimensions that some pixels are redundant.
04255         // Here redundant pixels are set to zero, however, should this change to something
04256         // like the mean.
04257         if (axis == "x" || axis == "X") {               // Horizontal flip
04258                 int offset = (nx%2 == 0);
04259                 size_t idx1, idx2;
04260                 for(int z = 0; z < nz; ++z) {
04261                         for(int y = 0; y < ny; ++y) {
04262                                 if (offset != 0 ) {
04263                                         idx1 = z*nxy + y*nx;
04264                                         d[idx1] = 0; // Here's where you'd make it the mean
04265                                 }
04266                                 for(int x = offset; x < nx / 2; ++x) {
04267                                         idx1 = z*nxy + y*nx + x;
04268                                         idx2 = z*nxy + y*nx + (nx-x-1+offset);
04269                                         std::swap(d[idx1], d[idx2]);
04270                                 }
04271 
04272                         }
04273                 }
04274         }
04275 
04276         else if (axis == "y" || axis == "Y") {          // vertical flip
04277                 int offset = (ny%2 == 0);
04278                 for(int z=0; z<nz; ++z) {
04279                         if (offset != 0) {
04280                                 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)
04281                         }
04282                         for(int y=offset; y<ny/2; ++y) {
04283                                 for(int x=0; x<nx; ++x) {
04284                                         std::swap(d[z*nxy + y*nx +x], d[z*nxy + (ny -y -1+offset)*nx +x]);
04285                                 }
04286                         }
04287                 }
04288         }
04289         else if (axis == "z" || axis == "Z") {          //z axis flip
04290                 int offset = (nz%2 == 0);
04291                 if (offset != 0) {
04292                         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)
04293                 }
04294                 size_t idx1, idx2;
04295                 for(int z=offset; z<nz/2; ++z) {
04296                         for(int y=0; y<ny; ++y) {
04297                                 for(int x=0; x<nx; ++x) {
04298                                         idx1 = z*nxy + y*nx + x;
04299                                         idx2 = (nz-z-1+offset)*nxy + y*nx + x;
04300                                         std::swap(d[idx1], d[idx2]);
04301                                 }
04302                         }
04303                 }
04304         }
04305 
04306         image->update();
04307         EXITFUNC;
04308 }
04309 
04310 void AddNoiseProcessor::process_inplace(EMData * image)
04311 {
04312         if (!image) {
04313                 LOGWARN("NULL Image");
04314                 return;
04315         }
04316 
04317         Randnum * randnum = Randnum::Instance();
04318         if(params.has_key("seed")) {
04319                 randnum->set_seed((int)params["seed"]);
04320         }
04321 
04322         float addnoise = params["noise"];
04323         addnoise *= get_sigma(image);
04324         float *dat = image->get_data();
04325 
04326         for (size_t j = 0; j < image->get_size(); ++j) {
04327                 dat[j] += randnum->get_gauss_rand(addnoise, addnoise / 2);
04328         }
04329 
04330         image->update();
04331 }
04332 
04333 float AddSigmaNoiseProcessor::get_sigma(EMData * image)
04334 {
04335         if (!image) {
04336                 LOGWARN("NULL Image");
04337                 return 0;
04338         }
04339         return image->get_attr("sigma");
04340 }
04341 
04342 void FourierToCornerProcessor::process_inplace(EMData * image)
04343 {
04344         if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04345 
04346         int nx=image->get_xsize();
04347         int ny=image->get_ysize();
04348         int nz=image->get_zsize();
04349 
04350         int nxy = nx*ny;
04351 
04352         if ( ny == 1 && nz == 1 ){
04353                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04354                 return;
04355         }
04356         int yodd = (ny%2==1);
04357         int zodd = (nz%2==1);
04358 
04359         float* rdata = image->get_data();
04360 
04361         float tmp[2];
04362         float* p1;
04363         float* p2;
04364 
04365         if (yodd){
04366                 // Swap the middle slice (with respect to the y direction) with the bottom slice
04367                 // shifting all slices above the middles slice upwards by one pixel, stopping
04368                 // at the middle slice, not if nz = 1 we are not talking about slices, we are
04369                 // talking about rows
04370                 float prev[2];
04371                 size_t idx;
04372                 for( int s = 0; s < nz; s++ ) {
04373                         for( int c =0; c < nx; c += 2 ) {
04374                                 idx = s*nxy+ny/2*nx+c;
04375                                 prev[0] = rdata[idx];
04376                                 prev[1] = rdata[idx+1];
04377                                 for( int r = 0; r <= ny/2; ++r ) {
04378                                         idx = s*nxy+r*nx+c;
04379                                         float* p1 = &rdata[idx];
04380                                         tmp[0] = p1[0];
04381                                         tmp[1] = p1[1];
04382 
04383                                         p1[0] = prev[0];
04384                                         p1[1] = prev[1];
04385 
04386                                         prev[0] = tmp[0];
04387                                         prev[1] = tmp[1];
04388                                 }
04389                         }
04390                 }
04391         }
04392 
04393         // Shift slices (3D) or rows (2D) correctly in the y direction
04394         size_t idx1, idx2;
04395         for( int s = 0; s < nz; ++s ) {
04396                 for( int r = 0 + yodd; r < ny/2+yodd; ++r ) {
04397                         for( int c =0; c < nx; c += 2 ) {
04398                                 idx1 = s*nxy+r*nx+c;
04399                                 idx2 = s*nxy+(r+ny/2)*nx+c;
04400                                 p1 = &rdata[idx1];
04401                                 p2 = &rdata[idx2];
04402 
04403                                 tmp[0] = p1[0];
04404                                 tmp[1] = p1[1];
04405 
04406                                 p1[0] = p2[0];
04407                                 p1[1] = p2[1];
04408 
04409                                 p2[0] = tmp[0];
04410                                 p2[1] = tmp[1];
04411                         }
04412                 }
04413         }
04414 
04415         if ( nz != 1 )
04416         {
04417 
04418                 if (zodd){
04419                         // Swap the middle slice (with respect to the z direction) and the front slice
04420                         // shifting all behind the front slice towards the middle a distance of 1 voxel,
04421                         // stopping at the middle slice.
04422                         float prev[2];
04423                         size_t idx;
04424                         for( int r = 0; r < ny; ++r ) {
04425                                 for( int c =0; c < nx; c += 2 ) {
04426                                         idx = nz/2*nxy+r*nx+c;
04427                                         prev[0] = rdata[idx];
04428                                         prev[1] = rdata[idx+1];
04429                                         for( int s = 0; s <= nz/2; ++s ) {
04430                                                 idx = s*nxy+r*nx+c;
04431                                                 float* p1 = &rdata[idx];
04432                                                 tmp[0] = p1[0];
04433                                                 tmp[1] = p1[1];
04434 
04435                                                 p1[0] = prev[0];
04436                                                 p1[1] = prev[1];
04437 
04438                                                 prev[0] = tmp[0];
04439                                                 prev[1] = tmp[1];
04440                                         }
04441                                 }
04442                         }
04443                 }
04444 
04445                 // Shift slices correctly in the z direction
04446                 size_t idx1, idx2;
04447                 for( int s = 0+zodd; s < nz/2 + zodd; ++s ) {
04448                         for( int r = 0; r < ny; ++r ) {
04449                                 for( int c =0; c < nx; c += 2 ) {
04450                                         idx1 = s*nxy+r*nx+c;
04451                                         idx2 = (s+nz/2)*nxy+r*nx+c;
04452                                         p1 = &rdata[idx1];
04453                                         p2 = &rdata[idx2];
04454 
04455                                         tmp[0] = p1[0];
04456                                         tmp[1] = p1[1];
04457 
04458                                         p1[0] = p2[0];
04459                                         p1[1] = p2[1];
04460 
04461                                         p2[0] = tmp[0];
04462                                         p2[1] = tmp[1];
04463                                 }
04464                         }
04465                 }
04466         }
04467         image->set_shuffled(false);
04468 }
04469 
04470 void FourierToCenterProcessor::process_inplace(EMData * image)
04471 {
04472 //      if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04473 
04474         int nx=image->get_xsize();
04475         int ny=image->get_ysize();
04476         int nz=image->get_zsize();
04477 
04478         int nxy = nx*ny;
04479 
04480         if ( ny == 1 && nz == 1 ){
04481                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04482                 return;
04483         }
04484 
04485         int yodd = (ny%2==1);
04486         int zodd = (nz%2==1);
04487 
04488         float* rdata = image->get_data();
04489 
04490         float tmp[2];
04491         float* p1;
04492         float* p2;
04493 
04494         // This will tackle the 'normalization' images which come out of the Fourier reconstructor.
04495         // ie- real-space 1/2 FFt images centered on the corner
04496         if ( !image->is_complex() ) {
04497                 if (nz!=1 && !yodd && !zodd) {
04498                         for (int x=0; x<nx; x++) {
04499                                 for (int y=0; y<ny; y++) {
04500                                         for (int z=0; z<nz/2; z++) {
04501                                                 int y2=(y+ny/2)%ny;
04502                                                 int z2=(z+nz/2)%nz;             // %nz should be redundant here
04503                                                 size_t i=x+y*nx+z*nxy;
04504                                                 size_t i2=x+y2*nx+z2*nxy;
04505                                                 float swp=rdata[i];
04506                                                 rdata[i]=rdata[i2];
04507                                                 rdata[i2]=swp;
04508                                         }
04509                                 }
04510                         }
04511 
04512                         return;
04513                 }
04514                 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");
04515         }
04516 
04517         if (yodd){
04518                 // In 3D this is swapping the bottom slice (with respect to the y direction) and the middle slice,
04519                 // shifting all slices below the middle slice down one. In 2D it is equivalent, but in terms of rows.
04520                 float prev[2];
04521                 size_t idx;
04522                 for( int s = 0; s < nz; s++ ) {
04523                         for( int c =0; c < nx; c += 2 ) {
04524                                 idx = s*nxy+c;
04525                                 prev[0] = rdata[idx];
04526                                 prev[1] = rdata[idx+1];
04527                                 for( int r = ny/2; r >= 0; --r ) {
04528                                         idx = s*nxy+r*nx+c;
04529                                         float* p1 = &rdata[idx];
04530                                         tmp[0] = p1[0];
04531                                         tmp[1] = p1[1];
04532 
04533                                         p1[0] = prev[0];
04534                                         p1[1] = prev[1];
04535 
04536                                         prev[0] = tmp[0];
04537                                         prev[1] = tmp[1];
04538                                 }
04539                         }
04540                 }
04541         }
04542 
04543         // 3D - Shift slices correctly in the y direction, 2D - shift rows
04544         size_t idx1, idx2;
04545         for( int s = 0; s < nz; ++s ) {
04546                 for( int r = 0; r < ny/2; ++r ) {
04547                         for( int c =0; c < nx; c += 2 ) {
04548                                 idx1 = s*nxy+r*nx+c;
04549                                 idx2 = s*nxy+(r+ny/2+yodd)*nx+c;
04550                                 p1 = &rdata[idx1];
04551                                 p2 = &rdata[idx2];
04552 
04553                                 tmp[0] = p1[0];
04554                                 tmp[1] = p1[1];
04555 
04556                                 p1[0] = p2[0];
04557                                 p1[1] = p2[1];
04558 
04559                                 p2[0] = tmp[0];
04560                                 p2[1] = tmp[1];
04561                         }
04562                 }
04563         }
04564 
04565         if ( nz != 1 )  {
04566                 if (zodd){
04567                         // Swap the front slice (with respect to the z direction) and the middle slice
04568                         // shifting all slices behind the middles slice towards the front slice 1 voxel.
04569                         float prev[2];
04570                         size_t idx;
04571                         for( int r = 0; r < ny; ++r ) {
04572                                 for( int c =0; c < nx; c += 2 ) {
04573                                         prev[0] = rdata[r*nx+c];
04574                                         prev[1] = rdata[r*nx+c+1];
04575                                         for( int s = nz/2; s >= 0; --s ) {
04576                                                 idx = s*nxy+r*nx+c;
04577                                                 float* p1 = &rdata[idx];
04578                                                 tmp[0] = p1[0];
04579                                                 tmp[1] = p1[1];
04580 
04581                                                 p1[0] = prev[0];
04582                                                 p1[1] = prev[1];
04583 
04584                                                 prev[0] = tmp[0];
04585                                                 prev[1] = tmp[1];
04586                                         }
04587                                 }
04588                         }
04589                 }
04590 
04591                 // Shift slices correctly in the y direction
04592                 size_t idx1, idx2;
04593                 for( int s = 0; s < nz/2; ++s ) {
04594                         for( int r = 0; r < ny; ++r ) {
04595                                 for( int c =0; c < nx; c += 2 ) {
04596                                         idx1 = s*nxy+r*nx+c;
04597                                         idx2 = (s+nz/2+zodd)*nxy+r*nx+c;
04598                                         p1 = &rdata[idx1];
04599                                         p2 = &rdata[idx2];
04600 
04601                                         tmp[0] = p1[0];
04602                                         tmp[1] = p1[1];
04603 
04604                                         p1[0] = p2[0];
04605                                         p1[1] = p2[1];
04606 
04607                                         p2[0] = tmp[0];
04608                                         p2[1] = tmp[1];
04609                                 }
04610                         }
04611                 }
04612         }
04613         image->set_shuffled(true);
04614 }
04615 
04616 void Phase180Processor::fourier_phaseshift180(EMData * image)
04617 {
04618         if ( !image->is_complex() ) throw ImageFormatException("Can not handle images that are not complex in fourier phase shift 180");
04619 
04620         int nx = image->get_xsize();
04621         int ny = image->get_ysize();
04622         int nz = image->get_zsize();
04623 
04624         int nxy = nx * ny;
04625 
04626         float *rdata = image->get_data();
04627 
04628         // Who uses this function? It doesn't work for odd images, and it will give incorrect results for some even images
04629         // d.woolford, March 15 2009
04630         int of=0;
04631         if (((ny/2)%2)+((nz/2)%2)==1) of=1;
04632 
04633         for (int k = 0; k < nz; k++) {
04634                 size_t k2 = k * nxy;
04635 
04636                 for (int j = 0; j < ny; j++) {
04637                         int i = ((k+j)%2==of?2:0);
04638                         size_t j2 = j * nx + k2;
04639 
04640                         for (; i < nx; i += 4) {
04641                                 rdata[i + j2] *= -1.0f;
04642                                 rdata[i + j2 + 1] *= -1.0f;
04643                         }
04644                 }
04645         }
04646 }
04647 
04648 void Phase180Processor::swap_corners_180(EMData * image)
04649 {
04650         int nx = image->get_xsize();
04651         int ny = image->get_ysize();
04652         int nz = image->get_zsize();
04653 
04654         int xodd = (nx % 2) == 1;
04655         int yodd = (ny % 2) == 1;
04656         int zodd = (nz % 2) == 1;
04657 
04658         int nxy = nx * ny;
04659 
04660         float *rdata = image->get_data();
04661 
04662         if ( ny == 1 && nz == 1 ){
04663                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04664         }
04665         else if ( nz == 1 ) {
04666 
04667                 // Swap the bottom left and top right corners
04668                 for ( int r = 0; r < ny/2; ++r ) {
04669                         for ( int c = 0; c < nx/2; ++c) {
04670                                 int idx1 = r*nx + c;
04671                                 int idx2 = (r+ny/2+yodd)*nx + c + nx/2+xodd;
04672                                 float tmp = rdata[idx1];
04673                                 rdata[idx1] = rdata[idx2];
04674                                 rdata[idx2] = tmp;
04675                         }
04676                 }
04677 
04678                 // Swap the top left and bottom right corners
04679                 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04680                         for ( int c = 0; c < nx/2; ++c) {
04681                                 int idx1 = r*nx + c;
04682                                 int idx2 = (r-ny/2-yodd)*nx + c + nx/2+xodd;
04683                                 float tmp = rdata[idx1];
04684                                 rdata[idx1] = rdata[idx2];
04685                                 rdata[idx2] = tmp;
04686                         }
04687                 }
04688         }
04689         else // nx && ny && nz are greater than 1
04690         {
04691                 float tmp;
04692                 // Swap the bottom left front and back right top quadrants
04693                 size_t idx1, idx2;
04694 
04695                 for ( int s = 0; s < nz/2; ++s ) {
04696                         for ( int r = 0; r < ny/2; ++r ) {
04697                                 for ( int c = 0; c < nx/2; ++ c) {
04698                                         idx1 = s*nxy+r*nx+c;
04699                                         idx2 = (s+nz/2+zodd)*nxy+(r+ny/2+yodd)*nx+c+nx/2+xodd;
04700                                         tmp = rdata[idx1];
04701                                         rdata[idx1] = rdata[idx2];
04702                                         rdata[idx2] = tmp;
04703                                 }
04704                         }
04705                 }
04706                 // Swap the bottom right front and back left top quadrants
04707                 for ( int s = 0; s < nz/2; ++s ) {
04708                         for ( int r = 0; r < ny/2; ++r ) {
04709                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04710                                         idx1 = s*nxy+r*nx+c;
04711                                         idx2 = (s+nz/2+zodd)*nxy+(r+ny/2+yodd)*nx+c-nx/2-xodd;
04712                                         tmp = rdata[idx1];
04713                                         rdata[idx1] = rdata[idx2];
04714                                         rdata[idx2] = tmp;
04715                                 }
04716                         }
04717                 }
04718                 // Swap the top right front and back left bottom quadrants
04719                 for ( int s = 0; s < nz/2; ++s ) {
04720                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04721                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04722                                         idx1 = s*nxy+r*nx+c;
04723                                         idx2 = (s+nz/2+zodd)*nxy+(r-ny/2-yodd)*nx+c-nx/2-xodd;
04724                                         tmp = rdata[idx1];
04725                                         rdata[idx1] = rdata[idx2];
04726                                         rdata[idx2] = tmp;
04727                                 }
04728                         }
04729                 }
04730                 // Swap the top left front and back right bottom quadrants
04731                 for ( int s = 0; s < nz/2; ++s ) {
04732                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04733                                 for ( int c = 0; c < nx/2; ++c) {
04734                                         idx1 = s*nxy+r*nx+c;
04735                                         idx2 = (s+nz/2+zodd)*nxy+(r-ny/2-yodd)*nx+c+nx/2+xodd;
04736                                         tmp = rdata[idx1];
04737                                         rdata[idx1] = rdata[idx2];
04738                                         rdata[idx2] = tmp;
04739                                 }
04740                         }
04741                 }
04742         }
04743 }
04744 
04745 void Phase180Processor::swap_central_slices_180(EMData * image)
04746 {
04747         int nx = image->get_xsize();
04748         int ny = image->get_ysize();
04749         int nz = image->get_zsize();
04750 
04751         int xodd = (nx % 2) == 1;
04752         int yodd = (ny % 2) == 1;
04753         int zodd = (nz % 2) == 1;
04754 
04755         int nxy = nx * ny;
04756 
04757         float *rdata = image->get_data();
04758 
04759         if ( ny == 1 && nz == 1 ){
04760                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04761         }
04762         else if ( nz == 1 ) {
04763                 float tmp;
04764                 if ( yodd ) {
04765                         // Iterate along middle row, swapping values where appropriate
04766                         int r = ny/2;
04767                         for ( int c = 0; c < nx/2; ++c ) {
04768                                 int idx1 = r*nx + c;
04769                                 int idx2 = r*nx + c + nx/2+ xodd;
04770                                 tmp = rdata[idx1];
04771                                 rdata[idx1] = rdata[idx2];
04772                                 rdata[idx2] = tmp;
04773                         }
04774                 }
04775 
04776                 if ( xodd )     {
04777                         // Iterate along the central column, swapping values where appropriate
04778                         int c = nx/2;
04779                         for (  int r = 0; r < ny/2; ++r ) {
04780                                 int idx1 = r*nx + c;
04781                                 int idx2 = (r+ny/2+yodd)*nx + c;
04782                                 tmp = rdata[idx1];
04783                                 rdata[idx1] = rdata[idx2];
04784                                 rdata[idx2] = tmp;
04785                         }
04786                 }
04787         }
04788         else // nx && ny && nz are greater than 1
04789         {
04790                 float tmp;
04791                 if ( xodd ) {
04792                         // Iterate along the x = nx/2 slice, swapping values where appropriate
04793                         int c = nx/2;
04794                         size_t idx1, idx2;
04795                         for( int s = 0; s < nz/2; ++s ) {
04796                                 for ( int r = 0; r < ny/2; ++r ) {
04797                                         idx1 = s*nxy+r*nx+c;
04798                                         idx2 = (s+nz/2+zodd)*nxy+(r+ny/2+yodd)*nx+c;
04799                                         tmp = rdata[idx1];
04800                                         rdata[idx1] = rdata[idx2];
04801                                         rdata[idx2] = tmp;
04802                                 }
04803                         }
04804 
04805                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
04806                                 for ( int r = 0; r < ny/2; ++r ) {
04807                                         idx1 = s*nxy+r*nx+c;
04808                                         idx2 = (s-nz/2-zodd)*nxy+(r+ny/2+yodd)*nx+c;
04809                                         tmp = rdata[idx1];
04810                                         rdata[idx1] = rdata[idx2];
04811                                         rdata[idx2] = tmp;
04812                                 }
04813                         }
04814                 }
04815                 if ( yodd ) {
04816                         // Iterate along the y = ny/2 slice, swapping values where appropriate
04817                         int r = ny/2;
04818                         size_t idx1, idx2;
04819                         for( int s = 0; s < nz/2; ++s ) {
04820                                 for ( int c = 0; c < nx/2; ++c ) {
04821                                         idx1 = s*nxy+r*nx+c;
04822                                         idx2 =(s+nz/2+zodd)*nxy+r*nx+c+nx/2+xodd;
04823                                         tmp = rdata[idx1];
04824                                         rdata[idx1] = rdata[idx2];
04825                                         rdata[idx2] = tmp;
04826                                 }
04827                         }
04828 
04829                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
04830                                 for ( int c = 0; c < nx/2; ++c ) {
04831                                         idx1 = s*nxy+r*nx+c;
04832                                         idx2 = (s-nz/2-zodd)*nxy+r*nx+c+nx/2+xodd;
04833                                         tmp = rdata[idx1];
04834                                         rdata[idx1] = rdata[idx2];
04835                                         rdata[idx2] = tmp;
04836                                 }
04837                         }
04838                 }
04839                 if ( zodd ) {
04840                         // Iterate along the z = nz/2 slice, swapping values where appropriate
04841                         int s = nz/2;
04842                         size_t idx1, idx2;
04843                         for( int r = 0; r < ny/2; ++r ) {
04844                                 for ( int c = 0; c < nx/2; ++c ) {
04845                                         idx1 = s*nxy+r*nx+c;
04846                                         idx2 = s*nxy+(r+ny/2+yodd)*nx+c+nx/2+xodd;
04847                                         tmp = rdata[idx1];
04848                                         rdata[idx1] = rdata[idx2];
04849                                         rdata[idx2] = tmp;
04850                                 }
04851                         }
04852 
04853                         for( int r = ny-1; r >= (ny/2+yodd); --r ) {
04854                                 for ( int c = 0; c < nx/2; ++c ) {
04855                                         idx1 = s*nxy+r*nx+c;
04856                                         idx2 = s*nxy+(r-ny/2-yodd)*nx+c+nx/2+xodd;
04857                                         tmp = rdata[idx1];
04858                                         rdata[idx1] = rdata[idx2];
04859                                         rdata[idx2] = tmp;
04860                                 }
04861                         }
04862                 }
04863         }
04864 }
04865 
04866 void PhaseToCornerProcessor::process_inplace(EMData * image)
04867 {
04868         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
04869 
04870         if (image->is_complex()) {
04871                 fourier_phaseshift180(image);
04872                 return;
04873         }
04874 
04875         int nx = image->get_xsize();
04876         int ny = image->get_ysize();
04877         int nz = image->get_zsize();
04878 
04879         if ( ny == 1 && nz == 1 && nx == 1) return;
04880 
04881         int nxy = nx * ny;
04882 
04883         float *rdata = image->get_data();
04884 
04885         bool xodd = (nx % 2) == 1;
04886         bool yodd = (ny % 2) == 1;
04887         bool zodd = (nz % 2) == 1;
04888 
04889         if ( ny == 1 && nz == 1 ){
04890                 if (xodd){
04891                         // Put the last pixel in the center, shifting the contents
04892                         // to right of the center one step to the right
04893                         float in_x = rdata[nx-1];
04894                         float tmp;
04895                         for ( int i = nx/2; i < nx; ++i ) {
04896                                 tmp = rdata[i];
04897                                 rdata[i] = in_x;
04898                                 in_x = tmp;
04899                         }
04900                 }
04901                 // now the operation is straight forward
04902                 for ( int i = 0; i < nx/2; ++i ) {
04903                         int idx = i+nx/2+xodd;
04904                         float tmp = rdata[i];
04905                         rdata[i] = rdata[idx];
04906                         rdata[idx] = tmp;
04907                 }
04908 
04909         }
04910         else if ( nz == 1 ) {
04911                 if (yodd) {
04912                         // Tranfer the top row into the middle row,
04913                         // shifting all pixels above and including the current middle up one.
04914                         for ( int c = 0; c < nx; ++c ) {
04915                                 // Get the value in the top row
04916                                 float last_val = rdata[(ny-1)*nx + c];
04917                                 float tmp;
04918                                 for ( int r = ny/2; r < ny; ++r ){
04919                                         int idx =r*nx+c;
04920                                         tmp = rdata[idx];
04921                                         rdata[idx] = last_val;
04922                                         last_val = tmp;
04923                                 }
04924                         }
04925                 }
04926 
04927                 if (xodd) {
04928                         // Transfer the right most column into the center column
04929                         // Shift all columns right of and including center to the right one pixel
04930                         for ( int r  = 0; r < ny; ++r ) {
04931                                 float last_val = rdata[(r+1)*nx -1];
04932                                 float tmp;
04933                                 for ( int c = nx/2; c < nx; ++c ){
04934                                         int idx =r*nx+c;
04935                                         tmp = rdata[idx];
04936                                         rdata[idx] = last_val;
04937                                         last_val = tmp;
04938                                 }
04939                         }
04940                 }
04941                 // It is important central slice shifting come after the previous two operations
04942                 swap_central_slices_180(image);
04943                 // Now the corners of the image can be shifted...
04944                 swap_corners_180(image);
04945 
04946         }
04947         else
04948         {
04949                 float tmp;
04950                 if (zodd) {
04951                         // Tranfer the back slice into the middle slice,
04952                         // shifting all pixels beyond and including the middle slice back one.
04953                         size_t idx = 0;
04954                         for (int r = 0; r < ny; ++r){
04955                                 for (int c = 0; c < nx; ++c) {
04956                                         float last_val = rdata[(nz-1)*nxy+r*nx+c];
04957                                         for (int s = nz/2; s < nz; ++s) {
04958                                                 idx = s*nxy+r*nx+c;
04959                                                 tmp = rdata[idx];
04960                                                 rdata[idx] = last_val;
04961                                                 last_val = tmp;
04962                                         }
04963                                 }
04964                         }
04965                 }
04966                 if (yodd) {
04967                         // Tranfer the top slice into the middle slice,
04968                         // shifting all pixels above and including the middle slice up one.
04969                         size_t idx = 0;
04970                         for (int s = 0; s < nz; ++s) {
04971                                 for (int c = 0; c < nx; ++c) {
04972                                 float last_val = rdata[s*nxy+(ny-1)*nx+c];
04973                                         for (int r = ny/2; r < ny; ++r){
04974                                                 idx = s*nxy+r*nx+c;
04975                                                 tmp = rdata[idx];
04976                                                 rdata[idx] = last_val;
04977                                                 last_val = tmp;
04978                                         }
04979                                 }
04980                         }
04981                 }
04982                 if (xodd) {
04983                         // Transfer the right most slice into the central slice
04984                         // Shift all pixels to right of and including center slice to the right one pixel
04985                         size_t idx = 0;
04986                         for (int s = 0; s < nz; ++s) {
04987                                 for (int r = 0; r < ny; ++r) {
04988                                         float last_val = rdata[s*nxy+r*nx+nx-1];
04989                                         for (int c = nx/2; c < nx; ++c){
04990                                                 idx = s*nxy+r*nx+c;
04991                                                 tmp = rdata[idx];
04992                                                 rdata[idx] = last_val;
04993                                                 last_val = tmp;
04994                                         }
04995                                 }
04996                         }
04997                 }
04998                 // Now swap the various parts in the central slices
04999                 swap_central_slices_180(image);
05000                 // Now shift the corners
05001                 swap_corners_180(image);
05002         }
05003 }
05004 
05005 
05006 void PhaseToCenterProcessor::process_inplace(EMData * image)
05007 {
05008         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05009         bool proceed = true;
05010 
05011 #ifdef EMAN2_USING_CUDA
05012         bool cpu = image->cpu_rw_is_current();
05013         bool gpu = image->gpu_rw_is_current();
05014         if ( !cpu && !gpu )
05015                 throw UnexpectedBehaviorException("Both the CPU and GPU data are not current");
05016         if (gpu && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05017                 EMDataForCuda tmp = image->get_data_struct_for_cuda();
05018                 emdata_phaseorigin_to_center(&tmp);
05019                 proceed = false;
05020                 image->gpu_update();
05021         }
05022 #endif // EMAN2_USING_CUDA
05023         if (!proceed) return; // GPU processing occurred
05024 
05025         if (image->is_complex()) {
05026                 fourier_phaseshift180(image);
05027                 return;
05028         }
05029 
05030         int nx = image->get_xsize();
05031         int ny = image->get_ysize();
05032         int nz = image->get_zsize();
05033 
05034         if ( ny == 1 && nz == 1 && nx == 1) return;
05035 
05036         int nxy = nx * ny;
05037 
05038         float *rdata = image->get_data();
05039 
05040         bool xodd = (nx % 2) == 1;
05041         bool yodd = (ny % 2) == 1;
05042         bool zodd = (nz % 2) == 1;
05043 
05044         if ( ny == 1 && nz == 1 ){
05045                 if (xodd) {
05046                         // Put the center pixel at the end, shifting the contents
05047                         // to right of the center one step to the left
05048                         float in_x = rdata[nx/2];
05049                         float tmp;
05050                         for ( int i = nx-1; i >= nx/2; --i ) {
05051                                 tmp = rdata[i];
05052                                 rdata[i] = in_x;
05053                                 in_x = tmp;
05054                         }
05055                 }
05056                 // now the operation is straight forward
05057                 for ( int i = 0; i < nx/2; ++i ) {
05058                         int idx = i + nx/2;
05059                         float tmp = rdata[i];
05060                         rdata[i] = rdata[idx];
05061                         rdata[idx] = tmp;
05062                 }
05063         }
05064         else if ( nz == 1 ){
05065                 // The order in which these operations occur literally undoes what the
05066                 // PhaseToCornerProcessor did to the image.
05067                 // First, the corners sections of the image are swapped appropriately
05068                 swap_corners_180(image);
05069                 // Second, central pixel lines are swapped
05070                 swap_central_slices_180(image);
05071 
05072                 float tmp;
05073                 // Third, appropriate sections of the image are cyclically shifted by one pixel
05074                 if (xodd) {
05075                         // Transfer the middle column to the far right
05076                         // Shift all from the far right to (but not including the) middle one to the left
05077                         for ( int r  = 0; r < ny; ++r ) {
05078                                 float last_val = rdata[r*nx+nx/2];
05079                                 for ( int c = nx-1; c >=  nx/2; --c ){
05080                                         int idx = r*nx+c;
05081                                         tmp = rdata[idx];
05082                                         rdata[idx] = last_val;
05083                                         last_val = tmp;
05084                                 }
05085                         }
05086                 }
05087                 if (yodd) {
05088                         // Tranfer the middle row to the top,
05089                         // shifting all pixels from the top row down one, until  but not including the) middle
05090                         for ( int c = 0; c < nx; ++c ) {
05091                                 // Get the value in the top row
05092                                 float last_val = rdata[ny/2*nx + c];
05093                                 for ( int r = ny-1; r >= ny/2; --r ){
05094                                         int idx = r*nx+c;
05095                                         tmp = rdata[idx];
05096                                         rdata[idx] = last_val;
05097                                         last_val = tmp;
05098                                 }
05099                         }
05100                 }
05101         }
05102         else
05103         {
05104                 // The order in which these operations occur literally undoes the
05105                 // PhaseToCornerProcessor operation - in 3D.
05106                 // First, the corner quadrants of the voxel volume are swapped
05107                 swap_corners_180(image);
05108                 // Second, appropriate parts of the central slices are swapped
05109                 swap_central_slices_180(image);
05110 
05111                 float tmp;
05112                 // Third, appropriate sections of the image are cyclically shifted by one voxel
05113                 if (xodd) {
05114                         // Transfer the central slice in the x direction to the far right
05115                         // moving all slices on the far right toward the center one pixel, until
05116                         // the center x slice is ecountered
05117                         size_t idx = 0;
05118                         for (int s = 0; s < nz; ++s) {
05119                                 for (int r = 0; r < ny; ++r) {
05120                                         float last_val = rdata[s*nxy+r*nx+nx/2];
05121                                         for (int c = nx-1; c >= nx/2; --c){
05122                                                 idx = s*nxy+r*nx+c;
05123                                                 tmp = rdata[idx];
05124                                                 rdata[idx] = last_val;
05125                                                 last_val = tmp;
05126                                         }
05127                                 }
05128                         }
05129                 }
05130                 if (yodd) {
05131                         // Tranfer the central slice in the y direction to the top
05132                         // shifting all pixels below it down on, until the center y slice is encountered.
05133                         size_t idx = 0;
05134                         for (int s = 0; s < nz; ++s) {
05135                                 for (int c = 0; c < nx; ++c) {
05136                                         float last_val = rdata[s*nxy+ny/2*nx+c];
05137                                         for (int r = ny-1; r >= ny/2; --r){
05138                                                 idx = s*nxy+r*nx+c;
05139                                                 tmp = rdata[idx];
05140                                                 rdata[idx] = last_val;
05141                                                 last_val = tmp;
05142                                         }
05143                                 }
05144                         }
05145                 }
05146                 if (zodd) {
05147                         // Tranfer the central slice in the z direction to the back
05148                         // shifting all pixels beyond and including the middle slice back one.
05149                         size_t idx = 0;
05150                         for (int r = 0; r < ny; ++r){
05151                                 for (int c = 0; c < nx; ++c) {
05152                                         float last_val = rdata[nz/2*nxy+r*nx+c];
05153                                         for (int s = nz-1; s >= nz/2; --s) {
05154                                                 idx = s*nxy+r*nx+c;
05155                                                 tmp = rdata[idx];
05156                                                 rdata[idx] = last_val;
05157                                                 last_val = tmp;
05158                                         }
05159                                 }
05160                         }
05161                 }
05162 
05163 
05164         }
05165 }
05166 
05167 void AutoMaskAsymUnit::process_inplace(EMData* image) {
05168         if (!image) {
05169                 LOGWARN("NULL Image");
05170                 return;
05171         }
05172 
05173         int nx = image->get_xsize();
05174         int ny = image->get_ysize();
05175         int nz = image->get_zsize();
05176 
05177         int ox = nx/2;
05178         int oy = ny/2;
05179         int oz = nz/2;
05180 
05181         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
05182         int au = params.set_default("au",0);
05183 
05184         float *d = image->get_data();
05185         for(int k = 0; k < nz; ++k ) {
05186                 for(int j = 0; j < ny; ++j ) {
05187                         for (int i = 0; i< nx; ++i, ++d) {
05188                                 //cout << i << " " << j << " " << k << endl;
05189                                 Vec3f v(i-ox,j-oy,k-oz);
05190 //                              v.normalize();
05191                                 int a = sym->point_in_which_asym_unit(v);
05192                                 if (au == -1) {
05193                                         *d = (float)a;
05194                                 } else {
05195                                         if ( a == au ) *d = 1;
05196                                         else *d = 0;
05197                                 }
05198                         }
05199                 }
05200         }
05201 
05202         delete sym;
05203 
05204 }
05205 
05206 void AutoMask2DProcessor::process_inplace(EMData * image)
05207 {
05208         if (!image) {
05209                 LOGWARN("NULL Image");
05210                 return;
05211         }
05212 
05213         if (image->get_ndim() != 2) {
05214                 throw ImageDimensionException("This processor only supports 2D images.");
05215         }
05216 
05217         /*
05218          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
05219          To get around this just use the return_mask parameter.
05220         string mask_output = params.set_default("write_mask", "");
05221         if ( mask_output != "") {
05222                 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.");
05223                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
05224         }
05225         */
05226 
05227         int radius=0;
05228         if (params.has_key("radius")) {
05229                 radius = params["radius"];
05230         }
05231         int nmaxseed=0;
05232         if (params.has_key("nmaxseed")) {
05233                 nmaxseed = params["nmaxseed"];
05234         }
05235 
05236         float threshold=0.0;
05237         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
05238         else threshold=params["threshold"];
05239 
05240 
05241         int nshells = params["nshells"];
05242         int nshellsgauss = params["nshellsgauss"];
05243         int verbose=params.set_default("verbose",0);
05244 
05245         int nx = image->get_xsize();
05246         int ny = image->get_ysize();
05247 
05248         EMData *amask = new EMData();
05249         amask->set_size(nx, ny);
05250 
05251         float *dat = image->get_data();
05252         float *dat2 = amask->get_data();
05253         int i,j,k;
05254         size_t l = 0;
05255 
05256         if (verbose) printf("%f\t%f\t%f\n",(float)image->get_attr("mean"),(float)image->get_attr("sigma"),threshold);
05257 
05258         // Seeds with the highest valued pixels
05259         if (nmaxseed>0) {
05260                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
05261 
05262                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
05263                         amask->set_value_at((*i).x,(*i).y,0,1.0);
05264                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
05265                 }
05266         }
05267 
05268         // Seeds with a circle
05269         if (radius>0) {
05270                 // start with an initial circle
05271                 l=0;
05272                 for (j = -ny / 2; j < ny / 2; ++j) {
05273                         for (i = -nx / 2; i < nx / 2; ++i,++l) {
05274                                 if ( abs(j) > radius || abs(i) > radius) continue;
05275 //                              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
05276                                 if ( (j * j + i * i) > (radius*radius) ) continue;
05277                                 dat2[l] = 1.0f;
05278                         }
05279                 }
05280         }
05281 
05282         // iteratively 'flood fills' the map... recursion would be better
05283         int done=0;
05284         int iter=0;
05285         while (!done) {
05286                 iter++;
05287                 done=1;
05288                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
05289                 for (j=1; j<ny-1; ++j) {
05290                         for (i=1; i<nx-1; ++i) {
05291                                 l=i+j*nx;
05292                                 if (dat2[l]) continue;
05293                                 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx])) {
05294                                         dat2[l]=1.0;
05295                                         done=0;
05296                                 }
05297                         }
05298                 }
05299         }
05300 
05301         amask->update();
05302 
05303         if (verbose) printf("extending mask\n");
05304         amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
05305 
05306         bool return_mask = params.set_default("return_mask",false);
05307         if (return_mask) {
05308                 // 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.
05309                 memcpy(dat,dat2,image->get_size()*sizeof(float));
05310         } else {
05311                 image->mult(*amask);
05312         }
05313 
05314         // EMAN2 policy is not to allow file io from with a processor
05315         //if (mask_output != "") {
05316         //      amask->write_image(mask_output);
05317         //}
05318 
05319 
05320         delete amask;
05321 }
05322 
05323 
05324 void AddRandomNoiseProcessor::process_inplace(EMData * image)
05325 {
05326         if (!image) {
05327                 LOGWARN("NULL Image");
05328                 return;
05329         }
05330 
05331         if (!image->is_complex()) {
05332                 LOGERR("AddRandomNoise Processor only works for complex image");
05333                 throw ImageFormatException("only work for complex image");
05334         }
05335 
05336         int n = params["n"];
05337         float x0 = params["x0"];
05338         float dx = params["dx"];
05339         vector < float >y = params["y"];
05340 
05341         int interpolation = 1;
05342         if (params.has_key("interpolation")) {
05343                 interpolation = params["interpolation"];
05344         }
05345 
05346         Randnum * randnum = Randnum::Instance();
05347         if(params.has_key("seed")) {
05348                 randnum->set_seed((int)params["seed"]);
05349         }
05350 
05351         int nx = image->get_xsize();
05352         int ny = image->get_ysize();
05353         int nz = image->get_zsize();
05354 
05355         image->ap2ri();
05356         float *rdata = image->get_data();
05357 
05358         size_t k = 0;
05359         float half_nz = 0;
05360         if (nz > 1) {
05361                 half_nz = nz / 2.0f;
05362         }
05363 
05364         const float sqrt_2 = sqrt((float) 2);
05365 
05366         float r;
05367         for (int h = 0; h < nz; h++) {
05368                 for (int j = 0; j < ny; j++) {
05369                         for (int i = 0; i < nx; i += 2, k += 2) {
05370                                 r = (Util::hypot3(i / 2.0f, j - ny / 2.0f, h - half_nz));
05371 //                              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
05372                                 r = (r - x0) / dx;
05373                                 int l = 0;
05374                                 if (interpolation) {
05375                                         l = Util::fast_floor(r);
05376                                 }
05377                                 else {
05378                                         l = Util::fast_floor(r + 0.5f);
05379                                 }
05380                                 r -= l;
05381                                 float f = 0;
05382                                 if (l >= n - 2) {
05383                                         f = y[n - 1];
05384                                 }
05385                                 else if (l < 0) {
05386                                         l = 0;
05387                                 }
05388                                 else {
05389                                         if (interpolation) {
05390                                                 f = (y[l] * (1 - r) + y[l + 1] * r);
05391                                         }
05392                                         else {
05393                                                 f = y[l];
05394                                         }
05395                                 }
05396                                 f = randnum->get_gauss_rand(sqrt(f), sqrt(f) / 3);
05397                                 float a = randnum->get_frand(0.0f, (float)(2 * M_PI));
05398                                 if (i == 0) {
05399                                         f *= sqrt_2;
05400                                 }
05401                                 rdata[k] += f * cos(a);
05402                                 rdata[k + 1] += f * sin(a);
05403                         }
05404                 }
05405         }
05406 
05407         image->update();
05408 }
05409 
05410 void AddMaskShellProcessor::process_inplace(EMData * image)
05411 {
05412         if (!image) {
05413                 LOGWARN("NULL Image");
05414                 return;
05415         }
05416 
05417         int nx = image->get_xsize();
05418         int ny = image->get_ysize();
05419         int nz = image->get_zsize();
05420 
05421         if (ny == 1) {
05422                 LOGERR("Tried to add mask shell to 1d image");
05423                 return;
05424         }
05425 
05426         int num_shells = params["nshells"];
05427 
05428         float *d = image->get_data();
05429         float k = 0.99999f;
05430         int nxy = nx * ny;
05431 
05432         if (nz == 1) {
05433                 for (int i = 0; i < num_shells; i++) {
05434                         for (int y = 1; y < ny - 1; y++) {
05435                                 int cur_y = y * nx;
05436 
05437                                 for (int x = 1; x < nx - 1; x++) {
05438                                         int j = x + cur_y;
05439                                         if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k || d[j - nx] > k)) {
05440                                                 d[j] = k;
05441                                         }
05442                                 }
05443                         }
05444                         k -= 0.00001f;
05445                 }
05446         }
05447         else {
05448                 for (int i = 0; i < num_shells; i++) {
05449                         for (int z = 1; z < nz - 1; z++) {
05450                                 size_t cur_z = z * nx * ny;
05451 
05452                                 for (int y = 1; y < ny - 1; y++) {
05453                                         size_t cur_y = y * nx + cur_z;
05454 
05455                                         for (int x = 1; x < nx - 1; x++) {
05456                                                 size_t j = x + cur_y;
05457 
05458                                                 if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k ||
05459                                                                           d[j - nx] > k || d[j - nxy] > k || d[j + nxy] > k)) {
05460                                                         d[j] = k;
05461                                                 }
05462                                         }
05463                                 }
05464                         }
05465 
05466                         k -= 0.00001f;
05467                 }
05468         }
05469 
05470         size_t size = nx * ny * nz;
05471         for (size_t i = 0; i < size; i++) {
05472                 if (d[i]) {
05473                         d[i] = 1;
05474                 }
05475                 else {
05476                         d[i] = 0;
05477                 }
05478         }
05479 
05480         image->update();
05481 }
05482 
05483 void ToMassCenterProcessor::process_inplace(EMData * image)
05484 {
05485         if (!image) {
05486                 LOGWARN("NULL Image");
05487                 return;
05488         }
05489 
05490         int int_shift_only = params.set_default("int_shift_only",1);
05491 //      int positive = params.set_default("positive",0);
05492 
05493         if ((float)image->get_attr("sigma")==0.0f) return;              // Can't center a constant valued image
05494 
05495         FloatPoint com = image->calc_center_of_mass();
05496 
05497         int nx = image->get_xsize();
05498         int ny = image->get_ysize();
05499         int nz = image->get_zsize();
05500 
05501         if (int_shift_only) {
05502                 int dx = -(int)(floor(com[0] + 0.5f) - nx / 2);
05503                 int dy = -(int)(floor(com[1] + 0.5f) - ny / 2);
05504                 int dz = 0;
05505                 if (nz > 1) {
05506                         dz = -(int)(floor(com[2] + 0.5f) - nz / 2);
05507                 }
05508                 image->translate(dx, dy, dz);
05509 
05510                 Transform t;
05511                 t.set_trans((float)dx,(float)dy,(float)dz);
05512 
05513                 if (nz > 1) {
05514                         image->set_attr("xform.align3d",&t);
05515                 } else {
05516                         image->set_attr("xform.align2d",&t);
05517                 }
05518         }
05519         else {
05520                 float dx = -(com[0] - nx / 2);
05521                 float dy = -(com[1] - ny / 2);
05522                 float dz = 0;
05523                 if (nz > 1) {
05524                         dz = -(com[2] - nz / 2);
05525                 }
05526                 image->translate(dx, dy, dz);
05527 
05528                 Transform t;
05529                 t.set_trans(dx,dy,dz);
05530 
05531                 if (nz > 1) {
05532                         image->set_attr("xform.align3d",&t);
05533                 } else {
05534                         image->set_attr("xform.align2d",&t);
05535                 }
05536         }
05537 }
05538 
05539 void PhaseToMassCenterProcessor::process_inplace(EMData * image)
05540 {
05541         if (!image) {
05542                 LOGWARN("NULL Image");
05543                 return;
05544         }
05545 
05546         int int_shift_only = params.set_default("int_shift_only",1);
05547 
05548         vector<float> pcog = image->phase_cog();
05549 
05550         int dims = image->get_ndim();
05551 
05552         if (int_shift_only) {
05553                 int dx=-int(pcog[0]+0.5f),dy=0,dz=0;
05554                 if ( dims >= 2 ) dy = -int(pcog[1]+0.5);
05555                 if ( dims == 3 ) dz = -int(pcog[2]+0.5);
05556 
05557                 Transform t;
05558                 t.set_trans((float)dx,(float)dy,(float)dz);
05559                 if (dims == 3) image->set_attr("xform.align3d",&t);
05560                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05561 
05562                 image->translate(dx,dy,dz);
05563         } else  {
05564                 float dx=-pcog[0],dy=0.0,dz=0.0;
05565                 if ( dims >= 2 ) dy = -pcog[1];
05566                 if ( dims == 3 ) dz = -pcog[2];
05567                 image->translate(dx,dy,dz);
05568 
05569                 Transform t;
05570                 t.set_trans(dx,dy,dz);
05571                 if (dims == 3) image->set_attr("xform.align3d",&t);
05572                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05573         }
05574 }
05575 
05576 void ACFCenterProcessor::process_inplace(EMData * image)
05577 {
05578         if (!image) {
05579                 LOGWARN("NULL Image");
05580                 return;
05581         }
05582 
05583         Dict params1;
05584         params1["intonly"] = 1;
05585         params1["maxshift"] = image->get_xsize() / 4;
05586         EMData* aligned = image->align("translational", 0, params1);
05587         if ( image->get_ndim() == 3 ) {
05588                 Transform* t = aligned->get_attr("xform.align3d");
05589                 image->translate(t->get_trans());
05590                 image->set_attr("xform.align3d",t);
05591                 delete t;
05592         }
05593         else {
05594                 // assumption is the image is 2D which may be  false
05595                 Transform* t = aligned->get_attr("xform.align2d");
05596                 image->translate(t->get_trans());
05597                 image->set_attr("xform.align2d",t);
05598                 delete t;
05599         }
05600 
05601         delete aligned;
05602 
05603 }
05604 
05605 void SNRProcessor::process_inplace(EMData * image)
05606 {
05607         if (!image) {
05608                 return;
05609         }
05610 
05611         int wiener = params["wiener"];
05612         const char *snrfile = params["snrfile"];
05613 
05614         XYData sf;
05615         int err = sf.read_file(snrfile);
05616         if (err) {
05617                 LOGERR("couldn't read structure factor file!");
05618                 return;
05619         }
05620 
05621 
05622         for (size_t i = 0; i < sf.get_size(); i++) {
05623                 if (sf.get_y(i) <= 0) {
05624                         sf.set_y(i, -4.0f);
05625                 }
05626                 else {
05627                         sf.set_y(i, log10(sf.get_y(i)));
05628                 }
05629         }
05630         sf.update();
05631 
05632         Ctf *image_ctf = image->get_ctf();
05633 
05634         vector < float >ctf;
05635         if (wiener) {
05636                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_WIENER_FILTER, &sf);
05637         }
05638         else {
05639                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR, &sf);
05640         }
05641 
05642         if(image_ctf) {delete image_ctf; image_ctf=0;}
05643 
05644         image->process_inplace("normalize.circlemean");
05645 
05646         int nx = image->get_xsize();
05647         int ny = image->get_ysize();
05648 
05649         Region clip_r(-nx / 2, -ny / 2, nx * 2, ny * 2);
05650         EMData *d3 = image->get_clip(clip_r);
05651         EMData *d2 = d3->do_fft();
05652 
05653         d2->apply_radial_func(0, 2.0f / Ctf::CTFOS, ctf, 0);
05654 
05655         if( d3 )
05656         {
05657                 delete d3;
05658                 d3 = 0;
05659         }
05660 
05661         if( image )
05662         {
05663                 delete image;
05664                 image = 0;
05665         }
05666 
05667         EMData *d1 = d2->do_ift();
05668         int d1_nx = d1->get_xsize();
05669         int d1_ny = d1->get_ysize();
05670         Region d1_r(d1_nx / 4, d1_ny / 4, d1_nx / 2, d1_ny / 2);
05671 
05672         image = d1->get_clip(d1_r);
05673 
05674         if( d1 )
05675         {
05676                 delete d1;
05677                 d1 = 0;
05678         }
05679 
05680         if( d2 )
05681         {
05682                 delete d2;
05683                 d2 = 0;
05684         }
05685 }
05686 
05687 void FileFourierProcessor::process_inplace(EMData * image)
05688 {
05689         if (!image) {
05690                 LOGWARN("NULL Image");
05691                 return;
05692         }
05693         const char *filename = params["filename"];
05694         float apix = params["apix"];
05695 
05696         FILE *in = fopen(filename, "rb");
05697         if (!in) {
05698                 LOGERR("FileFourierProcessor: cannot open file '%s'", filename);
05699                 return;
05700         }
05701 
05702         float f = 0;
05703         int n = 0;
05704         while (fscanf(in, " %f %f", &f, &f) == 2) {
05705                 n++;
05706         }
05707         rewind(in);
05708 
05709         vector < float >xd(n);
05710         vector < float >yd(n);
05711 
05712         float sf = apix * image->get_xsize();
05713 
05714         for (int i = 0; fscanf(in, " %f %f", &xd[i], &yd[i]) == 2; i++) {
05715                 xd[i] *= sf;
05716         }
05717 
05718         if (xd[2] - xd[1] != xd[1] - xd[0]) {
05719                 LOGWARN("Warning, x spacing appears nonuniform %g!=%g\n",
05720                                 xd[2] - xd[1], xd[1] - xd[0]);
05721         }
05722 
05723         EMData *d2 = image->do_fft();
05724         if( image )
05725         {
05726                 delete image;
05727                 image = 0;
05728         }
05729 
05730         d2->apply_radial_func(xd[0], xd[1] - xd[0], yd, 1);
05731         image = d2->do_ift();
05732 }
05733 
05734 void LocalNormProcessor::process_inplace(EMData * image)
05735 {
05736         if (!image) {
05737                 LOGWARN("NULL Image");
05738                 return;
05739         }
05740         float apix = params["apix"];
05741         float threshold = params["threshold"];
05742         float radius = params["radius"];
05743 
05744         if (apix > 0) {
05745                 int ny = image->get_ysize();
05746                 radius = ny * apix / radius;
05747                 //printf("Norm filter radius=%1.1f\n", radius);
05748         }
05749 
05750         EMData *blur = image->copy();
05751         EMData *maskblur = image->copy();
05752 
05753         maskblur->process_inplace("threshold.binary", Dict("value", threshold));
05754         maskblur->process_inplace("eman1.filter.lowpass.gaussian", Dict("lowpass", radius));
05755         maskblur->process_inplace("eman1.filter.highpass.tanh", Dict("highpass", -10.0f));
05756         maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
05757         maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
05758 
05759 
05760         blur->process_inplace("threshold.belowtozero", Dict("minval", threshold));
05761         blur->process_inplace("eman1.filter.lowpass.gaussian", Dict("lowpass", radius));
05762         blur->process_inplace("eman1.filter.highpass.tanh", Dict("highpass", -10.0f));
05763 
05764         maskblur->div(*blur);
05765         image->mult(*maskblur);
05766         maskblur->write_image("norm.mrc", 0, EMUtil::IMAGE_MRC);
05767 
05768         if( maskblur )
05769         {
05770                 delete maskblur;
05771                 maskblur = 0;
05772         }
05773 
05774         if( blur )
05775         {
05776                 delete blur;
05777                 blur = 0;
05778         }
05779 }
05780 
05781 
05782 void SymSearchProcessor::process_inplace(EMData * image)
05783 {
05784         if (!image) {
05785                 LOGWARN("NULL Image");
05786                 return;
05787         }
05788         float thresh = params["thresh"];
05789         int output_symlabel = params["output_symlabel"];
05790 
05791         // set up all the symmetry transforms for all the searched symmetries
05792         const vector<string> sym_list = params["sym"];
05793         int sym_num = sym_list.size();
05794         vector< vector< Transform > > transforms(sym_num);
05795         vector< float* > symvals(sym_num);
05796         for (int i =0; i < sym_num; i++) {
05797                 vector<Transform> sym_transform =  Symmetry3D::get_symmetries(sym_list[i]);
05798                 transforms[i] = sym_transform;
05799                 symvals[i] = new float[sym_transform.size()]; // new float(nsym);
05800         }
05801 
05802         EMData *orig = image->copy();
05803 
05804         image->to_zero();
05805 
05806         int nx= image->get_xsize();
05807         int ny= image->get_ysize();
05808         int nz= image->get_zsize();
05809         int xy = nx * ny;
05810         float * data = image->get_data();
05811         float * sdata = orig->get_data();
05812 
05813         EMData *symlabel = 0;
05814         float * ldata = symlabel->get_data();
05815         if (output_symlabel) {
05816                 symlabel = image->copy();
05817                 symlabel->to_zero();
05818                 ldata = symlabel->get_data();
05819         }
05820 
05821         for (int k = 0; k < nz; k++) {
05822                 for (int j = 0; j < ny; j++) {
05823                         for(int i = 0; i < nx; i++) {
05824                                 size_t index = k * nx * ny + j * nx + i;
05825                                 float val = sdata[ index ];
05826                                 float bestmean = val, bestsymlevel = FLT_MAX;
05827                                 int bestsym = 0;
05828                                 for( int sym = 0; sym< sym_num; sym++) {
05829                                         int cur_sym_num = transforms[sym].size();
05830                                         float *symval = symvals[sym];
05831                                         // first find out all the symmetry related location values
05832                                         for( int s = 0; s < cur_sym_num; s++){
05833                                                 Transform r = transforms[sym][s];
05834                                                 float x2 = (float)(r[0][0] * (i-nx/2) + r[0][1] * (j-ny/2) + r[0][2] * (k-nz/2) + nx / 2);
05835                                                 float y2 = (float)(r[1][0] * (i-nx/2) + r[1][1] * (j-ny/2) + r[1][2] * (k-nz/2) + ny / 2);
05836                                                 float z2 = (float)(r[2][0] * (i-nx/2) + r[2][1] * (j-ny/2) + r[2][2] * (k-nz/2) + nz / 2);
05837 
05838                                                 if (x2 >= 0 && y2 >= 0 && z2 >= 0 && x2 < (nx - 1) && y2 < (ny - 1)
05839                                                         && z2 < (nz - 1)) {
05840                                                         float x = (float)Util::fast_floor(x2);
05841                                                         float y = (float)Util::fast_floor(y2);
05842                                                         float z = (float)Util::fast_floor(z2);
05843 
05844                                                         float t = x2 - x;
05845                                                         float u = y2 - y;
05846                                                         float v = z2 - z;
05847 
05848                                                         int ii = (int) (x + y * nx + z * xy);
05849 
05850                                                         symval[s]=
05851                                                                 Util::trilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],
05852                                                                                                                         sdata[ii + nx + 1], sdata[ii + nx * ny],
05853                                                                                                                         sdata[ii + xy + 1], sdata[ii + xy + nx],
05854                                                                                                                         sdata[ii + xy + nx + 1], t, u, v);
05855                                                 }
05856                                                 else {
05857                                                         symval[s] = 0.0 ;
05858                                                 }
05859                                         }
05860                                         float tmean=0, tsigma=0;
05861                                         for( int s = 0; s < cur_sym_num; s++) {
05862                                                 tmean += symval[s];
05863                                                 tsigma += symval[s] * symval[s];
05864                                         }
05865                                         tmean /= cur_sym_num;
05866                                         tsigma = tsigma/cur_sym_num - tmean*tmean;
05867                                         if (tsigma < bestsymlevel ) {
05868                                                 bestsymlevel = tsigma;
05869                                                 bestmean = tmean;
05870                                                 bestsym = sym;
05871                                         }
05872                                 }
05873                                 if ( bestsymlevel > thresh) {
05874                                         if (output_symlabel) ldata[index] = (float)bestsym;
05875                                         data[index] = bestmean;
05876                                 }
05877                                 else {
05878                                         if (output_symlabel) ldata[index] = -1;
05879                                         data[index] = val;
05880                                 }
05881                         }
05882                 }
05883         }
05884         if( orig )
05885         {
05886                 delete orig;
05887                 orig = 0;
05888         }
05889         for (int i =0; i < sym_num; i++) {
05890                 if( symvals[i] )
05891                 {
05892                         delete symvals[i];
05893                         symvals[i] = 0;
05894                 }
05895         }
05896         if (symlabel) params.put("symlabel_map", EMObject(symlabel));
05897 }
05898 
05899 
05900 void IndexMaskFileProcessor::process_inplace(EMData * image)
05901 {
05902         if (!image) {
05903                 LOGWARN("NULL Image");
05904                 return;
05905         }
05906 
05907         const char *filename = params["filename"];
05908         EMData *msk = new EMData();
05909         msk->read_image(filename);
05910         if (!EMUtil::is_same_size(image, msk)) {
05911                 LOGERR("IndexMaskFileProcessor: Mask size different than image");
05912                 return;
05913         }
05914 
05915         if ((int) params["ismaskset"] != 0) {
05916                 msk->process_inplace("threshold.binaryrange", Dict("low", 0.5f, "high", 1.5f));
05917         }
05918 
05919         image->mult(*msk);
05920         if( msk )
05921         {
05922                 delete msk;
05923                 msk = 0;
05924         }
05925 }
05926 
05927 
05928 void CoordinateMaskFileProcessor::process_inplace(EMData * image)
05929 {
05930         if (!image) {
05931                 LOGWARN("NULL Image");
05932                 return;
05933         }
05934 
05935         const char *filename = params["filename"];
05936         EMData *msk = new EMData();
05937         msk->read_image(filename);
05938 
05939         int nx = image->get_xsize();
05940         int ny = image->get_ysize();
05941         int nz = image->get_zsize();
05942 
05943         int xm = msk->get_xsize();
05944         int ym = msk->get_ysize();
05945         int zm = msk->get_zsize();
05946 
05947         float apix = image->get_attr("apix_x");
05948         float apixm = msk->get_attr("apix_x");
05949 
05950         float xo = image->get_attr("origin_x");
05951         float yo = image->get_attr("origin_y");
05952         float zo = image->get_attr("origin_z");
05953 
05954         float xom = msk->get_attr("origin_x");
05955         float yom = msk->get_attr("origin_y");
05956         float zom = msk->get_attr("origin_z");
05957 
05958         float *dp = image->get_data();
05959         float *dpm = msk->get_data();
05960         int nxy = nx * ny;
05961 
05962         for (int k = 0; k < nz; k++) {
05963                 float zc = zo + k * apix;
05964                 if (zc <= zom || zc >= zom + zm * apixm) {
05965                         memset(&(dp[k * nxy]), 0, sizeof(float) * nxy);
05966                 }
05967                 else {
05968                         int km = (int) ((zc - zom) / apixm);
05969 
05970                         for (int j = 0; j < ny; j++) {
05971                                 float yc = yo + j * apix;
05972                                 if (yc <= yom || yc >= yom + ym * apixm) {
05973                                         memset(&(dp[k * nxy + j * nx]), 0, sizeof(float) * nx);
05974                                 }
05975                                 else {
05976                                         int jm = (int) ((yc - yom) / apixm);
05977                                         size_t idx = 0;
05978                                         float xc;
05979                                         int im;
05980                                         for (int i = 0; i < nx; i++) {
05981                                                 xc = xo + i * apix;
05982                                                 idx = k * nxy + j * nx + i;
05983                                                 if (xc <= xom || xc >= xom + xm * apixm) {
05984                                                         dp[idx] = 0;
05985                                                 }
05986                                                 else {
05987                                                         im = (int) ((xc - xom) / apixm);
05988                                                         if (dpm[km * xm * ym + jm * xm + im] <= 0) {
05989                                                                 dp[idx] = 0;
05990                                                         }
05991                                                 }
05992                                         }
05993                                 }
05994                         }
05995                 }
05996         }
05997 
05998         image->update();
05999         msk->update();
06000         if( msk )
06001         {
06002                 delete msk;
06003                 msk = 0;
06004         }
06005 }
06006 
06007 void MatchSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06008         // The radial mask comes in with the existing radial image profile
06009         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06010 
06011         EMData *to = params["to"];
06012         XYData *sf = new XYData();
06013         float apixto = to->get_attr("apix_x");
06014 
06015 
06016         if (to->is_complex()) {
06017                 vector<float> rd=to->calc_radial_dist(to->get_ysize()/2.0,0,1.0,1);
06018                 for (size_t i=0; i<rd.size(); i++) {
06019                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06020                         sf->set_y(i,rd[i]);
06021                 }
06022         }
06023         else {
06024                 EMData *tmp=to->do_fft();
06025                 vector<float> rd=tmp->calc_radial_dist(to->get_ysize()/2,0,1.0,1);
06026                 for (size_t i=0; i<rd.size(); i++) {
06027                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06028                         sf->set_y(i,rd[i]);
06029                 }
06030                 delete tmp;
06031         }
06032 
06033         float apix=image->get_attr("apix_x");
06034 
06035         sf->write_file("a.txt");
06036         Util::save_data(0,sf->get_x(1),radial_mask,"b.txt");
06037 
06038         int n = radial_mask.size();
06039         for (int i=0; i<n; i++) {
06040                 if (radial_mask[i]>0) radial_mask[i]= sqrt(sf->get_yatx(i/(apix*2.0f*n))/radial_mask[i]);
06041                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06042         }
06043 
06044         Util::save_data(0,sf->get_x(1),radial_mask,"c.txt");
06045 
06046         delete sf;
06047 }
06048 
06049 void SetSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06050         // The radial mask comes in with the existing radial image profile
06051         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06052 
06053         XYData *sf = params["strucfac"];
06054         if(params.has_key("apix")) {
06055                 image->set_attr("apix_x", (float)params["apix"]);
06056                 image->set_attr("apix_y", (float)params["apix"]);
06057                 image->set_attr("apix_z", (float)params["apix"]);
06058         }
06059 
06060         float apix=image->get_attr("apix_x");
06061 
06062         int n = radial_mask.size();
06063         for (int i=0; i<n; i++) {
06064                 if (radial_mask[i]>0) radial_mask[i]= n*n*n*sqrt(sf->get_yatx(i/(apix*2.0f*n))/radial_mask[i]);
06065                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06066         }
06067 
06068 }
06069 
06070 void SmartMaskProcessor::process_inplace(EMData * image)
06071 {
06072         if (!image) {
06073                 LOGWARN("NULL Image");
06074                 return;
06075         }
06076 
06077         float mask = params["mask"];
06078 
06079         int nx = image->get_xsize();
06080         int ny = image->get_ysize();
06081         int nz = image->get_zsize();
06082 
06083         float *dat = image->get_data();
06084         double sma = 0;
06085         int smn = 0;
06086         float r = 0.0f;
06087         for (int k = 0; k < nz; ++k) {
06088                 for (int j = 0; j < ny; ++j) {
06089                         for (int i = 0; i < nx; ++i, ++dat) {
06090                                 r =
06091                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06092                                                  Util::square(k - nz / 2));
06093                                 if (r > mask - 1.5f && r < mask - 0.5f) {
06094                                         sma += *dat;
06095                                         smn++;
06096                                 }
06097                         }
06098                 }
06099         }
06100 
06101         float smask = (float) sma / smn;
06102         image->update();
06103 
06104         dat = image->get_data();
06105         for (int k = 0; k < nz; ++k) {
06106                 for (int j = 0; j < ny; ++j) {
06107                         for (int i = 0; i < nx; ++i, ++dat) {
06108                                 r =
06109                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06110                                                  Util::square(k - nz / 2));
06111                                 if (r > mask - .5) {
06112                                         *dat = 0;
06113                                 }
06114                                 else {
06115                                         *dat -= smask;
06116                                 }
06117                         }
06118                 }
06119         }
06120 
06121         image->update();
06122 }
06123 
06124 void AutoMask3DProcessor::search_nearby(float *dat, float *dat2, int nx, int ny, int nz, float threshold)
06125 {
06126         Assert(dat != 0);
06127         Assert(dat2 != 0);
06128         Assert(nx > 0);
06129         Assert(ny > 0);
06130 
06131         bool done = false;
06132         int nxy = nx * ny;
06133 
06134         while (!done) {
06135                 done = true;
06136                 for (int k = 1; k < nz - 1; k++) {
06137                         size_t k2 = k * nxy;
06138                         for (int j = 1; j < ny - 1; j++) {
06139                                 size_t l = j * nx + k2 + 1;
06140 
06141                                 for (int i = 1; i < nx - 1; i++) {
06142                                         if (dat[l] >= threshold || dat2[l]) {
06143                                                 if (dat2[l - 1] || dat2[l + 1] ||
06144                                                         dat2[l - nx] || dat2[l + nx] || dat2[l - nxy] || dat2[l + nxy]) {
06145                                                         dat2[l] = 1.0f;
06146                                                         done = false;
06147                                                 }
06148                                         }
06149                                         ++l;
06150                                 }
06151                         }
06152                 }
06153         }
06154 }
06155 
06156 void AutoMask3DProcessor::fill_nearby(float *dat2, int nx, int ny, int nz)
06157 {
06158         Assert(dat2 != 0);
06159         Assert(nx > 0);
06160         Assert(ny > 0);
06161         Assert(nz >= 0);
06162 
06163         int nxy = nx * ny;
06164         size_t idx;
06165         for (int i = 0; i < nx; i++) {
06166                 for (int j = 0; j < ny; j++) {
06167                         int j2 = j * nx + i;
06168                         int k0 = 0;
06169                         for (int k = 0; k < nz; k++) {
06170                                 idx = j2 + k * nxy;
06171                                 if (dat2[idx]) {
06172                                         k0 = k;
06173                                         break;
06174                                 }
06175                         }
06176 
06177                         if (k0 != nz) {
06178                                 int k1 = nz - 1;
06179                                 for (int k = nz - 1; k >= 0; k--) {
06180                                         idx = j2 + k * nxy;
06181                                         if (dat2[idx]) {
06182                                                 k1 = k;
06183                                                 break;
06184                                         }
06185                                 }
06186 
06187                                 for (int k = k0 + 1; k < k1; k++) {
06188                                         idx = j2 + k * nxy;
06189                                         dat2[idx] = 1.0f;
06190                                 }
06191                         }
06192                 }
06193         }
06194 
06195         for (int i = 0; i < nx; i++) {
06196                 for (int j = 0; j < nz; j++) {
06197                         size_t j2 = j * nxy + i;
06198                         int k0 = 0;
06199                         for (int k = 0; k < ny; k++) {
06200                                 idx = k * nx + j2;
06201                                 if (dat2[idx]) {
06202                                         k0 = k;
06203                                         break;
06204                                 }
06205                         }
06206 
06207                         if (k0 != ny) {
06208                                 int k1 = ny - 1;
06209                                 for (int k = ny - 1; k >= 0; k--) {
06210                                         idx = k * nx + j2;
06211                                         if (dat2[idx]) {
06212                                                 k1 = k;
06213                                                 break;
06214                                         }
06215                                 }
06216 
06217                                 for (int k = k0 + 1; k < k1; k++) {
06218                                         idx = k * nx + j2;
06219                                         dat2[idx] = 1.0f;
06220                                 }
06221                         }
06222                 }
06223         }
06224 
06225         for (int i = 0; i < ny; i++) {
06226                 for (int j = 0; j < nz; j++) {
06227                         size_t j2 = i * nx + j * nxy;
06228                         int k0 = 0;
06229                         for (int k = 0; k < nx; k++) {
06230                                 if (dat2[k + j2]) {
06231                                         k0 = k;
06232                                         break;
06233                                 }
06234                         }
06235                         if (k0 != nx) {
06236                                 int k1 = nx - 1;
06237                                 for (int k = nx - 1; k >= 0; k--) {
06238                                         if (dat2[k + j2]) {
06239                                                 k1 = k;
06240                                                 break;
06241                                         }
06242                                 }
06243 
06244                                 for (int k = k0 + 1; k < k1; k++) {
06245                                         dat2[k + j2] = 1.0f;
06246                                 }
06247                         }
06248                 }
06249         }
06250 
06251 }
06252 
06253 void AutoMask3DProcessor::process_inplace(EMData * image)
06254 {
06255         if (!image) {
06256                 LOGWARN("NULL Image");
06257                 return;
06258         }
06259 
06260         int nx = image->get_xsize();
06261         int ny = image->get_ysize();
06262         int nz = image->get_zsize();
06263 
06264         EMData *amask = new EMData();
06265         amask->set_size(nx, ny, nz);
06266 
06267         float sig = 0;
06268         float mean = 0;
06269 
06270         if (params.has_key("threshold1") && params.has_key("threshold2")) {
06271                 sig = image->get_attr("sigma");
06272                 mean = image->get_attr("mean");
06273         }
06274 
06275         float *dat = image->get_data();
06276         float *dat2 = amask->get_data();
06277 
06278         float t = 0;
06279         if (params.has_key("threshold1")) {
06280                 t = params["threshold1"];
06281         }
06282         else {
06283                 t = mean + sig * 2.5f;
06284         }
06285 
06286         size_t l = 0;
06287         for (int k = 0; k < nz; ++k) {
06288                 for (int j = 0; j < ny; ++j) {
06289                         for (int i = 0; i < nx; ++i) {
06290                                 if (dat[l] > t) {
06291                                         dat2[l] = 1.0f;
06292                                 }
06293                                 ++l;
06294                         }
06295                 }
06296         }
06297 
06298 
06299         if (params.has_key("threshold2")) {
06300                 t = params["threshold2"];
06301         }
06302         else {
06303                 t = mean + sig * 0.5f;
06304         }
06305 
06306         search_nearby(dat, dat2, nx, ny, nz, t);
06307 
06308         int nxy = nx * ny;
06309 
06310         for (int k = 1; k < nz - 1; ++k) {
06311                 for (int j = 1; j < ny - 1; ++j) {
06312                         size_t l = j * nx + k * nxy + 1;
06313                         for (int i = 1; i < nx - 1; ++i, ++l) {
06314                                 if (dat2[l - 1] == 1.0f || dat2[l + 1] == 1.0f ||
06315                                         dat2[l - nx] == 1.0f || dat2[l + nx] == 1.0f ||
06316                                         dat2[l - nxy] == 1.0f || dat2[l + nxy] == 1.0f) {
06317                                         dat2[l] = 2.0f;
06318                                 }
06319                         }
06320                 }
06321         }
06322 
06323         size_t size = nx * ny * nz;
06324         for (size_t i = 0; i < size; i++) {
06325                 if (dat2[i] == 2.0f) {
06326                         dat2[i] = 1.0f;
06327                 }
06328         }
06329 
06330         fill_nearby(dat2, nx, ny, nz);
06331 
06332         image->update();
06333         amask->update();
06334 
06335         image->mult(*amask);
06336         amask->write_image("mask.mrc", 0, EMUtil::IMAGE_MRC);
06337         if( amask )
06338         {
06339                 delete amask;
06340                 amask = 0;
06341         }
06342 }
06343 
06344 
06345 void AutoMask3D2Processor::process_inplace(EMData * image)
06346 {
06347         if (!image) {
06348                 LOGWARN("NULL Image");
06349                 return;
06350         }
06351 
06352         if (image->get_ndim() != 3) {
06353                 throw ImageDimensionException("This processor was only ever designed to work on 3D images.");
06354         }
06355 
06356         /*
06357          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
06358          To get around this just use the return_mask parameter.
06359         string mask_output = params.set_default("write_mask", "");
06360         if ( mask_output != "") {
06361                 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.");
06362                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
06363         }
06364         */
06365 
06366         int radius=0;
06367         if (params.has_key("radius")) {
06368                 radius = params["radius"];
06369         }
06370         int nmaxseed=0;
06371         if (params.has_key("nmaxseed")) {
06372                 nmaxseed = params["nmaxseed"];
06373         }
06374 
06375         float threshold=0.0;
06376         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
06377         else threshold=params["threshold"];
06378 
06379         int nshells = params["nshells"];
06380         int nshellsgauss = params["nshellsgauss"];
06381         int verbose=params.set_default("verbose",0);
06382 
06383         int nx = image->get_xsize();
06384         int ny = image->get_ysize();
06385         int nz = image->get_zsize();
06386         int nxy=nx*ny;
06387 
06388         EMData *amask = new EMData();
06389         amask->set_size(nx, ny, nz);
06390 
06391         float *dat = image->get_data();
06392         float *dat2 = amask->get_data();
06393         int i,j,k;
06394         size_t l = 0;
06395 
06396         // Seeds with the highest valued pixels
06397         if (nmaxseed>0) {
06398                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
06399 
06400                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
06401                         amask->set_value_at((*i).x,(*i).y,(*i).z,1.0);
06402                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
06403                 }
06404         }
06405 
06406         // Seeds with a sphere
06407         if (radius>0) {
06408                 // start with an initial sphere
06409                 for (k = -nz / 2; k < nz / 2; ++k) {
06410                         for (j = -ny / 2; j < ny / 2; ++j) {
06411                                 for (i = -nx / 2; i < nx / 2; ++i,++l) {
06412                                         if (abs(k) > radius || abs(j) > radius || abs(i) > radius) continue;
06413                                         if ( (k * k + j * j + i * i) > (radius*radius) || dat[l] < threshold) continue;
06414                                         dat2[l] = 1.0f;
06415                                 }
06416                         }
06417                 }
06418         }
06419 
06420 
06421         // iteratively 'flood fills' the map... recursion would be better
06422         int done=0;
06423         int iter=0;
06424         while (!done) {
06425                 iter++;
06426                 done=1;
06427                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
06428                 for (k=1; k<nz-1; ++k) {
06429                         for (j=1; j<ny-1; ++j) {
06430                                 for (i=1; i<nx-1; ++i) {
06431                                         l=i+j*nx+k*nx*ny;
06432                                         if (dat2[l]) continue;
06433                                         if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx]||dat2[l-nxy]||dat2[l+nxy])) {
06434                                                 dat2[l]=1.0;
06435                                                 done=0;
06436                                         }
06437                                 }
06438                         }
06439                 }
06440         }
06441 
06442         amask->update();
06443 
06444         if (verbose) printf("extending mask\n");
06445         amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
06446 
06447         bool return_mask = params.set_default("return_mask",false);
06448         if (return_mask) {
06449                 // 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.
06450                 memcpy(dat,dat2,image->get_size()*sizeof(float));
06451         } else {
06452                 image->mult(*amask);
06453         }
06454 
06455         // EMAN2 policy is not to allow file io from with a processor
06456         //if (mask_output != "") {
06457         //      amask->write_image(mask_output);
06458         //}
06459 
06460 
06461         delete amask;
06462 }
06463 
06464 void IterBinMaskProcessor::process_inplace(EMData * image)
06465 {
06466         if (!image) {
06467                 LOGWARN("NULL Image");
06468                 return;
06469         }
06470 
06471         float val1 = params["val1"];
06472         float val2 = params["val2"];
06473 
06474         int nx = image->get_xsize();
06475         int ny = image->get_ysize();
06476         int nz = image->get_zsize();
06477         EMData *image2 = new EMData(nx,ny,nz);
06478 
06479         // Got a compile warning complaining that these things were never used. Hope I didn't break anything - apologies if so (d.woolford)
06480 //      float *dat = image->get_data();
06481 //      float *dat2 = image2->get_data();
06482 
06483 
06484         float *d = image->get_data();
06485         float *d2 = image2->get_data();
06486 
06487         const int nxy = nx * ny;
06488         size_t size = nx * ny * nz;
06489 
06490         // TODO: THIS IS EXTREMELY INEFFICIENT
06491         if (nz != 1) {
06492                 for (int l = 1; l <= (int) val1+val2; ++l) {
06493                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06494                         for (int k = 1; k < nz - 1; ++k) {
06495                                 for (int j = 1; j < ny - 1; ++j) {
06496                                         for (int i = 1; i < nx - 1; ++i) {
06497                                                 size_t t = i + j*nx+k*nx*ny;
06498                                                 if (d[t]) continue;
06499                                                 if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx] || d2[t + nxy] || d2[t - nxy]) d[t] = (float) l + 1;
06500                                         }
06501                                 }
06502                         }
06503                 }
06504         }
06505         else {
06506                 for (int l = 1; l <= (int) val1+val2; ++l) {
06507                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06508                         for (int j = 1; j < ny - 1; ++j) {
06509                                 for (int i = 1; i < nx - 1; ++i) {
06510                                         size_t t = i + j * nx;
06511                                         if (d[t]) continue;
06512                                         if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx]) d[t] = (float) l + 1;
06513                                 }
06514                         }
06515                 }
06516         }
06517 
06518         vector<float> vec;
06519         for (int i=0; i<val1+2; i++) vec.push_back(1.0);
06520         for (int i=0; i<val2; i++) {
06521                 vec.push_back(exp(-pow(2.0f*i/(val2),2.0f)));
06522 //              printf("%f\n",exp(-pow(2.0*i/(val1-val2),2.0)));
06523         }
06524         for (size_t i = 0; i < size; i++) if (d[i]) d[i]=vec[(int)d[i]];
06525 
06526         image->update();
06527         delete image2;
06528 }
06529 
06530 EMData* DirectionalSumProcessor::process(const EMData* const image ) {
06531         string dir = params.set_default("direction", "");
06532         if ( dir == "" || ( dir != "x" && dir != "y" && dir != "z" ) )
06533                 throw InvalidParameterException("The direction parameter must be either x, y, or z");
06534 
06535         int nx = image->get_xsize();
06536         int ny = image->get_ysize();
06537         int nz = image->get_zsize();
06538 
06539         // compress one of the dimensions
06540         if ( dir == "x" ) nx = 1;
06541         else if ( dir == "y" ) ny = 1;
06542         else if ( dir == "z" ) nz = 1;
06543 
06544         EMData* ret = new EMData;
06545         ret->set_size(nx,ny,nz);
06546         ret->to_zero();
06547 
06548         float* d = image->get_data();
06549         for(int k = 0; k < image->get_zsize(); ++k ) {
06550                 for(int j = 0; j < image->get_ysize(); ++j ) {
06551                         for(int i = 0; i < image->get_xsize(); ++i, ++d ) {
06552                                 if ( dir == "x" ) {
06553                                         float v = ret->get_value_at(0,j,k);
06554                                         ret->set_value_at(0,j,k,*d+v);
06555                                 }else if ( dir == "y" ) {
06556                                         float v = ret->get_value_at(i,0,k);
06557                                         ret->set_value_at(i,0,k,*d+v);
06558                                 }
06559                                 else if ( dir == "z" ) {
06560                                         float v = ret->get_value_at(i,j,0);
06561                                         ret->set_value_at(i,j,0,*d+v);
06562                                 }
06563                         }
06564                 }
06565         }
06566         ret->update();
06567         return ret;
06568 }
06569 
06570 void TestImageProcessor::preprocess(EMData * image)
06571 {
06572         if (!image) {
06573                 LOGWARN("NULL Image");
06574                 return;
06575         }
06576 
06577         nx = image->get_xsize();
06578         ny = image->get_ysize();
06579         nz = image->get_zsize();
06580 }
06581 
06582 
06583 void TestImageFourierNoiseGaussian::process_inplace(EMData* image)
06584 {
06585         if (!image->is_complex()) {
06586                 int nx = image->get_xsize();
06587                 int offset = 2 - nx%2;
06588 
06589                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
06590                 image->set_complex(true);
06591                 if (1 == offset) image->set_fftodd(true);
06592                 else image->set_fftodd(false);
06593                 image->set_fftpad(true);
06594         }
06595         image->ri2ap();
06596 
06597         float sigma = params.set_default("sigma",.25f);
06598 
06599         float * d = image->get_data();
06600         int nx = image->get_xsize();
06601         int ny = image->get_ysize();
06602         int nxy = image->get_ysize()*nx;
06603         int nzon2 = image->get_zsize()/2;
06604         int nyon2 = image->get_ysize()/2;
06605         float rx, ry, rz, length, amp, phase;
06606         int twox;
06607         for (int z = 0; z< image->get_zsize(); ++z) {
06608                 for (int y = 0; y < image->get_ysize(); ++y) {
06609                         for (int x = 0; x < image->get_xsize()/2; ++x) {
06610                                 rx = (float)x;
06611                                 ry = (float)nyon2 - (float)y;
06612                                 rz = (float)nzon2 - (float)z;
06613                                 length = sqrt(rx*rx + ry*ry + rz*rz);
06614                                 amp = exp(-sigma*length);
06615                                 phase = Util::get_frand(0,1)*2*M_PI;
06616 
06617                                 twox = 2*x;
06618                                 size_t idx1 = twox + y*nx+z*nxy;
06619                                 size_t idx2 = idx1 + 1;
06620                                 d[idx1] = amp;
06621                                 d[idx2] = phase;
06622 
06623                         }
06624                 }
06625         }
06626 
06627         image->ap2ri();
06628         if (image->get_ndim() == 2) {
06629                 bool yodd = image->get_ysize() % 2 == 1;
06630 
06631                 int yit = image->get_ysize()/2-1;
06632                 int offset = 1;
06633                 if (yodd) {
06634                         offset = 0;
06635                 }
06636                 for (int y = 0; y < yit; ++y) {
06637                         int bot_idx = (y+offset)*nx;
06638                         int top_idx = (ny-1-y)*nx;
06639                         float r1 = d[bot_idx];
06640                         float i1 = d[bot_idx+1];
06641                         float r2 = d[top_idx];
06642                         float i2 = d[top_idx+1];
06643                         float r = (r1 + r2)/2.0f;
06644                         float i = (i1 + i2)/2.0f;
06645                         d[bot_idx] = r;
06646                         d[top_idx] = r;
06647                         d[bot_idx+1] = i;
06648                         d[top_idx+1] = -i;
06649 
06650                         bot_idx = (y+offset)*nx+nx-2;
06651                         top_idx = (ny-1-y)*nx+nx-2;
06652                         r1 = d[bot_idx];
06653                         i1 = d[bot_idx+1];
06654                         r2 = d[top_idx];
06655                         i2 = d[top_idx+1];
06656                         r = (r1 + r2)/2.0f;
06657                         i = (i1 + i2)/2.0f;
06658                         d[bot_idx] = r;
06659                         d[top_idx] = r;
06660                         d[bot_idx+1] = i;
06661                         d[top_idx+1] = -i;
06662                 }
06663 
06664                 d[1] = 0; // 0 phase for this componenet
06665                 d[nx-1] = 0; // 0 phase for this component
06666                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
06667                 d[ny/2*nx+1] = 0;// 0 phase for this component
06668         }
06669 
06670         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
06671         image->do_ift_inplace();
06672         image->depad();
06673 }
06674 
06675 #include <iostream>
06676 using std::ostream_iterator;
06677 
06678 void CTFSNRWeightProcessor::process_inplace(EMData* image) {
06679         if (params.has_key("noise")==false) throw InvalidParameterException("You must supply the noise argument");
06680         if (params.has_key("snr")==false) throw InvalidParameterException("You must supply the snr argument");
06681 
06682         float boost = params.set_default("boost",1.0f);
06683 
06684         if (!image->is_complex()) {
06685                 image->do_fft_inplace();
06686         }
06687         EMData* cpy = image->copy();
06688         cpy->ri2inten();
06689         vector<float> sf = cpy->calc_radial_dist(cpy->get_ysize()/2,0.0,1.0,1);
06690         transform(sf.begin(),sf.end(),sf.begin(),sqrtf);
06691         delete cpy;
06692 
06693         image->ri2ap();
06694 
06695         vector<float> noise = params["noise"];
06696         vector<float> snr = params["snr"];
06697 
06698 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
06699 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
06700 
06701         for(vector<float>::iterator it = noise.begin(); it != noise.end(); ++it){
06702                 if ((*it) == 0) *it = 1;
06703         }
06704         for(vector<float>::iterator it = snr.begin(); it != snr.end(); ++it){
06705                 if ((*it) < 0) *it = 0;
06706         }
06707         // Subtract the mean from the data and store it in data_mm
06708         transform(snr.begin(),snr.end(),noise.begin(),snr.begin(),std::multiplies<float>());
06709         transform(snr.begin(),snr.end(),snr.begin(),sqrtf);
06710 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
06711 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
06712 
06713         int i = static_cast<int>(snr.size());
06714 
06715         float * d = image->get_data();
06716         int nx = image->get_xsize();
06717 //      int ny = image->get_ysize();
06718         int nxy = image->get_ysize()*nx;
06719         int nzon2 = image->get_zsize()/2;
06720         int nyon2 = image->get_ysize()/2;
06721         float rx, ry, rz, amp;
06722         int length;
06723         int twox;
06724         image->process_inplace("xform.fourierorigin.tocenter");
06725         for (int z = 0; z< image->get_zsize(); ++z) {
06726                 for (int y = 0; y < image->get_ysize(); ++y) {
06727                         for (int x = 0; x < image->get_xsize()/2; ++x) {
06728                                 rx = (float)x;
06729                                 ry = (float)nyon2 - (float)y;
06730                                 rz = (float)nzon2 - (float)z;
06731                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
06732 
06733                                 twox = 2*x;
06734                                 size_t idx1 = twox + y*nx+z*nxy;
06735                                 if (length >= i || length >= (int)sf.size()) {
06736                                         d[idx1] = 0;
06737                                         continue;
06738                                 } else {
06739                                         amp = boost*snr[length];
06740 //                                      if (amp > 0) amp =sqrtf(amp);
06741 //                                      else amp = 0;
06742                                 }
06743 
06744                                 if (sf[length] == 0) {
06745                                         d[idx1] = 0;
06746                                         continue;
06747                                 }
06748 
06749 //                              size_t idx2 = idx1 + 1;
06750 //                              cout << d[idx1] << " " << sf[length] << endl;
06751                                 d[idx1] /= sf[length];
06752                                 if (d[idx1] < 0) {
06753                                         d[idx1] *= amp;
06754                                 }else {
06755                                         d[idx1] *= -amp;
06756                                 }
06757 //                              d[idx2] = phase;
06758 
06759                         }
06760                 }
06761         }
06762 
06763         image->ap2ri();
06764         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
06765         image->do_ift_inplace();
06766         image->depad();
06767 }
06768 
06769 void TestImageFourierNoiseProfile::process_inplace(EMData * image) {
06770 
06771         if (params.has_key("profile")==false) throw InvalidParameterException("You must supply the profile argument");
06772 
06773         if (!image->is_complex()) {
06774                 int nx = image->get_xsize();
06775                 int offset = 2 - nx%2;
06776 
06777                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
06778                 image->set_complex(true);
06779                 if (1 == offset) image->set_fftodd(true);
06780                 else image->set_fftodd(false);
06781                 image->set_fftpad(true);
06782         }
06783         image->to_zero();
06784         image->ri2ap();
06785 
06786         vector<float> profile = params["profile"];
06787         transform(profile.begin(),profile.end(),profile.begin(),sqrtf);
06788 
06789         int i = static_cast<int>(profile.size());
06790 
06791         float * d = image->get_data();
06792         int nx = image->get_xsize();
06793         int ny = image->get_ysize();
06794         int nxy = image->get_ysize()*nx;
06795         int nzon2 = image->get_zsize()/2;
06796         int nyon2 = image->get_ysize()/2;
06797         float rx, ry, rz, amp, phase;
06798         int length;
06799         int twox;
06800         for (int z = 0; z< image->get_zsize(); ++z) {
06801                 for (int y = 0; y < image->get_ysize(); ++y) {
06802                         for (int x = 0; x < image->get_xsize()/2; ++x) {
06803                                 rx = (float)x;
06804                                 ry = (float)nyon2 - (float)y;
06805                                 rz = (float)nzon2 - (float)z;
06806                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
06807 
06808                                 twox = 2*x;
06809                                 size_t idx1 = twox + y*nx+z*nxy;
06810                                 size_t idx2 = idx1 + 1;
06811 
06812 
06813                                 if (length >= i) {
06814                                         d[idx1] = 0;
06815                                         d[idx2] = 0;
06816                                         continue;
06817                                 }
06818                                 amp = profile[length];
06819                                 phase = Util::get_frand(0,1)*2*M_PI;
06820 
06821 
06822                                 d[idx1] = amp;
06823                                 d[idx2] = phase;
06824 
06825                         }
06826                 }
06827         }
06828 
06829         image->ap2ri();
06830         if (image->get_ndim() == 2) {
06831                 bool yodd = image->get_ysize() % 2 == 1;
06832 
06833                 int yit = image->get_ysize()/2-1;
06834                 int offset = 1;
06835                 if (yodd) {
06836                         offset = 0;
06837                 }
06838                 for (int y = 0; y < yit; ++y) {
06839                         int bot_idx = (y+offset)*nx;
06840                         int top_idx = (ny-1-y)*nx;
06841                         float r1 = d[bot_idx];
06842                         float i1 = d[bot_idx+1];
06843                         float r2 = d[top_idx];
06844                         float i2 = d[top_idx+1];
06845                         float r = (r1 + r2)/2.0f;
06846                         float i = (i1 + i2)/2.0f;
06847                         d[bot_idx] = r;
06848                         d[top_idx] = r;
06849                         d[bot_idx+1] = i;
06850                         d[top_idx+1] = -i;
06851 
06852                         bot_idx = (y+offset)*nx+nx-2;
06853                         top_idx = (ny-1-y)*nx+nx-2;
06854                         r1 = d[bot_idx];
06855                         i1 = d[bot_idx+1];
06856                         r2 = d[top_idx];
06857                         i2 = d[top_idx+1];
06858                         r = (r1 + r2)/2.0f;
06859                         i = (i1 + i2)/2.0f;
06860                         d[bot_idx] = r;
06861                         d[top_idx] = r;
06862                         d[bot_idx+1] = i;
06863                         d[top_idx+1] = -i;
06864                 }
06865 
06866                 d[1] = 0; // 0 phase for this componenet
06867                 d[nx-1] = 0; // 0 phase for this component
06868                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
06869                 d[ny/2*nx+1] = 0;// 0 phase for this component
06870         }
06871 
06872         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
06873         image->do_ift_inplace();
06874         image->depad();
06875 }
06876 
06877 void TestImageLineWave::process_inplace(EMData * image)
06878 {
06879         preprocess(image);
06880 
06881         float period = params.set_default("period",10.0f);
06882         int n = image->get_xsize()*image->get_ysize()*image->get_zsize();
06883 
06884         for(int i = 0; i < n; ++i) {
06885                 float x = fmod((float)i,period);
06886                 x /= period;
06887                 x = (float)sin(x*EMConsts::pi*2.0);
06888                 image->set_value_at_fast(i,x);
06889         }
06890 }
06891 
06892 void TestImageGaussian::process_inplace(EMData * image)
06893 {
06894         preprocess(image);
06895 
06896         float sigma = params["sigma"];
06897         string axis = (const char*)params["axis"];
06898         float c = params["c"];
06899 
06900         float *dat = image->get_data();
06901         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
06902         float x2, y2, z2; //this is the coordinates of this pixel from image center
06903         for (int k = 0; k < nz; ++k) {
06904                 for (int j = 0; j < ny; ++j) {
06905                         for (int i = 0; i < nx; ++i, ++dat) {
06906                                 x2 = (float)( i - nx/2 );
06907                                 y2 = (float)( j - ny/2 );
06908                                 z2 = (float)( k - nz/2 );
06909 
06910                                 if(axis==""){
06911                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
06912                                 }
06913                                 else if(axis == "x"){
06914                                         float lc = -c;
06915                                         float rc = c;
06916                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
06917                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
06918                                 }
06919                                 else if(axis == "y"){
06920                                         float lc = -c;
06921                                         float rc = c;
06922                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
06923                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
06924                                 }
06925                                 else if(axis == "z"){
06926                                         if( nz == 1 ){
06927                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
06928                                         }
06929                                         float lc = -c;
06930                                         float rc = c;
06931                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
06932                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
06933                                 }
06934                                 else{
06935                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
06936                                 }
06937                                 //the amplitude of the pixel is proportional to the distance of this pixel from the center
06938                                 *dat = (float)gsl_ran_gaussian_pdf((double)r,(double)sigma);
06939                         }
06940                 }
06941         }
06942 
06943         image->update();
06944 }
06945 
06946 void TestImageGradient::process_inplace(EMData * image)
06947 {
06948         string axis = params.set_default("axis", "x");
06949 
06950         float m = params.set_default("m", 1.0f);
06951         float b = params.set_default("b", 0.0f);
06952 
06953         if ( axis != "z" && axis != "y" && axis != "x") throw InvalidParameterException("Axis must be x,y or z");
06954 
06955         preprocess(image);
06956 
06957         if ( axis == "x")
06958         {
06959                 for(int k=0; k<nz;++k) {
06960                         for(int j=0; j<ny; ++j) {
06961                                 for(int i=0; i <nx; ++i) {
06962                                         image->set_value_at(i,j,k,m*i+b);
06963                                 }
06964                         }
06965                 }
06966         }
06967         else if ( axis == "y")
06968         {
06969                 for(int k=0; k<nz;++k) {
06970                         for(int j=0; j<ny; ++j) {
06971                                 for(int i=0; i <nx; ++i) {
06972                                         image->set_value_at(i,j,k,m*j+b);
06973                                 }
06974                         }
06975                 }
06976         }
06977         else if ( axis == "z")
06978         {
06979                 for(int k=0; k<nz;++k) {
06980                         for(int j=0; j<ny; ++j) {
06981                                 for(int i=0; i <nx; ++i) {
06982                                         image->set_value_at(i,j,k,m*k+b);
06983                                 }
06984                         }
06985                 }
06986         }
06987         image->update();
06988 }
06989 
06990 void TestImageAxes::process_inplace(EMData * image)
06991 {
06992         preprocess(image);
06993 
06994         float fill = params.set_default("fill", 1.0f);
06995         // get the central coordinates
06996         int cx = nx/2;
06997         int cy = ny/2;
06998         int cz = nz/2;
06999 
07000         // Offsets are used to detect when "the extra pixel" needs to be filled in
07001         // They are implemented on the assumption that for odd dimensions
07002         // the "center pixel" is the center pixel, but for even dimensions the "center
07003         // pixel" is displaced in the positive direction by 1
07004         int xoffset = (nx % 2 == 0? 1:0);
07005         int yoffset = (ny % 2 == 0? 1:0);
07006         int zoffset = (nz % 2 == 0? 1:0);
07007 
07008         // This should never occur - but if indeed it did occur, the code in this function
07009         // would break - the function would proceed into the final "else" and seg fault
07010         // It is commented out but left for clarity
07011 //      if ( nx < 1 || ny < 1 || nz < 1 ) throw ImageDimensionException("Error: one of the image dimensions was less than zero");
07012 
07013         if ( nx == 1 && ny == 1 && nz == 1 )
07014         {
07015                 (*image)(0) = fill;
07016         }
07017         else if ( ny == 1 && nz == 1 )
07018         {
07019                 int radius = params.set_default("radius", cx );
07020                 if ( radius > cx ) radius = cx;
07021 
07022                 (*image)(cx) = fill;
07023                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i) = fill;
07024                 for ( int i = 1; i <= radius; ++i ) (*image)(cx-i) = fill;
07025         }
07026         else if ( nz == 1 )
07027         {
07028                 int min = ( nx < ny ? nx : ny );
07029                 min /= 2;
07030 
07031                 int radius = params.set_default("radius", min );
07032                 if ( radius > min ) radius = min;
07033 
07034                 (*image)(cx,cy) = fill;
07035 
07036                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i,cy) = fill;
07037                 for ( int i = 1; i <= radius-yoffset; ++i )(*image)(cx,cy+i) = fill;
07038 
07039                 for ( int i = 1; i <= radius; ++i )
07040                 {
07041                         (*image)(cx-i,cy) = fill;
07042                         (*image)(cx,cy-i) = fill;
07043                 }
07044 
07045         }
07046         else
07047         {
07048                 // nx > 1 && ny > 1 && nz > 1
07049                 int min = ( nx < ny ? nx : ny );
07050                 if (nz < min ) min = nz;
07051                 min /= 2;
07052 
07053                 int radius = params.set_default("radius", min);
07054                 if ( radius > min ) radius = min;
07055 
07056 
07057                 (*image)(cx,cy,cz) = fill;
07058                 for ( int i = 1; i <=radius-xoffset; ++i ) (*image)(cx+i,cy,cz) = fill;
07059                 for ( int i = 1; i <=radius-yoffset; ++i ) (*image)(cx,cy+i,cz) = fill;
07060                 for ( int i = 1; i <=radius-zoffset; ++i ) (*image)(cx,cy,cz+i) = fill;
07061                 for ( int i = 1; i <= radius; ++i )
07062                 {
07063                         (*image)(cx-i,cy,cz) = fill;
07064                         (*image)(cx,cy-i,cz) = fill;
07065                         (*image)(cx,cy,cz-i) = fill;
07066                 }
07067         }
07068 
07069         image->update();
07070 }
07071 
07072 void TestImageScurve::process_inplace(EMData * image)
07073 {
07074         preprocess(image);
07075 
07076         int dim_size = image->get_ndim();
07077         if( 2 != dim_size ) {
07078                 throw ImageDimensionException("works for 2D images only");
07079         }
07080 
07081         int nx = image->get_xsize();
07082         int ny = image->get_ysize();
07083         image->to_zero();
07084 
07085         for (int i=0; i<100; i++) {
07086                 int x=static_cast<int>( nx/2+nx/6.0*sin(i*2.0*3.14159/100.0) );
07087                 int y=ny/4+i*ny/200;
07088                 for (int xx=x-nx/10; xx<x+nx/10; xx++) {
07089                         for (int yy=y-ny/10; yy<y+ny/10; yy++) {
07090 #ifdef  _WIN32
07091                                 (*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);
07092 #else
07093                                 (*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);
07094 #endif
07095                         }
07096                 }
07097         }
07098 
07099         image->update();
07100 }
07101 
07102 void TestImagePureGaussian::process_inplace(EMData * image)
07103 {
07104         preprocess(image);
07105 
07106         float x_sigma = params["x_sigma"];
07107         float y_sigma = params["y_sigma"];
07108         float z_sigma = params["z_sigma"];
07109 
07110         float x_center = params["x_center"];
07111         float y_center = params["y_center"];
07112         float z_center = params["z_center"];
07113 
07114         int nx = image->get_xsize();
07115         int ny = image->get_ysize();
07116         int nz = image->get_zsize();
07117 
07118         float x_twosig2 = 2*x_sigma*x_sigma;
07119         float y_twosig2 = 2*y_sigma*y_sigma;
07120         float z_twosig2 = 2*z_sigma*z_sigma;
07121 
07122         float sr2pi = sqrt( 2.0f*(float)pi );
07123         float norm  = 1.0f/ ( x_sigma*sr2pi );
07124         if (ny > 1) {
07125                 norm *= 1.0f/ ( y_sigma*sr2pi );
07126                 if (nz > 1) norm  *= 1.0f/ ( z_sigma*sr2pi );
07127         }
07128 
07129         float z, y, x, sum, val;
07130         for (int iz=0; iz < nz; ++iz) {
07131                 z = static_cast<float>(iz) - z_center;
07132                 for (int iy=0; iy < ny; ++iy) {
07133                         y = static_cast<float>(iy) - y_center;
07134                         for (int ix=0; ix < nx; ++ix) {
07135                                 x = static_cast<float>(ix) - x_center;
07136                                 sum = x*x/x_twosig2 + y*y/y_twosig2 + z*z/z_twosig2;
07137                                 val = norm*exp(-sum);
07138                                 (*image)(ix,iy,iz) = val;
07139                         }
07140                 }
07141         }
07142         image->update();
07143 }
07144 
07145 void TestImageSphericalWave::process_inplace(EMData * image)
07146 {
07147         preprocess(image);
07148 
07149         if(!params.has_key("wavelength")) {
07150                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07151                 throw InvalidParameterException("wavelength parameter is required.");
07152         }
07153         float wavelength = params["wavelength"];
07154 
07155         float phase = 0;
07156         if(params.has_key("phase")) {
07157                 phase = params["phase"];
07158         }
07159 
07160         float x = (float)(nx/2);
07161         if (params.has_key("x")) x=params["x"];
07162         float y = (float)(ny/2);
07163         if (params.has_key("y")) y=params["y"];
07164         float z = (float)(nz/2);
07165         if (params.has_key("z")) z=params["z"];
07166 
07167         int ndim = image->get_ndim();
07168 
07169         if(ndim==2) {   //2D
07170                 for(int j=0; j<ny; ++j) {
07171                         for(int i=0; i<nx; ++i) {
07172 #ifdef _WIN32
07173                                 float r=_hypotf(x-(float)i,y-(float)j);
07174 #else
07175                                 float r=hypot(x-(float)i,y-(float)j);
07176 #endif  //_WIN32
07177                                 if (r<.5) continue;
07178                                 image->set_value_at(i,j,cos(2*(float)pi*r/wavelength+phase)/r);
07179                         }
07180                 }
07181         }
07182         else {  //3D
07183                 for(int k=0; k<nz; ++k) {
07184                         for(int j=0; j<ny; ++j) {
07185                                 for(int i=0; i<nx; ++i) {
07186                                         float r=Util::hypot3(x-(float)i,y-(float)j,z-(float)k);
07187                                         if (r<.5) continue;
07188                                         image->set_value_at(i,j,k,cos(2*(float)pi*r/wavelength+phase)/(r*r));
07189                                 }
07190                         }
07191                 }
07192         }
07193 
07194         image->update();
07195 }
07196 
07197 
07198 void TestImageSinewave::process_inplace(EMData * image)
07199 {
07200         preprocess(image);
07201 
07202         if(!params.has_key("wavelength")) {
07203                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07204                 throw InvalidParameterException("wavelength parameter is required.");
07205         }
07206         float wavelength = params["wavelength"];
07207 
07208         string axis = "";
07209         if(params.has_key("axis")) {
07210                 axis = (const char*)params["axis"];
07211         }
07212 
07213         float phase = 0;
07214         if(params.has_key("phase")) {
07215                 phase = params["phase"];
07216         }
07217 
07218         int ndim = image->get_ndim();
07219         float * dat = image->get_data();
07220 
07221         if(ndim==1) {   //1D
07222                 for(int i=0; i<nx; ++i, ++dat) {
07223                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07224                 }
07225         }
07226         else if(ndim==2) {      //2D
07227                 float alpha = 0;
07228                 if(params.has_key("az")) {
07229                         alpha = params["az"];
07230                 }
07231                 for(int j=0; j<ny; ++j) {
07232                         for(int i=0; i<nx; ++i, ++dat) {
07233                                 if(alpha != 0) {
07234                                         *dat = sin((i*sin((180-alpha)*M_PI/180)+j*cos((180-alpha)*M_PI/180))*(2.0f*M_PI/wavelength) + phase);
07235                                 }
07236                                 else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07237                                         *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07238                                 }
07239                                 else {
07240                                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07241                                 }
07242                         }
07243                 }
07244         }
07245         else {  //3D
07246                 float az = 0;
07247                 if(params.has_key("az")) {
07248                         az = params["az"];
07249                 }
07250                 float alt = 0;
07251                 if(params.has_key("alt")) {
07252                         alt = params["alt"];
07253                 }
07254                 float phi = 0;
07255                 if(params.has_key("phi")) {
07256                         phi = params["phi"];
07257                 }
07258 
07259                 for(int k=0; k<nz; ++k) {
07260                         for(int j=0; j<ny; ++j) {
07261                                 for(int i=0; i<nx; ++i, ++dat) {
07262                                         if(axis.compare("z")==0 || axis.compare("Z")==0) {
07263                                                 *dat = sin(k*(2.0f*M_PI/wavelength) + phase);
07264                                         }
07265                                         else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07266                                                 *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07267                                         }
07268                                         else {
07269                                                 *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07270                                         }
07271                                 }
07272                         }
07273                 }
07274 
07275                 if(az != 0 || alt != 0 || phi != 0) {
07276                         Dict d("type","eman");
07277                         d["az"] = az; d["phi"] = phi; d["alt"] = alt;
07278                         image->transform(Transform(d));
07279                 }
07280         }
07281 
07282         image->update();
07283 }
07284 
07285 void TestImageSinewaveCircular::process_inplace(EMData * image)
07286 {
07287         preprocess(image);
07288 
07289         float wavelength = params["wavelength"];
07290         string axis = (const char*)params["axis"];
07291         float c = params["c"];
07292         float phase = params["phase"];
07293 
07294         float *dat = image->get_data();
07295         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
07296         float x2, y2, z2; //this is the coordinates of this pixel from image center
07297         for (int k = 0; k < nz; ++k) {
07298                 for (int j = 0; j < ny; ++j) {
07299                         for (int i = 0; i < nx; ++i, ++dat) {
07300                                 x2 = (float)( i - nx/2 );
07301                                 y2 = (float)( j - ny/2 );
07302                                 z2 = (float)( k - nz/2 );
07303                                 if(axis == ""){
07304                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
07305                                 }
07306                                 else if(axis == "x"){
07307                                         float lc = -c;
07308                                         float rc = c;
07309                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
07310                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
07311                                 }
07312                                 else if(axis == "y"){
07313                                         float lc = -c;
07314                                         float rc = c;
07315                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
07316                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
07317                                 }
07318                                 else if(axis == "z"){
07319                                         if( nz == 1 ){
07320                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07321                                         }
07322                                         float lc = -c;
07323                                         float rc = c;
07324                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
07325                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
07326                                 }
07327                                 else{
07328                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07329                                 }
07330                                 *dat = sin( r * (2.0f*M_PI/wavelength) - phase*180/M_PI);
07331                         }
07332                 }
07333         }
07334 
07335         image->update();
07336 }
07337 
07338 void TestImageSquarecube::process_inplace(EMData * image)
07339 {
07340         preprocess(image);
07341 
07342         float edge_length = params["edge_length"];
07343         string axis = (const char*)params["axis"];
07344         float odd_edge = params["odd_edge"];
07345         int fill = (int)params["fill"];
07346 
07347         float *dat = image->get_data();
07348         float x2, y2, z2; //this coordinates of this pixel from center
07349         float xEdge, yEdge, zEdge; //half of edge length for this cube
07350         if(axis == ""){
07351                 xEdge = edge_length/2.0f;
07352                 yEdge = edge_length/2.0f;
07353                 zEdge = edge_length/2.0f;
07354         }
07355         else if(axis == "x"){
07356                 xEdge = odd_edge/2.0f;
07357                 yEdge = edge_length/2.0f;
07358                 zEdge = edge_length/2.0f;
07359         }
07360         else if(axis == "y"){
07361                 xEdge = edge_length/2.0f;
07362                 yEdge = odd_edge/2.0f;
07363                 zEdge = edge_length/2.0f;
07364         }
07365         else if(axis == "z"){
07366                 if( nz == 1 ){
07367                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07368                 }
07369                 xEdge = edge_length/2.0f;
07370                 yEdge = edge_length/2.0f;
07371                 zEdge = odd_edge/2.0f;
07372         }
07373         else{
07374                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07375         }
07376         for (int k = 0; k < nz; ++k) {
07377                 for (int j = 0; j < ny; ++j) {
07378                         for (int i = 0; i < nx; ++i, ++dat) {
07379                                 x2 = (float)fabs((float)i - nx/2);
07380                                 y2 = (float)fabs((float)j - ny/2);
07381                                 z2 = (float)fabs((float)k - nz/2);
07382                                 if( x2<=xEdge && y2<=yEdge && z2<=zEdge ) {
07383                                         if( !fill) {
07384                                                 *dat = 0;
07385                                         }
07386                                         else {
07387                                                 *dat = 1;
07388                                         }
07389                                 }
07390                                 else {
07391                                         if( !fill ) {
07392                                                 *dat = 1;
07393                                         }
07394                                         else {
07395                                                 *dat = 0;
07396                                         }
07397                                 }
07398                         }
07399                 }
07400         }
07401 
07402         image->update();
07403 }
07404 
07405 void TestImageCirclesphere::process_inplace(EMData * image)
07406 {
07407         preprocess(image);
07408 
07409         float radius = params.set_default("radius",nx/2.0f);
07410         string axis = (const char*)params["axis"];
07411         float c =  params.set_default("c",nx/2.0f);
07412         int fill = params.set_default("fill",1);
07413 
07414         float *dat = image->get_data();
07415         float x2, y2, z2; //this is coordinates of this pixel from center
07416         float r = 0.0f;
07417         float asy = 0.0f;
07418         if(axis == ""){
07419                 asy = radius;
07420         }
07421         else if(axis == "x" || axis == "y"){
07422                 asy = c;
07423         }
07424         else if(axis=="z"){
07425                 if( nz == 1 ){
07426                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07427                 }
07428                 asy = c;
07429         }
07430         else{
07431                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07432         }
07433 
07434         for (int k = 0; k < nz; ++k) {
07435                 for (int j = 0; j < ny; ++j) {
07436                         for (int i = 0; i < nx; ++i, ++dat) {
07437                                 x2 = fabs((float)i - nx/2);
07438                                 y2 = fabs((float)j - ny/2);
07439                                 z2 = fabs((float)k - nz/2);
07440                                 if( axis == "" ){
07441                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07442                                 }
07443                                 else if (axis == "x"){
07444                                         r = (x2*x2)/(asy*asy) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07445                                 }
07446                                 else if(axis == "y"){
07447                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(asy*asy) + (z2*z2)/(radius*radius);
07448                                 }
07449                                 else if(axis=="z"){
07450                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(asy*asy);
07451                                 }
07452                                 if( r<=1 ) {
07453                                         if( !fill) {
07454                                                 *dat = 0;
07455                                         }
07456                                         else {
07457                                                 *dat = 1;
07458                                         }
07459                                 }
07460                                 else {
07461                                         if( !fill ) {
07462                                                 *dat = 1;
07463                                         }
07464                                         else {
07465                                                 *dat = 0;
07466                                         }
07467                                 }
07468                         }
07469                 }
07470         }
07471 
07472         image->update();
07473 }
07474 
07475 void TestImageHollowEllipse::process_inplace(EMData * image)
07476 {
07477         preprocess(image);
07478 
07479         float width = params.set_default("width",2.0f);
07480 
07481         float a2 = params.set_default("a",nx/2.0f-1.0f);
07482         float b2 = params.set_default("b",ny/2.0f-1.0f);
07483         float c2 = params.set_default("c",nz/2.0f-1.0f);
07484 
07485         float a1 = params.set_default("xwidth",a2-width);
07486         float b1 = params.set_default("ywidth",b2-width);
07487         float c1 = params.set_default("zwidth",c2-width);
07488 
07489         float fill = params.set_default("fill",1.0f);
07490         Transform* t;
07491         if (params.has_key("transform")) {
07492                 t = params["transform"];
07493         } else {
07494                 t = new Transform;
07495         }
07496 
07497 
07498         int mz = 2*(int)c2+1;
07499         if ( nz < mz ) mz = nz;
07500         int my = 2*(int)b2+1;
07501         if ( ny < my ) my = ny;
07502         int mx = 2*(int)a2+1;
07503         if ( nx < mx ) mx = nx;
07504 
07505         float ai1 = 1/(a1*a1);
07506         float bi1 = 1/(b1*b1);
07507         float ci1 = 1/(c1*c1);
07508 
07509         float ai2 = 1/(a2*a2);
07510         float bi2 = 1/(b2*b2);
07511         float ci2 = 1/(c2*c2);
07512 
07513         Vec3f origin(nx/2,ny/2,nz/2);
07514 
07515         float x2, y2, z2, r1,r2;
07516         int xl, yl, zl;
07517         for (int k = 0; k < mz; ++k) {
07518                 for (int j = 0; j < my; ++j) {
07519                         for (int i = 0; i < mx; ++i) {
07520                                 x2 = (float)(i - mx/2);
07521                                 y2 = (float)(j - my/2);
07522                                 z2 = (float)(k - mz/2);
07523                                 r1 = (x2*x2)*ai1 + (y2*y2)*bi1 + (z2*z2)*ci1;
07524                                 r2 = (x2*x2)*ai2 + (y2*y2)*bi2 + (z2*z2)*ci2;
07525                                 if (r2 <= 1 && r1 >= 1) {
07526 
07527                                         if (t != 0) {
07528                                                 Vec3f v(x2,y2,z2);
07529                                                 v = (*t)*v;
07530                                                 v += origin;
07531 
07532                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07533                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07534 
07535                                                 for( int kk = -1; kk <= 1; ++kk)
07536                                                         for( int jj = -1; jj <= 1; ++jj)
07537                                                                 for( int ii = -1; ii <= 1; ++ii) {
07538                                                                         xl = (int)v[0]+ii;
07539                                                                         yl = (int)v[1]+jj;
07540                                                                         zl = (int)v[2]+kk;
07541                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07542                                                                                 image->set_value_at(xl,yl,zl,1.0);
07543                                                                 }
07544                                         } else {
07545                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07546                                         }
07547                                 }
07548                         }
07549                 }
07550         }
07551 
07552         delete t;
07553 
07554         image->update();
07555 }
07556 
07557 void TestImageEllipse::process_inplace(EMData * image)
07558 {
07559         preprocess(image);
07560 
07561 
07562         float a = params.set_default("a",nx/2.0f-1.0f);
07563         float b = params.set_default("b",ny/2.0f-1.0f);
07564         float c = params.set_default("c",nz/2.0f-1.0f);
07565         float fill = params.set_default("fill",1.0f);
07566         //bool hollow = params.set_default("hollow",false);
07567         Transform* t;
07568         if (params.has_key("transform")) {
07569                 t = params["transform"];
07570         } else {
07571                 t = new Transform;
07572         }
07573 
07574 
07575         int mz = 2*(int)c+1;
07576         if ( nz < mz ) mz = nz;
07577         int my = 2*(int)b+1;
07578         if ( ny < my ) my = ny;
07579         int mx = 2*(int)a+1;
07580         if ( nx < mx ) mx = nx;
07581 
07582 
07583         float ai = 1/(a*a);
07584         float bi = 1/(b*b);
07585         float ci = 1/(c*c);
07586 
07587         Vec3f origin(nx/2,ny/2,nz/2);
07588 
07589         float x2, y2, z2, r;
07590         int xl, yl, zl;
07591         for (int k = 0; k < mz; ++k) {
07592                 for (int j = 0; j < my; ++j) {
07593                         for (int i = 0; i < mx; ++i) {
07594                                 x2 = (float)(i - mx/2);
07595                                 y2 = (float)(j - my/2);
07596                                 z2 = (float)(k - mz/2);
07597                                 r = (x2*x2)*ai + (y2*y2)*bi + (z2*z2)*ci;
07598                                 if (r <= 1) {
07599 
07600                                         if (t != 0) {
07601                                                 Vec3f v(x2,y2,z2);
07602                                                 v = (*t)*v;
07603                                                 v += origin;
07604 
07605                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07606                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07607 
07608                                                 for( int kk = -1; kk <= 1; ++kk)
07609                                                         for( int jj = -1; jj <= 1; ++jj)
07610                                                                 for( int ii = -1; ii <= 1; ++ii) {
07611                                                                         xl = (int)v[0]+ii;
07612                                                                         yl = (int)v[1]+jj;
07613                                                                         zl = (int)v[2]+kk;
07614                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07615                                                                                 image->set_value_at(xl,yl,zl,fill);
07616                                                                 }
07617                                         } else {
07618                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07619                                         }
07620                                 }
07621                         }
07622                 }
07623         }
07624 
07625         delete t;
07626 
07627         image->update();
07628 }
07629 
07630 void TestImageNoiseUniformRand::process_inplace(EMData * image)
07631 {
07632         preprocess(image);
07633 
07634         Randnum * r = Randnum::Instance();
07635         if(params.has_key("seed")) {
07636                 r->set_seed((int)params["seed"]);
07637         }
07638 
07639         float *dat = image->get_data();
07640         size_t size = nx*ny*nz;
07641         for (size_t i=0; i<size; ++i) {
07642                 dat[i] = r->get_frand();
07643         }
07644 
07645         image->update();
07646 }
07647 
07648 void TestImageNoiseGauss::process_inplace(EMData * image)
07649 {
07650         preprocess(image);
07651 
07652         float sigma = params["sigma"];
07653         if (sigma<=0) { sigma = 1.0; }
07654         float mean = params["mean"];
07655 
07656         Randnum * r = Randnum::Instance();
07657         if (params.has_key("seed")) {
07658                 r->set_seed((int)params["seed"]);
07659         }
07660 
07661         float *dat = image->get_data();
07662         size_t size = nx*ny*nz;
07663         for (size_t i=0; i<size; ++i) {
07664                 dat[i] = r->get_gauss_rand(mean, sigma);
07665         }
07666 
07667         image->update();
07668 }
07669 
07670 void TestImageCylinder::process_inplace(EMData * image)
07671 {
07672         preprocess(image);
07673 
07674         int nx = image->get_xsize();
07675         int ny = image->get_ysize();
07676         int nz = image->get_zsize();
07677 
07678         if(nz == 1) {
07679                 throw ImageDimensionException("This processor only apply to 3D image");
07680         }
07681 
07682         float radius = params["radius"];
07683 #ifdef _WIN32
07684         if(radius > _cpp_min(nx, ny)/2.0) {
07685 #else
07686         if(radius > std::min(nx, ny)/2.0) {
07687 #endif
07688                 throw InvalidValueException(radius, "radius must be <= min(nx, ny)/2");
07689         }
07690 
07691         float height;
07692         if(params.has_key("height")) {
07693                 height = params["height"];
07694                 if(height > nz) {
07695                         throw InvalidValueException(radius, "height must be <= nz");
07696                 }
07697         }
07698         else {
07699                 height = static_cast<float>(nz);
07700         }
07701 
07702         float *dat = image->get_data();
07703         float x2, y2; //this is coordinates of this pixel from center axle
07704         float r = 0.0f;
07705         for (int k = 0; k < nz; ++k) {
07706                 for (int j = 0; j < ny; ++j) {
07707                         for (int i = 0; i < nx; ++i, ++dat) {
07708                                 x2 = fabs((float)i - nx/2);
07709                                 y2 = fabs((float)j - ny/2);
07710                                 r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius);
07711 
07712                                 if(r<=1 && k>=(nz-height)/2 && k<=(nz+height)/2) {
07713                                         *dat = 1;
07714                                 }
07715                                 else {
07716                                         *dat = 0;
07717                                 }
07718                         }
07719                 }
07720         }
07721 
07722         image->update();
07723 }
07724 
07725 void RampProcessor::process_inplace(EMData * image)
07726 {
07727         if (!image) {
07728                 return;
07729         }
07730 
07731         int nz = image->get_zsize();
07732         if (nz > 1) {
07733                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
07734                 throw ImageDimensionException("3D model not supported");
07735         }
07736 
07737         int nsam = image->get_xsize();
07738         int nrow = image->get_ysize();
07739         int n1 = nsam / 2;
07740         double sx1 = double(n1)*double(nsam+1);
07741         if ( nsam % 2 == 1 )
07742                 sx1 += 1 + n1;
07743         sx1 *= nrow;
07744         int n2 = nrow / 2;
07745         double sx2 = double(n2)*double(nrow+1);
07746         if ( nrow % 2 == 1 )
07747                 sx2 += 1 + n2;
07748         sx2 *= nsam;
07749         float *data = image->get_data();
07750         float *row = NULL; // handy pointer for values in a specific row of the data
07751         // statistical sums
07752         double syx1 = 0, syx2 = 0, sy = 0, sx1q = 0, sx2q = 0, syq = 0;
07753         for (int j=1; j <= nrow; j++) {
07754                 row = data + (j-1)*nsam - 1; // "-1" so that we can start counting at 1
07755                 for (int i=1; i<=nsam; i++) {
07756                         syx1 += row[i]*i;
07757                         syx2 += row[i]*j;
07758                         sy += row[i];
07759                         sx1q += i*i;
07760                         sx2q += j*j;
07761                         syq += row[i]*double(row[i]);
07762                 }
07763         }
07764         // least-squares
07765         float dn = float(nsam)*float(nrow);
07766         double qyx1 = syx1 - sx1*sy / dn;
07767         double qyx2 = syx2 - sx2*sy / dn;
07768         double qx1x2 = 0.0;
07769         double qx1 = sx1q - sx1*sx1 / dn;
07770         double qx2 = sx2q - sx2*sx2 / dn;
07771         double qy = syq - sy*sy / dn;
07772         double c = qx1*qx2 - qx1x2*qx1x2;
07773         if ( c > FLT_EPSILON ) {
07774                 double b1 = (qyx1*qx2 - qyx2*qx1x2) / c;
07775                 double b2 = (qyx2*qx1 - qyx1*qx1x2) / c;
07776                 double a = (sy - b1*sx1 - b2*sx2) / dn;
07777                 double d = a + b1 + b2;
07778                 for (int i=1; i<=nrow; i++) {
07779                         qy = d;
07780                         row = data + (i-1)*nsam - 1;
07781                         for (int k=1; k<=nsam; k++) {
07782                                 row[k] -= static_cast<float>(qy);
07783                                 qy += b1;
07784                         }
07785                         d += b2;
07786                 }
07787         } // image not altered if c is zero
07788 
07789         image->update();
07790 }
07791 
07792 
07793 void CCDNormProcessor::process_inplace(EMData * image)
07794 {
07795         if (!image) {
07796           Log::logger()->set_level(Log::ERROR_LOG);
07797           Log::logger()->error("Null image during call to CCDNorm\n");
07798           return;
07799         }
07800         if (image->get_zsize() > 1) {
07801           Log::logger()->set_level(Log::ERROR_LOG);
07802           Log::logger()->error("CCDNorm does not support 3d images\n");
07803           return;
07804         }
07805 
07806         int xs = image->get_xsize();
07807         int ys = image->get_ysize();
07808 
07809         // width of sample area on either side of the seams
07810         int width = params["width"];
07811 
07812         width%=(xs > ys ? xs/2 : ys/2);  // make sure width is a valid value
07813         if (width==0) {
07814           width=1;
07815         }
07816 
07817         // get the 4 "seams" of the image
07818         float *left, *right, *top, *bottom;
07819 
07820         double *temp;
07821         temp= (double*)malloc((xs > ys ? xs*width : ys*width)*sizeof(double));
07822         if (temp==NULL) {
07823           Log::logger()->set_level(Log::ERROR_LOG);
07824           Log::logger()->error("Could not allocate enough memory during call to CCDNorm\n");
07825           return;
07826         }
07827 
07828         int x, y, z;
07829 
07830         // the mean values of each seam and the average
07831         double mL,mR,mT,mB;
07832 
07833         // how much to shift each seam
07834         double nl,nr,nt,nb;
07835 
07836         // quad. shifting amount
07837         double q1,q2,q3,q4;
07838 
07839         // calc. the mean for each quadrant
07840         for (z=0; z<width; z++) {
07841           left = image->get_col(xs/2 -1-z)->get_data();
07842           for (y=0; y<ys; y++)
07843             temp[z*ys+y]=left[y];
07844         }
07845         mL=gsl_stats_mean(temp,1,ys*width);
07846 
07847         for (z=0; z<width; z++) {
07848           right = image->get_col(xs/2 +z)->get_data();
07849           for (y=0; y<ys; y++)
07850             temp[z*ys+y]=right[y];
07851         }
07852         mR=gsl_stats_mean(temp,1,ys*width);
07853 
07854         for (z=0; z<width; z++) {
07855           top = image->get_row(ys/2 -1-z)->get_data();
07856           for (x=0; x<xs; x++)
07857             temp[z*xs+x]=top[x];
07858         }
07859         mT=gsl_stats_mean(temp,1,xs*width);
07860 
07861         for (z=0; z<width; z++) {
07862           bottom = image->get_row(ys/2 +z)->get_data();
07863           for (x=0; x<xs; x++)
07864             temp[z*xs+x]=bottom[x];
07865         }
07866         mB=gsl_stats_mean(temp,1,xs*width);
07867 
07868         free(temp);
07869 
07870         nl=(mL+mR)/2-mL;
07871         nr=(mL+mR)/2-mR;
07872         nt=(mT+mB)/2-mT;
07873         nb=(mT+mB)/2-mB;
07874 
07875         q1=nl+nt;
07876         q2=nr+nt;
07877         q3=nr+nb;
07878         q4=nl+nb;
07879 
07880         // change the pixel values
07881         for (x = 0; x < xs / 2; x++)
07882           for (y = 0; y < ys / 2; y++) {
07883             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q1));
07884           }
07885         for (x = xs / 2; x < xs; x++)
07886           for (y = 0; y < ys / 2; y++) {
07887             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q2));
07888           }
07889         for (x = xs / 2; x < xs; x++)
07890           for (y = ys / 2; y < ys; y++) {
07891             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q3));
07892           }
07893         for (x = 0; x < xs / 2; x++)
07894           for (y = ys / 2; y < ys; y++) {
07895             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q4));
07896           }
07897 
07898 }
07899 
07900 void WaveletProcessor::process_inplace(EMData *image)
07901 {
07902         if (image->get_zsize() != 1) {
07903                         LOGERR("%s Processor doesn't support 3D", get_name().c_str());
07904                         throw ImageDimensionException("3D model not supported");
07905         }
07906 
07907         int i,nx,ny;
07908         const gsl_wavelet_type * T;
07909         nx=image->get_xsize();
07910         ny=image->get_ysize();
07911 
07912         if (nx != ny && ny!=1) throw ImageDimensionException("Wavelet transform only supports square images");
07913 //      float l=log((float)nx)/log(2.0f);
07914 //      if (l!=floor(l)) throw ImageDimensionException("Wavelet transform size must be power of 2");
07915         if( !Util::IsPower2(nx) )  throw ImageDimensionException("Wavelet transform size must be power of 2");
07916 
07917         // Unfortunately GSL works only on double() arrays
07918         // eventually we should put our own wavelet code in here
07919         // but this will work for now
07920         double *cpy = (double *)malloc(nx*ny*sizeof(double));
07921 
07922         for (i=0; i<nx*ny; i++) cpy[i]=image->get_value_at(i,0,0);
07923 
07924         string tp = (const char*)params["type"];
07925         if (tp=="daub") T=gsl_wavelet_daubechies;
07926         else if (tp=="harr") T=gsl_wavelet_haar;
07927         else if (tp=="bspl") T=gsl_wavelet_bspline;
07928         else throw InvalidStringException(tp,"Invalid wavelet name, 'daub', 'harr' or 'bspl'");
07929 
07930         int K=(int)params["ord"];
07931         gsl_wavelet_direction dir;
07932         if ((int)params["dir"]==1) dir=forward;
07933         else dir=backward;
07934 
07935         gsl_wavelet *w = gsl_wavelet_alloc(T, K);
07936         gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(nx);
07937 
07938         if (ny==1) gsl_wavelet_transform (w,cpy, 1, nx, dir, work);
07939         else gsl_wavelet2d_transform (w, cpy, nx,nx,ny, dir, work);
07940 
07941         gsl_wavelet_workspace_free (work);
07942         gsl_wavelet_free (w);
07943 
07944         for (i=0; i<nx*ny; i++) image->set_value_at_fast(i,0,0,static_cast<float>(cpy[i]));
07945 
07946         free(cpy);
07947 }
07948 
07949 void FFTProcessor::process_inplace(EMData* image)
07950 {
07951         if( params.has_key("dir") ) {
07952                 if ((int)params["dir"]==-1) {
07953                         image->do_ift_inplace();
07954                 }
07955                 else {
07956                         image->do_fft_inplace();
07957                 }
07958         }
07959 }
07960 
07961 void RadialProcessor::process_inplace(EMData * image)
07962 {
07963         if (!image) {
07964                 LOGWARN("NULL Image");
07965                 return;
07966         }
07967 
07968         //Note : real image only!
07969         if(image->is_complex()) {
07970                 LOGERR("%s Processor only operates on real images", get_name().c_str());
07971                 throw ImageFormatException("apply to real image only");
07972         }
07973 
07974         vector<float> table = params["table"];
07975         vector<float>::size_type tsize = table.size();
07976 
07977         int nx = image->get_xsize();
07978         int ny = image->get_ysize();
07979         int nz = image->get_zsize();
07980 
07981         int nx2 = nx / 2;
07982         int ny2 = ny / 2;
07983         int nz2 = nz / 2;
07984         float sz[3];
07985         sz[0] = static_cast<float>(nx2);
07986         sz[1] = static_cast<float>(ny2);
07987         sz[2] = static_cast<float>(nz2);
07988         float szmax = *std::max_element(&sz[0], &sz[3]);
07989         float maxsize;
07990         if(nz>1) {
07991                 maxsize = (float)(1.8f * szmax);
07992         }
07993         else{
07994                 maxsize = (float)(1.5f * szmax);
07995         }
07996         for(int i=tsize+1; i<maxsize; i++) {
07997                 table.push_back(0.0f);
07998         }
07999 
08000         float dx = 1.0f / (float)nx;
08001         float dy = 1.0f / (float)ny;
08002         float dz = 1.0f / (float)nz;
08003         float dx2 = dx * dx;
08004         float dy2 = dy * dy;
08005         float dz2 = dz * dz;
08006         int iz, iy, ix, jz, jy, jx;
08007         float argx, argy, argz;
08008         float rf, df, f;
08009         int ir;
08010         for(iz=1; iz<=nz; iz++) {
08011                 jz = iz - 1;
08012                 if(jz > nz2) {
08013                         jz -= nz;
08014                 }
08015                 argz = float(jz*jz) * dz2;
08016 
08017                 for(iy=1; iy<=ny; iy++) {
08018                         jy = iy - 1;
08019                         if(jy > ny2) {
08020                                 jy -= ny;
08021                         }
08022                         argy = argz + float(jy*jy) * dy2;
08023 
08024                         for(ix=1; ix<=nx; ix++) {
08025                                 jx = ix -1;
08026                                 argx = argy + float(jx*jx)*dx2;
08027 
08028                                 rf = sqrt(argx)*2.0f*nx2;
08029                                 ir = int(rf);
08030                                 df = rf - float(ir);
08031                                 f = table[ir] + df*(table[ir+1]-table[ir]);
08032 
08033                                 (*image)(ix-1,iy-1,iz-1) *= f;
08034                         }
08035                 }
08036         }
08037 
08038         image->update();
08039 }
08040 
08041 void MirrorProcessor::process_inplace(EMData *image)
08042 {
08043         if (!image) {
08044                 LOGWARN("NULL Image");
08045                 return;
08046         }
08047 
08048         string axis = (const char*)params["axis"];
08049 
08050         float* data = image->EMData::get_data();
08051 
08052         int nx = image->get_xsize();
08053         int ny = image->get_ysize();
08054         int nz = image->get_zsize();
08055         size_t nxy = nx*ny;
08056 
08057         int x_start = 1-nx%2;
08058         int y_start = 1-ny%2;
08059         int z_start = 1-nz%2;
08060 
08061         if (axis == "x" || axis == "X") {
08062                 for (int iz = 0; iz < nz; iz++)
08063                         for (int iy = 0; iy < ny; iy++) {
08064                                 int offset = nx*iy + nxy*iz;
08065                                  reverse(&data[offset+x_start],&data[offset+nx]);
08066                          }
08067          }
08068 
08069          if (axis == "y" || axis == "Y") {
08070                 float *tmp = new float[nx];
08071                  int nhalf   = ny/2;
08072                  size_t beg     = 0;
08073                  for (int iz = 0; iz < nz; iz++) {
08074                       beg = iz*nxy;
08075                       for (int iy = y_start; iy < nhalf; iy++) {
08076                                 memcpy(tmp, &data[beg+iy*nx], nx*sizeof(float));
08077                                 memcpy(&data[beg+iy*nx], &data[beg+(ny-iy-1+y_start)*nx], nx*sizeof(float));
08078                                 memcpy(&data[beg+(ny-iy-1+y_start)*nx], tmp, nx*sizeof(float));
08079                         }
08080                 }
08081                 delete[] tmp;
08082         }
08083 
08084          if (axis == "z" || axis == "Z") {
08085                 if(1-z_start){
08086                         int nhalf = nz/2;
08087                         float *tmp = new float[nxy];
08088                         for(int iz = 0;iz<nhalf;iz++){
08089                                 memcpy(tmp,&data[iz*nxy],nxy*sizeof(float));
08090                                 memcpy(&data[iz*nxy],&data[(nz-iz-1)*nxy],nxy*sizeof(float));
08091                                 memcpy(&data[(nz-iz-1)*nxy],tmp,nxy*sizeof(float));
08092                                 }
08093                         delete[] tmp;
08094                 }
08095                 else{
08096                         float *tmp = new float[nx];
08097                         int nhalf   = nz/2;
08098                         size_t beg     = 0;
08099                         for (int iy = 0; iy < ny; iy++) {
08100                                 beg = iy*nx;
08101                                 for (int iz = z_start; iz < nhalf; iz++) {
08102                                         memcpy(tmp, &data[beg+ iz*nxy], nx*sizeof(float));
08103                                         memcpy(&data[beg+iz*nxy], &data[beg+(nz-iz-1+z_start)*nxy], nx*sizeof(float));
08104                                         memcpy(&data[beg+(nz-iz-1+z_start)*nxy], tmp, nx*sizeof(float));
08105                                 }
08106                         }
08107                         delete[] tmp;
08108                 }
08109          }
08110 
08111          image->update();
08112 }
08113 
08114 
08115 int EMAN::multi_processors(EMData * image, vector < string > processornames)
08116 {
08117         Assert(image != 0);
08118         Assert(processornames.size() > 0);
08119 
08120         for (size_t i = 0; i < processornames.size(); i++) {
08121                 image->process_inplace(processornames[i]);
08122         }
08123         return 0;
08124 }
08125 
08126 
08127 float* TransformProcessor::transform(const EMData* const image, const Transform& t) const {
08128 
08129         ENTERFUNC;
08130 
08131         Transform inv = t.inverse();
08132         int nx = image->get_xsize();
08133         int ny = image->get_ysize();
08134         int nz = image->get_zsize();
08135         int nxy = nx*ny;
08136 
08137         const float * const src_data = image->get_const_data();
08138         float *des_data = (float *) EMUtil::em_malloc(nx*ny*nz* sizeof(float));
08139 
08140         if (nz == 1) {
08141                 Vec2f offset(nx/2,ny/2);
08142                 for (int j = 0; j < ny; j++) {
08143                         for (int i = 0; i < nx; i++) {
08144                                 Vec2f coord(i-nx/2,j-ny/2);
08145                                 Vec2f soln = inv*coord;
08146                                 soln += offset;
08147 
08148                                 float x2 = soln[0];
08149                                 float y2 = soln[1];
08150 
08151                                 if (x2 < 0 || x2 >= nx || y2 < 0 || y2 >= ny ) {
08152                                         des_data[i + j * nx] = 0; // It may be tempting to set this value to the
08153                                         // mean but in fact this is not a good thing to do. Talk to S.Ludtke about it.
08154                                 }
08155                                 else {
08156                                         int ii = Util::fast_floor(x2);
08157                                         int jj = Util::fast_floor(y2);
08158                                         int k0 = ii + jj * nx;
08159                                         int k1 = k0 + 1;
08160                                         int k2 = k0 + nx;
08161                                         int k3 = k0 + nx + 1;
08162 
08163                                         if (ii == nx - 1) {
08164                                                 k1--;
08165                                                 k3--;
08166                                         }
08167                                         if (jj == ny - 1) {
08168                                                 k2 -= nx;
08169                                                 k3 -= nx;
08170                                         }
08171 
08172                                         float t = x2 - ii;
08173                                         float u = y2 - jj;
08174 
08175                                         des_data[i + j * nx] = Util::bilinear_interpolate(src_data[k0],src_data[k1], src_data[k2], src_data[k3],t,u);
08176                                 }
08177                         }
08178                 }
08179         }
08180         else {
08181                 size_t l=0, ii, k0, k1, k2, k3, k4, k5, k6, k7;
08182                 Vec3f offset(nx/2,ny/2,nz/2);
08183                 float x2, y2, z2, tuvx, tuvy, tuvz;
08184                 int ix, iy, iz;
08185                 for (int k = 0; k < nz; ++k) {
08186                         for (int j = 0; j < ny; ++j) {
08187                                 for (int i = 0; i < nx; ++i,++l) {
08188                                         Vec3f coord(i-nx/2,j-ny/2,k-nz/2);
08189                                         Vec3f soln = inv*coord;
08190                                         soln += offset;
08191 
08192                                         x2 = soln[0];
08193                                         y2 = soln[1];
08194                                         z2 = soln[2];
08195 
08196                                         if (x2 < 0 || y2 < 0 || z2 < 0 || x2 >= nx  || y2 >= ny  || z2>= nz ) {
08197                                                 des_data[l] = 0;
08198                                         }
08199                                         else {
08200                                                 ix = Util::fast_floor(x2);
08201                                                 iy = Util::fast_floor(y2);
08202                                                 iz = Util::fast_floor(z2);
08203                                                 tuvx = x2-ix;
08204                                                 tuvy = y2-iy;
08205                                                 tuvz = z2-iz;
08206                                                 ii = ix + iy * nx + iz * nxy;
08207 
08208                                                 k0 = ii;
08209                                                 k1 = k0 + 1;
08210                                                 k2 = k0 + nx;
08211                                                 k3 = k0 + nx+1;
08212                                                 k4 = k0 + nxy;
08213                                                 k5 = k1 + nxy;
08214                                                 k6 = k2 + nxy;
08215                                                 k7 = k3 + nxy;
08216 
08217                                                 if (ix == nx - 1) {
08218                                                         k1--;
08219                                                         k3--;
08220                                                         k5--;
08221                                                         k7--;
08222                                                 }
08223                                                 if (iy == ny - 1) {
08224                                                         k2 -= nx;
08225                                                         k3 -= nx;
08226                                                         k6 -= nx;
08227                                                         k7 -= nx;
08228                                                 }
08229                                                 if (iz == nz - 1) {
08230                                                         k4 -= nxy;
08231                                                         k5 -= nxy;
08232                                                         k6 -= nxy;
08233                                                         k7 -= nxy;
08234                                                 }
08235 
08236                                                 des_data[l] = Util::trilinear_interpolate(src_data[k0],
08237                                                                 src_data[k1], src_data[k2], src_data[k3], src_data[k4],
08238                                                                 src_data[k5], src_data[k6],     src_data[k7], tuvx, tuvy, tuvz);
08239                                         }
08240                                 }
08241                         }
08242                 }
08243         }
08244 
08245         EXITFUNC;
08246         return des_data;
08247 }
08248 
08249 void TransformProcessor::assert_valid_aspect(const EMData* const image) const {
08250         int ndim = image->get_ndim();
08251         if (ndim != 2 && ndim != 3) throw ImageDimensionException("Transforming an EMData only works if it's 2D or 3D");
08252 
08253         if (! params.has_key("transform") ) throw InvalidParameterException("You must specify a Transform in order to perform this operation");
08254 }
08255 
08256 //void TransformProcessor::update_emdata_attributes(EMData* const p, const Dict& attr_dict, const float& scale) const {
08257 //
08258 //      float inv_scale = 1.0f/scale;
08259 //
08260 //      p->scale_pixel(1.0f/scale);
08261 //
08262 //      // According to Baker the origin attributes remain unchanged
08273 //
08274 //      vector<string> scale_attrs;
08275 //      scale_attrs.push_back("apix_x");
08276 //      scale_attrs.push_back("apix_y");
08277 //      scale_attrs.push_back("apix_z");
08278 //
08279 //
08280 //      for(vector<string>::const_iterator it = scale_attrs.begin(); it != scale_attrs.end(); ++it) {
08281 //              if (attr_dict.has_key(*it)) {
08282 //                      p->set_attr(*it,(float) attr_dict[*it] * inv_scale);
08283 //              }
08284 //      }
08285 //
08286 //}
08287 
08288 EMData* TransformProcessor::process(const EMData* const image) {
08289         ENTERFUNC;
08290 
08291         assert_valid_aspect(image);
08292 
08293         Transform* t = params["transform"];
08294 
08295         EMData* p  = 0;
08296 #ifdef EMAN2_USING_CUDA
08297         if (image->gpu_operation_preferred()) {
08298 //              cout << "cuda transform" << endl;
08299                 float * m = new float[12];
08300                 Transform inv = t->inverse();
08301                 inv.copy_matrix_into_array(m);
08302                 image->bind_cuda_texture();
08303                 EMDataForCuda* tmp = emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize());
08304                 image->unbind_cuda_texture();
08305                 delete [] m;
08306                 if (tmp == 0) throw;
08307 
08308                 p = new EMData();
08309                 p->set_gpu_rw_data(tmp->data,tmp->nx,tmp->ny,tmp->nz);
08310                 free(tmp);
08311         }
08312 #endif
08313         if ( p == 0 ) {
08314                 float* des_data = transform(image,*t);
08315                 p = new EMData(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict());
08316         }
08317 
08318         //      all_translation += transform.get_trans();
08319 
08320         float scale = t->get_scale();
08321         if (scale != 1.0) {
08322                 p->scale_pixel(1.0f/scale);
08323 //              update_emdata_attributes(p,image->get_attr_dict(),scale);
08324         }
08325 
08326         if(t) {delete t; t=0;}
08327         EXITFUNC;
08328         return p;
08329 }
08330 
08331 void TransformProcessor::process_inplace(EMData* image) {
08332         ENTERFUNC;
08333 
08334         assert_valid_aspect(image);
08335 
08336         Transform* t = params["transform"];
08337 
08338         //      all_translation += transform.get_trans();
08339         bool use_cpu = true;
08340 #ifdef EMAN2_USING_CUDA
08341         if (image->gpu_operation_preferred()) {
08342                 use_cpu = false;
08343                 float * m = new float[12];
08344                 Transform inv = t->inverse();
08345                 inv.copy_matrix_into_array(m);
08346                 image->bind_cuda_texture();
08347                 EMDataForCuda* tmp = emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize());
08348                 image->unbind_cuda_texture();
08349                 delete [] m;
08350                 if (tmp == 0) throw;
08351                 image->set_gpu_rw_data(tmp->data,tmp->nx,tmp->ny,tmp->nz);
08352                 free(tmp);
08353         }
08354 #endif
08355         if ( use_cpu ) {
08356                 float* des_data = transform(image,*t);
08357                 image->set_data(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize());
08358                 image->update();
08359         }
08360         float scale = t->get_scale();
08361         if (scale != 1.0) {
08362                 image->scale_pixel(1.0f/scale);
08363 //              update_emdata_attributes(image,image->get_attr_dict(),scale);
08364         }
08365 
08366         if(t) {delete t; t=0;}
08367 
08368         EXITFUNC;
08369 }
08370 
08371 
08372 void IntTranslateProcessor::assert_valid_aspect(const vector<int>& translation, const EMData* const image) const {
08373         if (translation.size() == 0 ) throw InvalidParameterException("You must specify the trans argument");
08374 }
08375 
08376 Region IntTranslateProcessor::get_clip_region(vector<int>& translation, const EMData* const image) const {
08377         unsigned int dim = static_cast<unsigned int> (image->get_ndim());
08378 
08379         if ( translation.size() != dim ) {
08380                 for(unsigned int i = translation.size(); i < dim; ++i ) translation.push_back(0);
08381         }
08382 
08383         Region clip_region;
08384         if (dim == 1) {
08385                 clip_region = Region(-translation[0],image->get_xsize());
08386         } else if ( dim == 2 ) {
08387                 clip_region = Region(-translation[0],-translation[1],image->get_xsize(),image->get_ysize());
08388         } else if ( dim == 3 ) {
08389                 clip_region = Region(-translation[0],-translation[1],-translation[2],image->get_xsize(),image->get_ysize(),image->get_zsize());
08390         } else throw ImageDimensionException("Only 1,2 and 3D images are supported");
08391 
08392         return clip_region;
08393 }
08394 
08395 void IntTranslateProcessor::process_inplace(EMData* image) {
08396 
08397         vector<int> translation = params.set_default("trans",vector<int>() );
08398 
08399 
08400         assert_valid_aspect(translation,image);
08401 
08402         Region clip_region = get_clip_region(translation,image);
08403 
08404         image->clip_inplace(clip_region,0);
08405         // clip_inplace does the update!
08406 }
08407 
08408 EMData* IntTranslateProcessor::process(const EMData* const image) {
08409 
08410         vector<int> translation = params.set_default("trans",vector<int>() );
08411 
08412         assert_valid_aspect(translation,image);
08413 
08414         Region clip_region = get_clip_region(translation,image);
08415 
08416         return image->get_clip(clip_region,0);
08417         // clip_inplace does the update!
08418 }
08419 
08420 
08421 void ScaleTransformProcessor::process_inplace(EMData* image) {
08422         int ndim = image->get_ndim();
08423         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08424 
08425         if ( image->get_xsize() != image->get_ysize()) {
08426                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08427         }
08428         if ( ndim == 3 ) {
08429                 if ( image->get_xsize() != image->get_zsize()) {
08430                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08431                 }
08432         }
08433 
08434         float scale = params.set_default("scale",0.0f);
08435         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08436 
08437         int clip = 0;
08438 
08439         if(params.has_key("clip"))
08440         {
08441                 clip = params["clip"];
08442                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08443         }
08444         else
08445         {
08446                 clip = (int)(scale*image->get_xsize());
08447         }
08448 
08449         Region r;
08450         if (ndim == 3) {
08451                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08452         } else { // ndim == 2 guaranteed by check at beginning of function
08453                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08454         }
08455 
08456         if (scale > 1) {
08457                 if ( clip != 0) {
08458                         image->clip_inplace(r);
08459                 }
08460                 Transform t;
08461                 t.set_scale(scale);
08462                 image->process_inplace("xform",Dict("transform",&t));
08463         } else if (scale < 1) {
08464                 Transform t;
08465                 t.set_scale(scale);
08466                 image->process_inplace("xform",Dict("transform",&t));
08467                 if ( clip != 0) {
08468                         image->clip_inplace(r);
08469                 }
08470         } else {
08471                 if ( clip != 0) {
08472                         image->clip_inplace(r);
08473                 }
08474         }
08475 }
08476 
08477 EMData* ScaleTransformProcessor::process(const EMData* const image) {
08478         int ndim = image->get_ndim();
08479         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08480 
08481         if ( image->get_xsize() != image->get_ysize()) {
08482                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08483         }
08484         if ( ndim == 3 ) {
08485                 if ( image->get_xsize() != image->get_zsize()) {
08486                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08487                 }
08488         }
08489 
08490         float scale = params.set_default("scale",0.0f);
08491         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08492 
08493         int clip = 0;
08494 
08495         if(params.has_key("clip"))
08496         {
08497                 clip = params["clip"];
08498                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08499         }
08500         else
08501         {
08502                 clip = (int)(scale*image->get_xsize());
08503         }
08504 
08505         Region r;
08506         if (ndim == 3) {
08507                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08508         } else { // ndim == 2 guaranteed by check at beginning of function
08509                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08510         }
08511 
08512         EMData* ret = 0;
08513         if (scale > 1) {
08514                 if ( clip != 0) {
08515                         ret = image->get_clip(r);
08516                 }
08517                 Transform t;
08518                 t.set_scale(scale);
08519                 if (ret != 0) {
08520                         ret->process_inplace("xform",Dict("transform",&t));
08521                 } else {
08522                         ret = image->process("xform",Dict("transform",&t));
08523                 }
08524         } else if (scale < 1) {
08525                 Transform t;
08526                 t.set_scale(scale);
08527                 ret = image->process("xform",Dict("transform",&t));
08528                 if ( clip != 0) {
08529                         ret->clip_inplace(r);
08530                 }
08531         } else {
08532                 if ( clip != 0) {
08533                         ret = image->get_clip(r);
08534                 } else {
08535                         ret = image->copy();
08536                 }
08537         }
08538         return ret;
08539 
08540 }
08541 
08542 void Rotate180Processor::process_inplace(EMData* image) {
08543         ENTERFUNC;
08544 
08545 
08546         if (image->get_ndim() != 2) {
08547                 throw ImageDimensionException("2D only");
08548         }
08549 
08550 #ifdef EMAN2_USING_CUDA
08551         if (image->gpu_operation_preferred() ) {
08552                 EMDataForCuda tmp = image->get_data_struct_for_cuda();
08553                 emdata_rotate_180(&tmp);
08554                 image->gpu_update();
08555                 EXITFUNC;
08556                 return;
08557         }
08558 #endif
08559 
08560         float *d = image->get_data();
08561         int nx = image->get_xsize();
08562         int ny = image->get_ysize();
08563 
08564         // x and y offsets are used to handle even vs odd cases
08565         int x_offset = 0;
08566         if (nx % 2 == 1) x_offset=1;
08567         int y_offset = 0;
08568         if (ny % 2 == 1) y_offset=1;
08569 
08570         bool stop = false;
08571         for (int x = 1; x <= (nx/2+x_offset); x++) {
08572                 int y = 0;
08573                 for (y = 1; y < (ny+y_offset); y++) {
08574                         if (x == (nx / 2+x_offset) && y == (ny / 2+y_offset)) {
08575                                 stop = true;
08576                                 break;
08577                         }
08578                         int i = (x-x_offset) + (y-y_offset) * nx;
08579                         int k = nx - x + (ny - y) * nx;
08580 
08581                         float t = d[i];
08582                         d[i] = d[k];
08583                         d[k] = t;
08584                 }
08585                 if (stop) break;
08586         }
08587 
08588         /* Here we guard against irregularites that occur at the boundaries
08589          * of even dimensioned images. The basic policy is to replace the pixel
08590          * in row 0 and/or column 0 with those in row 1 and/or column 1, respectively.
08591          * The pixel at 0,0 is replaced with the pixel at 1,1 if both image dimensions
08592          * are even. FIXME - it may be better to use an average at the corner, in
08593          * this latter case, using pixels (1,1), (0,1) and (1,0). I am not sure. (dsawoolford)
08594         */
08595         if (x_offset == 0) {
08596                 for (int y = 0; y < ny; y++) {
08597                         image->set_value_at_fast(0,y,image->get_value_at(1,y));
08598                 }
08599         }
08600 
08601         if (y_offset == 0) {
08602                 for (int x = 0; x < nx; x++) {
08603                         image->set_value_at_fast(x,0,image->get_value_at(x,1));
08604                 }
08605         }
08606 
08607         if (y_offset == 0 && x_offset == 0) {
08608                 image->set_value_at_fast(0,0,image->get_value_at(1,1));
08609         }
08610 
08611         image->update();
08612         EXITFUNC;
08613 }
08614 
08615 
08616 void ClampingProcessor::process_inplace( EMData* image )
08617 {
08618 
08619         if ( image->is_complex() ) throw ImageFormatException("Error: clamping processor does not work on complex images");
08620 
08621         float min = params.set_default("minval",default_min);
08622         float max = params.set_default("maxval",default_max);
08623         bool tomean = params.set_default("tomean",false);
08624         float new_min_vals = min;
08625         float new_max_vals = max;
08626         if (tomean){
08627 
08628                 new_min_vals = image->get_attr("mean");
08629                 new_max_vals = image->get_attr("mean");
08630         }
08631 
08632         // Okay, throwing such an error is probably overkill - but atleast the user will get a loud message
08633         // saying what went wrong.
08634         if ( max < min ) throw InvalidParameterException("Error: minval was greater than maxval, aborting");
08635 
08636         size_t size = image->get_size();
08637         for(size_t i = 0; i < size; ++i )
08638         {
08639                 float * data = &image->get_data()[i];
08640                 if ( *data < min ) *data = new_min_vals;
08641                 else if ( *data > max ) *data = new_max_vals;
08642         }
08643         image->update();
08644 }
08645 
08646 void TestTomoImage::insert_rectangle( EMData* image, const Region& region, const float& value, const Transform& t3d )
08647 {
08648         int startx = (int)region.origin[0] - (int)region.size[0]/2;
08649         int starty = (int)region.origin[1] - (int)region.size[1]/2;
08650         int startz = (int)region.origin[2] - (int)region.size[2]/2;
08651 
08652         int endx  = (int)region.origin[0] + (int)region.size[0]/2;
08653         int endy  = (int)region.origin[1] + (int)region.size[1]/2;
08654         int endz  = (int)region.origin[2] + (int)region.size[2]/2;
08655 
08656         if ( ! t3d.is_identity() ) {
08657                 float xt, yt, zt;
08658                 for ( float z = (float)startz; z < (float)endz; z += 0.25f ) {
08659                         for ( float y = (float)starty; y < (float)endy; y += 0.25f ) {
08660                                 for ( float x = (float)startx; x < (float)endx; x += 0.25f ) {
08661                                         xt = (float) x - region.origin[0];
08662                                         yt = (float) y - region.origin[1];
08663                                         zt = (float) z - region.origin[2];
08664                                         Vec3f v((float)xt,(float)yt,(float)zt);
08665                                         v = t3d*v;
08666                                         image->set_value_at((int)(v[0]+region.origin[0]),(int)(v[1]+region.origin[1]),(int)(v[2]+region.origin[2]), value);
08667                                 }
08668                         }
08669                 }
08670         } else {
08671                 for ( int z = startz; z < endz; ++z ) {
08672                         for ( int y = starty; y < endy; ++y ) {
08673                                 for ( int x = startx; x < endx; ++x ) {
08674                                         image->set_value_at(x,y,z, value);
08675                                 }
08676                         }
08677                 }
08678         }
08679 }
08680 
08681 void TestTomoImage::process_inplace( EMData* image )
08682 {
08683         //float nx = 240;
08684         //float ny = 240;
08685         //float nz = 60;
08686 
08687         //image->set_size((int)nx,(int)ny,(int)nz);
08688         float nx = (float) image->get_xsize();
08689         float ny = (float) image->get_ysize();
08690         float nz = (float) image->get_zsize();
08691 
08692         // This increment is used to simplified positioning
08693         // It's an incremental factor that matches the grid size of the paper
08694         // that I drew this design on before implementing it in code
08695         float inc = 1.0f/22.0f;
08696         float xinc = inc;
08697         float yinc = inc;
08698         float zinc = inc;
08699 
08700         Dict d;
08701         d["a"] = (float) .4*nx+3;
08702         d["b"] = (float) .4*ny+3;
08703         d["c"] = (float) .4*nz+3;
08704         d["fill"] = 0.2;
08705         image->process_inplace("testimage.ellipsoid",d);
08706 
08707         d["a"] = (float) .4*nx;
08708         d["b"] = (float) .4*ny;
08709         d["c"] = (float) .4*nz;
08710         d["fill"] = 0.1;
08711         image->process_inplace("testimage.ellipsoid",d);
08712 
08713         // Center x, center z, bottom y ellipsoids that grow progessively smaller
08714         {
08715                 Transform t;
08716                 t.set_trans(0.,ny*4.0f*yinc-ny/2,0);
08717                 Dict d;
08718                 d["transform"] = &t;
08719                 d["a"] = (float) 2.*xinc*nx;
08720                 d["b"] = (float)0.5*yinc*ny;
08721                 d["c"] = (float) 1.*zinc*nz;
08722                 d["fill"] = 0.3;
08723                 image->process_inplace("testimage.ellipsoid",d);
08724         }
08725 
08726         {
08727                 Transform t;
08728                 t.set_trans(0.,ny*5.5f*yinc-ny/2,0);
08729                 Dict d;
08730                 d["transform"] = &t;
08731                 d["a"] = (float) 1.5*xinc*nx;
08732                 d["b"] = (float)0.5*yinc*ny;
08733                 d["c"] = (float) 1.*zinc*nz;
08734                 d["fill"] = 0.0;
08735                 image->process_inplace("testimage.ellipsoid",d);
08736         }
08737         {
08738                 Transform t;
08739                 t.set_trans(0.,ny*7*yinc-ny/2,0);
08740                 Dict d;
08741                 d["transform"] = &t;
08742                 d["a"] = (float) 1.*xinc*nx;
08743                 d["b"] = (float)0.5*yinc*ny;
08744                 d["c"] = (float) 1.*zinc*nz;
08745                 d["fill"] = 0.3;
08746                 image->process_inplace("testimage.ellipsoid",d);
08747         }
08748 
08749 
08750         {
08751                 Transform t;
08752                 t.set_trans(0.,ny*8.5f*yinc-ny/2,0);
08753                 Dict d;
08754                 d["transform"] = &t;
08755                 d["a"] = (float) .75*xinc*nx;
08756                 d["b"] = (float)0.5*yinc*ny;
08757                 d["c"] = (float) 1.*zinc*nz;
08758                 d["fill"] = 0.0;
08759                 image->process_inplace("testimage.ellipsoid",d);
08760         }
08761 
08762         // Center x, center z, bottom y ellipsoids that grow progessively smaller
08763         {
08764                 Transform t;
08765                 t.set_trans(0.,ny*18*yinc-ny/2,0);
08766                 Dict d;
08767                 d["transform"] = &t;
08768                 d["a"] = (float) 2*xinc*nx;
08769                 d["b"] = (float)0.5*yinc*ny;
08770                 d["c"] = (float) 1.*zinc*nz;
08771                 d["fill"] = 0.3;
08772                 image->process_inplace("testimage.ellipsoid",d);
08773         }
08774 
08775         {
08776                 Transform t;
08777                 t.set_trans(0.,ny*16.5f*yinc-ny/2,0);
08778                 Dict d;
08779                 d["transform"] = &t;
08780                 d["a"] = (float) 1.5*xinc*nx;
08781                 d["b"] = (float)0.5*yinc*ny;
08782                 d["c"] = (float) 1.*zinc*nz;
08783                 d["fill"] = 0.3;
08784                 image->process_inplace("testimage.ellipsoid",d);
08785         }
08786 
08787         {
08788                 Transform t;
08789                 t.set_trans(0.,ny*15*yinc-ny/2,0);
08790                 Dict d;
08791                 d["transform"] = &t;
08792                 d["a"] = (float) 1*xinc*nx;
08793                 d["b"] = (float)0.5*yinc*ny;
08794                 d["c"] = (float) 1.*zinc*nz;
08795                 d["fill"] = 0.3f;
08796                 image->process_inplace("testimage.ellipsoid",d);
08797         }
08798 
08799         {
08800                 Transform t;
08801                 t.set_trans(0.,ny*13.5f*yinc-ny/2,0);
08802                 Dict d;
08803                 d["transform"] = &t;
08804                 d["a"] = (float).75*xinc*nx;
08805                 d["b"] = (float)0.5*yinc*ny;
08806                 d["c"] = (float) 1.*zinc*nz;
08807                 d["fill"] = 0.3;
08808                 image->process_inplace("testimage.ellipsoid",d);
08809         }
08810 
08811         // Left ellipsoids from the bottom up
08812         {
08813 
08814                 Transform t;
08815                 t.set_trans(nx*6*xinc-nx/2,ny*5*yinc-ny/2,0);
08816                 Dict d;
08817                 d["transform"] = &t;
08818                 d["a"] = (float)1*xinc*nx;
08819                 d["b"] = (float).75*yinc*ny;
08820                 d["c"] = (float) .75*zinc*nz;
08821                 d["fill"] = 0.25;
08822                 image->process_inplace("testimage.ellipsoid",d);
08823         }
08824 
08825         {
08826                 Transform t;
08827                 t.set_trans(nx*6*xinc-nx/2,ny*7*yinc-ny/2,0);
08828                 Dict d;
08829                 d["transform"] = &t;
08830                 d["a"] = (float)1.5*xinc*nx;
08831                 d["b"] = (float).75*yinc*ny;
08832                 d["c"] = (float) .75*zinc*nz;
08833                 d["fill"] = 0.25;
08834                 image->process_inplace("testimage.ellipsoid",d);
08835         }
08836 
08837         {
08838                 Transform t;
08839                 t.set_trans(nx*6*xinc-nx/2,ny*9*yinc-ny/2,0);
08840                 Dict d;
08841                 d["transform"] = &t;
08842                 d["a"] = (float)2*xinc*nx;
08843                 d["b"] = (float).75*yinc*ny;
08844                 d["c"] = (float) .75*zinc*nz;
08845                 d["fill"] = 0.25;
08846                 image->process_inplace("testimage.ellipsoid",d);
08847         }
08848 
08849         {
08850                 Transform t;
08851                 t.set_trans(nx*6*xinc-nx/2,ny*11*yinc-ny/2,0);
08852                 Dict d;
08853                 d["transform"] = &t;
08854                 d["a"] = (float)2.5*xinc*nx;
08855                 d["b"] = (float).75*yinc*ny;
08856                 d["c"] = (float) 1*zinc*nz;
08857                 d["fill"] = 0.25;
08858                 image->process_inplace("testimage.ellipsoid",d);
08859         }
08860 
08861         {
08862                 Transform t;
08863                 t.set_trans(nx*6*xinc-nx/2,ny*13*yinc-ny/2,0);
08864                 Dict d;
08865                 d["transform"] = &t;
08866                 d["a"] = (float) 3*xinc*nx;
08867                 d["b"] = (float).75*yinc*ny;
08868                 d["c"] = (float) 1*zinc*nz;
08869                 d["fill"] = 0.25;
08870                 image->process_inplace("testimage.ellipsoid",d);
08871         }
08872 
08873         // Right rectangle from the top down
08874         {
08875                 Region region(nx*15.*inc,ny*17.*inc,nz/2.,1.*inc*nx,1.5*inc*ny,1.5*inc*nz);
08876                 insert_rectangle(image, region, 0.25);
08877         }
08878         {
08879                 Region region(nx*15.*inc,ny*15.*inc,nz/2.,1.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
08880                 insert_rectangle(image, region, 0.25);
08881         }
08882         {
08883                 Region region(nx*15.*inc,ny*13.*inc,nz/2.,2.*inc*nx,1.5*inc*ny,1.5*inc*nz);
08884                 insert_rectangle(image, region, 0.25);
08885         }
08886         {
08887                 Region region(nx*15.*inc,ny*11.*inc,nz/2.,2.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
08888                 insert_rectangle(image, region, 0.25);
08889         }
08890         {
08891                 Region region(nx*15.*inc,ny*9.*inc,nz/2.,3.*inc*nx,1.5*inc*ny,1.5*inc*nz);
08892                 insert_rectangle(image, region, 0.25);
08893         }
08894 
08895         // Center rotated rectangle
08896         {
08897                 Region region(nx/2.,ny/2.,nz/2.,2.*inc*nx,2.5*inc*ny,1.*inc*nz);
08898                 Transform t3d(Dict("type","eman","az",(float)-25.0));
08899                 insert_rectangle(image, region, 0.4f, t3d);
08900         }
08901 
08902         // Rotated ellipsoids
08903         {
08904                 Transform t;
08905                 t.set_trans(nx*6.8f*xinc-nx/2,ny*16*yinc-ny/2,0);
08906                 Dict rot;
08907                 rot["type"] = "eman";
08908                 rot["az"] = 43.0f;
08909                 t.set_rotation(rot);
08910                 Dict d;
08911                 d["transform"] = &t;
08912                 d["a"] = (float) 1.5*xinc*nx;
08913                 d["b"] = (float) .5*yinc*ny;
08914                 d["c"] = (float) .5*zinc*nz;
08915                 d["fill"] = 0.2;
08916                 image->process_inplace("testimage.ellipsoid",d);
08917         }
08918         {
08919                 Transform t;
08920                 t.set_trans(nx*7.2f*xinc-nx/2,ny*16*yinc-ny/2,0);
08921                 Dict rot;
08922                 rot["type"] = "eman";
08923                 rot["az"] = 135.0f;
08924                 t.set_rotation(rot);
08925                 Dict d;
08926                 d["transform"] = &t;
08927                 d["a"] = (float) 1.5*xinc*nx;
08928                 d["b"] = (float) .5*yinc*ny;
08929                 d["c"] = (float) .5*zinc*nz;
08930                 d["fill"] = 0.3;
08931                 image->process_inplace("testimage.ellipsoid",d);
08932         }
08933 
08934         // Dense small ellipsoids
08935         {
08936                 Transform t;
08937                 t.set_trans(nx*3.5f*xinc-nx/2,ny*8*yinc-ny/2,0);
08938                 Dict d;
08939                 d["transform"] = &t;
08940                 d["a"] = (float) .5*xinc*nx;
08941                 d["b"] = (float) .5*yinc*ny;
08942                 d["c"] = (float) .5*zinc*nz;
08943                 d["fill"] = 2.05;
08944                 image->process_inplace("testimage.ellipsoid",d);
08945 
08946                 t.set_trans(nx*8*xinc-nx/2,ny*18*yinc-ny/2,0);
08947                 image->process_inplace("testimage.ellipsoid",d);
08948 
08949                 t.set_trans(nx*14*xinc-nx/2,ny*18.2f*yinc-ny/2,0);
08950                 image->process_inplace("testimage.ellipsoid",d);
08951 
08952                 t.set_trans(nx*18*xinc-nx/2,ny*14*yinc-ny/2,0);
08953                 image->process_inplace("testimage.ellipsoid",d);
08954 
08955                 t.set_trans(nx*17*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
08956                 image->process_inplace("testimage.ellipsoid",d);
08957         }
08958 
08959 
08960         // Dense small rectangles
08961         {
08962                 Region region(nx*18.*inc,ny*11.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
08963                 Transform t3d(Dict("type","eman","az",(float)45.0));
08964                 insert_rectangle(image, region, 1.45f, t3d);
08965         }
08966         {
08967                 Region region(nx*3.*inc,ny*10.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
08968                 Transform t3d(Dict("type","eman","az",(float)45.0));
08969                 insert_rectangle(image, region, 1.45f, t3d);
08970         }
08971 
08972         // Insert small cluster of spheres
08973         {
08974                 Transform t;
08975                 t.set_trans(nx*14*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
08976                 Dict d;
08977                 d["transform"] = &t;
08978                 d["a"] = (float) .5*xinc*nx;
08979                 d["b"] = (float) .5*yinc*ny;
08980                 d["c"] = (float) .5*zinc*nz;
08981                 d["fill"] = .35;
08982                 image->process_inplace("testimage.ellipsoid",d);
08983         }
08984         {
08985                 Transform t;
08986                 t.set_trans(nx*15*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
08987                 Dict d;
08988                 d["transform"] = &t;
08989                 d["a"] = (float) .25*xinc*nx;
08990                 d["b"] = (float) .25*yinc*ny;
08991                 d["c"] = (float) .25*zinc*nz;
08992                 d["fill"] = .35;
08993                 image->process_inplace("testimage.ellipsoid",d);
08994 
08995                 t.set_trans(nx*13.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
08996                 image->process_inplace("testimage.ellipsoid",d);
08997 
08998                 t.set_trans(nx*14.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
08999                 image->process_inplace("testimage.ellipsoid",d);
09000 
09001                 t.set_trans(nx*15.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09002                 image->process_inplace("testimage.ellipsoid",d);
09003 
09004                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09005                 image->process_inplace("testimage.ellipsoid",d);
09006 
09007                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09008                 image->process_inplace("testimage.ellipsoid",d);
09009 
09010                 t.set_trans(nx*15*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09011                 image->process_inplace("testimage.ellipsoid",d);
09012 
09013                 t.set_trans(nx*16*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09014                 image->process_inplace("testimage.ellipsoid",d);
09015 
09016                 t.set_trans(nx*14.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09017                 image->process_inplace("testimage.ellipsoid",d);
09018 
09019                 t.set_trans(nx*15.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09020                 image->process_inplace("testimage.ellipsoid",d);
09021         }
09022         // Insert feducials around the outside of the "cell"
09023 //      for ( float i = 0.; i < 3.; i += 1. ) {
09024 //              for ( float j = 0.; j < 3.; j += 1. ) {
09025 //                      Region region(nx*2.+i*inc,ny*2.+j*inc,nz/2.,0.05*inc*nx,0.05*inc*ny,0.05*inc*nz);
09026 //                      insert_solid_ellipse(image, region, 2.0);
09027 //              }
09028 //      }
09029 
09030 }
09031 
09032 void NSigmaClampingProcessor::process_inplace(EMData *image)
09033 {
09034         float nsigma = params.set_default("nsigma",default_sigma);
09035         float sigma = image->get_attr("sigma");
09036         float mean = image->get_attr("mean");
09037         params.set_default("minval",mean - nsigma*sigma);
09038         params.set_default("maxval",mean + nsigma*sigma);
09039 
09040         ClampingProcessor::process_inplace(image);
09041 }
09042 
09043 void HistogramBin::process_inplace(EMData *image)
09044 {
09045         float min = image->get_attr("minimum");
09046         float max = image->get_attr("maximum");
09047         float nbins = (float)params.set_default("nbins",default_bins);
09048         bool debug = params.set_default("debug",false);
09049 
09050         vector<int> debugscores;
09051         if ( debug ) {
09052                 debugscores = vector<int>((int)nbins, 0);
09053         }
09054 
09055         if ( nbins < 0 ) throw InvalidParameterException("nbins must be greater than 0");
09056 
09057         float bin_width = (max-min)/nbins;
09058         float bin_val_offset = bin_width/2.0f;
09059 
09060         size_t size = image->get_size();
09061         float* dat = image->get_data();
09062 
09063         for(size_t i = 0; i < size; ++i ) {
09064                 float val = dat[i];
09065                 val -= min;
09066                 int bin = (int) (val/bin_width);
09067 
09068                 // This makes the last interval [] and not [)
09069                 if (bin == nbins) bin -= 1;
09070 
09071                 dat[i] = min + bin*bin_width + bin_val_offset;
09072                 if ( debug ) {
09073                         debugscores[bin]++;
09074                 }
09075         }
09076 
09077         if ( debug ) {
09078                 int i = 0;
09079                 for( vector<int>::const_iterator it = debugscores.begin(); it != debugscores.end(); ++it, ++i)
09080                         cout << "Bin " << i << " has " << *it << " pixels in it" << endl;
09081         }
09082 
09083 }
09084 void ConvolutionProcessor::process_inplace(EMData* image)
09085 {
09086         //bool complexflag = false;
09087         EMData* null = 0;
09088         EMData* with = params.set_default("with", null);
09089         if ( with == NULL ) throw InvalidParameterException("Error - the image required for the convolution is null");
09090 
09091         EMData* newimage = fourierproduct(image, with, CIRCULANT, CONVOLUTION, false);
09092 
09093         float* orig = image->get_data();
09094         float* work = newimage->get_data();
09095         int nx  = image->get_xsize();
09096         int ny  = image->get_ysize();
09097         int nz  = image->get_zsize();
09098         memcpy(orig,work,nx*ny*nz*sizeof(float));
09099         image->update();
09100 
09101         delete newimage;
09102 }
09103 
09104 void XGradientProcessor::process_inplace( EMData* image )
09105 {
09106         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09107 
09108         EMData* e = new EMData();
09109         int nx = image->get_xsize();
09110         int ny = image->get_ysize();
09111         int nz = image->get_zsize();
09112 
09113         if ( nz == 1 && ny == 1 ) {
09114                 if ( nx < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09115 
09116                 e->set_size(3,1,1);
09117                 e->set_value_at(0,-1);
09118                 e->set_value_at(2, 1);
09119 
09120                 Region r = Region(-nx/2+1,nx);
09121                 e->clip_inplace(r);
09122         } else if ( nz == 1 ) {
09123                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09124                 e->set_size(3,3,1);
09125                 e->set_value_at(0,0,-1);
09126                 e->set_value_at(0,1,-2);
09127                 e->set_value_at(0,2,-1);
09128 
09129                 e->set_value_at(2,0,1);
09130                 e->set_value_at(2,1,2);
09131                 e->set_value_at(2,2,1);
09132                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09133                 e->clip_inplace(r);
09134         } else {
09135                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09136                 e->set_size(3,3,3);
09137                 e->set_value_at(0,0,0,-1);
09138                 e->set_value_at(0,1,0,-1);
09139                 e->set_value_at(0,2,0,-1);
09140                 e->set_value_at(0,0,1,-1);
09141                 e->set_value_at(0,1,1,-8);
09142                 e->set_value_at(0,2,1,-1);
09143                 e->set_value_at(0,0,2,-1);
09144                 e->set_value_at(0,1,2,-1);
09145                 e->set_value_at(0,2,2,-1);
09146 
09147                 e->set_value_at(2,0,0,1);
09148                 e->set_value_at(2,1,0,1);
09149                 e->set_value_at(2,2,0,1);
09150                 e->set_value_at(2,0,1,1);
09151                 e->set_value_at(2,1,1,8);
09152                 e->set_value_at(2,2,1,1);
09153                 e->set_value_at(2,0,2,1);
09154                 e->set_value_at(2,1,2,1);
09155                 e->set_value_at(2,2,2,1);
09156 
09157                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09158                 e->clip_inplace(r);
09159         }
09160 
09161         Dict conv_parms;
09162         conv_parms["with"] = e;
09163         image->process_inplace("math.convolution", conv_parms);
09164         image->process_inplace("xform.phaseorigin.tocenter");
09165 
09166         delete e;
09167 }
09168 
09169 
09170 void TomoTiltAngleWeightProcessor::process_inplace( EMData* image )
09171 {
09172         bool fim = params.set_default("angle_fim", false);
09173         float alt;
09174         if ( fim ) {
09175                 alt = image->get_attr("euler_alt");
09176         }
09177         else alt = params.set_default("angle", 0.0f);
09178 
09179         float cosine = cos(alt*M_PI/180.0f);
09180         float mult_fac =  1.0f/(cosine);
09181         image->mult( mult_fac );
09182 }
09183 
09184 void TomoTiltEdgeMaskProcessor::process_inplace( EMData* image )
09185 {
09186         bool biedgemean = params.set_default("biedgemean", false);
09187         bool edgemean = params.set_default("edgemean", false);
09188         // You can only do one of these - so if someone specifies them both the code complains loudly
09189         if (biedgemean && edgemean) throw InvalidParameterException("The edgemean and biedgemean options are mutually exclusive");
09190 
09191         bool fim = params.set_default("angle_fim", false);
09192         float alt;
09193         if ( fim ) {
09194                 Transform* t = (Transform*)image->get_attr("xform.projection");
09195                 Dict d = t->get_params("eman");
09196                 alt = (float) d["alt"];
09197                 if(t) {delete t; t=0;}
09198         }
09199         else alt = params.set_default("angle", 0.0f);
09200 
09201 
09202         float cosine = cos(alt*M_PI/180.0f);
09203 
09204         // Zero the edges
09205         int nx = image->get_xsize();
09206         int ny = image->get_ysize();
09207         int x_clip = static_cast<int>( (float) nx * ( 1.0 - cosine ) / 2.0);
09208 
09209         float x1_edge_mean = 0.0;
09210         float x2_edge_mean = 0.0;
09211 
09212         if ( biedgemean )
09213         {
09214                 float edge_mean = 0.0;
09215 
09216                 // Accrue the pixel densities on the side strips
09217                 for ( int i = 0; i < ny; ++i ) {
09218                         edge_mean += image->get_value_at(x_clip, i );
09219                         edge_mean += image->get_value_at(nx - x_clip-1, i );
09220                 }
09221                 // Now make it so the mean is stored
09222                 edge_mean /= 2*ny;
09223 
09224                 // Now shift pixel values accordingly
09225                 for ( int i = 0; i < ny; ++i ) {
09226                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09227                                 image->set_value_at(j,i,edge_mean);
09228                         }
09229                         for ( int j = 0; j < x_clip; ++j) {
09230                                 image->set_value_at(j,i,edge_mean);
09231                         }
09232                 }
09233                 x1_edge_mean = edge_mean;
09234                 x2_edge_mean = edge_mean;
09235         }
09236         else if (edgemean)
09237         {
09238                 for ( int i = 0; i < ny; ++i ) {
09239                         x1_edge_mean += image->get_value_at(x_clip, i );
09240                         x2_edge_mean += image->get_value_at(nx - x_clip-1, i );
09241                 }
09242                 x1_edge_mean /= ny;
09243                 x2_edge_mean /= ny;
09244 
09245                 for ( int i = 0; i < ny; ++i ) {
09246                         for ( int j = 0; j < x_clip; ++j) {
09247                                 image->set_value_at(j,i,x1_edge_mean);
09248                         }
09249                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09250                                 image->set_value_at(j,i,x2_edge_mean);
09251                         }
09252                 }
09253         }
09254         else
09255         {
09256                 // The edges are just zeroed -
09257                 Dict zero_dict;
09258                 zero_dict["x0"] = x_clip;
09259                 zero_dict["x1"] = x_clip;
09260                 zero_dict["y0"] = 0;
09261                 zero_dict["y1"] = 0;
09262                 image->process_inplace( "mask.zeroedge2d", zero_dict );
09263         }
09264 
09265         int gauss_rad = params.set_default("gauss_falloff", 0);
09266         if ( gauss_rad != 0)
09267         {
09268                 // If the gaussian falloff distance is greater than x_clip, it will technically
09269                 // go beyond the image boundaries. Thus we clamp gauss_rad so this cannot happen.
09270                 // Therefore, there is potential here for (benevolent) unexpected behavior.
09271                 if ( gauss_rad > x_clip ) gauss_rad = x_clip;
09272 
09273                 float gauss_sigma = params.set_default("gauss_sigma", 3.0f);
09274                 if ( gauss_sigma < 0 ) throw InvalidParameterException("Error - you must specify a positive, non-zero gauss_sigma");
09275                 float sigma = (float) gauss_rad/gauss_sigma;
09276 
09277                 GaussianFunctoid gf(sigma);
09278 
09279                 for ( int i = 0; i < ny; ++i ) {
09280 
09281                         float left_value = image->get_value_at(x_clip, i );
09282                         float scale1 = left_value-x1_edge_mean;
09283 
09284                         float right_value = image->get_value_at(nx - x_clip - 1, i );
09285                         float scale2 = right_value-x2_edge_mean;
09286 
09287                         for ( int j = 1; j < gauss_rad; ++j )
09288                         {
09289                                 image->set_value_at(x_clip-j, i, scale1*gf((float)j)+x1_edge_mean );
09290                                 image->set_value_at(nx - x_clip + j-1, i, scale2*gf((float)j)+x2_edge_mean);
09291                         }
09292                 }
09293         }
09294 
09295         image->update();
09296 }
09297 
09298 void YGradientProcessor::process_inplace( EMData* image )
09299 {
09300         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09301 
09302         EMData* e = new EMData();
09303         int nx = image->get_xsize();
09304         int ny = image->get_ysize();
09305         int nz = image->get_zsize();
09306 
09307         if ( nz == 1 && ny == 1 ) {
09308                 throw ImageDimensionException("Error - cannot detect Y edges for an image that that is 1D!");
09309         } else if ( nz == 1 ) {
09310                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09311                 e->set_size(3,3,1);
09312                 e->set_value_at(0,0,-1);
09313                 e->set_value_at(1,0,-2);
09314                 e->set_value_at(2,0,-1);
09315 
09316                 e->set_value_at(0,2,1);
09317                 e->set_value_at(1,2,2);
09318                 e->set_value_at(2,2,1);
09319                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09320                 e->clip_inplace(r);
09321         } else {
09322                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09323                 e->set_size(3,3,3);
09324                 e->set_value_at(0,0,0,-1);
09325                 e->set_value_at(1,0,0,-1);
09326                 e->set_value_at(2,0,0,-1);
09327                 e->set_value_at(0,0,1,-1);
09328                 e->set_value_at(1,0,1,-8);
09329                 e->set_value_at(2,0,1,-1);
09330                 e->set_value_at(0,0,2,-1);
09331                 e->set_value_at(1,0,2,-1);
09332                 e->set_value_at(2,0,2,-1);
09333 
09334                 e->set_value_at(0,2,0,1);
09335                 e->set_value_at(1,2,0,1);
09336                 e->set_value_at(2,2,0,1);
09337                 e->set_value_at(0,2,1,1);
09338                 e->set_value_at(1,2,1,8);
09339                 e->set_value_at(2,2,1,1);
09340                 e->set_value_at(0,2,2,1);
09341                 e->set_value_at(1,2,2,1);
09342                 e->set_value_at(2,2,2,1);
09343 
09344                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09345                 e->clip_inplace(r);
09346         }
09347 
09348         Dict conv_parms;
09349         conv_parms["with"] = e;
09350         image->process_inplace("math.convolution", conv_parms);
09351 
09352         delete e;
09353 }
09354 
09355 
09356 void ZGradientProcessor::process_inplace( EMData* image )
09357 {
09358         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09359 
09360         EMData* e = new EMData();
09361         int nx = image->get_xsize();
09362         int ny = image->get_ysize();
09363         int nz = image->get_zsize();
09364 
09365         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");
09366 
09367         e->set_size(3,3,3);
09368         e->set_value_at(0,0,0,-1);
09369         e->set_value_at(1,0,0,-1);
09370         e->set_value_at(2,0,0,-1);
09371         e->set_value_at(0,1,0,-1);
09372         e->set_value_at(1,1,0,-8);
09373         e->set_value_at(2,1,0,-1);
09374         e->set_value_at(0,2,0,-1);
09375         e->set_value_at(1,2,0,-1);
09376         e->set_value_at(2,2,0,-1);
09377 
09378         e->set_value_at(0,0,2,1);
09379         e->set_value_at(1,0,2,1);
09380         e->set_value_at(2,0,2,1);
09381         e->set_value_at(0,1,2,1);
09382         e->set_value_at(1,1,2,8);
09383         e->set_value_at(2,1,2,1);
09384         e->set_value_at(0,2,2,1);
09385         e->set_value_at(1,2,2,1);
09386         e->set_value_at(2,2,2,1);
09387 
09388         Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09389         e->clip_inplace(r);
09390 
09391         Dict conv_parms;
09392         conv_parms["with"] = e;
09393         image->process_inplace("math.convolution", conv_parms);
09394 
09395         delete e;
09396 }
09397 
09398 
09399 #ifdef EMAN2_USING_CUDA
09400 
09401 /* CLASS MPICUDA_kmeans processor
09402  *
09403  */
09404 #include "sparx/cuda/cuda_mpi_kmeans.h"
09405 MPICUDA_kmeans::MPICUDA_kmeans() {
09406     h_IM = NULL;
09407     h_AVE = NULL;
09408     h_ASG = NULL;
09409     h_dist = NULL;
09410     h_AVE2 = NULL;
09411     h_im2 = NULL;
09412     h_NC = NULL;
09413     params = NULL;
09414     d_im = NULL;
09415     d_AVE = NULL;
09416     d_dist = NULL;
09417 }
09418 
09419 MPICUDA_kmeans::~MPICUDA_kmeans() {
09420     if (h_IM) delete h_IM;
09421     if (h_ASG) delete h_ASG;
09422     if (h_AVE) delete h_AVE;
09423     if (h_dist) delete h_dist;
09424     if (h_AVE2) delete h_AVE2;
09425     if (h_im2) delete h_im2;
09426     if (h_NC) delete h_NC;
09427     if (params) delete params;
09428 }
09429 
09430 #include "sparx/cuda/cuda_mpi_kmeans.h"
09431 int MPICUDA_kmeans::setup(int extm, int extN, int extn, int extK, int extn_start) {
09432     m = extm;                           // number of pixels per image
09433     N = extN;                           // Total number of images
09434     n = extn;                           // Number of images used locally
09435     K = extK;                           // number of classes
09436     n_start = extn_start;               // Starting point to local images
09437     size_IM = m * N;                    // nb elements in IM
09438     size_im = m * n;                    // nb elements in im
09439     size_AVE = m * K;                   // nb elements in ave
09440     size_dist = n * K;                  // nb elements in dist
09441     ite = 0;                            // init nb of iterations
09442     BLOCK_SIZE = 512;
09443     NB = size_dist / BLOCK_SIZE;
09444     ins_BLOCK = NB * BLOCK_SIZE;
09445     // Host memory allocation for images
09446     h_IM = (float*)malloc(size_IM * sizeof(float));
09447     if (h_IM == 0) return 1;
09448     h_im = &h_IM[n_start * m]; // for local images
09449     // Host memory allocation for the averages
09450     h_AVE = (float*)malloc(size_AVE * sizeof(float));
09451     if (h_AVE == 0) return 1;
09452     // Host memory allocation for all assignment
09453     h_ASG = (unsigned short int*)malloc(N * sizeof(unsigned short int));
09454     if (h_ASG == 0) return 1;
09455     h_asg = &h_ASG[n_start]; // for local assignment
09456     // allocate the memory for the sum squared of averages
09457     h_AVE2 = (float*)malloc(K * sizeof(float));
09458     if (h_AVE2 == 0) return 1;
09459     // allocate the memory for the sum squared of images
09460     h_im2 = (float*)malloc(n * sizeof(float));
09461     if (h_im2 == 0) return 1;
09462     // allocate the memory for the distances
09463     h_dist = (float*)malloc(size_dist * sizeof(float));
09464     if (h_dist == 0) return 1;
09465     // allocate the memory for the number of images per class
09466     h_NC = (unsigned int*)malloc(K * sizeof(unsigned int));
09467     if (h_NC == 0) return 1;
09468     // allocate the memory to parameters
09469     params = (int*)malloc(8 * sizeof(int));
09470     if (params == 0) return 1;
09471     params[0] = n;
09472     params[1] = m;
09473     params[2] = K;
09474     params[3] = 0;          // Reserve for flag_stop_iteration
09475     params[4] = 0;          // Reserve for ct_im_mv (debug)
09476     params[5] = BLOCK_SIZE; // Size of threads block (512)
09477     params[6] = NB;         // Number of blocks which fit with BLOCK_SIZE
09478     params[7] = ins_BLOCK;  // Number of blocks remaining
09479 
09480     return 0;
09481 }
09482 
09483 // add image pre-process by Util.compress_image_mask
09484 void MPICUDA_kmeans::append_flat_image(EMData* im, int pos) {
09485     for (int i = 0; i < m ; ++i) h_IM[pos * m + i] = (*im)(i);
09486 }
09487 
09488 // cuda init mem device, cublas (get device ptr)
09489 int MPICUDA_kmeans::init_mem(int numdev) {
09490     int stat = 1;
09491     float** hd_AVE = NULL;
09492     float** hd_im = NULL;
09493     float** hd_dist = NULL;
09494     hd_AVE = &d_AVE;
09495     hd_im = &d_im;
09496     hd_dist = &d_dist;
09497     stat = cuda_mpi_init(h_im, hd_im, hd_AVE, hd_dist, size_im, size_AVE, size_dist, numdev);
09498     //printf("C++ get this pointer for d_AVE: %p\n", d_AVE);
09499     //printf("C++ get this pointer for d_im: %p\n", d_im);
09500     //printf("C++ get this pointer for d_dist: %p\n", d_dist);
09501     return stat;
09502 }
09503 
09504 // precalculate im2
09505 void MPICUDA_kmeans::compute_im2() {
09506     for (int i = 0; i < n; i++) {
09507         h_im2[i] = 0.0f;
09508         for (int j = 0; j < m; j++) h_im2[i] += (h_im[i * m + j] * h_im[i * m + j]);
09509     }
09510 }
09511 
09512 // init randomly the first assignment
09513 int MPICUDA_kmeans::random_ASG(long int rnd) {
09514     srand(rnd);
09515     int ret = 20;
09516     int flag = 0;
09517     int i, k;
09518     for (k = 0; k < K; k++) h_NC[k] = 0;
09519     while (ret > 0) {
09520         ret--;
09521         for (i = 0; i < N; i++) {
09522             h_ASG[i] = rand() % K;
09523             h_NC[h_ASG[i]]++;
09524         }
09525         flag = 1;
09526         k = K;
09527         while (k > 0 && flag) {
09528             k--;
09529             if (h_NC[k] <= 1) {
09530                 flag = 0;
09531                 if (ret == 0) {
09532                     //printf("Erreur randomize assignment\n");
09533                     return -1;
09534                 }
09535                 for (k = 0; k < K; k++) h_NC[k] = 0;
09536             }
09537         if (flag == 1) ret = 0;
09538         }
09539     }
09540     return 0;
09541 }
09542 
09543 // get back the assignment
09544 vector <int> MPICUDA_kmeans::get_ASG() {
09545     vector <int> ASG(h_ASG, &h_ASG[N]);
09546     return ASG;
09547 }
09548 
09549 // get back the global assignment
09550 vector <int> MPICUDA_kmeans::get_asg() {
09551     vector <int> asg(h_asg, &h_asg[n]);
09552     return asg;
09553 }
09554 
09555 // compute NC from ASG
09556 void MPICUDA_kmeans::compute_NC() {
09557     for (int i = 0; i < K; ++i) h_NC[i] = 0;
09558     for (int i = 0; i < N; ++i) h_NC[h_ASG[i]]++;
09559 }
09560 
09561 // get NC
09562 vector <int> MPICUDA_kmeans::get_NC() {
09563     vector <int> NC(h_NC, &h_NC[K]);
09564     return NC;
09565 }
09566 
09567 // set a new global assignment
09568 void MPICUDA_kmeans::set_ASG(const vector <int>& ASG) {
09569     for (int i = 0; i < N ; ++i) h_ASG[i] = ASG[i];
09570 }
09571 
09572 // set number of objects per group
09573 void MPICUDA_kmeans::set_NC(const vector <int>& NC) {
09574     for (int i = 0; i < K; ++i) h_NC[i] = NC[i];
09575 }
09576 
09577 // get back some information (ite and T0)
09578 int MPICUDA_kmeans::get_ct_im_mv() {
09579     return params[4]; // ct_im_mov
09580 }
09581 
09582 // set the value of T
09583 void MPICUDA_kmeans::set_T(float extT) {
09584     T = extT;
09585 }
09586 
09587 // get the T value
09588 float MPICUDA_kmeans::get_T() {
09589     return T;
09590 }
09591 
09592 // compute ave and ave2
09593 void MPICUDA_kmeans::compute_AVE() {
09594     float buf = 0.0f;
09595     int i, j, c, d, ind;
09596     // compute the averages according ASG
09597     for (i = 0; i < size_AVE; ++i) h_AVE[i] = 0.0f;                          // set averages to zero
09598     for (i = 0; i < N; ++i) {
09599         c = h_ASG[i] * m;
09600         d = i * m;
09601         for (j = 0; j < m; ++j) h_AVE[c + j] += h_IM[d + j];                 // accumulate images
09602     }
09603     for (i = 0; i < K; i++) {
09604         buf = 0.0f;
09605         for (j = 0 ; j < m; j++) {
09606             ind = i * m + j;
09607             h_AVE[ind] /= (float)h_NC[i];                                    // compute average
09608             buf += (h_AVE[ind] * h_AVE[ind]);                                // do sum squared AVE
09609         }
09610         h_AVE2[i] = buf;
09611     }
09612 }
09613 
09614 // set averages
09615 void MPICUDA_kmeans::set_AVE(EMData* im, int pos) {
09616     for (int i = 0; i < m ; ++i) h_AVE[pos * m + i] = (*im)(i);
09617 }
09618 
09619 // get back the averages
09620 vector<EMData*> MPICUDA_kmeans::get_AVE() {
09621     vector<EMData*> ave(K);
09622     for (int k = 0; k < K; ++k) {
09623         EMData* im = new EMData();
09624         im->set_size(m, 1, 1);
09625         float *ptr = im->get_data();
09626         for (int i = 0; i < m; ++i) {ptr[i] =  h_AVE[k * m + i];}
09627         ave[k] = im->copy();
09628         delete im;
09629     }
09630     return ave;
09631 }
09632 
09633 // k-means one iteration
09634 int MPICUDA_kmeans::one_iter() {
09635     int status = cuda_mpi_kmeans(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params);
09636     ite++;
09637     return status;
09638 }
09639 
09640 // k-means SA one iteration
09641 int MPICUDA_kmeans::one_iter_SA() {
09642     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);
09643     ite++;
09644     return status;
09645 }
09646 
09647 // compute ji
09648 vector <float> MPICUDA_kmeans::compute_ji() {
09649     int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
09650     vector <float> ji(K);
09651     int i;
09652     if (status != 0) {
09653         for (i = 0; i < K; ++i) ji[i] = -1.0;
09654         return ji;
09655     }
09656     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]]);
09657     return ji;
09658 }
09659 
09660 //
09661 vector <float> MPICUDA_kmeans::compute_criterion(const vector <float>& Ji) {
09662     float buf = 0.0f;
09663     float Je = 0.0f;
09664     float Tr_AVE = 0.0f;
09665     float v_max = 0.0f;
09666     float* S_AVE2 = (float*)calloc(m, sizeof(float));
09667     float* S_AVE = (float*)calloc(m, sizeof(float));
09668     vector <float> crit(4);
09669     int i, j, k;
09670     // Je
09671     for (i = 0; i < K; ++i) Je += (Ji[i] / float(m));
09672     crit[0] = Je;
09673     // trace ave
09674     for (i = 0; i < K; ++i) {
09675         for (j = 0; j < m; ++j) {
09676             S_AVE[j] += h_AVE[i * m + j];
09677             S_AVE2[j] += (h_AVE[i * m + j] * h_AVE[i * m +j]);
09678         }
09679     }
09680     buf = 1 / (float)K;
09681     for (i = 0; i < m; ++i) Tr_AVE += (buf * (S_AVE2[i] - buf * S_AVE[i] * S_AVE[i]));
09682     // Coleman
09683     crit[1] = Tr_AVE * Je;
09684     // Harabasz
09685     crit[2] = (Tr_AVE * (float)(N - K)) / (Je * (float)(K - 1));
09686     // Davies-Bouldin
09687     for (i = 0; i < K; ++i) {
09688         v_max = 0.0f;
09689         for (j = 0; j < K; ++j) {
09690             if (j != i) {
09691                 buf = 0.0f;
09692                 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]));
09693                 buf = (Ji[i] / (float)h_NC[i] + Ji[j] / (float)h_NC[j]) * ((float)m / buf);
09694             }
09695             if (buf > v_max) v_max = buf;
09696         }
09697         crit[3] += v_max;
09698     }
09699     crit[3] /= (float)K;
09700     free(S_AVE);
09701     free(S_AVE2);
09702     return crit;
09703 }
09704 
09705 // shutdown cublas and release device mem
09706 int MPICUDA_kmeans::shutdown() {
09707     return cuda_mpi_shutdown(d_im, d_AVE, d_dist);
09708 }
09710 
09711 void CudaMultProcessor::process_inplace(EMData* image) {
09712         float val = params.set_default("scale",(float) 1.0);
09713         EMDataForCuda tmp = image->get_data_struct_for_cuda();
09714         emdata_processor_mult(&tmp,val);
09715         image->gpu_update();
09716 }
09717 
09718 
09719 void CudaCorrelationProcessor::process_inplace(EMData* image) {
09720         EMData* with = params.set_default("with",(EMData*)0);
09721         if (with == 0) throw InvalidParameterException("You must supply the with parameter, and it must be valid. It is NULL.");
09722 
09723         EMDataForCuda left = image->get_data_struct_for_cuda();
09724         with->bind_cuda_texture(false);
09725         emdata_processor_correlation_texture(&left,1);
09726         image->gpu_update();
09727 
09728 }
09729 
09730 #endif //EMAN2_USING_CUDA
09731 
09732 void EMAN::dump_processors()
09733 {
09734         dump_factory < Processor > ();
09735 }
09736 
09737 map<string, vector<string> > EMAN::dump_processors_list()
09738 {
09739         return dump_factory_list < Processor > ();
09740 }
09741 
09742 map<string, vector<string> > EMAN::group_processors()
09743 {
09744         map<string, vector<string> > processor_groups;
09745 
09746         vector <string> processornames = Factory<Processor>::get_list();
09747 
09748         for (size_t i = 0; i < processornames.size(); i++) {
09749                 Processor * f = Factory<Processor>::get(processornames[i]);
09750                 if (dynamic_cast<RealPixelProcessor*>(f) != 0) {
09751                         processor_groups["RealPixelProcessor"].push_back(f->get_name());
09752                 }
09753                 else if (dynamic_cast<BoxStatProcessor*>(f)  != 0) {
09754                         processor_groups["BoxStatProcessor"].push_back(f->get_name());
09755                 }
09756                 else if (dynamic_cast<ComplexPixelProcessor*>(f)  != 0) {
09757                         processor_groups["ComplexPixelProcessor"].push_back(f->get_name());
09758                 }
09759                 else if (dynamic_cast<CoordinateProcessor*>(f)  != 0) {
09760                         processor_groups["CoordinateProcessor"].push_back(f->get_name());
09761                 }
09762                 else if (dynamic_cast<FourierProcessor*>(f)  != 0) {
09763                         processor_groups["FourierProcessor"].push_back(f->get_name());
09764                 }
09765                 else if (dynamic_cast<NewFourierProcessor*>(f)  != 0) {
09766                         processor_groups["FourierProcessor"].push_back(f->get_name());
09767                 }
09768                 else if (dynamic_cast<NormalizeProcessor*>(f)  != 0) {
09769                         processor_groups["NormalizeProcessor"].push_back(f->get_name());
09770                 }
09771                 else {
09772                         processor_groups["Others"].push_back(f->get_name());
09773                 }
09774         }
09775 
09776         return processor_groups;
09777 }
09778 
09779 
09780 
09781 /* vim: set ts=4 noet: */
09782 
09783 float ModelHelixProcessor::radprofile(float r, int type)
09784 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09785 {
09786         // r in angstrom
09787         double ret = 0;//iterations ==> rounding is problematic with float types if 15 < r < 20 and really bad if 20 < r < 30
09788         if (type == 0) { // pure Gaussian falloff
09789                 r /= 2;
09790                 ret = exp(-r * r);
09791         } else if (type == 1) { // pure Gaussian falloff + negative dip, so mean is 0
09792                 r /= 2;
09793                 ret = (1 - r * r / 4) * exp(-r * r / 4);
09794         } else if (type == 2) {
09795                 // polynomial fitting to the radial profile of real helix density
09796                 // f=a0*x^n+a1+x^(n-1)+ ... +a[n-1]*x+an
09797                 //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};
09798 
09799                 // now the fitting to the original profile
09800                 if (r >= 12.2)
09801                         return 0; //We don't want that part of the polynomial --> goes way below zero
09802                 static float an[15] = { -3.9185246832229140e-16f,
09803                                 3.3957205298900993e-14f, 2.0343351971222658e-12f,
09804                                 -4.4935965816879751e-10f, 3.0668169835080933e-08f,
09805                                 -1.1904544689091790e-06f, 2.9753088549414953e-05f,
09806                                 -4.9802112876220150e-04f, 5.5900917825309360e-03f,
09807                                 -4.0823714462925299e-02f, 1.8021733669148599e-01f,
09808                                 -4.0992557296268717e-01f, 3.3980328566901458e-01f,
09809                                 -3.6062024812411908e-01f, 1.0000000000000000e+00f };
09810 
09811                 ret = an[0];
09812                 for (int i = 1; i < 15; i++) {
09813                         ret = ret * r + an[i];
09814                 }
09815         }
09816         return (float)ret;
09817 }
09818 
09819 void ModelEMCylinderProcessor::process_inplace(EMData * in)
09820 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09821 {
09822         // synthesize model alpha helix, len is Angstrom, default to 2 turns
09823         //The helical axis is parallel to the z axis.
09824         EMData * cyl = in;
09825         int nx = cyl->get_xsize();
09826         int ny = cyl->get_ysize();
09827         int nz = cyl->get_zsize();
09828 
09829         int type = params.set_default("type", 2);
09830         float len = params.set_default("length", 16.2); //in angstroms
09831         int x0 = params.set_default("x0", -1); //in voxels -- default value changed a few lines down
09832         int y0 = params.set_default("y0", -1); //in voxels
09833         int z0 = params.set_default("z0", -1); //in voxels
09834         //TODO: check with Matt about default values
09835 
09836         if (x0 < 0 || x0 >= nx)
09837                 x0 = nx / 2;
09838         if (y0 < 0 || y0 >= ny)
09839                 y0 = ny / 2;
09840         if (z0 < 0 || z0 >= nz)
09841                 z0 = nz / 2;
09842 
09843         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
09844         float apix_y = cyl->get_attr("apix_y");
09845         float apix_z = cyl->get_attr("apix_z");
09846 
09847         float * dat = cyl->get_data();
09848         int cyl_voxel_len = (int) (len / apix_z);
09849         int cyl_k_min = z0 - cyl_voxel_len / 2;
09850         int cyl_k_max = z0 + cyl_voxel_len / 2;
09851 
09852         int x, y;
09853         for (int k = 0; k < nz; k++) {
09854                 for (int j = 0; j < ny; j++) {
09855                         for (int i = 0; i < nx; i++, dat++) {
09856                                 x = i - x0;//coordinate sys centered on cylinder
09857                                 y = j - y0;//coordinate sys centered on cylinder
09858                                 float radius = (float)hypot(x * apix_x, y * apix_y);
09859                                 if ((k > cyl_k_min) && (k < cyl_k_max))
09860                                         *dat += radprofile(radius, type); //pointer arithmetic for array done in loop
09861                                 //else
09862                                         //continue;
09863 
09864                         }
09865                 }
09866         }
09867 }
09868 
09869 void ApplyPolynomialProfileToHelix::process_inplace(EMData * in)
09870 {
09871         EMData * cyl = in;
09872         int nx = cyl->get_xsize();
09873         int ny = cyl->get_ysize();
09874         int nz = cyl->get_zsize();
09875         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
09876         float apix_y = cyl->get_attr("apix_y");
09877         float apix_z = cyl->get_attr("apix_z");
09878         float lengthAngstroms = params["length"];
09879         int z0 = params.set_default("z0", -1); //in voxels
09880 
09881         if (z0 < 0 || z0 >= nz)
09882                 z0 = nz / 2;
09883 
09884         int z_start = Util::round( z0 - 0.5*lengthAngstroms/apix_z );
09885         int z_stop = Util::round( z0 + 0.5*lengthAngstroms/apix_z );
09886 
09887         float * dat = cyl->get_data();
09888         double rho_x_sum, rho_y_sum, rho_sum, x_cm, y_cm, radius;
09889 
09890         for (int k = 0; k < nz; k++) //taking slices along z axis
09891         {
09892                 rho_x_sum = rho_y_sum = rho_sum = 0; //Set to zero for a new slice
09893 
09894                 if (k >= z_start && k <= z_stop)
09895                 //Apply the radial profile only between z_start and z_stop on the z axis
09896                 {
09897                         //Calculating CM for the slice...
09898                         for (int j = 0; j < ny; j++)
09899                         {
09900                                 for (int i = 0; i < nx; i++, dat++)
09901                                 {
09902                                         rho_x_sum += (*dat)*i;
09903                                         rho_y_sum += (*dat)*j;
09904                                         rho_sum += *dat;
09905                                 }
09906                         }
09907                         if (rho_sum != 0)
09908                         {
09909                                 dat -= nx*ny;//going back to the beginning of the dat array
09910                                 x_cm = rho_x_sum/rho_sum;
09911                                 y_cm = rho_y_sum/rho_sum;
09912 
09913                                 //Applying radial profile...
09914                                 for (int j=0; j<ny;j++)
09915                                 {
09916                                         for (int i=0;i<nx;i++,dat++)
09917                                         {
09918                                                 radius = hypot( (i-x_cm)*apix_x, (j-y_cm)*apix_y );
09919                                                 *dat = radprofile((float)radius, 2);//Type 2 is the polynomial radial profile.
09920                                         }
09921                                 }
09922                         }
09923                 }
09924                 else
09925                 //Clear the map, setting the density to zero everywhere else.
09926                 {
09927                         for (int j=0; j<ny; j++)
09928                                 for(int i=0; i<nx; i++)
09929                                 {
09930                                         *dat = 0;
09931                                         dat++;
09932                                 }
09933                 }
09934 
09935         }
09936 }
09937 
09938 EMData* BinarySkeletonizerProcessor::process(EMData * image)
09939 {
09940         using namespace wustl_mm::GraySkeletonCPP;
09941         using namespace wustl_mm::SkeletonMaker;
09942 
09943         Volume * vimage = new Volume(image);
09944         float threshold = params["threshold"];
09945         int min_curvew = params.set_default("min_curve_width", 4);
09946         int min_srfcw = params.set_default("min_surface_width", 4);
09947         bool mark_surfaces = params.set_default("mark_surfaces", true);
09948         Volume* vskel = VolumeSkeletonizer::PerformPureJuSkeletonization(vimage, "unused", static_cast<double>(threshold), min_curvew, min_srfcw);
09949         //VolumeSkeletonizer::CleanUpSkeleton(vskel, 4, 0.01f);
09950         if (mark_surfaces) {
09951                 VolumeSkeletonizer::MarkSurfaces(vskel);
09952         }
09953 
09954         vskel->getVolumeData()->owns_emdata = false; //ensure the EMData object will remain when the Volume and its VolumeData object are freed
09955         EMData* skel = vskel->get_emdata();
09956         skel->update();
09957         return skel;
09958 }
09959 
09960 void BinarySkeletonizerProcessor::process_inplace(EMData * image)
09961 {
09962         EMData* em_skel = this->process(image);
09963         //TODO: use memcpy and copy metadata explicitly
09964         *image = *em_skel; //Deep copy performed by EMData::operator=
09965         image->update();
09966         delete em_skel;
09967         em_skel = NULL;
09968         return;
09969 }

Generated on Fri Apr 30 15:38:55 2010 for EMAN2 by  doxygen 1.3.9.1