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

processor.cpp

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

Generated on Thu Dec 9 13:45:49 2010 for EMAN2 by  doxygen 1.3.9.1