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

Generated on Mon Mar 7 18:18:33 2011 for EMAN2 by  doxygen 1.3.9.1