EMAN2
processor.cpp
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32#include "processor.h"
33#include "sparx/processor_sparx.h"
35#include "reconstructor_tools.h"
36#include "cmp.h"
37#include "ctf.h"
38#include "xydata.h"
39#include "emdata.h"
40#include "emfft.h"
41#include "emassert.h"
42#include "randnum.h"
43#include "symmetry.h"
44#include "averager.h"
45#include "util.h"
46
47#include <gsl/gsl_randist.h>
48#include <gsl/gsl_statistics.h>
49#include <gsl/gsl_wavelet.h>
50#include <gsl/gsl_wavelet2d.h>
51#include <gsl/gsl_multimin.h>
52#include <algorithm>
53#include <gsl/gsl_fit.h>
54#include <ctime>
55
56#ifdef __APPLE__
57 typedef unsigned int uint;
58#endif //__APPLE__
59
60#ifdef _WIN32
61 typedef unsigned int uint;
62#endif //_WIN32
63
64#ifdef EMAN2_USING_CUDA
65//#include "cuda/cuda_util.h"
66#include "cuda/cuda_processor.h"
67#endif // EMAN2_USING_CUDA
68
69using namespace EMAN;
70using std::reverse;
71
72const string SNREvalProcessor::NAME = "eval.maskedsnr";
73const string AmpweightFourierProcessor::NAME = "filter.ampweight";
74const string Axis0FourierProcessor::NAME = "filter.xyaxes0";
75const string ConvolutionProcessor::NAME = "math.convolution";
76const string BispecSliceProcessor::NAME = "math.bispectrum.slice";
77const string HarmonicProcessor::NAME = "math.harmonic";
78const string XGradientProcessor::NAME = "math.edge.xgradient";
79const string YGradientProcessor::NAME = "math.edge.ygradient";
80const string ZGradientProcessor::NAME = "math.edge.zgradient";
81const string ImageDivergenceProcessor::NAME = "math.divergence";
82const string GradientMagnitudeProcessor::NAME = "math.gradient.magnitude";
83const string GradientDirectionProcessor::NAME = "math.gradient.direction";
84const string SDGDProcessor::NAME = "math.laplacian.sdgd";
85const string LaplacianProcessor::NAME = "math.laplacian";
86const string LaplacianDirectionProcessor::NAME = "math.laplacian.direction";
87const string LaplacianMagnitudeProcessor::NAME = "math.laplacian.magnitude";
88const string Wiener2DAutoAreaProcessor::NAME = "filter.wiener2dauto";
89const string Wiener2DFourierProcessor::NAME = "filter.wiener2d";
90const string CtfSimProcessor::NAME = "math.simulatectf";
91const string LinearRampFourierProcessor::NAME = "filter.linearfourier";
92const string LoGFourierProcessor::NAME = "filter.LoG";
93const string DoGFourierProcessor::NAME = "filter.DoG";
94const string AzSharpProcessor::NAME = "filter.azimuthal.contrast";
95const string HighpassAutoPeakProcessor::NAME = "filter.highpass.autopeak";
96const string LinearRampProcessor::NAME = "eman1.filter.ramp";
97const string AbsoluteValueProcessor::NAME = "math.absvalue";
98const string CCCSNRProcessor::NAME = "math.ccc_snr_wiener";
99const string FloorValueProcessor::NAME = "math.floor";
100const string BooleanProcessor::NAME = "threshold.notzero";
101const string KmeansSegmentProcessor::NAME = "segment.kmeans";
102const string GaussSegmentProcessor::NAME = "segment.gauss";
103const string DistanceSegmentProcessor::NAME = "segment.distance";
104const string WatershedProcessor::NAME = "segment.watershed";
105const string SegmentSubunitProcessor::NAME = "segment.subunit";
106const string RecipCarefullyProcessor::NAME = "math.reciprocal";
107const string SubtractOptProcessor::NAME = "math.sub.optimal";
108const string ValuePowProcessor::NAME = "math.pow";
109const string ValueSquaredProcessor::NAME = "math.squared";
110const string ValueSqrtProcessor::NAME = "math.sqrt";
111const string DiscritizeProcessor::NAME = "threshold.discritize.sigma";
112const string ToZeroProcessor::NAME = "threshold.belowtozero";
113const string AboveToZeroProcessor::NAME="threshold.abovetozero";
114const string OutlierProcessor::NAME="threshold.outlier.localmean";
115const string Rotate180Processor::NAME = "math.rotate.180";
116const string TransformProcessor::NAME = "xform";
117const string IntTranslateProcessor::NAME = "xform.translate.int";
118const string ScaleTransformProcessor::NAME = "xform.scale";
119const string ApplySymProcessor::NAME = "xform.applysym";
120const string ClampingProcessor::NAME = "threshold.clampminmax";
121const string RangeZeroProcessor::NAME = "threshold.rangetozero";
122const string NSigmaClampingProcessor::NAME = "threshold.clampminmax.nsigma";
123const string ToMinvalProcessor::NAME = "threshold.belowtominval";
124const string CutToZeroProcessor::NAME = "threshold.belowtozero_cut";
125const string BinarizeProcessor::NAME = "threshold.binary";
126//const string BinarizeAmpProcessor::NAME = "threshold.amp.binary";
127const string BinarizeFourierProcessor::NAME = "threshold.binary.fourier";
128const string CollapseProcessor::NAME = "threshold.compress";
129const string LinearXformProcessor::NAME = "math.linear";
130const string ExpProcessor::NAME = "math.exp";
131const string FiniteProcessor::NAME = "math.finite";
132const string RangeThresholdProcessor::NAME = "threshold.binaryrange";
133const string SigmaProcessor::NAME = "math.sigma";
134const string LogProcessor::NAME = "math.log";
135const string MaskSharpProcessor::NAME = "mask.sharp";
136const string MaskSoftProcessor::NAME = "mask.soft";
137const string MaskEdgeMeanProcessor::NAME = "mask.ringmean";
138const string MaskNoiseProcessor::NAME = "mask.noise";
139const string MaskGaussProcessor::NAME = "mask.gaussian";
140const string MaskAzProcessor::NAME = "mask.cylinder";
141const string MaskGaussNonuniformProcessor::NAME = "mask.gaussian.nonuniform";
142const string MaskGaussInvProcessor::NAME = "math.gausskernelfix";
143const string GridKernelFixProcessor::NAME = "math.gridkernelfix";
144const string LinearPyramidProcessor::NAME = "math.linearpyramid";
145const string SetBitsProcessor::NAME = "math.setbits";
146const string MakeRadiusSquaredProcessor::NAME = "math.toradiussqr";
147const string MakeRadiusProcessor::NAME = "math.toradius";
148const string ComplexNormPixel::NAME = "complex.normpixels";
149const string ZeroConstantProcessor::NAME = "mask.contract"; // This is broken, it never worked. Somebody didn't think it through properly
150const string BoxMedianProcessor::NAME = "eman1.filter.median";
151const string BoxSigmaProcessor::NAME = "math.localsigma";
152const string NonConvexProcessor::NAME = "math.nonconvex";
153const string BoxMaxProcessor::NAME = "math.localmax";
154const string LocalMinAbsProcessor::NAME = "math.localminabs";
155const string MinusPeakProcessor::NAME = "math.submax";
156const string PeakOnlyProcessor::NAME = "mask.onlypeaks";
157const string DiffBlockProcessor::NAME = "eman1.filter.blockrange";
158const string CutoffBlockProcessor::NAME = "eman1.filter.blockcutoff";
159const string MaxShrinkProcessor::NAME = "math.maxshrink";
160const string MinShrinkProcessor::NAME = "math.minshrink";
161const string MeanShrinkProcessor::NAME = "math.meanshrink";
162const string MedianShrinkProcessor::NAME = "math.medianshrink";
163const string FFTResampleProcessor::NAME = "math.fft.resample";
164const string GradientRemoverProcessor::NAME = "math.lineargradientfix";
165const string GradientPlaneRemoverProcessor::NAME = "filter.gradientPlaneRemover";
166const string FlattenBackgroundProcessor::NAME = "filter.flattenbackground";
167const string RampProcessor::NAME = "filter.ramp";
168const string VerticalStripeProcessor::NAME = "math.verticalstripefix";
169const string RealToFFTProcessor::NAME = "math.realtofft";
170const string SigmaZeroEdgeProcessor::NAME = "mask.zeroedgefill";
171const string WedgeFillProcessor::NAME = "mask.wedgefill";
172const string FFTPeakProcessor::NAME = "mask.fft.peak";
173const string FFTConeProcessor::NAME = "mask.fft.cone";
174const string FFTWedgeProcessor::NAME = "mask.fft.wedge";
175const string BeamstopProcessor::NAME = "mask.beamstop";
176const string MeanZeroEdgeProcessor::NAME = "mask.dampedzeroedgefill";
177const string AverageXProcessor::NAME = "math.averageovery";
178const string DecayEdgeProcessor::NAME = "mask.decayedge2d";
179const string ZeroEdgeRowProcessor::NAME = "mask.zeroedge2d";
180const string ZeroEdgePlaneProcessor::NAME = "mask.zeroedge3d";
181const string BilateralProcessor::NAME = "filter.bilateral";
182const string NormalizeUnitProcessor::NAME = "normalize.unitlen";
183const string NormalizeUnitSumProcessor::NAME = "normalize.unitsum";
184const string NormalizeStdProcessor::NAME = "normalize";
185const string NormalizeMaskProcessor::NAME = "normalize.mask";
186const string NormalizeRampNormVar::NAME = "normalize.ramp.normvar";
187const string NormalizeByMassProcessor::NAME = "normalize.bymass";
188const string NormalizeEdgeMeanProcessor::NAME = "normalize.edgemean";
189const string NormalizeCircleMeanProcessor::NAME = "normalize.circlemean";
190const string NormalizeLREdgeMeanProcessor::NAME = "normalize.lredge";
191const string NormalizeHistPeakProcessor::NAME = "normalize.histpeak";
192const string NormalizeMaxMinProcessor::NAME = "normalize.maxmin";
193const string NormalizeRowProcessor::NAME = "normalize.rows";
194const string NormalizeToLeastSquareProcessor::NAME = "normalize.toimage";
195const string RotationalAverageProcessor::NAME = "math.rotationalaverage";
196const string RotationalSubstractProcessor::NAME = "math.rotationalsubtract";
197const string TransposeProcessor::NAME = "xform.transpose";
198const string FlipProcessor::NAME = "xform.flip";
199const string AddNoiseProcessor::NAME = "math.addnoise";
200const string AddSigmaNoiseProcessor::NAME = "math.addsignoise";
201const string AddRandomNoiseProcessor::NAME = "math.addspectralnoise";
202const string FourierToCornerProcessor::NAME = "xform.fourierorigin.tocorner";
203const string FourierToCenterProcessor::NAME = "xform.fourierorigin.tocenter";
204const string PhaseToCenterProcessor::NAME = "xform.phaseorigin.tocenter";
205const string PhaseToCornerProcessor::NAME = "xform.phaseorigin.tocorner";
206const string AutoMask2DProcessor::NAME = "mask.auto2d";
207const string AutoMaskAsymUnit::NAME = "mask.asymunit";
208const string AutoMask3DProcessor::NAME = "mask.auto3d.thresh";
209const string AutoMask3D2Processor::NAME = "mask.auto3d";
210const string AutoMaskDustProcessor::NAME = "mask.dust3d";
211const string AddMaskShellProcessor::NAME = "mask.addshells";
212const string IterMultiMaskProcessor::NAME = "mask.addshells.multilevel";
213const string IterBinMaskProcessor::NAME = "mask.addshells.gauss";
214const string PhaseToMassCenterProcessor::NAME = "xform.phasecenterofmass";
215const string ToMassCenterProcessor::NAME = "xform.centerofmass";
216const string ToCenterProcessor::NAME = "xform.center";
217const string ACFCenterProcessor::NAME = "xform.centeracf";
218const string CTFCorrProcessor::NAME = "filter.ctfcorr.simple";
219const string SNRProcessor::NAME = "eman1.filter.snr";
220const string FileFourierProcessor::NAME = "eman1.filter.byfile";
221const string FSCFourierProcessor::NAME = "filter.wiener.byfsc";
222const string SymSearchProcessor::NAME = "misc.symsearch";
223const string MaskPackProcessor::NAME = "misc.mask.pack";
224const string LocalNormProcessor::NAME = "normalize.local";
225const string StripeXYProcessor::NAME = "math.xystripefix";
226const string BadLineXYProcessor::NAME = "math.xybadlines";
227const string IndexMaskFileProcessor::NAME = "mask.fromfile";
228// const string CoordinateMaskFileProcessor::NAME = "mask.fromfile.sizediff";
229const string PaintProcessor::NAME = "mask.paint";
230const string DirectionalSumProcessor::NAME = "misc.directional_sum";
231template<> const string BinaryOperateProcessor<MaxPixelOperator>::NAME = "math.max"; // These 2 should not really be processors
232template<> const string BinaryOperateProcessor<MinPixelOperator>::NAME = "math.min";
233const string MaxPixelOperator::NAME = "math.max";
234const string MinPixelOperator::NAME = "math.min";
235const string MatchSFProcessor::NAME = "filter.matchto";
236const string SetSFProcessor::NAME = "filter.setstrucfac";
237const string SetIsoPowProcessor::NAME = "filter.setisotropicpow";
238const string SmartMaskProcessor::NAME = "mask.smart";
239const string TestImagePureGaussian::NAME = "testimage.puregaussian";
240const string TestImageFourierGaussianBand::NAME = "testimage.fourier.gaussianband";
241const string TestImageFourierNoiseGaussian::NAME = "testimage.noise.fourier.gaussian";
242const string TestImageFourierNoiseProfile::NAME = "testimage.noise.fourier.profile";
243const string CTFSNRWeightProcessor::NAME = "ctf.snr.weight";
244const string TestImageLineWave::NAME = "testimage.linewave";
245const string TestTomoImage::NAME = "testimage.tomo.objects";
246const string TestImageGradient::NAME = "testimage.gradient";
247const string TestImageAxes::NAME = "testimage.axes";
248const string TestImageGaussian::NAME = "testimage.gaussian";
249const string TestImageScurve::NAME = "testimage.scurve";
250const string TestImageSphericalWave::NAME = "testimage.sphericalwave";
251const string TestImageSinewave::NAME = "testimage.sinewave";
252const string TestImageSinewaveCircular::NAME = "testimage.sinewave.circular";
253const string TestImageSquarecube::NAME = "testimage.squarecube";
254const string TestImageEllipse::NAME = "testimage.ellipsoid";
255const string TestImageHollowEllipse::NAME = "testimage.ellipsoid.hollow";
256const string TestImageCirclesphere::NAME = "testimage.circlesphere";
257const string TestImageNoiseUniformRand::NAME = "testimage.noise.uniform.rand";
258const string TestImageNoiseGauss::NAME = "testimage.noise.gauss";
259const string TestImageCylinder::NAME = "testimage.cylinder";
260const string TestImageDisc::NAME = "testimage.disc";
261const string CCDNormProcessor::NAME = "filter.ccdnorm";
262const string WaveletProcessor::NAME = "basis.wavelet";
263const string EnhanceProcessor::NAME = "filter.enhance";
264const string TomoTiltEdgeMaskProcessor::NAME = "tomo.tiltedgemask";
265const string TomoTiltAngleWeightProcessor::NAME = "tomo.tiltangleweight";
266const string FFTProcessor::NAME = "basis.fft";
267const string RadialProcessor::NAME = "mask.radialprofile";
268const string HistogramBin::NAME = "histogram.bin";
269const string ModelEMCylinderProcessor::NAME = "math.model_em_cylinder";
270const string ApplyPolynomialProfileToHelix::NAME = "math.poly_radial_profile";
271const string BinarySkeletonizerProcessor::NAME="gorgon.binary_skel";
272const string MirrorProcessor::NAME = "xform.mirror";
273const string ReverseProcessor::NAME = "xform.reverse";
274const string NewLowpassTopHatProcessor::NAME = "filter.lowpass.tophat";
275const string NewHighpassTopHatProcessor::NAME = "filter.highpass.tophat";
276const string NewBandpassTopHatProcessor::NAME = "filter.bandpass.tophat";
277const string NewHomomorphicTopHatProcessor::NAME = "filter.homomorphic.tophat";
278const string NewLowpassGaussProcessor::NAME = "filter.lowpass.gauss";
279const string LowpassAutoBProcessor::NAME="filter.lowpass.autob";
280const string NewHighpassGaussProcessor::NAME = "filter.highpass.gauss";
281const string NewBandpassGaussProcessor::NAME = "filter.bandpass.gauss";
282const string NewHomomorphicGaussProcessor::NAME = "filter.homomorphic.gauss";
283const string NewInverseGaussProcessor::NAME = "filter.gaussinverse";
284const string GaussZFourierProcessor::NAME = "filter.lowpass.gaussz";
285const string SHIFTProcessor::NAME = "filter.shift";
286const string InverseKaiserI0Processor::NAME = "filter.kaiser_io_inverse";
287const string InverseKaiserSinhProcessor::NAME = "filter.kaisersinhinverse";
288const string NewRadialTableProcessor::NAME = "filter.radialtable";
289const string LowpassRandomPhaseProcessor::NAME = "filter.lowpass.randomphase";
290const string NewLowpassButterworthProcessor::NAME = "filter.lowpass.butterworth";
291const string NewHighpassButterworthProcessor::NAME = "filter.highpass.butterworth";
292const string NewHomomorphicButterworthProcessor::NAME = "filter.homomorphic.butterworth";
293const string NewLowpassTanhProcessor::NAME = "filter.lowpass.tanh";
294const string NewHighpassTanhProcessor::NAME = "filter.highpass.tanh";
295const string NewHomomorphicTanhProcessor::NAME = "filter.homomorphic.tanh";
296const string NewBandpassTanhProcessor::NAME = "filter.bandpass.tanh";
297const string CTF_Processor::NAME = "filter.CTF_";
298const string ConvolutionKernelProcessor::NAME = "filter.convolution.kernel";
299const string RotateInFSProcessor::NAME = "rotateinfs";
300const string CircularAverageBinarizeProcessor::NAME = "threshold.binary.circularmean";
301const string ObjDensityProcessor::NAME = "morph.object.density";
302const string ObjLabelProcessor::NAME = "morph.object.label";
303const string BwThinningProcessor::NAME = "morph.thin";
304const string BwMajorityProcessor::NAME = "morph.majority";
305const string PruneSkeletonProcessor::NAME = "morph.prune";
306const string ManhattanDistanceProcessor::NAME = "math.distance.manhattan";
307const string BinaryDilationProcessor::NAME = "morph.dilate.binary";
308const string BinaryErosionProcessor::NAME = "morph.erode.binary";
309const string BinaryOpeningProcessor::NAME = "morph.open.binary";
310const string BinaryClosingProcessor::NAME = "morph.close.binary";
311const string BinaryMorphGradientProcessor::NAME = "morph.gradient.binary";
312const string BinaryExternalGradientProcessor::NAME = "morph.ext_grad.binary";
313const string BinaryInternalGradientProcessor::NAME = "morph.int_grad.binary";
314const string BinaryTopHatProcessor::NAME = "morph.tophat.binary";
315const string BinaryBlackHatProcessor::NAME = "morph.blackhat.binary";
316const string GrowSkeletonProcessor::NAME = "morph.grow";
317const string FixSignProcessor::NAME = "math.fixmode";
318const string ZThicknessProcessor::NAME = "misc.zthick";
319const string ReplaceValuefromListProcessor::NAME = "misc.colorlabel";
320const string PolyMaskProcessor::NAME = "mask.poly";
321const string AmpMultProcessor::NAME = "math.multamplitude";
322
323//#ifdef EMAN2_USING_CUDA
324//const string CudaMultProcessor::NAME = "cuda.math.mult";
325//const string CudaCorrelationProcessor::NAME = "cuda.correlate";
326//#endif //EMAN2_USING_CUDA
327
328#if 0
329//const string XYZProcessor::NAME = "XYZ";
330#endif //0
331
332
334{
335 force_add<HighpassAutoPeakProcessor>();
336 force_add<LinearRampFourierProcessor>();
337 force_add<LoGFourierProcessor>();
338 force_add<DoGFourierProcessor>();
339// force_add<AzSharpProcessor>();
340 force_add<FixSignProcessor>();
341
342 force_add<AmpweightFourierProcessor>();
343 force_add<Axis0FourierProcessor>();
344 force_add<Wiener2DFourierProcessor>();
345 force_add<LowpassAutoBProcessor>();
346 force_add<CtfSimProcessor>();
347
348 force_add<LinearPyramidProcessor>();
349 force_add<LinearRampProcessor>();
350 force_add<AbsoluteValueProcessor>();
351 force_add<FloorValueProcessor>();
352 force_add<BooleanProcessor>();
353 force_add<KmeansSegmentProcessor>();
354 force_add<GaussSegmentProcessor>();
355 force_add<SegmentSubunitProcessor>();
356 force_add<DistanceSegmentProcessor>();
357 force_add<ValuePowProcessor>();
358 force_add<ValueSquaredProcessor>();
359 force_add<ValueSqrtProcessor>();
360 force_add<DiscritizeProcessor>();
361 force_add<Rotate180Processor>();
362 force_add<TransformProcessor>();
363 force_add<ScaleTransformProcessor>();
364 force_add<ApplySymProcessor>();
365 force_add<IntTranslateProcessor>();
366 force_add<RecipCarefullyProcessor>();
367 force_add<SubtractOptProcessor>();
368
369 force_add<ClampingProcessor>();
370 force_add<NSigmaClampingProcessor>();
371
372 force_add<ToZeroProcessor>();
373 force_add<RangeZeroProcessor>();
374 force_add<AboveToZeroProcessor>();
375 force_add<OutlierProcessor>();
376 force_add<ToMinvalProcessor>();
377 force_add<CutToZeroProcessor>();
378 force_add<BinarizeProcessor>();
379// force_add<BinarizeAmpProcessor>();
380 force_add<BinarizeFourierProcessor>();
381 force_add<CollapseProcessor>();
382 force_add<LinearXformProcessor>();
383 force_add<SetBitsProcessor>();
384
385 force_add<CCCSNRProcessor>();
386 force_add<ExpProcessor>();
387 force_add<RangeThresholdProcessor>();
388 force_add<SigmaProcessor>();
389 force_add<LogProcessor>();
390 force_add<FiniteProcessor>();
391
392 force_add< BinaryOperateProcessor<MaxPixelOperator> >();
393 force_add< BinaryOperateProcessor<MinPixelOperator> >();
394
395 force_add<PaintProcessor>();
396 force_add<WatershedProcessor>();
397 force_add<MaskSharpProcessor>();
398 force_add<MaskSoftProcessor>();
399 force_add<MaskEdgeMeanProcessor>();
400 force_add<MaskNoiseProcessor>();
401 force_add<MaskGaussProcessor>();
402 force_add<MaskGaussNonuniformProcessor>();
403 force_add<MaskGaussInvProcessor>();
404 force_add<GridKernelFixProcessor>();
405 force_add<MaskAzProcessor>();
406
407 force_add<MaxShrinkProcessor>();
408 force_add<MinShrinkProcessor>();
409 force_add<MeanShrinkProcessor>();
410 force_add<MedianShrinkProcessor>();
411 force_add<FFTResampleProcessor>();
412 force_add<NonConvexProcessor>();
413
414 force_add<MakeRadiusSquaredProcessor>();
415 force_add<MakeRadiusProcessor>();
416
417 force_add<ComplexNormPixel>();
418
419 force_add<LaplacianProcessor>();
420// force_add<ZeroConstantProcessor>(); // this is badly written, it does not work and never did. Who wrote this !?!?
421
422 force_add<BoxMedianProcessor>();
423 force_add<BoxSigmaProcessor>();
424 force_add<BoxMaxProcessor>();
425 force_add<LocalMinAbsProcessor>();
426
427 force_add<MinusPeakProcessor>();
428 force_add<PeakOnlyProcessor>();
429 force_add<DiffBlockProcessor>();
430
431 force_add<CutoffBlockProcessor>();
432// force_add<GradientRemoverProcessor>();
433 force_add<GradientPlaneRemoverProcessor>();
434 force_add<FlattenBackgroundProcessor>();
435 force_add<VerticalStripeProcessor>();
436 force_add<RealToFFTProcessor>();
437 force_add<SigmaZeroEdgeProcessor>();
438 force_add<WedgeFillProcessor>();
439 force_add<FFTPeakProcessor>();
440 force_add<FFTConeProcessor>();
441 force_add<FFTWedgeProcessor>();
442 force_add<RampProcessor>();
443
444 force_add<BeamstopProcessor>();
445 force_add<MeanZeroEdgeProcessor>();
446 force_add<AverageXProcessor>();
447 force_add<DecayEdgeProcessor>();
448 force_add<ZeroEdgeRowProcessor>();
449 force_add<ZeroEdgePlaneProcessor>();
450
451 force_add<BilateralProcessor>();
452
453 force_add<ConvolutionProcessor>();
454 force_add<BispecSliceProcessor>();
455 force_add<HarmonicProcessor>();
456
457 force_add<NormalizeStdProcessor>();
458 force_add<NormalizeHistPeakProcessor>();
459 force_add<NormalizeUnitProcessor>();
460 force_add<NormalizeUnitSumProcessor>();
461 force_add<NormalizeMaskProcessor>();
462 force_add<NormalizeEdgeMeanProcessor>();
463 force_add<NormalizeCircleMeanProcessor>();
464 force_add<NormalizeLREdgeMeanProcessor>();
465 force_add<NormalizeMaxMinProcessor>();
466 force_add<NormalizeByMassProcessor>();
467 force_add<NormalizeRowProcessor>();
468 force_add<NormalizeRampNormVar>();
469
470 force_add<HistogramBin>();
471
472 force_add<NormalizeToLeastSquareProcessor>();
473
474 force_add<RotationalAverageProcessor>();
475 force_add<RotationalSubstractProcessor>();
476 force_add<FlipProcessor>();
477 force_add<TransposeProcessor>();
478 force_add<MirrorProcessor>();
479 force_add<ReverseProcessor>();
480
481 force_add<AddNoiseProcessor>();
482 force_add<AddSigmaNoiseProcessor>();
483 force_add<AddRandomNoiseProcessor>();
484
485 force_add<PhaseToCenterProcessor>();
486 force_add<PhaseToCornerProcessor>();
487 force_add<FourierToCenterProcessor>();
488 force_add<FourierToCornerProcessor>();
489 force_add<AutoMask2DProcessor>();
490 force_add<AutoMask3DProcessor>();
491 force_add<AutoMask3D2Processor>();
492 force_add<AutoMaskDustProcessor>();
493 force_add<AddMaskShellProcessor>();
494 force_add<IterMultiMaskProcessor>();
495 force_add<IterBinMaskProcessor>();
496 force_add<AutoMaskAsymUnit>();
497
498 force_add<CTFSNRWeightProcessor>();
499
500 force_add<ToMassCenterProcessor>();
501 force_add<ToCenterProcessor>();
502 force_add<PhaseToMassCenterProcessor>();
503 force_add<ACFCenterProcessor>();
504// force_add<SNRProcessor>();
505 force_add<CTFCorrProcessor>();
506 force_add<FSCFourierProcessor>();
507
508 force_add<XGradientProcessor>();
509 force_add<YGradientProcessor>();
510 force_add<ZGradientProcessor>();
511
512 force_add<ImageDivergenceProcessor>();
513 force_add<GradientMagnitudeProcessor>();
514 force_add<GradientDirectionProcessor>();
515 force_add<LaplacianMagnitudeProcessor>();
516 force_add<LaplacianDirectionProcessor>();
517 force_add<SDGDProcessor>();
518
519// force_add<FileFourierProcessor>();
520
521 force_add<SymSearchProcessor>();
522 force_add<MaskPackProcessor>();
523 force_add<StripeXYProcessor>();
524 force_add<BadLineXYProcessor>();
525 force_add<LocalNormProcessor>();
526
527 force_add<IndexMaskFileProcessor>();
528// force_add<CoordinateMaskFileProcessor>();
529 force_add<SetIsoPowProcessor>();
530 force_add<SetSFProcessor>();
531 force_add<MatchSFProcessor>();
532
533 force_add<SmartMaskProcessor>();
534
535 force_add<TestImageGaussian>();
536 force_add<TestImagePureGaussian>();
537 force_add<TestImageSinewave>();
538 force_add<TestImageSphericalWave>();
539 force_add<TestImageSinewaveCircular>();
540 force_add<TestImageSquarecube>();
541 force_add<TestImageCirclesphere>();
542 force_add<TestImageAxes>();
543 force_add<TestImageNoiseUniformRand>();
544 force_add<TestImageNoiseGauss>();
545 force_add<TestImageScurve>();
546 force_add<TestImageCylinder>();
547 force_add<TestImageDisc>();
548 force_add<TestImageGradient>();
549 force_add<TestTomoImage>();
550 force_add<TestImageLineWave>();
551 force_add<TestImageEllipse>();
552 force_add<TestImageHollowEllipse>();
553 force_add<TestImageFourierGaussianBand>();
554 force_add<TestImageFourierNoiseGaussian>();
555 force_add<TestImageFourierNoiseProfile>();
556
557 force_add<TomoTiltEdgeMaskProcessor>();
558 force_add<TomoTiltAngleWeightProcessor>();
559
560 force_add<NewLowpassTopHatProcessor>();
561 force_add<NewHighpassTopHatProcessor>();
562 force_add<NewBandpassTopHatProcessor>();
563 force_add<NewHomomorphicTopHatProcessor>();
564 force_add<NewLowpassGaussProcessor>();
565 force_add<NewHighpassGaussProcessor>();
566 force_add<NewBandpassGaussProcessor>();
567 force_add<NewHomomorphicGaussProcessor>();
568 force_add<NewInverseGaussProcessor>();
569 force_add<GaussZFourierProcessor>();
570 force_add<LowpassRandomPhaseProcessor>();
571 force_add<NewLowpassButterworthProcessor>();
572 force_add<NewHighpassButterworthProcessor>();
573 force_add<NewHomomorphicButterworthProcessor>();
574 force_add<NewLowpassTanhProcessor>();
575 force_add<NewHighpassTanhProcessor>();
576 force_add<NewBandpassTanhProcessor>();
577 force_add<NewHomomorphicTanhProcessor>();
578 force_add<NewRadialTableProcessor>();
579 force_add<InverseKaiserI0Processor>();
580 force_add<InverseKaiserSinhProcessor>();
581 force_add<CCDNormProcessor>();
582 force_add<CTF_Processor>();
583 force_add<SHIFTProcessor>();
584
585// force_add<WaveletProcessor>();
586 force_add<EnhanceProcessor>();
587 force_add<FFTProcessor>();
588 force_add<RadialProcessor>();
589
590 force_add<DirectionalSumProcessor>();
591 force_add<ConvolutionKernelProcessor>();
592
593 //Gorgon-related processors
594 force_add<ModelEMCylinderProcessor>();
595 force_add<ApplyPolynomialProfileToHelix>();
596 force_add<BinarySkeletonizerProcessor>();
597 force_add<RotateInFSProcessor>();
598 force_add<CircularAverageBinarizeProcessor>();
599 force_add<ObjDensityProcessor>();
600 force_add<ObjLabelProcessor>();
601 force_add<BwThinningProcessor>();
602 force_add<BwMajorityProcessor>();
603 force_add<PruneSkeletonProcessor>();
604 force_add<GrowSkeletonProcessor>();
605
606 force_add<ManhattanDistanceProcessor>();
607 force_add<BinaryDilationProcessor>();
608 force_add<BinaryErosionProcessor>();
609 force_add<BinaryClosingProcessor>();
610 force_add<BinaryOpeningProcessor>();
611 force_add<BinaryMorphGradientProcessor>();
612 force_add<BinaryExternalGradientProcessor>();
613 force_add<BinaryInternalGradientProcessor>();
614 force_add<BinaryTopHatProcessor>();
615 force_add<BinaryBlackHatProcessor>();
616 force_add<ZThicknessProcessor>();
617 force_add<ReplaceValuefromListProcessor>();
618 force_add<PolyMaskProcessor>();
619 force_add<AmpMultProcessor>();
620
621//#ifdef EMAN2_USING_CUDA
622// force_add<CudaMultProcessor>();
623// force_add<CudaCorrelationProcessor>();
624//#endif // EMAN2_USING_CUDA
625
626// force_add<XYZProcessor>();
627}
628
629void FiniteProcessor::process_pixel(float *x) const
630{
631 if ( !Util::goodf(x) ) {
632 *x = to;
633 }
634}
635
636
637EMData* Processor::process(const EMData * const image)
638{
639 EMData * result = image->copy();
640// printf("Default copy called\n");
641 process_inplace(result);
642 return result;
643}
644
646{
647 if (!image) {
648 LOGWARN("NULL image");
649 return;
650 }
651
652 EMData *processor_image = create_processor_image();
653
654 if (image->is_complex()) {
655 (*image) *= *processor_image;
656 }
657 else {
658 EMData *fft = image->do_fft();
659 (*fft) *= (*processor_image);
660 EMData *ift = fft->do_ift();
661
662 float *data = image->get_data();
663 float *t = data;
664 float *ift_data = ift->get_data();
665
666 data = ift_data;
667 ift_data = t;
668
669 ift->update();
670
671 if( fft )
672 {
673 delete fft;
674 fft = 0;
675 }
676
677 if( ift )
678 {
679 delete ift;
680 ift = 0;
681 }
682 }
683
684 image->update();
685}
686
687#define FFTRADIALOVERSAMPLE 4
689{
690 if (!image) {
691 LOGWARN("NULL Image");
692 return;
693 }
694
695 preprocess(image);
696
697 int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
698 float step=0.5f/array_size;
699
700 bool return_radial=(bool)params.set_default("return_radial",0);
701 vector < float >yarray(array_size);
702
703 create_radial_func(yarray);
704
705 if (image->is_complex()) {
706 image->apply_radial_func(0, step, yarray);
707 }
708 else {
709 EMData *fft = image->do_fft();
710 fft->apply_radial_func(0, step, yarray);
711 EMData *ift = fft->do_ift();
712
713 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
714
715 //ift->update(); Unecessary
716
717 if( fft )
718 {
719 delete fft;
720 fft = 0;
721 }
722
723 if( ift )
724 {
725 delete ift;
726 ift = 0;
727 }
728 }
729 if (return_radial) image->set_attr("filter_curve",yarray);
730
731 image->update();
732}
733
735{
736 if (!image) {
737 LOGWARN("NULL Image");
738 return;
739 }
740
741 preprocess(image);
742
743// int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
744// float step=0.5f/array_size;
745//
746// vector < float >yarray(array_size);
747
748 bool return_radial=(bool)params.set_default("return_radial",0);
749 bool interpolate=(bool)params.set_default("interpolate",1);
750
751 float cornerscale;
752 if (image->get_zsize()>1) cornerscale=sqrt(3.0);
753 else cornerscale=sqrt(2.0);
754
755 if (image->is_complex()) {
756 vector <float>yarray = image->calc_radial_dist(floor(image->get_ysize()*cornerscale/2),0,1.0,1);
757 create_radial_func(yarray,image);
758 image->apply_radial_func(0, 1.0f/image->get_ysize(), yarray,interpolate);
759 if (return_radial) image->set_attr("filter_curve",yarray);
760 }
761 else {
762 EMData *fft = image->do_fft();
763 vector <float>yarray = fft->calc_radial_dist((int)floor(fft->get_ysize()*cornerscale/2.0),0,1.0,1);
764 create_radial_func(yarray,fft);
765 // 4/30/10 stevel turned off interpolation to fix problem with matched filter
766 // 9/12/14 stevel, not sure why I turned off interp. Seems to cause rather than fix problems. Adding option to enable. Afraid to turn it on
767 fft->apply_radial_func(0, 1.0f/image->get_ysize(), yarray,interpolate);
768 EMData *ift = fft->do_ift();
769
770 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
771 if (return_radial) image->set_attr("filter_curve",yarray);
772
773// for (int i=0; i<yarray.size(); i++) printf("%d\t%f\n",i,yarray[i]);
774
775 //ift->update(); Unecessary
776
777 delete fft;
778 delete ift;
779
780 }
781
782 image->update();
783}
784
786 EMData *mask=(EMData *)params["mask"];
787 bool unpack = (int)params.set_default("unpack",0);
788
789 if ((float)mask->get_attr("mean_nonzero")!=1.0f) throw InvalidParameterException("MaskPackProcessor requires a binary mask");
790
791 int n_nz=(int)mask->get_attr("square_sum"); // true only for a binary mask
792
793 EMData *ret = 0;
794 if (unpack) {
795 ret = new EMData(mask->get_xsize(),mask->get_ysize(),mask->get_zsize());
796 ret->to_zero();
797
798 size_t ix=0;
799 for (size_t i=0; i<ret->get_size(); i++) {
800 if (mask->get_value_at_index(i)) ret->set_value_at_index(i,image->get_value_at_index(ix++));
801 }
802
803 } else {
804 ret = new EMData(n_nz,1,1);
805 ret->to_zero();
806
807 size_t ix=0;
808 for (size_t i=0; i<image->get_size(); i++) {
809 if (mask->get_value_at_index(i)) ret->set_value_at_index(ix++,image->get_value_at_index(i));
810 }
811 }
812
813 ret->update();
814 return ret;
815}
816
817// Looks like this hasn't actually been written yet...
819{
820 if (!image) {
821 LOGWARN("NULL Image");
822 return;
823 }
824
825 string mode=(string)params["mode"];
826
827 int nx = image->get_xsize();
828 int ny = image->get_ysize();
829 int nz = image->get_zsize();
830
831 // make an empty FFT object.
832 EMData *fft=new EMData((nx&0xfffffffe)+2,ny,nz);
833 fft->set_complex(1);
834 fft->set_ri(1);
835 if (nx&1) fft->set_fftpad(1);
836 fft->to_zero();
837
838 // Copy the kernel. Note that the kernel is 3x oversampled, so we are just computing an approximate kernel locally
839 if (mode=="gridding_5") {
840 for (int z=-2; z<3; z++) {
841 for (int y=-2; y<3; y++) {
842 for (int x=0; x<3; x++) {
843 fft->set_complex_at(x,y,z,FourierInserter3DMode7::kernel[x*3][abs(y)*3][abs(z)*3]);
844 }
845 }
846 }
847 }
848 else if (mode=="gridding_7") {
849 for (int z=-3; z<4; z++) {
850 for (int y=-3; y<4; y++) {
851 for (int x=0; x<4; x++) {
852 fft->set_complex_at(x,y,z,FourierInserter3DMode11::kernel[x*3][abs(y)*3][abs(z)*3]);
853 }
854 }
855 }
856 }
857 else throw InvalidParameterException("Gridding kernel correction of unknown mode, only gridding_5 or gridding_7 allowed");
858
859 EMData *real=fft->do_ift(); // this is the kernel ift
860 real->process_inplace("xform.phaseorigin.tocenter");
861 real->mult(2.0f/(float)real->get_attr("maximum"));
862 real->process_inplace("math.reciprocal"); // reciprocal to make a correction volume
863 real->process_inplace("threshold.clampminmax",Dict("minval",-4.0f,"maxval",4.0f)); // block overcorrection of noise near the edges
864// real->write_image("invkernel.hdf");
865
866 image->mult(*real); // apply the correction
867 delete real;
868 delete fft;
869}
870
871// Looks like this hasn't actually been written yet...
873{
874 if (!image) {
875 LOGWARN("NULL Image");
876 return;
877 }
878
879 float az_scale=(float)params.set_default("az_scale",1.0);
880 float cornerscale;
881 EMData *fft;
882
883 if (image->is_complex()) fft=image;
884 else EMData *fft = image->do_fft();
885
886 int nx=fft->get_xsize();
887 int ny=fft->get_ysize();
888 int nz=fft->get_zsize();
889 if (nz!=1) {
890 }
891 else {
892
893 }
894 if (image->is_complex()) {
895 EMData *ift = fft->do_ift();
896
897 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
898
899 delete fft;
900 delete ift;
901 }
902
903 image->update();
904}
905
907{
908 EMData *fft;
909
910 if (!image) throw InvalidParameterException("FFTPeakProcessor: no image provided");
911 if (!image->is_complex()) fft = image->do_fft();
912 else fft = image;
913
914 int nx=fft->get_xsize();
915 int ny=fft->get_ysize();
916 int nz=fft->get_zsize();
917 float thresh_sigma = (float)params.set_default("thresh_sigma", 1.0);
918 bool removepeaks = (bool)params.set_default("removepeaks",0);
919 bool to_mean = (bool)params.set_default("to_mean",0);
920
921 vector<float> amp=fft->calc_radial_dist(nx/2,0,1,0); // amplitude
922 vector<float> thr=fft->calc_radial_dist(nx/2,0,1,1); // start with inten (avg of amp^2)
923
924 for (int i=0; i<nx/2; i++) thr[i]=thresh_sigma*sqrt(thr[i]-amp[i]*amp[i])+amp[i]; // sqrt(inten-amp^2) is st
925
926 if (nz>1) {
927 for (int z=-nz/2; z<nz/2; z++) {
928 for (int y=-ny/2; y<ny/2; y++) {
929 for (int x=0; x<nx/2; x++) {
930 float r2=Util::hypot3(x,y,z);
931 int r=int(r2);
932 if (r>=nx/2) continue;
933 complex<float> v=fft->get_complex_at(x,y,z);
934 float va=std::abs(v);
935 if (va>=thr[r]) {
936 if (removepeaks) {
937 if (to_mean) {
938 v*=amp[r]/va;
939 fft->set_complex_at(x,y,z,v);
940 }
941 else fft->set_complex_at(x,y,z,0.0);
942 }
943 }
944 else {
945 if (!removepeaks) {
946 if (to_mean) {
947 v*=amp[r]/va;
948 fft->set_complex_at(x,y,z,v);
949 }
950 else fft->set_complex_at(x,y,z,0.0);
951 }
952 }
953 }
954 }
955 }
956 }
957 else {
958 for (int y=-ny/2; y<ny/2; y++) {
959 for (int x=0; x<nx/2; x++) {
960 int r=Util::hypot_fast_int(x,y);
961 if (r>=nx/2) continue;
962 complex<float> v=fft->get_complex_at(x,y);
963 float va=std::abs(v);
964 if (va>=thr[r]) {
965 if (removepeaks) {
966 if (to_mean) {
967 v*=amp[r]/va;
968 fft->set_complex_at(x,y,v);
969 }
970 else fft->set_complex_at(x,y,0.0);
971 }
972 }
973 else {
974 if (!removepeaks) {
975 if (to_mean) {
976 v*=amp[r]/va;
977 fft->set_complex_at(x,y,v);
978 }
979 else fft->set_complex_at(x,y,0.0);
980 }
981 }
982 }
983 }
984 }
985
986 if (fft!=image) {
987 EMData *ift=fft->do_ift();
988 memcpy(image->get_data(),ift->get_data(),(nx-2)*ny*nz*sizeof(float));
989 delete fft;
990 delete ift;
991 }
992 image->update();
993
994// image->update();
995}
996
998{
999 EMData *fft;
1000
1001 if (!image) throw InvalidParameterException("FFTConeProcessor: no image provided");
1002 if (!image->is_complex()) fft = image->do_fft();
1003 else fft = image;
1004
1005
1006 int nx=fft->get_xsize();
1007 int ny=fft->get_ysize();
1008 int nz=fft->get_zsize();
1009 if (nz==1) throw ImageDimensionException("FFTConeProcessor only works on 3-D images");
1010
1011 float angle = (float)params.set_default("angle",15.0f);
1012 float rmin = (float)params.set_default("rmin",1.0f);
1013
1014 for (int z=-nz/2; z<nz/2; z++) {
1015 for (int y=-ny/2; y<ny/2; y++) {
1016 for (int x=0; x<nx/2; x++) {
1017 float ang=0;
1018 if (x!=0 ||y!=0) ang=90.0-atan(fabs(float(z)/nz)/hypot(float(x)/nx,float(y)/ny))*180.0/M_PI;
1019 if (ang>angle || Util::hypot3(x,y,z)<rmin) continue;
1020 fft->set_complex_at(x,y,z,0.0f);
1021 }
1022 }
1023 }
1024
1025 if (fft!=image) {
1026 EMData *ift=fft->do_ift();
1027 memcpy(image->get_data(),ift->get_data(),(nx-2)*ny*nz*sizeof(float));
1028 delete fft;
1029 delete ift;
1030 }
1031 image->update();
1032
1033// image->update();
1034}
1035
1037{
1038 EMData *fft;
1039
1040 if (!image) throw InvalidParameterException("FFTWedgeProcessor: no image provided");
1041 if (!image->is_complex()) fft = image->do_fft();
1042 else fft = image;
1043
1044
1045 int nx=fft->get_xsize();
1046 int ny=fft->get_ysize();
1047 int nz=fft->get_zsize();
1048 if (nz==1) throw ImageDimensionException("FFTWedgeProcessor only works on 3-D images");
1049
1050 float anglemin = (float)params.set_default("anglemin",-30.0f);
1051 float anglemax = (float)params.set_default("anglemax",30.0f);
1052 float rmin = (float)params.set_default("rmin",1.0f);
1053
1054 for (int z=-nz/2; z<nz/2; z++) {
1055 for (int y=-ny/2; y<ny/2; y++) {
1056 for (int x=0; x<nx/2; x++) {
1057 float ang=90.0f;
1058 if (z!=0) ang=atan((float(y)/ny)/fabs(float(z)/nz))*180.0/M_PI;
1059 if (ang<anglemin||ang>anglemax || Util::hypot3(x,y,z)<rmin) continue;
1060 fft->set_complex_at(x,y,z,0.0f);
1061 }
1062 }
1063 }
1064
1065 if (fft!=image) {
1066 EMData *ift=fft->do_ift();
1067 memcpy(image->get_data(),ift->get_data(),(nx-2)*ny*nz*sizeof(float));
1068 delete fft;
1069 delete ift;
1070 }
1071 image->update();
1072
1073// image->update();
1074}
1075
1076
1078{
1079 if (!image) throw InvalidParameterException("WedgeFillProcessor: no image provided");
1080 if (!image->is_complex()) throw ImageFormatException("WedgeFillProcessor: target image must be complex");
1081
1082 EMData *source=(EMData *)params.set_default("fillsource",(EMData *)NULL);
1083// if (!source) throw InvalidParameterException("WedgeFillProcessor: fillsource required");
1084
1085 if (source && !source->is_complex()) throw ImageFormatException("WedgeFillProcessor: fillsource must be complex");
1086 if (image->get_xsize()!=source->get_xsize()||image->get_ysize()!=source->get_ysize()||image->get_zsize()!=source->get_zsize()) throw ImageFormatException("WedgeFillProcessor: image/fill size mismatch");
1087
1088 int nx=image->get_xsize();
1089 int ny=image->get_ysize();
1090 int nz=image->get_zsize();
1091 float thresh_sigma = (float)params.set_default("thresh_sigma", 0.5);
1092 bool dosigma = 1 ? thresh_sigma>0.0 : 0;
1093
1094 float maxtilt = (float)params.set_default("maxtilt", 90.0);
1095 bool dotilt = 1 ? maxtilt <90.0 : 0;
1096 maxtilt*=M_PI/180.0;
1097
1098 vector<float> sigmaimg;
1099 if (dosigma) {
1100 sigmaimg=image->calc_radial_dist(nx/2,0,1,4);
1101 for (int i=0; i<nx/2; i++) sigmaimg[i]*=sigmaimg[i]*thresh_sigma; // anything less than 1/10 sigma is considered to be missing
1102 }
1103
1104 vector<int> realpixel(nx/2);
1105 for (int i=0; i<nx/2; i++) realpixel[i]=0;
1106
1107 for (int z=0; z<nz; z++) {
1108 for (int y=0; y<ny; y++) {
1109 for (int x=0; x<nx; x+=2) {
1110 float r2=Util::hypot3(x/2,y<ny/2?y:ny-y,z<nz/2?z:nz-z); // origin at 0,0; periodic
1111 int r=int(r2);
1112 if (r<3) continue; // too few points at r<3 to consider any "missing"
1113
1114 float tilt = 0.0;
1115 if (dotilt) tilt=atan2((float)(z<nz/2?z:nz-z),(float)(x/2));
1116
1117 float v1r=image->get_value_at(x,y,z);
1118 float v1i=image->get_value_at(x+1,y,z);
1119 float v1=Util::square_sum(v1r,v1i);
1120// if (r<10) printf("%d %d %d %d\t%1.3g %1.3g\n",x,y,z,r,v1,sigmaimg[r]);
1121 if ((!dosigma || v1>sigmaimg[r]) && r<nx/2 && (!dotilt || fabs(tilt)<maxtilt)){
1122 realpixel[r]++;
1123 continue;
1124 }
1125
1126 if (!source) {
1127 image->set_value_at_fast(x,y,z,0);
1128 image->set_value_at_fast(x+1,y,z,0);
1129 }
1130 else {
1131 image->set_value_at_fast(x,y,z,source->get_value_at(x,y,z));
1132 image->set_value_at_fast(x+1,y,z,source->get_value_at(x+1,y,z));
1133 }
1134 }
1135 }
1136 }
1137
1138 image->set_attr("real_pixels", realpixel);
1139 image->update();
1140}
1141
1142
1143void LowpassAutoBProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const{
1144 float apix=(float)image->get_attr("apix_x");
1145 int verbose=(int)params["verbose"];
1146// int adaptnoise=params.set_default("adaptnoise",0);
1147 float noisecutoff=(float)params.set_default("noisecutoff",1.0/6.0);
1148 if (apix<=0 || apix>7.0f) throw ImageFormatException("apix_x > 7.0 or <0");
1149 float ds=1.0f/(apix*image->get_ysize()); // 0.5 is because radial mask is 2x oversampled
1150 unsigned int start=(int)floor(1.0/(15.0*ds));
1151 unsigned int end=radial_mask.size()-2;
1152 if (noisecutoff>0) end=(int)floor(noisecutoff/ds);
1153 if (end>radial_mask.size()-2) {
1154 if (verbose) printf("WARNING: specified noisecutoff too close to Nyquist, reset !");
1155 end=radial_mask.size()-2;
1156 }
1157 if (end<start+2) {
1158 printf("WARNING: noise cutoff too close to 15 A ! Results will not be good...");
1159 start=end-5;
1160 }
1161
1162 FILE *out=NULL;
1163 if (verbose>2) {
1164 printf("Autob -> %d - %d ds=%g apix=%g rdlmsk=%d\n",start,end,ds,apix,int(radial_mask.size()));
1165 out=fopen("fitplot.txt","w");
1166 }
1167 int N=(radial_mask.size()-start-2);
1168 float *x=(float *)malloc(N*sizeof(float));
1169 float *y=(float *)malloc(N*sizeof(float));
1170 float *dy=(float *)malloc(N*sizeof(float));
1171 for (unsigned int i=start; i<radial_mask.size()-2; i++ ) { // -2 is arbitrary because sometimes the last pixel or two have funny values
1172 x[i-start]=ds*ds*i*i;
1173 if (radial_mask[i]>0) y[i-start]=log(radial_mask[i]); // ok
1174 else if (i>start) y[i-start]=y[i-start-1]; // not good
1175 else y[i-start]=0.0; // bad
1176 if (i>start &&i<radial_mask.size()-3) dy[i-start]=y[i-start]-y[i-start-1]; // creates a 'derivative' of sorts, for use in adaptnoise
1177 if (out) fprintf(out,"%f\t%f\n",x[i-start],y[i-start]);
1178 }
1179 if (out) fclose(out);
1180
1181 float slope=0,intercept=0;
1182 Util::calc_least_square_fit(end-start, x,y,&slope,&intercept,1);
1183
1184 if (verbose) printf("slope=%f intercept=%f\n",slope,intercept);
1185
1186 float B=(float)params["bfactor"]+slope*4.0f/2.0f; // *4 is for Henderson definition, 2.0 is for intensity vs amplitude
1187 float B2=(float)params["bfactor"];
1188
1189 if (verbose) printf("User B = %1.2f Corrective B = %1.2f Total B=%1.3f\n",(float)params["bfactor"],slope*2.0,B);
1190
1191 float cutval=exp(-B*pow(end*ds,2.0f)/4.0f)/exp(-B2*pow(end*ds,2.0f)/4.0f);
1192 for (unsigned int i=0; i<radial_mask.size(); i++) {
1193 if (i<=end) radial_mask[i]=exp(-B*pow(i*ds,2.0f)/4.0f);
1194 else radial_mask[i]=cutval*exp(-B2*pow(i*ds,2.0f)/4.0f);
1195 }
1196 if (verbose>1) Util::save_data(0,ds,radial_mask,"filter.txt");
1197
1198 free(x);
1199 free(y);
1200 free(dy);
1201 }
1202
1204 size_t nxyz = image->get_size();
1205 int mode=params.set_default("wiener",0);
1206 float scale=params.set_default("scalesnr",2.0f);
1207
1208 for (size_t i=0; i<nxyz; i++) {
1209 float v=image->get_value_at_index(i);
1210 float snr=(v>=.9999)?10000.0f:scale*v/(1.0f-v);
1211 if (snr<0) snr=0.0f;
1212 if (mode) image->set_value_at_index(i,snr/(1.0f+snr));
1213 else image->set_value_at_index(i,snr);
1214 }
1215}
1216
1217
1219{
1220 int ys=image->get_ysize();
1221
1222 EMData *mask1=new EMData(ys,ys,1);
1223 mask1->process_inplace("mask.gaussian",Dict("outer_radius", ys/2.0));
1224 EMData *mask2=mask1->copy();
1225 mask2->mult(-1.0f);
1226 mask2->add(1.0);
1227 mask2->process_inplace("mask.decayedge2d",Dict("width",4));
1228
1229/*
1230
1231
1232
1233mask1=EMData(ys2,ys2,1)
1234 mask1.to_one()
1235 mask1.process_inplace("mask.gaussian",{"outer_radius":radius})
1236 mask2=mask1.copy()*-1+1
1237# mask1.process_inplace("mask.decayedge2d",{"width":4})
1238 mask2.process_inplace("mask.decayedge2d",{"width":4})
1239 mask1.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
1240 mask2.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
1241 ratio1=mask1.get_attr("square_sum")/(ys*ys) #/1.035
1242 ratio2=mask2.get_attr("square_sum")/(ys*ys)
1243 masks[(ys,radius)]=(mask1,ratio1,mask2,ratio2)
1244
1245
1246
1247*/
1248}
1249
1251{
1252 EMData *fft;
1253 float *fftd;
1254 int f=0;
1255// static float sum1=0,sum1a=0;
1256// static double sum2=0,sum2a=0;
1257
1258 if (!image) {
1259 LOGWARN("NULL Image");
1260 return;
1261 }
1262
1263 if (!image->is_complex()) fft = image->do_fft();
1264 else fft = image;
1265
1266 int neighbor=params.set_default("neighbor",0);
1267 float neighbornorm=params.set_default("neighbornorm",sqrt(2.0f));
1268
1269 int nx=fft->get_xsize()/2;
1270 int ny=fft->get_ysize();
1271 if (params.set_default("x",1)) {
1272 if (neighbor) {
1273 for (int x=1; x<nx; x++) fft->set_complex_at(x,0,(fft->get_complex_at(x,1)+fft->get_complex_at(x,-1))/neighbornorm); // sqrt is because the pixels are normally pretty noisy
1274 }
1275 else {
1276 for (int x=1; x<nx; x++) fft->set_complex_at(x,0,0.0f);
1277 }
1278 }
1279 if (params.set_default("y",1)) {
1280 if (neighbor) {
1281 for (int y=1; y<ny; y++) fft->set_complex_at(0,y,(fft->get_complex_at(-1,y)+fft->get_complex_at(1,y))/neighbornorm); // sqrt is because the pixels are normally pretty noisy
1282 }
1283 else {
1284 for (int y=1; y<ny; y++) fft->set_complex_at(0,y,0.0f);
1285 }
1286 }
1287
1288 if (fft!=image) {
1289// fft->update();
1290 EMData *ift=fft->do_ift();
1291 memcpy(image->get_data(),ift->get_data(),(nx*2-2)*ny*sizeof(float));
1292 delete fft;
1293 delete ift;
1294 }
1295
1296// image->update();
1297
1298}
1299
1301{
1302 if(params.has_key("apix")) {
1303 image->set_attr("apix_x", (float)params["apix"]);
1304 image->set_attr("apix_y", (float)params["apix"]);
1305 image->set_attr("apix_z", (float)params["apix"]);
1306 }
1307
1308 int xynoz = params.set_default("xynoz",0);
1309
1310 const Dict dict = image->get_attr_dict();
1311 if( params.has_key("cutoff_freq") ) {
1312 float val = (float)params["cutoff_freq"] * (float)dict["apix_x"];
1313 params["cutoff_abs"] = val;
1314 }
1315 else if( params.has_key("cutoff_pixels") ) {
1316 float val = ((float)params["cutoff_pixels"] / (float)dict["nx"]);
1317 params["cutoff_abs"] = val;
1318 }
1319
1320 float omega = params["cutoff_abs"];
1321 float zcenter=params.set_default("centerfreq",0.0f);
1322 float hppix = params.set_default("hppix",-1.0f);
1323
1324 omega = (omega<0?-1.0:1.0)*0.5f/omega/omega;
1325
1326 EMData *fft;
1327 int f=0;
1328
1329 if (!image) {
1330 LOGWARN("NULL Image");
1331 return;
1332 }
1333
1334 if (!image->is_complex()) {
1335 fft = image->do_fft();
1336 f=1;
1337 }
1338 else {
1339 fft=image;
1340 }
1341
1342 int nx=fft->get_xsize();
1343 int ny=fft->get_ysize();
1344 int nz=fft->get_ysize();
1345 omega /=(nz*nz)/4;
1346 zcenter=zcenter*(float)dict["apix_x"]*nz;
1347
1348 if (xynoz) {
1349 for (int x=0; x<nx/2; x++) {
1350 for (int z=(x==0?0:-nz/2); z<nz/2; z++) {
1351 for (int y=(x==0&&z==0?0:-ny/2); y<ny/2; y++) {
1352 std::complex <float> v=fft->get_complex_at(x,y,z);
1353 float r=Util::hypot_fast(x,y);
1354 fft->set_complex_at(x,y,z,v*exp(-omega*(r-zcenter)*(r-zcenter))*(r>hppix?1.0f:Util::hypot3(x,y,z)/hppix));
1355 }
1356 }
1357 }
1358 }
1359 else {
1360 for (int z=-nz/2; z<nz/2; z++) {
1361 for (int y=-ny/2; y<ny/2; y++) {
1362 for (int x=0; x<nx/2; x++) {
1363 std::complex <float> v=fft->get_complex_at(x,y,z);
1364 fft->set_complex_at(x,y,z,v*exp(-omega*(abs(z)-zcenter)*(abs(z)-zcenter))*(fabs(z)>hppix?1.0f:Util::hypot3(x,y,z)/hppix));
1365 }
1366 }
1367 }
1368 }
1369
1370 if (f) {
1371 EMData *ift=fft->do_ift();
1372 memcpy(image->get_data(),ift->get_data(),(nx-2)*ny*nz*sizeof(float));
1373 delete fft;
1374 delete ift;
1375 }
1376
1377}
1378
1379
1381{
1382 EMData *fft;
1383 float *fftd;
1384 int f=0;
1385// static float sum1=0,sum1a=0;
1386// static double sum2=0,sum2a=0;
1387
1388 if (!image) {
1389 LOGWARN("NULL Image");
1390 return;
1391 }
1392
1393 if (!image->is_complex()) {
1394 fft = image->do_fft();
1395 fftd = fft->get_data();
1396 f=1;
1397 }
1398 else {
1399 fft=image;
1400 fftd=image->get_data();
1401 }
1402 float *sumd = NULL;
1403 if (sum) sumd=sum->get_data();
1404//printf("%d %d %d %d\n",fft->get_xsize(),fft->get_ysize(),sum->get_xsize(),sum->get_ysize());
1405 size_t n = (size_t)fft->get_xsize()*fft->get_ysize()*fft->get_zsize();
1406 for (size_t i=0; i<n; i+=2) {
1407 float c;
1408 if (dosqrt) c=pow(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1],0.25f);
1409 else c = static_cast<float>(hypot(fftd[i],fftd[i+1]));
1410 if (c==0) c=1.0e-30f; // prevents divide by zero in normalization
1411 fftd[i]*=c;
1412 fftd[i+1]*=c;
1413 if (sumd) { sumd[i]+=c; sumd[i+1]+=0; }
1414
1415 // debugging
1416/* if (i==290*1+12) {
1417 sum1+=fftd[i];
1418 sum2+=fftd[i];
1419 printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1,sum2,fftd[i],fftd[i+1],sumd[i],c);
1420 }
1421 if (i==290*50+60) {
1422 sum1a+=fftd[i];
1423 sum2a+=fftd[i];
1424 printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1a,sum2a,fftd[i],fftd[i+1],sumd[i],c);
1425 }*/
1426 }
1427
1428 if (f) {
1429 fft->update();
1430 EMData *ift=fft->do_ift();
1431 memcpy(image->get_data(),ift->get_data(),n*sizeof(float));
1432 delete fft;
1433 delete ift;
1434 }
1435
1436 sum->update();
1437 image->update();
1438
1439}
1440
1442{
1443 printf("Process inplace not implemented. Please use process.\n");
1444 return;
1445}
1446
1447
1449{
1450
1451 float minratio = params.set_default("minratio",0.5f);
1452 int maxnseg = params.set_default("maxnseg",0);
1453 int skipseg = params.set_default("skipseg",0);
1454 float width = params.set_default("width",10.0f);
1455 int verbose = params.set_default("verbose",0);
1456 EMData *mask= (EMData *)params.set_default("mask",(EMData *)NULL);
1457 float apix=image->get_attr("apix_x");
1458 int nx=image->get_xsize();
1459 int ny=image->get_ysize();
1460 int nz=image->get_zsize();
1461
1462 EMData * result = image->process("threshold.belowtozero",Dict("minval",0.0f));
1463 // The intent of these filters is to insure that the map effectively
1464// result->process_inplace("filter.lowpass.gauss",Dict("cutoff_freq",0.45/width)); // 0.45 = sqrt(2)/pi, resolvability threshold
1465// result->process_inplace("filter.lowpass.gauss",Dict("cutoff_freq",0.637/width)); // 0.637 = 2/pi, (may be Rayleigh criterion?)
1466 if (mask!=NULL) {
1467 result->mult(*mask);
1468 result->process_inplace("normalize.local",Dict("radius",nx*apix/(3.0f*width),"threshold",(float)result->get_attr("sigma_nonzero")*1.2));
1469 }
1470
1471 XYData gsf;
1472 gsf.make_gauss(nx*4,1.0f/apix,0.45/width);
1473// gsf.make_gauss(nx*4,1.0f/apix,0.637/width);
1474 result->process_inplace("filter.setstrucfac",Dict("apix",apix,"strucfac",&gsf));
1475
1476 // Generate a Gaussian we can subtract out of the volume quickly
1477 int gs=2*width/(float)image->get_attr("apix_x");
1478 EMData gsub(gs,gs,gs);
1479 gsub.to_one();
1480 gsub.process_inplace("mask.gaussian",Dict("outer_radius",int(width/(2.0*apix))));
1481
1482 if (verbose>2) {
1483 result->set_attr("render_bits",12);
1484 result->set_attr("render_min",(float)result->get_attr("minimum"));
1485 result->set_attr("render_max",(float)result->get_attr("maximum"));
1486 result->write_image("segfilt.hdf",0,EMUtil::IMAGE_UNKNOWN,false,0,EMUtil::EM_COMPRESSED);
1487 }
1488
1489 EMData *cache = NULL;
1490 if (skipseg==2) cache=result->copy();
1491
1492 // original version of the code. A bit slow but works very well
1493// vector<float> centers;
1494// vector<float> amps;
1495// if (maxnseg==0) maxnseg=2000000000;
1496// float maxval=0.0f;
1497//
1498// while (amps.size()<maxnseg) {
1499// IntPoint p = result->calc_max_location();
1500// FloatPoint fp(p[0],p[1],p[2]);
1501//
1502// float amp=result->get_value_at(p[0],p[1],p[2]);
1503// if (amp<maxval*minratio) break;
1504// amps.push_back(amp);
1505// centers.push_back(p[0]);
1506// centers.push_back(p[1]);
1507// centers.push_back(p[2]);
1508// if (amp>maxval) maxval=amp; // really this should only happen once...
1509//
1510// result->insert_scaled_sum(&gsub,fp,1.0,-amp);
1511// }
1512
1513 // This was an alternate version, to improve speed. While it is faster, the approximations its making
1514 // produce slightly less optimal results.
1515 vector<float> centers;
1516 vector<float> amps;
1517 if (maxnseg==0) maxnseg=2000000000;
1518
1519 float thr=(float)result->get_attr("maximum")*minratio;
1520 while (amps.size()<maxnseg) {
1521 if ((float)result->get_attr("maximum")<=thr) break;
1522 // We find all peak values greater than our threshold
1523 vector<Pixel> pixels=result->calc_highest_locations(thr);
1524 if (pixels.size()==0) break;
1525 if (verbose>1) printf("%d %f %f %f %d\n",pixels.size(),pixels[0].get_value(),pixels[1].get_value(),pixels[2].get_value(),amps.size());
1526
1527 for (int i=0; i<pixels.size(); i++) {
1528 IntPoint p = pixels[i].get_point();
1529 FloatPoint fp(p[0],p[1],p[2]);
1530
1531 float amp=result->get_value_at(p[0],p[1],p[2]);
1532 if (amp!=pixels[i].get_value()) continue; // skip any values near a value we've just changed, should come back in the next round
1533 // printf("%d %d %d %f %f %f\n",p[0],p[1],p[2],amp,pixels[i].get_value(),pixels[i+1].get_value());
1534// if (i<pixels.size()-1 && amp<pixels[i+1].get_value()) continue; // if one of the identified peaks has been reduced by a nearby peak too much
1535 if (amp<thr) continue;
1536// if (amp<thr) { maxnseg=amps.size(); break; }
1537 amps.push_back(amp);
1538 centers.push_back(p[0]);
1539 centers.push_back(p[1]);
1540 centers.push_back(p[2]);
1541
1542 result->insert_scaled_sum(&gsub,fp,1.0,-amp);
1543 }
1544 }
1545
1546 if (verbose) printf("Found %d centers\n",amps.size());
1547
1548 if (verbose>2) {
1549 result->set_attr("render_bits",12);
1550 result->set_attr("render_min",(float)result->get_attr("minimum"));
1551 result->set_attr("render_max",(float)result->get_attr("maximum"));
1552 result->write_image("segfilt.hdf",1,EMUtil::IMAGE_UNKNOWN,false,0,EMUtil::EM_COMPRESSED);
1553 }
1554 if (!skipseg) {
1555 // after we have our list of centers classify pixels
1556 for (int z=0; z<nz; z++) {
1557 for (int y=0; y<ny; y++) {
1558 for (int x=0; x<nz; x++) {
1559// if (image->get_value_at(x,y,z)<thr) {
1560// result->set_value_at(x,y,z,-1.0); //below threshold -> -1 (unclassified)
1561// continue;
1562// }
1563 int bcls=-1; // best matching class
1564 float bdist=(float)(nx+ny+nz); // distance for best class
1565 for (unsigned int c=0; c<centers.size()/3; c++) {
1566 float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
1567 if (d<bdist) { bdist=d; bcls=c; }
1568 }
1569 result->set_value_at(x,y,z,(float)bcls); // set the pixel to the class number
1570 }
1571 }
1572 }
1573 if (verbose) printf("segmented\n");
1574 }
1575
1576 //if skipseg is set to 2, we return the filtered, unsegmented map (with valid centers)
1577 if (skipseg==2) {
1578 delete result;
1579 result=cache;
1580 }
1581
1582 result->set_attr("segment_centers",centers);
1583 result->set_attr("segment_amps",amps);
1584
1585 return result;
1586}
1587
1589{
1590 printf("Process inplace not implemented. Please use process.\n");
1591 return;
1592}
1593
1594
1596{
1597 EMData * result = image->copy();
1598
1599 float thr = params.set_default("thr",0.9f);
1600 float minsegsep = params.set_default("minsegsep",5.0f);
1601 float maxsegsep = params.set_default("maxsegsep",5.1f);
1602 int verbose = params.set_default("verbose",0);
1603
1604 vector<Pixel> pixels=image->calc_highest_locations(thr);
1605
1606 vector<float> centers(3); // only 1 to start
1607 int nx=image->get_xsize();
1608 int ny=image->get_ysize();
1609 int nz=image->get_zsize();
1610// int nxy=nx*ny;
1611
1612 // seed the process with the highest valued point
1613 centers[0]=(float)pixels[0].x;
1614 centers[1]=(float)pixels[0].y;
1615 centers[2]=(float)pixels[0].z;
1616 pixels.erase(pixels.begin());
1617
1618 // outer loop. We add one center per iteration
1619 // This is NOT a very efficient algorithm, it assumes points are fairly sparse
1620 while (pixels.size()>0) {
1621 // iterate over pixels until we find a new center (then stop), delete any 'bad' pixels
1622 // no iterators because we remove elements
1623
1624 for (unsigned int i=0; i<pixels.size(); i++) {
1625
1626 Pixel p=pixels[i];
1627 // iterate over existing centers to see if this pixel should be removed ... technically we only should need to check the last center
1628 for (unsigned int j=0; j<centers.size(); j+=3) {
1629 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
1630 if (d<minsegsep) { // conflicts with existing center, erase
1631 pixels.erase(pixels.begin()+i);
1632 i--;
1633 break;
1634 }
1635 }
1636 }
1637
1638 int found=0;
1639 for (unsigned int i=0; i<pixels.size() && found==0; i++) {
1640 Pixel p=pixels[i];
1641
1642 // iterate again to see if this may be a new valid center. Start at the end so we tend to build chains
1643 for (unsigned int j=centers.size()-3; j>0; j-=3) {
1644 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
1645 if (d<maxsegsep) { // we passed minsegsep question already, so we know we're in the 'good' range
1646 centers.push_back((float)p.x);
1647 centers.push_back((float)p.y);
1648 centers.push_back((float)p.z);
1649 pixels.erase(pixels.begin()+i); // in the centers list now, don't need it any more
1650 found=1;
1651 break;
1652 }
1653 }
1654 }
1655
1656 // If we went through the whole list and didn't find one, we need to reseed again
1657 if (!found && pixels.size()) {
1658 if (verbose) printf("New chain\n");
1659 centers.push_back((float)pixels[0].x);
1660 centers.push_back((float)pixels[0].y);
1661 centers.push_back((float)pixels[0].z);
1662 pixels.erase(pixels.begin());
1663 }
1664
1665 if (verbose) printf("%d points found\n",(int)(centers.size()/3));
1666 }
1667
1668 // after we have our list of centers classify pixels
1669 for (int z=0; z<nz; z++) {
1670 for (int y=0; y<ny; y++) {
1671 for (int x=0; x<nz; x++) {
1672 if (image->get_value_at(x,y,z)<thr) {
1673 result->set_value_at(x,y,z,-1.0); //below threshold -> -1 (unclassified)
1674 continue;
1675 }
1676 int bcls=-1; // best matching class
1677 float bdist=(float)(nx+ny+nz); // distance for best class
1678 for (unsigned int c=0; c<centers.size()/3; c++) {
1679 float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
1680 if (d<bdist) { bdist=d; bcls=c; }
1681 }
1682 result->set_value_at(x,y,z,(float)bcls); // set the pixel to the class number
1683 }
1684 }
1685 }
1686
1687 result->set_attr("segment_centers",centers);
1688
1689 return result;
1690}
1691
1693{
1694 string s=(string)params.set_default("sym","c1");
1695 if (s.length()<2) return image->copy();
1696 int n=atoi(s.c_str()+1);
1697 if ((s[0]=='c' || s[0]=='C') && n==1) return image->copy();
1698
1699 Averager* imgavg = Factory<Averager>::get((string)params.set_default("averager","mean"));
1700
1701 if (image->get_zsize()==1) {
1702 if (s[0]!='c' && s[0]!='C') throw ImageDimensionException("xform.applysym: Cn symmetry required for 2-D symmetrization");
1703 if (n<=0) throw InvalidValueException(n,"xform.applysym: Cn symmetry, n>0");
1704
1705 for (int i=0; i<n; i++) {
1706 Transform t(Dict("type","2d","alpha",(float)(i*360.0f/n)));
1707 EMData* transformed = image->process("xform",Dict("transform",&t));
1708 imgavg->add_image(transformed);
1709 delete transformed;
1710 }
1711 EMData *ret=imgavg->finish();
1712 delete imgavg;
1713 return ret;
1714 }
1715
1716 Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1"));
1717 vector<Transform> transforms = sym->get_syms();
1718
1719 for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
1720 Transform t = *trans_it;
1721 EMData* transformed = image->process("xform",Dict("transform",&t));
1722 imgavg->add_image(transformed);
1723 delete transformed;
1724 }
1725 EMData *ret=imgavg->finish();
1726 delete imgavg;
1727 return ret;
1728}
1729
1731{
1732 EMData *tmp=process(image);
1733 memcpy(image->get_data(),tmp->get_data(),(size_t)image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
1734 delete tmp;
1735 image->update();
1736 return;
1737}
1738
1740{
1741 EMData * result = image->copy();
1742
1743 int nseg = params.set_default("nseg",12);
1744 float thr = params.set_default("thr",-1.0e30f);
1745 int ampweight = params.set_default("ampweight",1);
1746 float maxsegsize = params.set_default("maxsegsize",10000.0f);
1747 float minsegsep = params.set_default("minsegsep",0.0f);
1748 int maxiter = params.set_default("maxiter",100);
1749 int maxvoxmove = params.set_default("maxvoxmove",25);
1750 int verbose = params.set_default("verbose",0);
1751 bool pseudoatom = params.set_default("pseudoatom",0);
1752 float sep = params.set_default("sep",3.78f);
1753
1754 int nx=image->get_xsize();
1755 int ny=image->get_ysize();
1756 int nz=image->get_zsize();
1757// int nxy=nx*ny;
1758// image->process_inplace("threshold.belowtozero");
1759 if (thr==-1.0e30f){
1760 thr=float(image->get_attr("mean_nonzero"))+ 1.0 *float(image->get_attr("sigma_nonzero"));
1761 printf("Estimated map threshold: %4f\n", thr);
1762 }
1763 // seed
1764 vector<float> centers(nseg*3);
1765 vector<float> count(nseg);
1766 // Alternative seeding method for paudoatom generation. Seed on the gird.
1767 if (pseudoatom){
1768 float ax=image->get_attr("apix_x");
1769 sep/=ax;
1770 if (verbose) printf("Seeding .....\n");
1771 int sx=int(nx/sep)+1,sy=int(ny/sep)+1,sz=int(nz/sep)+1;
1772 EMData m(sx,sy,sz);
1773 EMData mcount(sx,sy,sz);
1774 for (int i=0; i<nx; i++){
1775 for (int j=0; j<ny; j++){
1776 for (int k=0; k<nz; k++){
1777 int ni=(i/sep),nj=(j/sep),nk=(k/sep);
1778 float v=image->get_value_at(i,j,k);
1779 if (v>thr){
1780 m.set_value_at(ni,nj,nk,(m.get_value_at(ni,nj,nk)+v));
1781 mcount.set_value_at(ni,nj,nk,(mcount.get_value_at(ni,nj,nk)+1));
1782 }
1783 }
1784 }
1785 }
1786 m.div((nx/sx)*(ny/sy)*(nz/sz));
1787 int nsum=0;
1788 float l=image->get_attr("minimum"),r=image->get_attr("maximum"),th=0;
1789 while (abs(nsum-nseg)>0){
1790 th=(l+r)/2;
1791 nsum=0;
1792 for (int i=0; i<sx; i++){
1793 for (int j=0; j<sy; j++){
1794 for (int k=0; k<sz; k++){
1795 if (m.get_value_at(i,j,k)>th) nsum+=1;
1796 }
1797 }
1798 }
1799// if (verbose) printf("%3f\t %3f\t %3f,\t %4d\t %4d\n", l,th,r,nsum,nseg);
1800 if (nsum>nseg) l=th;
1801 if (nsum<nseg) r=th;
1802 if ((r-l)<.0001)break;
1803 }
1804// nseg=nsum;
1805 if (verbose) printf("%3d pseudoatoms seeded at threshold value %3f\n", nsum, th);
1806 int q=0;
1807 for (int i=0; i<sx; i++){
1808 for (int j=0; j<sy; j++){
1809 for (int k=0; k<sz; k++){
1810 if (m.get_value_at(i,j,k)>th){
1811 if(q<nseg*3){
1812 centers[q]= float(i+.5)*sep;
1813 centers[q+1]=float(j+.5)*sep;
1814 centers[q+2]=float(k+.5)*sep;
1815 q+=3;
1816 }
1817 }
1818 }
1819 }
1820 }
1821
1822 }
1823 // Default: random seeding.
1824 else{
1825 for (int i=0; i<nseg*3; i+=3) {
1826 centers[i]= Util::get_frand(0.0f,(float)nx);
1827 centers[i+1]=Util::get_frand(0.0f,(float)ny);
1828 centers[i+2]=Util::get_frand(0.0f,(float)nz);
1829 }
1830 }
1831
1832 for (int iter=0; iter<maxiter; iter++) {
1833 // **** classify
1834 size_t pixmov=0; // count of moved pixels
1835 for (int z=0; z<nz; z++) {
1836 for (int y=0; y<ny; y++) {
1837 for (int x=0; x<nx; x++) {
1838 if (image->get_value_at(x,y,z)<thr) {
1839 result->set_value_at(x,y,z,-1.0); //below threshold -> -1 (unclassified)
1840 continue;
1841 }
1842 int bcls=-1; // best matching class
1843 float bdist=(float)(nx+ny+nz); // distance for best class
1844 for (int c=0; c<nseg; c++) {
1845 float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
1846 if (d<bdist) { bdist=d; bcls=c; }
1847 }
1848 if ((int)result->get_value_at(x,y,z)!=bcls) pixmov++;
1849 if (bdist>maxsegsize) result->set_value_at(x,y,z,-1); // pixel is too far from any center
1850 else result->set_value_at(x,y,z,(float)bcls); // set the pixel to the class number
1851 }
1852 }
1853 }
1854
1855 // **** adjust centers
1856 for (int i=0; i<nseg*3; i++) centers[i]=0;
1857 for (int i=0; i<nseg; i++) count[i]=0;
1858 // weighted sums
1859 for (int z=0; z<nz; z++) {
1860 for (int y=0; y<ny; y++) {
1861 for (int x=0; x<nx; x++) {
1862 int cls = (int)result->get_value_at(x,y,z);
1863 if (cls==-1) continue;
1864 float w=1.0;
1865 if (ampweight) w=image->get_value_at(x,y,z);
1866
1867 centers[cls*3]+=x*w;
1868 centers[cls*3+1]+=y*w;
1869 centers[cls*3+2]+=z*w;
1870 count[cls]+=w;
1871 }
1872 }
1873 }
1874 // now each becomes center of mass, or gets randomly reseeded
1875 int nreseed=0;
1876 for (int c=0; c<nseg; c++) {
1877 // reseed
1878 if (count[c]==0) {
1879 nreseed++;
1880 do {
1881 centers[c*3]= Util::get_frand(0.0f,(float)nx);
1882 centers[c*3+1]=Util::get_frand(0.0f,(float)ny);
1883 centers[c*3+2]=Util::get_frand(0.0f,(float)nz);
1884 } 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
1885 }
1886 // center of mass
1887 else {
1888 centers[c*3]/=count[c];
1889 centers[c*3+1]/=count[c];
1890 centers[c*3+2]/=count[c];
1891 }
1892 }
1893
1894 // with minsegsep, check separation
1895 if (minsegsep>0) {
1896 for (int c1=0; c1<nseg-1; c1++) {
1897 for (int c2=c1+1; c2<nseg; c2++) {
1898 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) {
1899 nreseed++;
1900 do {
1901 centers[c1*3]= Util::get_frand(0.0f,(float)nx);
1902 centers[c1*3+1]=Util::get_frand(0.0f,(float)ny);
1903 centers[c1*3+2]=Util::get_frand(0.0f,(float)nz);
1904 } while (image->get_value_at((int)centers[c1*3],(int)centers[c1*3+1],(int)centers[c1*3+2])<thr);
1905 }
1906 }
1907 }
1908 }
1909
1910
1911 if (verbose) printf("Iteration %3d: %6ld voxels moved, %3d classes reseeded\n",iter,pixmov,nreseed);
1912 if (nreseed==0 && pixmov<(size_t)maxvoxmove) break; // termination conditions met
1913 }
1914
1915 result->set_attr("segment_centers",centers);
1916
1917 return result;
1918}
1919
1921{
1922 printf("Process inplace not implemented. Please use process.\n");
1923 return;
1924}
1925
1926
1928
1929// if (image->get_zsize()!=1) { throw ImageDimensionException("Only 2-D images supported"); }
1930
1931 int nx=image->get_xsize();
1932 int ny=image->get_ysize();
1933 int nz=image->get_zsize();
1934 float x0 = params.set_default("x0",nx/2);
1935 float y0 = params.set_default("y0",ny/2);
1936 float z0 = params.set_default("z0",nz/2);
1937 float xwidth = params.set_default("xwidth",nx);
1938 float ywidth = params.set_default("ywidth",ny);
1939 float zwidth = params.set_default("zwidth",nz);
1940
1941 for (int z=0; z<nz; z++) {
1942 for (int y=0; y<ny; y++) {
1943 for (int x=0; x<nx; x++) {
1944 float xf=1.0-fabs(x-x0)*2.0/xwidth;
1945 float yf=1.0-fabs(y-y0)*2.0/ywidth;
1946 float zf=1.0-fabs(z-z0)*2.0/zwidth;
1947 float val=0.0;
1948 if (xf>0&&yf>0&&zf>0) val=xf*yf*zf;
1949 image->mult_value_at_fast(x,y,z,val);
1950 }
1951 }
1952 }
1953}
1954
1956{
1957// TODO NOT IMPLEMENTED YET !!!
1958 EMData *ret = 0;
1959 const EMData *fft;
1960// float *fftd;
1961// int f=0;
1962
1963 if (!image) {
1964 LOGWARN("NULL Image");
1965 return ret;
1966 }
1967 throw NullPointerException("Processor not yet implemented");
1968
1969// if (!image->is_complex()) {
1970// fft = image->do_fft();
1971// fftd = fft->get_data();
1972// f=1;
1973// }
1974// else {
1975// fft=image;
1976// fftd=image->get_data();
1977// }
1978
1979 return ret;
1980}
1981
1983 EMData *tmp=process(image);
1984 memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
1985 delete tmp;
1986 image->update();
1987 return;
1988}
1989
1990
1992{
1993 const EMData *in2 = 0;
1994 if (in->is_complex()) in2=in;
1995 else in=in->do_fft();
1996
1997 EMData *filt = in->copy_head();
1998 Ctf *ictf = ctf;
1999
2000 if (!ictf) ctf=(Ctf *)in->get_attr("ctf");
2001
2003 filt->mult(*in2);
2004 EMData *ret=filt->do_ift();
2005
2006 delete filt;
2007 if (!in->is_complex()) delete in2;
2008
2009 if(!ictf && ctf) {delete ctf; ctf=0;}
2010 return(ret);
2011/* const EMData *fft;
2012 float *fftd;
2013 int f=0;
2014
2015 if (!image) {
2016 LOGWARN("NULL Image");
2017 return ret;
2018 }
2019
2020 if (!image->is_complex()) {
2021 fft = image->do_fft();
2022 fftd = fft->get_data();
2023 f=1;
2024 }
2025 else {
2026 fft=image;
2027 fftd=image->get_data();
2028 }
2029 powd=image->get_data();
2030
2031 int bad=0;
2032 for (int i=0; i<image->get_xsize()*image->get_ysize(); i+=2) {
2033 snr=(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1]-powd[i])/powd[i];
2034 if (snr<0) { bad++; snr=0; }
2035
2036 }
2037
2038 print("%d bad pixels\n",snr);
2039*/ return ret;
2040
2041}
2042
2044 EMData *tmp=process(image);
2045 memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
2046 delete tmp;
2047 image->update();
2048 return;
2049}
2050
2051void LinearRampFourierProcessor::create_radial_func(vector < float >&radial_mask) const
2052{
2053 Assert(radial_mask.size() > 0);
2054 for (size_t i = 0; i < radial_mask.size(); i++) {
2055 radial_mask[i] = (float)i;
2056 }
2057}
2058
2059void LowpassRandomPhaseProcessor::create_radial_func(vector < float >&radial_mask) const { };
2060
2062{
2063 float cutoff=0;
2064 preprocess(image);
2065 if( params.has_key("cutoff_abs") ) {
2066 cutoff=(float)params["cutoff_abs"];
2067 }
2068 else {
2069 printf("A cutoff_* parameter is required by filter.lowpass.randomphase\n");
2070 return;
2071 }
2072
2073
2074 if (image->get_zsize()==1) {
2075 int flag=0;
2076 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
2077 image->ri2ap();
2078 int nx=image->get_xsize();
2079 int ny=image->get_ysize();
2080
2081 int z=0;
2082 float *data=image->get_data();
2083 for (int y=-ny/2; y<ny/2; y++) {
2084 for (int x=0; x<nx/2+1; x++) {
2085 if (hypot(x/float(nx),y/float(ny))>=cutoff) {
2086 size_t idx=image->get_complex_index_fast(x,y,z); // location of the amplitude
2087 data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
2088 }
2089 }
2090 }
2091
2092 image->ap2ri();
2093
2094 if (flag) {
2095 image->do_ift_inplace();
2096 image->depad();
2097 }
2098 }
2099 else { // 3D
2100 int flag=0;
2101 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
2102 image->ri2ap();
2103 int nx=image->get_xsize();
2104 int ny=image->get_ysize();
2105 int nz=image->get_zsize();
2106
2107 float *data=image->get_data();
2108 for (int z=-nz/2; z<nz/2; z++) {
2109 for (int y=-ny/2; y<ny/2; y++) {
2110 for (int x=0; x<nx/2; x++) {
2111 if (Util::hypot3(x/float(nx),y/float(ny),z/float(nz))>=cutoff) {
2112 size_t idx=image->get_complex_index_fast(x,y,z); // location of the amplitude
2113 data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
2114 }
2115 }
2116 }
2117 }
2118 image->ap2ri();
2119
2120 if (flag) {
2121 image->do_ift_inplace();
2122 image->depad();
2123 }
2124 }
2125}
2126
2128{
2129 if(params.has_key("apix")) {
2130 image->set_attr("apix_x", (float)params["apix"]);
2131 image->set_attr("apix_y", (float)params["apix"]);
2132 image->set_attr("apix_z", (float)params["apix"]);
2133 }
2134
2135 const Dict dict = image->get_attr_dict();
2136
2137 if( params.has_key("cutoff_abs") ) {
2138 highpass = params["cutoff_abs"];
2139 }
2140 else if( params.has_key("cutoff_freq") ) {
2141 highpass = (float)params["cutoff_freq"] * (float)dict["apix_x"] * (float)dict["ny"] / 2.0f;
2142 }
2143 else if( params.has_key("cutoff_pixels") ) {
2144 highpass = (float)params["cutoff_pixels"] / (float)dict["nx"];
2145 }
2146}
2147
2148void HighpassAutoPeakProcessor::create_radial_func(vector < float >&radial_mask, EMData *) const
2149{
2150 unsigned int c;
2151
2152// for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
2153 for (c=2; c<radial_mask.size(); c++) if (radial_mask[c-1]<=radial_mask[c]) break;
2154 if (c>highpass) c=(unsigned int)highpass; // the *2 is for the 2x oversampling
2155
2156 radial_mask[0]=0.0;
2157// for (int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?radial_mask[c+1]/radial_mask[i]:1.0);
2158 for (unsigned int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?0.0f:1.0f);
2159
2160 printf("%f %d\n",highpass,c);
2161// for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
2162
2163}
2164
2165void LinearRampProcessor::create_radial_func(vector < float >&radial_mask) const
2166{
2167 Assert(radial_mask.size() > 0);
2168 float x = 0.0f , step = 0.5f/radial_mask.size();
2169 size_t size=radial_mask.size();
2170 for (size_t i = 0; i < size; i++) {
2171 radial_mask[i] = intercept + ((slope - intercept) * i) / (size - 1.0f);
2172 x += step;
2173 }
2174}
2175
2176void LoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
2177{
2178
2179 Assert(radial_mask.size() > 0);
2180 float x = 0.0f , nqstep = 0.5f/radial_mask.size();
2181 size_t size=radial_mask.size();
2182 float var = sigma*sigma;
2183 for (size_t i = 0; i < size; i++) {
2184 radial_mask[i] = ((x*x - var)/var*var)*exp(-x*x/2*var);
2185 x += nqstep;
2186 }
2187}
2188
2189void DoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
2190{
2191
2192 Assert(radial_mask.size() > 0);
2193 float x = 0.0f , nqstep = 0.5f/radial_mask.size();
2194 size_t size=radial_mask.size();
2195 float norm = 1.0f/sqrt(2*M_PI);
2196 for (size_t i = 0; i < size; i++) {
2197 radial_mask[i] = norm*((1.0f/sigma1*exp(-x*x/(2.0f*sigma1*sigma1))) - (1.0f/sigma2*exp(-x*x/(2.0f*sigma2*sigma2))));
2198 x += nqstep;
2199 }
2200}
2201
2203{
2204 if (!image) {
2205 LOGWARN("NULL Image");
2206 return;
2207 }
2208
2209 float gauss_width = params.set_default("gauss_width",0.0f);
2210
2211 if (gauss_width<=0) {
2212 size_t size = (size_t)image->get_xsize() *
2213 (size_t)image->get_ysize() *
2214 (size_t)image->get_zsize();
2215 float *data = image->get_data();
2216
2217 for (size_t i = 0; i < size; ++i) {
2218 if (data[i]>=minval && data[i]<=maxval) data[i]=0.0f;
2219 }
2220 image->update();
2221 }
2222 else {
2223 int nx = image->get_xsize();
2224 int ny = image->get_ysize();
2225 int nz = image->get_zsize();
2226 float wid=gauss_width/(ny*ny);
2227
2228 for (int z=0; z<nz; z++) {
2229 for (int y=0; y<ny; y++) {
2230 for (int x=0; x<nx; x++) {
2231 float cor=exp(-Util::hypot3sq(x-nx/2,y-ny/2,z-nz/2)*wid);
2232 if (image->get_value_at(x,y,z)>=minval*cor && image->get_value_at(x,y,z)<=maxval*cor) image->set_value_at(x,y,z,0.0f);
2233 }
2234 }
2235 }
2236 image->update();
2237 }
2238
2239}
2240
2241
2242
2244{
2245 if (!image) {
2246 LOGWARN("NULL Image");
2247 return;
2248 }
2249
2250 maxval = image->get_attr("maximum");
2251 mean = image->get_attr("mean");
2252 sigma = image->get_attr("sigma");
2253
2254 calc_locals(image);
2255
2256 size_t size = (size_t)image->get_xsize() *
2257 (size_t)image->get_ysize() *
2258 (size_t)image->get_zsize();
2259 float *data = image->get_data();
2260
2261 for (size_t i = 0; i < size; ++i) {
2262 process_pixel(&data[i]);
2263 }
2264 image->update();
2265}
2266
2267
2269{
2270 if (!image) {
2271 LOGWARN("NULL Image");
2272 return;
2273 }
2274
2275 maxval = image->get_attr("maximum");
2276 mean = image->get_attr("mean");
2277 sigma = image->get_attr("sigma");
2278 nx = image->get_xsize();
2279 ny = image->get_ysize();
2280 nz = image->get_zsize();
2281 is_complex = image->is_complex();
2282
2283 calc_locals(image);
2284
2285
2286 if (!is_valid()) {
2287 return;
2288 }
2289
2290 float *data = image->get_data();
2291 size_t i = 0;
2292
2293 for (int z = 0; z < nz; z++) {
2294 for (int y = 0; y < ny; y++) {
2295 for (int x = 0; x < nx; x++) {
2296 process_pixel(&data[i], x, y, z);
2297 ++i;
2298 }
2299 }
2300 }
2301 image->update();
2302}
2303
2305 int nx=image->get_xsize();
2306 int ny=image->get_ysize();
2307 int nz=image->get_zsize();
2308
2309 if (nz==1) {
2310 float r;
2311 for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
2312 for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
2313 r=sqrt(float(Util::square(i-x)+Util::square(j-y)));
2314 if (r>r2 && r>r1) continue;
2315 if (r>r1) image->set_value_at(i,j,0,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
2316 else image->set_value_at(i,j,0,v1);
2317 }
2318 }
2319 }
2320 else {
2321 float r;
2322 for (int k=(z<r2?0:z-r2); k<(z+r2>nz?nz:z+r2); k++) {
2323 for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
2324 for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
2325 r=sqrt(float(Util::square(i-x)+Util::square(j-y)+Util::square(k-z)));
2326 if (r>r2 && r>r1) continue;
2327 if (r>r1) image->set_value_at(i,j,k,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
2328 else image->set_value_at(i,j,k,v1);
2329 }
2330 }
2331 }
2332 }
2333 image->update();
2334}
2335
2337 if (image->is_complex()) throw ImageFormatException("MaskAzProcessor: target image must be real");
2338
2339 int nx=image->get_xsize();
2340 int ny=image->get_ysize();
2341 int nz=image->get_zsize();
2342
2343 float phicen = params.set_default("phicen",0.0f)*M_PI/180.0;
2344 phicen=Util::angle_norm_pi(phicen);
2345 float phirange = params.set_default("phirange",180.0f)*M_PI/180.0;
2346 float phitrirange = params.set_default("phitrirange",0.0f)*M_PI/180.0;
2347 int phitriangle = params.set_default("phitriangle",0);
2348 float cx = params.set_default("cx",nx/2);
2349 float cy = params.set_default("cy",ny/2);
2350 float zmin = params.set_default("zmin",0);
2351 float zmax = params.set_default("zmax",nz);
2352 float ztri = params.set_default("ztriangle",0.0f);
2353 float inner_radius = params.set_default("inner_radius",0.0f);
2354 float outer_radius = params.set_default("outer_radius",nx+ny);
2355
2356 for (int x=0; x<nx; x++) {
2357 for (int y=0; y<ny; y++) {
2358 float az=atan2(y-cy,x-cx);
2359 float az2=az-M_PI*2.0f;
2360 float az3=az+M_PI*2.0f;
2361 float r=hypot(y-cy,x-cx);
2362 float val=0.0f;
2363 if (r>inner_radius&&r<=outer_radius) {
2364 float as=Util::angle_sub_2pi(az,phicen);
2365 if (as<phirange) val=1.0f;
2366 else if (!phitriangle || as>phirange+phitrirange) val=0.0f;
2367 else val=1.0-(as-phirange)/float(phitrirange);
2368 }
2369 if (r==0 && inner_radius<=0) val=1.0;
2370
2371 for (int z=0; z<nz; z++) {
2372 if (z<zmin-ztri || z>zmax+ztri) image->mult_value_at_fast(x,y,z,0);
2373 else if (z>=zmin+ztri && z<=zmax-ztri) image->mult_value_at_fast(x,y,z,val);
2374 else if (z>=zmin-ztri && z<=zmin+ztri) image->mult_value_at_fast(x,y,z,val*((z-zmin)/(2.0f*ztri)+0.5));
2375 else image->mult_value_at_fast(x,y,z,val*((zmax-z)/(2.0f*ztri)+0.5));
2376 }
2377 }
2378 }
2379
2380}
2381
2383{
2384 xc = Util::fast_floor(nx/2.0f) + dx;
2385 yc = Util::fast_floor(ny/2.0f) + dy;
2386 zc = Util::fast_floor(nz/2.0f) + dz;
2387
2388 if (outer_radius < 0) {
2389 outer_radius = nx / 2 + outer_radius +1;
2391 }
2392
2393 if (inner_radius <= 0) {
2395 }
2396}
2397
2398
2400{
2401 if (!image) {
2402 throw NullPointerException("NULL image");
2403 }
2404 int nitems = 0;
2405 float sum = 0;
2406 float *data = image->get_data();
2407 size_t i = 0;
2408
2409 xc = Util::fast_floor(nx/2.0f) + dx;
2410 yc = Util::fast_floor(ny/2.0f) + dy;
2411 zc = Util::fast_floor(nz/2.0f) + dz;
2412
2413 for (int z = 0; z < nz; ++z) {
2414 for (int y = 0; y < ny; ++y) {
2415 for (int x = 0; x < nx; ++x) {
2416 float x1 = sqrt((x - xc) * (x - xc) + (y - yc) * (y - yc) + (z - zc) * (z - zc));
2417 if (x1 <= outer_radius + ring_width && x1 >= outer_radius - ring_width) {
2418 sum += data[i];
2419 ++nitems;
2420 }
2421 ++i;
2422 }
2423 }
2424 }
2425
2426 ring_avg = sum / nitems;
2427}
2428
2430{
2431 if (!image) {
2432 LOGWARN("NULL Image");
2433 return;
2434 }
2435
2436 float minval = params.set_default("minval",0.0f);
2437 float newval = params.set_default("newval",minval);
2438
2439 size_t size = (size_t)image->get_xsize() *
2440 (size_t)image->get_ysize() *
2441 (size_t)image->get_zsize();
2442 float *data = image->get_data();
2443
2444
2445
2446 for (size_t i = 0; i < size; ++i) {
2447 if (data[i]<minval) data[i]=newval;
2448 }
2449 image->update();
2450}
2451
2452
2454{
2455 if (!image) {
2456 LOGWARN("NULL image");
2457 return;
2458 }
2459 if (!image->is_complex()) {
2460 LOGWARN("cannot apply complex processor on a real image. Nothing is done.");
2461 return;
2462 }
2463
2464 size_t size = (size_t)image->get_xsize() *
2465 (size_t)image->get_ysize() *
2466 (size_t)image->get_zsize();
2467 float *data = image->get_data();
2468
2469 image->ri2ap();
2470
2471 for (size_t i = 0; i < size; i += 2) {
2472 process_pixel(data);
2473 data += 2;
2474 }
2475
2476 image->update();
2477 image->ap2ri();
2478}
2479
2480
2481
2483{
2484 if (!image) {
2485 LOGWARN("NULL Image");
2486 return;
2487 }
2488
2489 float *data = image->get_data();
2490
2491 nx = image->get_xsize();
2492 ny = image->get_ysize();
2493 nz = image->get_zsize();
2494
2495 int n = (areasize - 1) / 2;
2497
2498 if (nz > 1) {
2500 }
2501
2502 float *matrix = new float[matrix_size];
2503 kernel = new float[matrix_size];
2504
2505 size_t cpysize = areasize * sizeof(float);
2506 size_t start = (nx * ny + nx + 1) * n;
2507
2508 int xend = nx - n;
2509 int yend = ny - n;
2510
2511 int zstart = n;
2512 int zend = nz - n;
2513
2514 int zbox_start = 0;
2515 int zbox_end = areasize;
2516
2517 if (nz == 1) {
2518 zstart = 0;
2519 zend = 1;
2520 zbox_end = 1;
2521 }
2522
2523 size_t nsec = (size_t)nx * (size_t)ny;
2524 int box_nsec = areasize * areasize;
2525
2526 create_kernel();
2527
2528 size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
2529 float *data2 = new float[total_size];
2530 memcpy(data2, data, total_size * sizeof(float));
2531
2532 size_t k;
2533 for (int z = zstart; z < zend; z++) {
2534 for (int y = n; y < yend; y++) {
2535 for (int x = n; x < xend; x++) {
2536
2537 k = (size_t)z * nsec + y * nx + x;
2538
2539 for (int bz = zbox_start; bz < zbox_end; bz++) {
2540 for (int by = 0; by < areasize; by++) {
2541 memcpy(&matrix[(size_t)bz * box_nsec + by * areasize],
2542 &data2[k - start + bz * nsec + by * nx], cpysize);
2543 }
2544 }
2545
2546 process_pixel(&data[k], (float) x, (float) y, (float) z, matrix);
2547 }
2548 }
2549 }
2550
2551 if( matrix )
2552 {
2553 delete[]matrix;
2554 matrix = 0;
2555 }
2556
2557 if( kernel )
2558 {
2559 delete[]kernel;
2560 kernel = 0;
2561 }
2562 image->update();
2563}
2564
2566{
2567 EMData* d = new EMData();
2568 d = image->process("math.edge.xgradient");
2569 d->process_inplace("math.edge.xgradient");
2570 image->process_inplace("math.edge.ygradient");
2571 image->process_inplace("math.edge.xgradient");
2572 image->add(*d);
2573 image->process_inplace("normalize");
2574 delete d;
2575}
2576
2578{
2579 if (nz == 1) {
2580 memset(kernel, 0, areasize * areasize);
2581 kernel[1] = -0.25f;
2582 kernel[3] = -0.25f;
2583 kernel[5] = -0.25f;
2584 kernel[7] = -0.25f;
2585 kernel[4] = 1;
2586 }
2587 else {
2588 memset(kernel, 0, (size_t)areasize * areasize * areasize);
2589 kernel[4] = -1.0f / 6.0f;
2590 kernel[10] = -1.0f / 6.0f;
2591 kernel[12] = -1.0f / 6.0f;
2592 kernel[14] = -1.0f / 6.0f;
2593 kernel[16] = -1.0f / 6.0f;
2594 kernel[22] = -1.0f / 6.0f;
2595 kernel[13] = 1;
2596 }
2597}
2598
2600{
2601 if (!image) return;
2602
2603 float nsigma = params.set_default("nsigma",3.0f);
2604 int bits = params.set_default("bits",5);
2605 int floatbits = params.set_default("floatbits",-1);
2606 float sigma = image->get_attr("sigma");
2607 float mean = image->get_attr("mean");
2608 float bitmax=pow(2.,bits);
2609
2610 int nx = image->get_xsize();
2611 int ny = image->get_ysize();
2612 int nz = image->get_zsize();
2613 size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
2614
2615 if (floatbits<=0) {
2616 float min=image->get_attr("minimum");
2617 float max=image->get_attr("maximum");
2618
2619 // our max/min are either the actual max/min, or mean+-nsigma*sigma
2620 // whichever produces the smaller range. That way by specifying a large
2621 // nsigma you can get the actual min/max of the image easily
2622 if (mean-nsigma*sigma>min) min=mean-nsigma*sigma;
2623 if (mean+nsigma*sigma<max) max=mean+nsigma*sigma;
2624
2625
2626 for (size_t i=0; i<total_size; i++) {
2627 float newval=floor((image->get_value_at_index(i)-min)*bitmax/(max-min)
2628
2629 );
2630 if (newval<0) newval=0;
2631 if (newval>=bitmax) newval=bitmax-1.0f;
2632 image->set_value_at_index(i,newval);
2633 }
2634 }
2635 else {
2636 // In this version, we keep a specified number of significant bits in the floating point significand, leaving the exponent and sign alone
2637 if (floatbits>22) throw InvalidValueException(floatbits,"floatbits must be <23");
2638 unsigned int bitmask= 0xffffffff << (23-floatbits); // this will leave 1 in the sign and exponent bits, along with the specified number of significand bits
2639 for (size_t i=0; i<total_size; i++) {
2640 float newval=image->get_value_at_index(i);
2641 unsigned int *newvali = (unsigned int*)&newval;
2642 *newvali&=bitmask;
2643 image->set_value_at_index(i,newval);
2644 }
2645 }
2646}
2647
2648
2650 EMData *cpy = process(image);
2651 memcpy(image->get_data(),cpy->get_data(),image->get_size()*sizeof(float));
2652 delete cpy;
2653}
2654
2655// mirrors coordinates at box edges
2656inline int MIRE(int x,int nx) { return x<0?-x:(x>=nx?nx-(x-nx+1):x); }
2657
2659{
2660 if (!image) {
2661 LOGWARN("NULL Image");
2662 return NULL;
2663 }
2664
2665
2666 int nx = image->get_xsize();
2667 int ny = image->get_ysize();
2668 int nz = image->get_zsize();
2669
2670 int dx=1,dy=1,dz=1;
2671 if (params.has_key("radius")) dx=dy=dz=params["radius"];
2672 if (params.has_key("xsize")) dx=params["xsize"];
2673 if (params.has_key("ysize")) dy=params["ysize"];
2674 if (params.has_key("zsize")) dz=params["zsize"];
2675 if (nz==1) dz=0;
2676
2677 int matrix_size = (2*dx+1)*(2*dy+1)*(2*dz+1);
2678
2679 vector<float> array(matrix_size);
2680// image->process_inplace("normalize");
2681
2682 EMData *ret = image->copy_head();
2683
2684 // The old version of this code had a lot of hand optimizations, which likely weren't accomplishing much
2685 // This is much simpler, but relies on the compiler to optimize. May be some cost associated with the new
2686 // edge-mirroring policy which could be hand optomized if necessary
2687 for (int k=0; k<nz; k++) {
2688 for (int j=0; j<ny; j++) {
2689 for (int i=0; i<nx; i++) {
2690
2691 for (int kk=k-dz,s=0; kk<=k+dz; kk++) {
2692 for (int jj=j-dy; jj<=j+dy; jj++) {
2693 for (int ii=i-dx; ii<=i+dx; ii++,s++) {
2694 array[s]=image->get_value_at(MIRE(ii,nx),MIRE(jj,ny),MIRE(kk,nz));
2695 }
2696 }
2697 }
2698 float newv=image->get_value_at(i,j,k);
2699 process_pixel(&newv,array.data(),matrix_size);
2700 ret->set_value_at(i,j,k,newv);
2701 }
2702 }
2703 }
2704
2705 ret->update();
2706
2707 return ret;
2708}
2709
2711{
2712 if (!image) {
2713 LOGWARN("NULL Image");
2714 return;
2715 }
2716
2717 int nz = image->get_zsize();
2718
2719 if (nz > 1) {
2720 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
2721 throw ImageDimensionException("3D model not supported");
2722 }
2723
2724 int nx = image->get_xsize();
2725 int ny = image->get_ysize();
2726
2727 int v1 = params["cal_half_width"];
2728 int v2 = params["fill_half_width"];
2729
2730 int v0 = v1 > v2 ? v1 : v2;
2731
2732 if (v2 <= 0) {
2733 v2 = v1;
2734 }
2735
2736 float *data = image->get_data();
2737
2738 for (int y = v0; y <= ny - v0 - 1; y += v2) {
2739 for (int x = v0; x <= nx - v0 - 1; x += v2) {
2740
2741 float sum = 0;
2742 for (int y1 = y - v1; y1 <= y + v1; y1++) {
2743 for (int x1 = x - v1; x1 <= x + v1; x1++) {
2744 sum += data[x1 + y1 * nx];
2745 }
2746 }
2747 float mean = sum / ((v1 * 2 + 1) * (v1 * 2 + 1));
2748
2749 for (int j = y - v2; j <= y + v2; j++) {
2750 for (int i = x - v2; i <= x + v2; i++) {
2751 data[i + j * nx] = mean;
2752 }
2753 }
2754 }
2755 }
2756
2757 image->update();
2758}
2759
2760
2762{
2763 if (!image) {
2764 LOGWARN("NULL Image");
2765 return;
2766 }
2767 int nz = image->get_zsize();
2768
2769 if (nz > 1) {
2770 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
2771 throw ImageDimensionException("3D model not supported");
2772 }
2773
2774 int nx = image->get_xsize();
2775 int ny = image->get_ysize();
2776
2777 float value1 = params["value1"];
2778 float value2 = params["value2"];
2779
2780 int v1 = (int) value1;
2781 int v2 = (int) value2;
2782 if (v2 > v1 / 2) {
2783 LOGERR("invalid value2 '%f' in CutoffBlockProcessor", value2);
2784 return;
2785 }
2786
2787 if (v2 <= 0) {
2788 v2 = v1;
2789 }
2790
2791 float *data = image->get_data();
2792 int y = 0, x = 0;
2793 for (y = 0; y <= ny - v1; y += v1) {
2794 for (x = 0; x <= nx - v1; x += v1) {
2795
2796 EMData *clip = image->get_clip(Region(x, y, v1, v1));
2797 EMData *fft = clip->do_fft();
2798
2799 float *fft_data = fft->get_data();
2800 float sum = 0;
2801 int nitems = 0;
2802
2803 for (int i = -v2; i < v2; i++) {
2804 for (int j = 0; j < v2; j++) {
2805 if (j == 0 && i == 0) {
2806 continue;
2807 }
2808
2809 if (hypot(j, i) < value2) {
2810 int t = j * 2 + (i + v1 / 2) * (v1 + 2);
2811 sum += (fft_data[t] * fft_data[t] + fft_data[t + 1] * fft_data[t + 1]);
2812 nitems++;
2813 }
2814 }
2815 }
2816
2817 if( clip )
2818 {
2819 delete clip;
2820 clip = 0;
2821 }
2822
2823 float mean = sum / nitems;
2824
2825 for (int i = y; i < y + v1; i++) {
2826 for (int j = x; j < x + v1; j++) {
2827 data[i * nx + j] = mean;
2828 }
2829 }
2830 }
2831 }
2832
2833 memset(&data[y * nx], 0, (ny - y) * nx * sizeof(float));
2834
2835 for (int i = 0; i < ny; i++) {
2836 memset(&data[i * nx + x], 0, (nx - x) * sizeof(float));
2837 }
2838
2839 image->update();
2840}
2841
2843{
2844 if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
2845
2846 int shrink_factor = params.set_default("n",0);
2847 if (shrink_factor <= 1) {
2848 throw InvalidValueException(shrink_factor,
2849 "median shrink: shrink factor must > 1");
2850 }
2851
2852 int nx = image->get_xsize();
2853 int ny = image->get_ysize();
2854 int nz = image->get_zsize();
2855
2856// if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
2857// throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
2858// }
2859
2860
2861 int shrunken_nx = nx / shrink_factor;
2862 int shrunken_ny = ny / shrink_factor;
2863 int shrunken_nz = 1;
2864 if (nz > 1) shrunken_nz = nz / shrink_factor;
2865
2866 EMData* copy = image->copy();
2867 image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
2868 accrue_median(image,copy,shrink_factor);
2869 image->update();
2870 if( copy )
2871 {
2872 delete copy;
2873 copy = 0;
2874 }
2875}
2876
2877//
2879{
2880 if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
2881
2882 int shrink_factor = params.set_default("n",0);
2883 if (shrink_factor <= 1) {
2884 throw InvalidValueException(shrink_factor,
2885 "median shrink: shrink factor must > 1");
2886 }
2887 int nx = image->get_xsize();
2888 int ny = image->get_ysize();
2889 int nz = image->get_zsize();
2890
2891
2892// if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
2893// throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
2894// }
2895
2896
2897 int shrunken_nx = nx / shrink_factor;
2898 int shrunken_ny = ny / shrink_factor;
2899 int shrunken_nz = 1;
2900 if (nz > 1) shrunken_nz = nz / shrink_factor;
2901
2902// EMData* ret = new EMData(shrunken_nx, shrunken_ny, shrunken_nz);
2903 EMData *ret = image->copy_head();
2904 ret->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
2905
2906 accrue_median(ret,image,shrink_factor);
2907 ret->update();
2908 return ret;
2909}
2910
2911void MedianShrinkProcessor::accrue_median(EMData* to, const EMData* const from,const int shrink_factor)
2912{
2913
2914 int nx_old = from->get_xsize();
2915 int ny_old = from->get_ysize();
2916
2917 int threed_shrink_factor = shrink_factor * shrink_factor;
2918 int z_shrink_factor = 1;
2919 if (from->get_zsize() > 1) {
2920 threed_shrink_factor *= shrink_factor;
2921 z_shrink_factor = shrink_factor;
2922 }
2923
2924 float *mbuf = new float[threed_shrink_factor];
2925
2926
2927 int nxy_old = nx_old * ny_old;
2928
2929 int nx = to->get_xsize();
2930 int ny = to->get_ysize();
2931 int nz = to->get_zsize();
2932 int nxy_new = nx * ny;
2933
2934 float * rdata = to->get_data();
2935 const float *const data_copy = from->get_const_data();
2936
2937 for (int l = 0; l < nz; l++) {
2938 int l_min = l * shrink_factor;
2939 int l_max = l * shrink_factor + z_shrink_factor;
2940 size_t cur_l = (size_t)l * nxy_new;
2941
2942 for (int j = 0; j < ny; j++) {
2943 int j_min = j * shrink_factor;
2944 int j_max = (j + 1) * shrink_factor;
2945 size_t cur_j = j * nx + cur_l;
2946
2947 for (int i = 0; i < nx; i++) {
2948 int i_min = i * shrink_factor;
2949 int i_max = (i + 1) * shrink_factor;
2950
2951 size_t k = 0;
2952 for (int l2 = l_min; l2 < l_max; l2++) {
2953 size_t cur_l2 = l2 * nxy_old;
2954
2955 for (int j2 = j_min; j2 < j_max; j2++) {
2956 size_t cur_j2 = j2 * nx_old + cur_l2;
2957
2958 for (int i2 = i_min; i2 < i_max; i2++) {
2959 mbuf[k] = data_copy[i2 + cur_j2];
2960 ++k;
2961 }
2962 }
2963 }
2964
2965 for (k = 0; k < size_t(threed_shrink_factor / 2 + 1); k++) {
2966 for (int i2 = k + 1; i2 < threed_shrink_factor; i2++) {
2967 if (mbuf[i2] < mbuf[k]) {
2968 float f = mbuf[i2];
2969 mbuf[i2] = mbuf[k];
2970 mbuf[k] = f;
2971 }
2972 }
2973 }
2974
2975 rdata[i + cur_j] = mbuf[threed_shrink_factor / 2];
2976 }
2977 }
2978 }
2979
2980 if( mbuf )
2981 {
2982 delete[]mbuf;
2983 mbuf = 0;
2984 }
2985
2986 to->scale_pixel((float)shrink_factor);
2987}
2988
2990{
2991 if (image->is_complex()) throw ImageFormatException("FFTResampleProcessor does not support complex images.");
2992
2993 float sample_rate = params.set_default("n",0.0f);
2994 if (sample_rate <= 0.0F ) {
2995 throw InvalidValueException(sample_rate, "downsampling must be >0 ");
2996 }
2997
2998 int nx=image->get_xsize();
2999 int ny=image->get_ysize();
3000 int nz=image->get_zsize();
3001
3002 int nnx=(int)floor(nx/sample_rate+0.5f);
3003 int nny=(ny==1?1:(int)floor(ny/sample_rate+0.5f));
3004 int nnz=(nz==1?1:(int)floor(nz/sample_rate+0.5f));
3005
3006 if (nnx==nx && nny==ny && nnz==nz) return image->copy();
3007
3008 EMData *result;
3009 //downsample
3010 if (nnx<nx||nny<ny||nnz<nz) {
3011 // the type casting here is because FourTruncate was not defined to be const (but it is)
3012 result=((EMData *)image)->FourTruncate(nnx, nny, nnz, 1, 0); // nnx,nny,nnz,returnreal,normalize
3013 } //upscale
3014 else {
3015 // the type casting here is because FourTruncate was not defined to be const (but it is)
3016 result=((EMData *)image)->FourInterpol(nnx, nny, nnz, 1, 0); // nnx,nny,nnz,returnreal,normalize
3017 }
3018 result->scale_pixel((float)nx/(float)nnx);
3019 result->update();
3020 return result;
3021
3022
3023// EMData* result;
3024// if (image->is_complex()) result = image->copy();
3025// else result = image->do_fft();
3026// fft_resample(result,image,sample_rate);
3027 // The image may have been padded - we should shift it so that the phase origin is where FFTW expects it
3028// result->update();
3029// result->scale_pixel(sample_rate);
3030// return result;
3031}
3032
3034{
3035 float sample_rate = params.set_default("n",0.0f);
3036 if (sample_rate <= 0.0F ) {
3037 throw InvalidValueException(sample_rate, "sample rate (n) must be >0 ");
3038 }
3039 //if (image->is_complex()) throw ImageFormatException("Error, the fft resampling processor does not work on complex images");
3040
3041 int nx=image->get_xsize();
3042 int ny=image->get_ysize();
3043 int nz=image->get_zsize();
3044
3045 int nnx=(int)floor(nx/sample_rate+0.5f);
3046 int nny=(ny==1?1:(int)floor(ny/sample_rate+0.5f));
3047 int nnz=(nz==1?1:(int)floor(nz/sample_rate+0.5f));
3048
3049 if (nnx==nx && nny==ny && nnz==nz) return;
3050
3051 EMData *result;
3052 //downsample
3053 if (nnx<nx||nny<ny||nnz<nz) {
3054 // the type casting here is because FourTruncate was not defined to be const (but it is)
3055 result=((EMData *)image)->FourTruncate(nnx, nny, nnz, 1, 0); // nnx,nny,nnz,returnreal,normalize
3056 } //upscale
3057 else {
3058 // the type casting here is because FourTruncate was not defined to be const (but it is)
3059 result=((EMData *)image)->FourInterpol(nnx, nny, nnz, 1, 0); // nnx,nny,nnz,returnreal,normalize
3060 }
3061
3062 image->set_size(nnx,nny,nnz);
3063 memcpy(image->get_data(),result->get_data(),nnx*nny*nnz*sizeof(float));
3064 image->scale_pixel((float)nx/(float)nnx);
3065 image->update();
3066 delete result;
3067
3068 //fft_resample(image,image,sample_rate);
3069
3070 //image->scale_pixel(sample_rate);
3071
3072}
3073
3074void FFTResampleProcessor::fft_resample(EMData* to, const EMData *const from, const float& sample_rate) {
3075 int nx = from->get_xsize();
3076 int ny = from->get_ysize();
3077 int nz = from->get_zsize();
3078
3079 int new_nx = static_cast<int>( static_cast<float> (nx) / sample_rate);
3080 int new_ny = static_cast<int>( static_cast<float> (ny) / sample_rate);
3081 int new_nz = static_cast<int>( static_cast<float> (nz) / sample_rate);
3082
3083 if (new_nx == 0) throw UnexpectedBehaviorException("The resample rate causes the pixel dimensions in the x direction to go to zero");
3084 if (new_ny == 0) new_ny = 1;
3085 if (new_nz == 0) new_nz = 1;
3086
3087 int ndim = from->get_ndim();
3088 if ( ndim < 3 ) {
3089 new_nz = 1;
3090 }
3091 if ( ndim < 2 ) {
3092 new_ny = 1;
3093 }
3094
3095 int fft_x_correction = 1;
3096 if (new_nx % 2 == 0) fft_x_correction = 2;
3097
3098 int fft_y_correction = 0;
3099 if (ny != 1 && new_ny % 2 == 0 && ny % 2 == 1) fft_y_correction = 1;
3100 else if (ny != 1 && new_ny % 2 == 1 && ny % 2 == 0) fft_y_correction = -1;
3101
3102 int fft_z_correction = 0;
3103 if (nz != 1 && new_nz % 2 == 0 && nz % 2 == 1) fft_z_correction = 1;
3104 else if (nz != 1 && new_nz % 2 == 1 && nz % 2 == 0) fft_z_correction = -1;
3105
3106 if ( ! to->is_complex()) to->do_fft_inplace();
3107
3108 if (ndim != 1) to->process_inplace("xform.fourierorigin.tocenter");
3109
3110 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);
3111 to->clip_inplace(clip);
3112
3113 if (fft_x_correction == 1) to->set_fftodd(true);
3114 else to->set_fftodd(false);
3115
3116 if (ndim != 1) to->process_inplace("xform.fourierorigin.tocorner");
3117
3118 to->do_ift_inplace();
3119 to->depad_corner();
3120
3121}
3122
3123
3125{
3126 if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
3127
3128 if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
3129
3130 float shrink_factor0 = params.set_default("n",0.0f);
3131 int shrink_factor = int(shrink_factor0);
3132 if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
3133 throw InvalidValueException(shrink_factor0,
3134 "mean shrink: shrink factor must be >1 integer or 1.5");
3135 }
3136
3137 int nx = image->get_xsize();
3138 int ny = image->get_ysize();
3139 int nz = image->get_zsize();
3140
3141
3142 // here handle the special averaging by 1.5 for 2D case
3143 if (shrink_factor0==1.5 ) {
3144 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
3145
3146 int shrunken_nx = (int(nx / 1.5)+1)/2*2; // make sure the output size is even
3147 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
3148 EMData* result = new EMData(shrunken_nx,shrunken_ny,1);
3149
3150 accrue_mean_one_p_five(result,image);
3151 result->update();
3152
3153 return result;
3154 }
3155
3156 int shrunken_nx = nx / shrink_factor;
3157 int shrunken_ny = ny / shrink_factor;
3158 int shrunken_nz = 1;
3159
3160 if (nz > 1) {
3161 shrunken_nz = nz / shrink_factor;
3162 }
3163
3164// EMData* result = new EMData(shrunken_nx,shrunken_ny,shrunken_nz);
3165 EMData* result = image->copy_head();
3166 result->set_size(shrunken_nx,shrunken_ny,shrunken_nz);
3167 accrue_mean(result,image,shrink_factor);
3168
3169 result->update();
3170
3171 return result;
3172}
3173
3175{
3176 if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
3177
3178 if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
3179
3180 float shrink_factor0 = params.set_default("n",0.0f);
3181 int shrink_factor = int(shrink_factor0);
3182 if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
3183 throw InvalidValueException(shrink_factor0,
3184 "mean shrink: shrink factor must be >1 integer or 1.5");
3185 }
3186
3187/* if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) ||
3188 (nz > 1 && (nz % shrink_factor != 0))) {
3189 throw InvalidValueException(shrink_factor,
3190 "Image size not divisible by shrink factor");
3191}*/
3192
3193 int nx = image->get_xsize();
3194 int ny = image->get_ysize();
3195 int nz = image->get_zsize();
3196 // here handle the special averaging by 1.5 for 2D case
3197 if (shrink_factor0==1.5 ) {
3198 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
3199
3200 int shrunken_nx = (int(nx / 1.5)+1)/2*2; // make sure the output size is even
3201 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
3202
3203 EMData* orig = image->copy();
3204 image->set_size(shrunken_nx, shrunken_ny, 1); // now nx = shrunken_nx, ny = shrunken_ny
3205 image->to_zero();
3206
3207 accrue_mean_one_p_five(image,orig);
3208
3209 if( orig ) {
3210 delete orig;
3211 orig = 0;
3212 }
3213 image->update();
3214
3215 return;
3216 }
3217
3218 accrue_mean(image,image,shrink_factor);
3219
3220 int shrunken_nx = nx / shrink_factor;
3221 int shrunken_ny = ny / shrink_factor;
3222 int shrunken_nz = 1;
3223 if (nz > 1) shrunken_nz = nz / shrink_factor;
3224
3225 image->update();
3226 image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
3227}
3228
3229void MeanShrinkProcessor::accrue_mean(EMData* to, const EMData* const from,const int shrink_factor)
3230{
3231 const float * const data = from->get_const_data();
3232 float* rdata = to->get_data();
3233
3234 size_t nx = from->get_xsize();
3235 size_t ny = from->get_ysize();
3236 size_t nz = from->get_zsize();
3237 size_t nxy = nx*ny;
3238
3239
3240 size_t shrunken_nx = nx / shrink_factor;
3241 size_t shrunken_ny = ny / shrink_factor;
3242 size_t shrunken_nz = 1;
3243 size_t shrunken_nxy = shrunken_nx * shrunken_ny;
3244
3245 int normalize_shrink_factor = shrink_factor * shrink_factor;
3246 int z_shrink_factor = 1;
3247
3248 if (nz > 1) {
3249 shrunken_nz = nz / shrink_factor;
3250 normalize_shrink_factor *= shrink_factor;
3251 z_shrink_factor = shrink_factor;
3252 }
3253
3254 float invnormfactor = 1.0f/(float)normalize_shrink_factor;
3255
3256 for (size_t k = 0; k < shrunken_nz; k++) {
3257 size_t k_min = k * shrink_factor;
3258 size_t k_max = k * shrink_factor + z_shrink_factor;
3259 size_t cur_k = k * shrunken_nxy;
3260
3261 for (size_t j = 0; j < shrunken_ny; j++) {
3262 size_t j_min = j * shrink_factor;
3263 size_t j_max = j * shrink_factor + shrink_factor;
3264 size_t cur_j = j * shrunken_nx + cur_k;
3265
3266 for (size_t i = 0; i < shrunken_nx; i++) {
3267 size_t i_min = i * shrink_factor;
3268 size_t i_max = i * shrink_factor + shrink_factor;
3269
3270 float sum = 0;
3271 for (size_t kk = k_min; kk < k_max; kk++) {
3272 size_t cur_kk = kk * nxy;
3273
3274 for (size_t jj = j_min; jj < j_max; jj++) {
3275 size_t cur_jj = jj * nx + cur_kk;
3276 for (size_t ii = i_min; ii < i_max; ii++) {
3277 sum += data[ii + cur_jj];
3278 }
3279 }
3280 }
3281 rdata[i + cur_j] = sum * invnormfactor;
3282 }
3283 }
3284 }
3285 to->scale_pixel((float)shrink_factor);
3286}
3287
3288
3290{
3291 int nx0 = from->get_xsize(), ny0 = from->get_ysize(); // the original size
3292
3293 int nx = to->get_xsize(), ny = to->get_ysize();
3294
3295 float *data = to->get_data();
3296 const float * const data0 = from->get_const_data();
3297
3298 for (int j = 0; j < ny; j++) {
3299 int jj = int(j * 1.5);
3300 float jw0 = 1.0F, jw1 = 0.5F; // 3x3 -> 2x2, so each new pixel should have 2.25 of the old pixels
3301 if ( j%2 ) {
3302 jw0 = 0.5F;
3303 jw1 = 1.0F;
3304 }
3305 for (int i = 0; i < nx; i++) {
3306 int ii = int(i * 1.5);
3307 float iw0 = 1.0F, iw1 = 0.5F;
3308 float w = 0.0F;
3309
3310 if ( i%2 ) {
3311 iw0 = 0.5F;
3312 iw1 = 1.0F;
3313 }
3314 if ( jj < ny0 ) {
3315 if ( ii < nx0 ) {
3316 data[j * nx + i] = data0[ jj * nx0 + ii ] * jw0 * iw0 ;
3317 w += jw0 * iw0 ;
3318 if ( ii+1 < nx0 ) {
3319 data[j * nx + i] += data0[ jj * nx0 + ii + 1] * jw0 * iw1;
3320 w += jw0 * iw1;
3321 }
3322 }
3323 if ( jj +1 < ny0 ) {
3324 if ( ii < nx0 ) {
3325 data[j * nx + i] += data0[ (jj+1) * nx0 + ii ] * jw1 * iw0;
3326 w += jw1 * iw0;
3327 if ( ii+1 < nx0 ) {
3328 data[j * nx + i] += data0[ (jj+1) * nx0 + ii + 1] * jw1 * iw1;
3329 w += jw1 * iw1;
3330 }
3331 }
3332 }
3333 }
3334 if ( w>0 ) data[j * nx + i] /= w;
3335 }
3336 }
3337
3338 to->update();
3339 to->scale_pixel((float)1.5);
3340}
3341
3342// This would have to be moved into the header if it were required in other source files
3343template<class LogicOp>
3345{
3346 // The basic idea of this code is to iterate through each pixel in the output image
3347 // determining its value by investigation a region of the input image
3348
3349 if (!image) throw NullPointerException("Attempt to max shrink a null image");
3350
3351 if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
3352
3353
3354 int shrink = params.set_default("n",2);
3355 int search = params.set_default("search",2);
3356
3357 if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
3358
3359
3360 int nz = image->get_zsize();
3361 int ny = image->get_ysize();
3362 int nx = image->get_xsize();
3363
3364 if (nx == 1 && ny == 1 && nz == 1 ) return image->copy();
3365
3366 LogicOp op;
3367 EMData* return_image = new EMData();
3368
3369 int shrinkx = shrink;
3370 int shrinky = shrink;
3371 int shrinkz = shrink;
3372
3373 int searchx = search;
3374 int searchy = search;
3375 int searchz = search;
3376
3377 // Clamping the shrink values to the dimension lengths
3378 // ensures that the return image has non zero dimensions
3379 if ( shrinkx > nx ) shrinkx = nx;
3380 if ( shrinky > ny ) shrinky = ny;
3381 if ( shrinkz > nz ) shrinkz = nz;
3382
3383 if ( nz == 1 && ny == 1 )
3384 {
3385 return_image->set_size(nx/shrinkx);
3386 for(int i = 0; i < nx/shrinkx; ++i)
3387 {
3388 float tmp = op.get_start_val();
3389 for(int s=0; s < searchx; ++s)
3390 {
3391 int idx = shrinkx*i+s;
3392 // Don't ask for memory beyond limits
3393 if ( idx > nx ) break;
3394 else
3395 {
3396 float val = image->get_value_at(idx);
3397 if ( op( val,tmp) ) tmp = val;
3398 }
3399 }
3400 return_image->set_value_at(i,tmp);
3401 }
3402 }
3403 else if ( nz == 1 )
3404 {
3405 int ty = ny/shrinky;
3406 int tx = nx/shrinkx;
3407 return_image->set_size(tx,ty);
3408 for(int y = 0; y < ty; ++y) {
3409 for(int x = 0; x < tx; ++x) {
3410 float tmp = op.get_start_val();
3411 for(int sy=0; sy < searchy; ++sy) {
3412 int yidx = shrinky*y+sy;
3413 if ( yidx >= ny) break;
3414 for(int sx=0; sx < searchx; ++sx) {
3415 int xidx = shrinkx*x+sx;
3416 if ( xidx >= nx) break;
3417
3418 float val = image->get_value_at(xidx,yidx);
3419 if ( op( val,tmp) ) tmp = val;
3420 }
3421 }
3422 return_image->set_value_at(x,y,tmp);
3423 }
3424 }
3425 }
3426 else
3427 {
3428 int tz = nz/shrinkz;
3429 int ty = ny/shrinky;
3430 int tx = nx/shrinkx;
3431
3432 return_image->set_size(tx,ty,tz);
3433 for(int z = 0; z < tz; ++z) {
3434 for(int y = 0; y < ty; ++y) {
3435 for(int x = 0; x < tx; ++x) {
3436 float tmp = op.get_start_val();
3437
3438 for(int sz=0; sz < searchz; ++sz) {
3439 int zidx = shrinkz*z+sz;
3440 if ( zidx >= nz) break;
3441
3442 for(int sy=0; sy < searchy; ++sy) {
3443 int yidx = shrinky*y+sy;
3444 if ( yidx >= ny) break;
3445
3446 for(int sx=0; sx < searchx; ++sx) {
3447 int xidx = shrinkx*x+sx;
3448 if ( xidx >= nx) break;
3449 float val = image->get_value_at(xidx,yidx,zidx);
3450 if ( op( val,tmp) ) tmp = val;
3451 }
3452 }
3453 }
3454 return_image->set_value_at(x,y,z,tmp);
3455 }
3456 }
3457 }
3458 }
3459 return_image->update();
3460
3461 return return_image;
3462}
3463
3464template<class LogicOp>
3466{
3467 // The basic idea of this code is to iterate through each pixel in the output image
3468 // determining its value by investigation a region of the input image
3469 if (!image) throw NullPointerException("Attempt to max shrink a null image");
3470
3471 if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
3472
3473
3474 int shrink = params.set_default("shrink",2);
3475 int search = params.set_default("search",2);
3476
3477 if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
3478
3479
3480 int nz = image->get_zsize();
3481 int ny = image->get_ysize();
3482 int nx = image->get_xsize();
3483
3484 LogicOp op;
3485
3486 int shrinkx = shrink;
3487 int shrinky = shrink;
3488 int shrinkz = shrink;
3489
3490 int searchx = search;
3491 int searchy = search;
3492 int searchz = search;
3493
3494 // Clamping the shrink values to the dimension lengths
3495 // ensures that the return image has non zero dimensions
3496 if ( shrinkx > nx ) shrinkx = nx;
3497 if ( shrinky > ny ) shrinky = ny;
3498 if ( shrinkz > nz ) shrinkz = nz;
3499
3500 if (nx == 1 && ny == 1 && nz == 1 ) return;
3501
3502 if ( nz == 1 && ny == 1 )
3503 {
3504 for(int i = 0; i < nx/shrink; ++i)
3505 {
3506 float tmp = op.get_start_val();
3507 for(int s=0; s < searchx; ++s)
3508 {
3509 int idx = shrinkx*i+s;
3510 if ( idx > nx ) break;
3511 else
3512 {
3513 float val = image->get_value_at(idx);
3514 if ( op( val,tmp) ) tmp = val;
3515 }
3516 }
3517 image->set_value_at(i,tmp);
3518 }
3519
3520 image->set_size(nx/shrinkx);
3521 }
3522 else if ( nz == 1 )
3523 {
3524 int ty = ny/shrinky;
3525 int tx = nx/shrinkx;
3526 for(int y = 0; y < ty; ++y) {
3527 for(int x = 0; x < tx; ++x) {
3528 float tmp = op.get_start_val();
3529 for(int sy=0; sy < searchy; ++sy) {
3530 int yidx = shrinky*y+sy;
3531 if ( yidx >= ny) break;
3532 for(int sx=0; sx < searchx; ++sx) {
3533 int xidx = shrinkx*x+sx;
3534 if ( xidx >= nx) break;
3535
3536 float val = image->get_value_at(xidx,yidx);
3537 if ( op( val,tmp) ) tmp = val;
3538 }
3539 }
3540 (*image)(x+tx*y) = tmp;
3541 }
3542 }
3543 image->set_size(tx,ty);
3544 }
3545 else
3546 {
3547 int tnxy = nx/shrinkx*ny/shrinky;
3548 int tz = nz/shrinkz;
3549 int ty = ny/shrinky;
3550 int tx = nx/shrinkx;
3551
3552 for(int z = 0; z < tz; ++z) {
3553 for(int y = 0; y < ty; ++y) {
3554 for(int x = 0; x < tx; ++x) {
3555 float tmp = op.get_start_val();
3556 for(int sz=0; sz < searchz; ++sz) {
3557 int zidx = shrinkz*z+sz;
3558 if ( zidx >= nz) break;
3559 for(int sy=0; sy < searchy; ++sy) {
3560 int yidx = shrinky*y+sy;
3561 if ( yidx >= ny) break;
3562 for(int sx=0; sx < shrinkx; ++sx) {
3563 int xidx = shrinkx*x+sx;
3564 if ( xidx >= nx) break;
3565
3566 float val = image->get_value_at(xidx,yidx,zidx);
3567 if ( op( val,tmp) ) tmp = val;
3568 }
3569 }
3570 }
3571 (*image)(x+tx*y+tnxy*z) = tmp;
3572 }
3573 }
3574 }
3575 image->set_size(tx,ty,tz);
3576 }
3577 image->update();
3578}
3579
3580
3581
3583{
3584 if (!image) {
3585 LOGWARN("NULL Image");
3586 return;
3587 }
3588
3589 int nz = image->get_zsize();
3590 if (nz > 1) {
3591 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
3592 throw ImageDimensionException("3D model not supported");
3593 }
3594
3595 int nx = image->get_xsize();
3596 int ny = image->get_ysize();
3597 float *dy = new float[ny];
3598 float m = 0;
3599 float b = 0;
3600 float sum_y = 0;
3601 float *data = image->get_data();
3602
3603 for (int i = 0; i < ny; i++) {
3604 Util::calc_least_square_fit(nx, 0, data + i * nx, &m, &b, false);
3605 dy[i] = b;
3606 sum_y += m;
3607 }
3608
3609 float mean_y = sum_y / ny;
3610 float sum_x = 0;
3611 Util::calc_least_square_fit(ny, 0, dy, &sum_x, &b, false);
3612
3613 for (int j = 0; j < ny; j++) {
3614 for (int i = 0; i < nx; i++) {
3615 data[i + j * nx] -= i * sum_x + j * mean_y + b;
3616 }
3617 }
3618
3619 image->update();
3620}
3621
3623{
3624
3625 EMData* mask = params.set_default("mask",(EMData*)0);
3626 int radius = params.set_default("radius",0);
3627
3628 if (radius != 0 && mask != 0) throw InvalidParameterException("Error - the mask and radius parameters are mutually exclusive.");
3629
3630 if (mask == 0 && radius == 0) throw InvalidParameterException("Error - you must specify either the mask or the radius parameter.");
3631
3632 // If the radius isn't 0, then turn the mask into the thing we want...
3633 bool deletemask = false;
3634 if (radius != 0) {
3635 mask = new EMData;
3636 int n = image->get_ndim();
3637 if (n==1){
3638 mask->set_size(2*radius+1);
3639 } else if (n==2) {
3640 mask->set_size(2*radius+1,2*radius+1);
3641 }
3642 else /*n==3*/ {
3643 mask->set_size(2*radius+1,2*radius+1,2*radius+1);
3644 }
3645 // assuming default behavior is to make a circle/sphere with using the radius of the mask
3646 mask->process_inplace("testimage.circlesphere");
3647 }
3648
3649 // Double check that that mask isn't too big
3650 int mnx = mask->get_xsize(); int mny = mask->get_ysize(); int mnz = mask->get_zsize();
3651 int nx = image->get_xsize(); int ny = image->get_ysize(); int nz = image->get_zsize();
3652 int nxc = nx+mnx; int nyc = ny+mny; int nzc = nz+mnz;
3653 if (nz == 1) nzc = 1; // Sanity check
3654 if (ny == 1) nyc = 1; // Sanity check
3655
3656 if ( mnx > nx || mny > ny || mnz > nz)
3657 throw ImageDimensionException("Can not flatten using a mask that is larger than the image.");
3658
3659 // Get the normalization factor
3660 float normfac = 0.0;
3661 for (int i=0; i<mask->get_xsize()*mask->get_ysize()*mask->get_zsize(); ++i){
3662 normfac += mask->get_value_at(i);
3663 }
3664 // If the sum is zero the user probably doesn't understand that determining a measure of the mean requires
3665 // strictly positive numbers. The user has specified a mask that consists entirely of zeros, or the mask
3666 // has a mean of zero.
3667 if (normfac == 0) throw InvalidParameterException("Error - the pixels in the mask sum to zero. This breaks the flattening procedure");
3668 normfac = 1.0f/normfac;
3669
3670 // The mask can now be automatically resized to the dimensions of the image
3671// bool undoclip = false;
3672
3673 Region r;
3674 if (ny == 1) r = Region((mnx-nxc)/2,nxc);
3675 else if (nz == 1) r = Region((mnx-nxc)/2, (mny-nyc)/2,nxc,nyc);
3676 else r = Region((mnx-nxc)/2, (mny-nyc)/2,(mnz-nzc)/2,nxc,nyc,nzc);
3677 mask->clip_inplace(r,0);
3678// undoclip = true;
3679// if ( mnx < nx || mny < ny || mnz < nz) {
3680// Region r((mnx-nx)/2, (mny-ny)/2,(mnz-nz)/2,nx,ny,nz);
3681// mask->clip_inplace(r);
3682// undoclip = true;
3683// }
3684
3685 Region r2;
3686 if (ny == 1) r2 = Region((nx-nxc)/2,nxc);
3687 else if (nz == 1) r2 = Region((nx-nxc)/2, (ny-nyc)/2,nxc,nyc);
3688 else r2 = Region((nx-nxc)/2, (ny-nyc)/2,(nz-nzc)/2,nxc,nyc,nzc);
3689 image->clip_inplace(r2,image->get_edge_mean());
3690 // Finally do the convolution
3691 EMData* m = image->convolute(mask);
3692 // Normalize so that m is truly the local mean
3693 m->mult(normfac);
3694 // Before we can subtract, the mean must be phase shifted
3695 m->process_inplace("xform.phaseorigin.tocenter");
3696 // Subtract the local mean
3697// image->write_image("a.mrc");
3698// m->write_image("b.mrc");
3699 image->sub(*m); // WE'RE DONE!
3700 delete m;
3701
3702 if (deletemask) {
3703 delete mask;
3704 } else { // I clipped it inplace, so undo this clipping so the user gets back what the put in
3705 Region r;
3706 if (ny == 1) r = Region((nxc-mnx)/2,mnx);
3707 else if (nz == 1) r = Region((nxc-mnx)/2, (nyc-mny)/2,mnx,mny);
3708 else r = Region((nxc-mnx)/2, (nyc-mny)/2,(nzc-mnz)/2,mnx,mny,mnz);
3709 mask->clip_inplace(r);
3710 }
3711
3712 Region r3;
3713 if (ny == 1) r3 = Region((nxc-nx)/2,nx);
3714 else if (nz == 1) r3 = Region((nxc-nx)/2, (nyc-ny)/2,nx,ny);
3715 else r3 = Region((nxc-nx)/2, (nyc-ny)/2,(nzc-nz)/2,nx,ny,nz);
3716 image->clip_inplace(r3);
3717// if ( undoclip ) {
3718// Region r((nx-mnx)/2, (ny-mny)/2, (nz-mnz)/2,mnx,mny,mnz);
3719// mask->clip_inplace(r);
3720// }
3721
3722}
3723
3725 if (!image) { LOGWARN("NULL IMAGE"); return; }
3726 //int isinten=image->get_attr_default("is_intensity",0);
3727
3728 // 1-D
3729 if (image->get_ysize()==1) {
3730
3731 }
3732 // 2-D
3733 else if (image->get_zsize()==1) {
3734// if (!isinten) throw ImageDimensionException("Only complex intensity images currently supported by NonConvexProcessor");
3735 int nx2=image->get_xsize()/2;
3736 int ny2=image->get_ysize()/2;
3737 vector<float> rdist = image->calc_radial_dist(nx2*1.5,0,1,false); // radial distribution to make sure nonconvex values decrease radially
3738 // Make sure rdist is decreasing (or flat)
3739 for (int i=1; i<nx2; i++) {
3740 if (rdist[i]>rdist[i-1]) rdist[i]=rdist[i-1];
3741 }
3742
3743 image->process_inplace("xform.fourierorigin.tocenter");
3744 EMData* binary=image->copy();
3745
3746 // First we eliminate convex points from the input image (set to zero)
3747 for (int x=0; x<image->get_xsize(); x+=2) {
3748 for (int y=1; y<image->get_ysize()-1; y++) {
3749 int r=(int)hypot((float)(x/2),(float)(y-ny2));
3750 float cen=(*binary)(x,y);
3751 if (x==0 || x==nx2*2-2 || (cen>(*binary)(x+2,y) || cen>(*binary)(x-2,y) || cen>(*binary)(x,y+1) || cen >(*binary)(x,y-1) || (*binary)(x,y)>rdist[r])) { // point is considered nonconvex if lower than surrounding values and lower than mean
3752 image->set_value_at_fast(x/2+nx2,y,0.0); // we are turning image into a full real-space intensity image for now
3753 image->set_value_at_fast(nx2-x/2,ny2*2-y-1,0.0);
3754 }
3755 else {
3756 image->set_value_at_fast(x/2+nx2,y,cen); // we are turning image into a full real-space intensity image for now
3757 image->set_value_at_fast(nx2-x/2,ny2*2-y-1,cen); // It will contain non-zero values only for nonconvex points
3758 }
3759 }
3760 }
3761 image->set_value_at_fast(nx2+1,ny2,(*binary)(2,ny2)); // We keep the points near the Fourier origin as a central anchor even though it's convex
3762 image->set_value_at_fast(nx2-1,ny2,(*binary)(2,ny2)); // We keep the points near the Fourier origin as a central anchor even though it's convex
3763 image->set_value_at_fast(nx2,ny2+1,(*binary)(0,ny2+1)); // We keep the points near the Fourier origin as a central anchor even though it's convex
3764 image->set_value_at_fast(nx2,ny2-1,(*binary)(0,ny2-1)); // We keep the points near the Fourier origin as a central anchor even though it's convex
3765 for (int y=0; y<ny2*2; y++) image->set_value_at_fast(0,y,0.0f);
3766
3767 // Now make a binary version of the convex points
3768 float *idat=image->get_data();
3769 float *bdat=binary->get_data();
3770 int nxy=(nx2*ny2*4);
3771 for (int i=0; i<nxy; i++) {
3772 bdat[i]=idat[i]==0?0:1.0f; // binary version of the convex points in image
3773 }
3774 binary->update();
3775
3776 // We now use a Gaussian filter on both images, to use Gaussian interpolation to fill in zero values
3777 image->set_complex(false); // so we can use a Gaussian filter on it
3778 binary->set_complex(false);
3779
3780/* image->write_image("con.hdf",0);*/
3781 image->set_fftpad(false);
3782 binary->set_fftpad(false);
3783
3784 // Gaussian blur of both images
3785 image->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
3786 binary->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
3787
3788/* image->write_image("con.hdf",1);
3789 binary->write_image("con.hdf",2);*/
3790
3791 for (int x=0; x<image->get_xsize(); x+=2) {
3792 for (int y=0; y<image->get_ysize(); y++) {
3793 float bv=binary->get_value_at(x/2+nx2,y);
3794 image->set_value_at_fast(x,y,image->get_value_at(x/2+nx2,y)/(bv<=0?1.0f:bv));
3795 image->set_value_at_fast(x+1,y,0.0);
3796 }
3797 }
3798 image->set_complex(true);
3799 image->set_fftpad(true);
3800 image->process_inplace("xform.fourierorigin.tocorner");
3801 delete binary;
3802 }
3803 else throw ImageDimensionException("3D maps not yet supported by NonConvexProcessor");
3804
3805}
3806
3807
3808#include <gsl/gsl_linalg.h>
3810{
3811 if (!image) {
3812 LOGWARN("NULL Image");
3813 return;
3814 }
3815
3816 int nz = image->get_zsize();
3817 if (nz > 1) {
3818 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
3819 throw ImageDimensionException("3D map not supported");
3820 }
3821
3822 int nx = image->get_xsize();
3823 int ny = image->get_ysize();
3824 float *d = image->get_data();
3825 EMData *mask = 0;
3826 float *dm = 0;
3827 if (params.has_key("mask")) {
3828 mask = params["mask"];
3829 if (nx!=mask->get_xsize() || ny!=mask->get_ysize()) {
3830 LOGERR("%s Processor requires same size mask image", get_name().c_str());
3831 throw ImageDimensionException("wrong size mask image");
3832 }
3833 dm = mask->get_data();
3834 }
3835 int count = 0;
3836 if (dm) {
3837 for(int i=0; i<nx*ny; i++) {
3838 if(dm[i]) count++;
3839 }
3840 }
3841 else {
3842 count = nx * ny;
3843 }
3844 if(count<3) {
3845 LOGERR("%s Processor requires at least 3 pixels to fit a plane", get_name().c_str());
3846 throw ImageDimensionException("too few usable pixels to fit a plane");
3847 }
3848 // Allocate the working space
3849 gsl_vector *S=gsl_vector_calloc(3);
3850 gsl_matrix *A=gsl_matrix_calloc(count,3);
3851 gsl_matrix *V=gsl_matrix_calloc(3,3);
3852
3853 double m[3] = {0, 0, 0};
3854 int index=0;
3855 if (dm) {
3856 for(int j=0; j<ny; j++){
3857 for(int i=0; i<nx; i++){
3858 int ij=j*nx+i;
3859 if(dm[ij]) {
3860 m[0]+=i; // x
3861 m[1]+=j; // y
3862 m[2]+=d[ij]; // z
3863 /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
3864 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
3865 index++;
3866 }
3867 }
3868 }
3869 }
3870 else {
3871 for(int j=0; j<ny; j++){
3872 for(int i=0; i<nx; i++){
3873 int ij=j*nx+i;
3874 m[0]+=i; // x
3875 m[1]+=j; // y
3876 m[2]+=d[ij]; // z
3877 /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
3878 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
3879 index++;
3880 }
3881 }
3882 }
3883
3884 for(int i=0; i<3; i++) m[i]/=count; // compute center of the plane
3885
3886 index=0;
3887 if (dm) {
3888 for(int j=0; j<ny; j++){
3889 for(int i=0; i<nx; i++){
3890 int ij=j*nx+i;
3891 if(dm[ij]) {
3892 //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
3893 gsl_matrix_set(A,index,0,i-m[0]);
3894 gsl_matrix_set(A,index,1,j-m[1]);
3895 gsl_matrix_set(A,index,2,d[ij]-m[2]);
3896 index++;
3897 }
3898 }
3899 }
3900 mask->update();
3901 }
3902 else {
3903 for(int j=0; j<ny; j++){
3904 for(int i=0; i<nx; i++){
3905 int ij=j*nx+i;
3906 //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
3907 gsl_matrix_set(A,index,0,i-m[0]);
3908 gsl_matrix_set(A,index,1,j-m[1]);
3909 gsl_matrix_set(A,index,2,d[ij]-m[2]);
3910 index++;
3911 }
3912 }
3913 }
3914
3915 // SVD decomposition and use the V vector associated with smallest singular value as the plan normal
3916 gsl_linalg_SV_decomp_jacobi(A, V, S);
3917
3918 double n[3];
3919 for(int i=0; i<3; i++) n[i] = gsl_matrix_get(V, i, 2);
3920
3921 #ifdef DEBUG
3922 printf("S=%g,%g,%g\n",gsl_vector_get(S,0), gsl_vector_get(S,1), gsl_vector_get(S,2));
3923 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));
3924 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));
3925 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));
3926 printf("Fitted plane: p0=%g,%g,%g\tn=%g,%g,%g\n",m[0],m[1],m[2],n[0],n[1],n[2]);
3927 #endif
3928
3929 int changeZero = 0;
3930 if (params.has_key("changeZero")) changeZero = params["changeZero"];
3931 if (changeZero) {
3932 for(int j=0; j<nx; j++){
3933 for(int i=0; i<ny; i++){
3934 int ij = j*nx+i;
3935 d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
3936 }
3937 }
3938 }
3939 else {
3940 for(int j=0; j<nx; j++){
3941 for(int i=0; i<ny; i++){
3942 int ij = j*nx+i;
3943 if(d[ij]) d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
3944 }
3945 }
3946 }
3947 image->update();
3948 // set return plane parameters
3949 vector< float > planeParam;
3950 planeParam.resize(6);
3951 for(int i=0; i<3; i++) planeParam[i] = static_cast<float>(n[i]);
3952 for(int i=0; i<3; i++) planeParam[i+3] = static_cast<float>(m[i]);
3953 params["planeParam"]=EMObject(planeParam);
3954}
3955
3957{
3958 if (!image) {
3959 LOGWARN("NULL Image");
3960 return;
3961 }
3962
3963 int nx = image->get_xsize();
3964 int ny = image->get_ysize();
3965 int nz = image->get_zsize();
3966
3967 float *data = image->get_data();
3968 float sigma = image->get_attr("sigma");
3969
3970 for (int k = 0; k < nz; k++) {
3971 for (int i = 0; i < nx; i++) {
3972 double sum = 0;
3973 for (int j = ny / 4; j < 3 * ny / 4; j++) {
3974 sum += data[i + j * nx];
3975 }
3976
3977 float mean = (float)sum / (ny / 2);
3978 for (int j = 0; j < ny; j++) {
3979 data[i + j * nx] = (data[i + j * nx] - mean) / sigma;
3980 }
3981 }
3982 }
3983
3984 image->update();
3985}
3986
3988{
3989 if (!image) {
3990 LOGWARN("NULL Image");
3991 return;
3992 }
3993
3994 //Note : real image only!
3995 if(image->is_complex()) {
3996 LOGERR("%s Processor only operates on real images", get_name().c_str());
3997 throw ImageFormatException("apply to real image only");
3998 }
3999
4000 // Note : 2D only!
4001 int nz = image->get_zsize();
4002 if (nz > 1) {
4003 LOGERR("%s Processor doesn't support 3D models", get_name().c_str());
4004 throw ImageDimensionException("3D model not supported");
4005 }
4006
4007 EMData *ff=image->do_fft();
4008 ff->ri2ap();
4009
4010 int nx=image->get_xsize();
4011 int ny=image->get_ysize();
4012
4013 int x,y;
4014 float norm=static_cast<float>(nx*ny);
4015
4016 for (y=0; y<ny; y++) image->set_value_at(0,y,0);
4017
4018 for (x=1; x<nx/2; x++) {
4019 for (y=0; y<ny; y++) {
4020 int y2;
4021 if (y<ny/2) y2=y+ny/2;
4022 else if (y==ny/2) y2=ny;
4023 else y2=y-ny/2;
4024 image->set_value_at(x,y,ff->get_value_at(nx-x*2,ny-y2)/norm);
4025 }
4026 }
4027
4028 for (x=nx/2; x<nx; x++) {
4029 for (y=0; y<ny; y++) {
4030 int y2;
4031 if (y<ny/2) y2=y+ny/2;
4032 else y2=y-ny/2;
4033 image->set_value_at(x,y,ff->get_value_at(x*2-nx,y2)/norm);
4034 }
4035 }
4036
4037 image->update();
4038 if( ff )
4039 {
4040 delete ff;
4041 ff = 0;
4042 }
4043}
4044
4046{
4047 if (!image) {
4048 LOGWARN("NULL Image");
4049 return;
4050 }
4051
4052 if (image->get_zsize() > 1) {
4053 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
4054 throw ImageDimensionException("3D model not supported");
4055 }
4056
4057 float nonzero = params.set_default("nonzero",false);
4058
4059 float *d = image->get_data();
4060 int i = 0;
4061 int j = 0;
4062
4063 int nx = image->get_xsize();
4064 int ny = image->get_ysize();
4065
4066 float zval=9.99e23f; // we're assuming we won't run into this exact value for an edge, not great programming, but good enough
4067 if (nonzero) {
4068 int x,y;
4069 size_t corn=nx*ny-1;
4070
4071 // this set of 4 tests looks for any edges with exactly the same value
4072 for (x=1; x<nx; x++) { if (d[x]!=d[0]) break;}
4073 if (x==nx) zval=d[0];
4074
4075 for (y=1; y<ny; y++) { if (d[y*nx]!=d[0]) break; }
4076 if (y==ny) zval=d[0];
4077
4078 for (x=1; x<nx; x++) { if (d[corn-x]!=d[corn]) break;}
4079 if (x==nx) zval=d[corn];
4080
4081 for (y=1; y<ny; y++) { if (d[corn-y*nx]!=d[corn]) break; }
4082 if (y==ny) zval=d[corn];
4083
4084 if (zval!=9.99e23f) {
4085 image->set_attr("hadzeroedge",1);
4086// printf("zeroedge %f\n",zval);
4087
4088 }
4089 else image->set_attr("hadzeroedge",0);
4090
4091 // This tries to detect images where the edges have been filled with the nearest non-zero value. The filter does nothing, but we set the tag.
4092 for (x=nx/2-5; x<nx/2+5; x++) {
4093 if (d[x]!=d[x+nx] || d[x]!=d[x+nx*2] ) break;
4094 }
4095 if (x==nx/2+5) image->set_attr("hadzeroedge",2);
4096
4097 for (x=nx/2-5; x<nx/2+5; x++) {
4098 if (d[corn-x]!=d[corn-x-nx] || d[corn-x]!=d[corn-x-nx*2]) break;
4099 }
4100 if (x==nx/2+5) image->set_attr("hadzeroedge",2);
4101
4102 for (y=ny/2-5; y<ny/2+5; y++) {
4103 if (d[y*nx]!=d[y*nx+1] || d[y*nx]!=d[y*nx+2] ) break;
4104 }
4105 if (y==ny/2+5) image->set_attr("hadzeroedge",2);
4106
4107 for (y=ny/2-5; y<ny/2+5; y++) {
4108 if (d[corn-y*nx]!=d[corn-y*nx-1] || d[corn-y*nx]!=d[corn-y*nx-2]) break;
4109 }
4110 if (y==ny/2+5) image->set_attr("hadzeroedge",2);
4111
4112 }
4113 if (zval==9.99e23f) zval=0;
4114
4115 for (j = 0; j < ny; j++) {
4116 for (i = 0; i < nx - 1; i++) {
4117 if (d[i + j * nx] != zval) {
4118 break;
4119 }
4120 }
4121
4122 float v = d[i + j * nx];
4123 while (i >= 0) {
4124 d[i + j * nx] = v;
4125 i--;
4126 }
4127
4128 for (i = nx - 1; i > 0; i--) {
4129 if (d[i + j * nx] != zval)
4130 break;
4131 }
4132 v = d[i + j * nx];
4133 while (i < nx) {
4134 d[i + j * nx] = v;
4135 i++;
4136 }
4137 }
4138
4139 for (i = 0; i < nx; i++) {
4140 for (j = 0; j < ny; j++) {
4141 if (d[i + j * nx] != zval)
4142 break;
4143 }
4144
4145 float v = d[i + j * nx];
4146 while (j >= 0) {
4147 d[i + j * nx] = v;
4148 j--;
4149 }
4150
4151 for (j = ny - 1; j > 0; j--) {
4152 if (d[i + j * nx] != zval)
4153 break;
4154 }
4155 v = d[i + j * nx];
4156 while (j < ny) {
4157 d[i + j * nx] = v;
4158 j++;
4159 }
4160 }
4161
4162
4163 image->update();
4164}
4165
4167{
4168 if (!image) {
4169 LOGWARN("NULL Image");
4170 return;
4171 }
4172
4173 bool fix_zero=(bool)params.set_default("fix_zero",0);
4174 float sigmamult=(float)params.set_default("sigma",3.0);
4175
4176 if (sigmamult<=0.0) throw InvalidValueException(sigmamult,"threshold.outlier.localmean: sigma must be >0");
4177
4178 float hithr=(float)image->get_attr("mean")+(float)(image->get_attr("sigma"))*sigmamult;
4179 float lothr=(float)image->get_attr("mean")-(float)(image->get_attr("sigma"))*sigmamult;
4180
4181 int nx=image->get_xsize();
4182 int ny=image->get_ysize();
4183 int nz=image->get_zsize();
4184
4185 // This isn't optimally efficient
4186 EMData *im[2];
4187 im[0]=image;
4188 im[1]=image->copy_head();
4189
4190 if (nz==1) {
4191 int repeat=1;
4192 while (repeat) {
4193 memcpy(im[1]->get_data(),im[0]->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
4194 repeat=0;
4195 for (int y=0; y<ny; y++) {
4196 for (int x=0; x<nx; x++) {
4197 // if the pixel is an outlier
4198 float pix=im[1]->get_value_at(x,y);
4199 if (pix>hithr || pix<lothr || (pix==0 && fix_zero)) {
4200 int y0=0>y-1?0:y-1;
4201 int y1=y>=ny-1?ny-1:y+1;
4202 int x0=0>x-1?0:x-1;
4203 int x1=x>=nx-1?nx-1:x+1;
4204 float c=0.0f,nc=0.0f;
4205 for (int yy=y0; yy<=y1; yy++) {
4206 for (int xx=x0; xx<=x1; xx++) {
4207 float lpix=im[1]->get_value_at(xx,yy);
4208 if (lpix>hithr || lpix<lothr || (lpix==0 && fix_zero)) continue;
4209 c+=lpix;
4210 nc++;
4211 }
4212 }
4213 if (nc!=0) im[0]->set_value_at(x,y,c/nc);
4214 else repeat=1;
4215 }
4216 }
4217 }
4218 }
4219 }
4220 else {
4221 throw ImageDimensionException("threshold.outlier.localmean: 3D not yet implemented");
4222 }
4223 delete im[1];
4224}
4225
4226
4228{
4229 if (!image) {
4230 LOGWARN("NULL Image");
4231 return;
4232 }
4233 if (image->get_zsize() > 1) {
4234 LOGERR("BeamstopProcessor doesn't support 3D model");
4235 throw ImageDimensionException("3D model not supported");
4236 }
4237
4238 float value1 = params["value1"];
4239 float value2 = params["value2"];
4240 float value3 = params["value3"];
4241
4242 float thr = fabs(value1);
4243 float *data = image->get_data();
4244 int cenx = (int) value2;
4245 int ceny = (int) value3;
4246
4247 int nx = image->get_xsize();
4248 int ny = image->get_ysize();
4249
4250 if (cenx <= 0) {
4251 cenx = nx / 2;
4252 }
4253
4254 if (ceny <= 0) {
4255 ceny = ny / 2;
4256 }
4257
4258 int mxr = (int) floor(sqrt(2.0f) * nx / 2);
4259
4260 float *mean_values = new float[mxr];
4261 float *sigma_values = new float[mxr];
4262 double sum = 0;
4263 int count = 0;
4264 double square_sum = 0;
4265
4266 for (int i = 0; i < mxr; i++) {
4267 sum = 0;
4268 count = 0;
4269 square_sum = 0;
4270 int nitems = 6 * i + 2;
4271
4272 for (int j = 0; j < nitems; j++) {
4273 float ang = j * 2 * M_PI / nitems;
4274 int x0 = (int) floor(cos(ang) * i + cenx);
4275 int y0 = (int) floor(sin(ang) * i + ceny);
4276
4277 if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny) {
4278 continue;
4279 }
4280
4281 float f = data[x0 + y0 * nx];
4282 sum += f;
4283 square_sum += f * f;
4284 count++;
4285 }
4286
4287 mean_values[i] = (float)sum / count;
4288 sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
4289 }
4290
4291
4292 for (int k = 0; k < 5; k++) {
4293 for (int i = 0; i < mxr; i++) {
4294 sum = 0;
4295 count = 0;
4296 square_sum = 0;
4297 int nitems = 6 * i + 2;
4298 double thr1 = mean_values[i] - sigma_values[i] * thr;
4299 double thr2 = mean_values[i] + sigma_values[i];
4300
4301 for (int j = 0; j < nitems; j++) {
4302 float ang = j * 2 * M_PI / nitems;
4303 int x0 = (int) floor(cos(ang) * i + cenx);
4304 int y0 = (int) floor(sin(ang) * i + ceny);
4305
4306 if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny ||
4307 data[x0 + y0 * nx] < thr1 || data[x0 + y0 * nx] > thr2) {
4308 continue;
4309 }
4310
4311 sum += data[x0 + y0 * nx];
4312 square_sum += data[x0 + y0 * nx] * data[x0 + y0 * nx];
4313 count++;
4314 }
4315
4316 mean_values[i] = (float) sum / count;
4317 sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
4318 }
4319 }
4320
4321 for (int i = 0; i < nx; i++) {
4322 for (int j = 0; j < ny; j++) {
4323
4324 int r = Util::round(hypot((float) i - cenx, (float) j - ceny));
4325
4326 if (value1 < 0) {
4327 if (data[i + j * nx] < (mean_values[r] - sigma_values[r] * thr)) {
4328 data[i + j * nx] = 0;
4329 }
4330 else {
4331 data[i + j * nx] -= mean_values[r];
4332 }
4333 continue;
4334 }
4335 if (data[i + j * nx] > (mean_values[r] - sigma_values[r] * thr)) {
4336 continue;
4337 }
4338 data[i + j * nx] = mean_values[r];
4339 }
4340 }
4341
4342 if( mean_values )
4343 {
4344 delete[]mean_values;
4345 mean_values = 0;
4346 }
4347
4348 if( sigma_values )
4349 {
4350 delete[]sigma_values;
4351 sigma_values = 0;
4352 }
4353
4354 image->update();
4355}
4356
4357
4358
4360{
4361 if (!image) {
4362 LOGWARN("NULL Image");
4363 return;
4364 }
4365 if (image->get_zsize() > 1) {
4366 LOGERR("MeanZeroEdgeProcessor doesn't support 3D model");
4367 throw ImageDimensionException("3D model not supported");
4368 }
4369
4370 int nx = image->get_xsize();
4371 int ny = image->get_ysize();
4372 Dict dict = image->get_attr_dict();
4373 float mean_nonzero = dict.get("mean_nonzero");
4374
4375 float *d = image->get_data();
4376 int i = 0;
4377 int j = 0;
4378
4379 for (j = 0; j < ny; j++) {
4380 for (i = 0; i < nx - 1; i++) {
4381 if (d[i + j * nx] != 0) {
4382 break;
4383 }
4384 }
4385
4386 if (i == nx - 1) {
4387 i = -1;
4388 }
4389
4390 float v = d[i + j * nx] - mean_nonzero;
4391
4392 while (i >= 0) {
4393 v *= 0.9f;
4394 d[i + j * nx] = v + mean_nonzero;
4395 i--;
4396 }
4397
4398
4399 for (i = nx - 1; i > 0; i--) {
4400 if (d[i + j * nx] != 0) {
4401 break;
4402 }
4403 }
4404
4405 if (i == 0) {
4406 i = nx;
4407 }
4408
4409 v = d[i + j * nx] - mean_nonzero;
4410
4411 while (i < nx) {
4412 v *= .9f;
4413 d[i + j * nx] = v + mean_nonzero;
4414 i++;
4415 }
4416 }
4417
4418
4419 for (i = 0; i < nx; i++) {
4420 for (j = 0; j < ny; j++) {
4421 if (d[i + j * nx] != 0)
4422 break;
4423 }
4424
4425 float v = d[i + j * nx] - mean_nonzero;
4426
4427 while (j >= 0) {
4428 v *= .9f;
4429 d[i + j * nx] = v + mean_nonzero;
4430 j--;
4431 }
4432
4433 for (j = ny - 1; j > 0; j--) {
4434 if (d[i + j * nx] != 0)
4435 break;
4436 }
4437
4438 v = d[i + j * nx] - mean_nonzero;
4439
4440 while (j < ny) {
4441 v *= .9f;
4442 d[i + j * nx] = v + mean_nonzero;
4443 j++;
4444 }
4445 }
4446
4447 image->update();
4448}
4449
4450
4451
4453{
4454 if (!image) {
4455 LOGWARN("NULL Image");
4456 return;
4457 }
4458
4459 float *data = image->get_data();
4460 int nx = image->get_xsize();
4461 int ny = image->get_ysize();
4462 int nz = image->get_zsize();
4463 size_t nxy = (size_t)nx * ny;
4464
4465 size_t idx;
4466 for (int z = 0; z < nz; z++) {
4467 for (int x = 0; x < nx; x++) {
4468 double sum = 0;
4469 for (int y = 0; y < ny; y++) {
4470 idx = x + y * nx + z * nxy;
4471 sum += data[idx];
4472 }
4473 float mean = (float) sum / ny;
4474
4475 for (int y = 0; y < ny; y++) {
4476 idx = x + y * nx + z * nxy;
4477 data[idx] = mean;
4478 }
4479 }
4480 }
4481
4482 image->update();
4483}
4484
4486{
4487 if (!image) {
4488 LOGWARN("NULL Image");
4489 return;
4490 }
4491
4492 int nx = image->get_xsize();
4493 int ny = image->get_ysize();
4494
4495 float *d = image->get_data();
4496 int width = params["width"];
4497
4498 if (width > min(nx,ny)/2.){
4499 LOGERR("width parameter cannot be greater than min(nx,ny)/2");
4500 throw InvalidParameterException("width cannot be greater than min(nx,ny)/2");
4501 }
4502
4503 if (image->get_zsize() > 1){
4504 for (int k=0; k<image->get_zsize(); k++){
4505 int zidx = k*nx*ny;
4506 for (int i=0; i<width; i++) {
4507 float frac=i/(float)width;
4508 for (int j=0; j<nx; j++) {
4509 d[zidx+j+i*nx]*=frac;
4510 d[zidx+nx*ny-j-i*nx-1]*=frac;
4511 }
4512 for (int j=0; j<ny; j++) {
4513 d[zidx+j*nx+i]*=frac;
4514 d[zidx+nx*ny-j*nx-i-1]*=frac;
4515 }
4516 }
4517 }
4518 }
4519 else {
4520
4521 for (int i=0; i<width; i++) {
4522 float frac=i/(float)width;
4523 for (int j=0; j<nx; j++) {
4524 d[j+i*nx]*=frac;
4525 d[nx*ny-j-i*nx-1]*=frac;
4526 }
4527 for (int j=0; j<ny; j++) {
4528 d[j*nx+i]*=frac;
4529 d[nx*ny-j*nx-i-1]*=frac;
4530 }
4531 }
4532 }
4533
4534 image->update();
4535}
4536
4538{
4539 if (!image) {
4540 LOGWARN("NULL Image");
4541 return;
4542 }
4543
4544 if (image->get_zsize() > 1) {
4545 LOGERR("ZeroEdgeRowProcessor is not supported in 3D models");
4546 throw ImageDimensionException("3D model not supported");
4547 }
4548
4549 int nx = image->get_xsize();
4550 int ny = image->get_ysize();
4551
4552 float *d = image->get_data();
4553 int apodize = params.set_default("apodize",0);
4554 if (apodize>0) throw InvalidValueException(apodize," apodize not yet supported.");
4555
4556 int top_nrows = std::max(0,params.set_default("y0",0)-apodize);
4557 int bottom_nrows = std::max(0,params.set_default("y1",top_nrows)-apodize);
4558
4559 int left_ncols = std::max(0,params.set_default("x0",0)-apodize);
4560 int right_ncols = std::max(0,params.set_default("x1",left_ncols)-apodize);
4561
4562
4563
4564 size_t row_size = nx * sizeof(float);
4565
4566 memset(d, 0, top_nrows * row_size);
4567 memset(d + (ny - bottom_nrows) * nx, 0, bottom_nrows * row_size);
4568
4569 for (int i = top_nrows; i < ny - bottom_nrows; i++) {
4570 memset(d + i * nx, 0, left_ncols * sizeof(float));
4571 memset(d + i * nx + nx - right_ncols, 0, right_ncols * sizeof(float));
4572 }
4573 image->update();
4574}
4575
4577{
4578 if (!image) {
4579 LOGWARN("NULL Image");
4580 return;
4581 }
4582
4583 if (image->get_zsize() <= 1) {
4584 LOGERR("ZeroEdgePlaneProcessor only support 3D models");
4585 throw ImageDimensionException("3D model only");
4586 }
4587
4588 int nx = image->get_xsize();
4589 int ny = image->get_ysize();
4590 int nz = image->get_zsize();
4591
4592 float *d = image->get_data();
4593
4594 int x0=params["x0"];
4595 int x1=params.set_default("x1",x0);
4596 int y0=params["y0"];
4597 int y1=params.set_default("y1",y0);
4598 int z0=params["z0"];
4599 int z1=params.set_default("z1",z0);
4600
4601 size_t row_size = nx * sizeof(float);
4602 size_t nxy = nx * ny;
4603 size_t sec_size = nxy * sizeof(float);
4604 size_t y0row = y0 * row_size;
4605 size_t y1row = y1 * row_size;
4606 int max_y = ny-y1;
4607 size_t x0size = x0*sizeof(float);
4608 size_t x1size = x1*sizeof(float);
4609
4610 memset(d,0,z0*sec_size); // zero -z
4611 memset(d+(nxy*(nz-z1)),0,sec_size*z1); // zero +z
4612
4613 for (int z=z0; z<nz-z1; z++) {
4614 memset(d+z*nxy,0,y0row); // zero -y
4615 memset(d+z*nxy+(ny-y1)*nx,0,y1row); // zero +y
4616
4617 int znxy = z * nxy;
4618 int znxy2 = znxy + nx - x1;
4619
4620 for (int y=y0; y<max_y; y++) {
4621 memset(d+znxy+y*nx,0,x0size); // zero -x
4622 memset(d+znxy2+y*nx,0,x1size); // zero +x
4623 }
4624 }
4625
4626 image->update();
4627}
4628
4629
4631{
4632 return image->get_attr("sigma");
4633}
4634
4636{
4637 if (!image) {
4638 LOGWARN("cannot do normalization on NULL image");
4639 return;
4640 }
4641
4642 if (image->is_complex()) {
4643 LOGWARN("cannot do normalization on complex image");
4644 return;
4645 }
4646
4647 float sigma = calc_sigma(image);
4648 if (sigma == 0 || !Util::goodf(&sigma)) {
4649 LOGWARN("cannot do normalization on image with sigma = 0");
4650 return;
4651 }
4652
4653 float mean = calc_mean(image);
4654
4655 size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
4656 float *data = image->get_data();
4657
4658 for (size_t i = 0; i < size; ++i) {
4659 data[i] = (data[i] - mean) / sigma;
4660 }
4661
4662 image->update();
4663}
4664
4666{
4667 if (!image) {
4668 LOGWARN("NULL Image");
4669 return 0;
4670 }
4671 float ret=sqrt((float)image->get_attr("square_sum"));
4672 return ret==0.0f?1.0f:ret;
4673}
4674
4676{
4677 if (!image) {
4678 LOGWARN("NULL Image");
4679 return 0;
4680 }
4681 float ret=(float)image->get_attr("mean")*image->get_xsize()*image->get_ysize()*image->get_zsize();
4682 return ret==0.0f?1.0f:ret;
4683}
4684
4686{
4687 if (!image) {
4688 LOGWARN("NULL Image");
4689 return;
4690 }
4691 EMData *mask = params["mask"];
4692 int no_sigma = params.set_default("no_sigma",0);
4693 int apply_mask = params.set_default("apply_mask",0);
4694
4695 int nx=image->get_xsize();
4696 int ny=image->get_ysize();
4697 int nz=image->get_zsize();
4698
4699 double sum=0;
4700 double sumsq=0;
4701 double nnz=0;
4702
4703 for (int z=0; z<nz; z++) {
4704 for (int y=0; y<ny; y++) {
4705 for (int x=0; x<nx; x++) {
4706 double m=mask->get_value_at(x,y,z);
4707 if (m==0) continue;
4708 if (!apply_mask) m=1.0; // If not applying the mask (which may have values between 0 and 1) we don't want to alter the values
4709 double v=(double)image->get_value_at(x,y,z)*m;
4710 sum+=v;
4711 sumsq+=v*v;
4712 nnz+=1.0;
4713 }
4714 }
4715 }
4716
4717 float mean=(float)(sum/nnz);
4718 float sigma=sqrt((float)(sumsq-sum*sum/nnz)/nnz);
4719 if (no_sigma) sigma=1.0f;
4720
4721 for (int z=0; z<nz; z++) {
4722 for (int y=0; y<ny; y++) {
4723 for (int x=0; x<nx; x++) {
4724 float m=mask->get_value_at(x,y,z);
4725 if (!apply_mask) m=1.0; // If not applying the mask (which may have values between 0 and 1) we don't want to alter the values
4726 if (m==0) image->set_value_at(x,y,z,0);
4727 else image->set_value_at(x,y,z,(image->get_value_at(x,y,z)*m-mean)/sigma);
4728 }
4729 }
4730 }
4731}
4732
4734{
4735 if (!image) {
4736 LOGWARN("cannot do normalization on NULL image");
4737 return;
4738 }
4739
4740 if (image->is_complex()) {
4741 LOGWARN("cannot do normalization on complex image");
4742 return;
4743 }
4744
4745 image->process_inplace( "filter.ramp" );
4746 int nx = image->get_xsize();
4747 EMData mask(nx,nx);
4748 mask.process_inplace("testimage.circlesphere", Dict("radius",nx/2-2,"fill",1));
4749
4750 vector<float> rstls = Util::infomask( image, &mask, false);
4751 image->add((float)-rstls[0]);
4752 image->mult((float)1.0/rstls[1]);
4753 image->update();
4754}
4755
4757{
4758 float mass = params.set_default("mass",-1.0f);
4759 int verbose = params.set_default("verbose",0);
4760
4761 if (mass <= 0) throw InvalidParameterException("You must specify a positive non zero mass");
4762
4763 float tthr = params.set_default("thr",(float)image->get_attr("mean")+(float)image->get_attr("sigma"));
4764
4765 float apix = image->get_attr_default("apix_x",1.0f);
4766 apix = params.set_default("apix",apix);
4767
4768 if (apix <= 0) throw InvalidParameterException("You must specify a positive non zero apix");
4769
4770 float step = ((float)image->get_attr("sigma"))/5.0f;
4771
4772 if (step==0) throw InvalidParameterException("This image has sigma=0, cannot give it mass");
4773
4774
4775 size_t n = image->get_size();
4776 float* d = image->get_data();
4777
4778
4779 float thr=(float)image->get_attr("mean")+(float)image->get_attr("sigma")/2.0;
4780 int count=0;
4781 for (size_t i=0; i<n; ++i) {
4782 if (d[i]>=thr) ++count;
4783 }
4784 if (verbose) printf("apix=%1.3f\tmass=%1.1f\tthr=%1.2f\tstep=%1.3g\n",apix,mass,thr,step);
4785
4786 float max = image->get_attr("maximum");
4787 float min = image->get_attr("minimum");
4788 for (int j=0; j<4; j++) {
4789 int err=0;
4790 while (thr<max && count*apix*apix*apix*.81/1000.0>mass) {
4791 thr+=step;
4792 count=0;
4793 for (size_t i=0; i<n; ++i) {
4794 if (d[i]>=thr) ++count;
4795 }
4796 err+=1;
4797 if (err>1000) throw InvalidParameterException("Specified mass could not be achieved");
4798 if (verbose>1) printf("%d\t%d\t%1.3f\t%1.2f\n",err,count,thr,count*apix*apix*apix*.81/1000.0);
4799 }
4800
4801 step/=4.0;
4802
4803 while (thr>min && count*apix*apix*apix*.81/1000.0<mass) {
4804 thr-=step;
4805 count=0;
4806 for (size_t i=0; i<n; ++i) {
4807 if (d[i]>=thr) ++count;
4808 }
4809 err+=1;
4810 if (err>1000) throw InvalidParameterException("Specified mass could not be achieved");
4811 if (verbose>1) printf("%d\t%d\t%1.3f\t%1.2f\n",err,count,thr,count*apix*apix*apix*.81/1000.0);
4812
4813 }
4814 step/=4.0;
4815 }
4816
4817 // We don't adjust the map if we get a negative value
4818 if ((float)tthr/thr>0) image->mult((float)tthr/thr);
4819 else printf("WARNING: could not normalize map to specified mass.");
4820 image->update();
4821}
4822
4824{
4825 if (!image) {
4826 LOGWARN("NULL Image");
4827 return 0;
4828 }
4829 return image->get_edge_mean();
4830}
4831
4833{
4834 if (!image) {
4835 LOGWARN("NULL Image");
4836 return 0;
4837 }
4838// return image->get_circle_mean();
4839 int nx=image->get_xsize();
4840 int ny=image->get_ysize();
4841 int nz=image->get_zsize();
4842
4843 float radius = params.set_default("radius",((float)ny/2-2));
4844 float width = params.set_default("width",2.0f);
4845 if (radius<0) radius=ny/2+radius;
4846
4847 static bool busy = false; // reduce problems with threads and different image sizes
4848 static EMData *mask = 0;
4849 static int oldradius=radius;
4850 static int oldwidth=width;
4851
4852 if (!mask || !EMUtil::is_same_size(image, mask)||radius!=oldradius||width!=oldwidth) {
4853 while (busy) ;
4854 busy=true;
4855 if (!mask) {
4856 mask = new EMData();
4857 }
4858 mask->set_size(nx, ny, nz);
4859 mask->to_one();
4860
4861 mask->process_inplace("mask.sharp", Dict("inner_radius", radius,
4862 "outer_radius", radius + width));
4863
4864 }
4865 busy=true;
4866 double n = 0,s=0;
4867 float *d = mask->get_data();
4868 float * data = image->get_data();
4869 size_t size = (size_t)nx*ny*nz;
4870 for (size_t i = 0; i < size; ++i) {
4871 if (d[i]!=0.0f) { n+=1.0; s+=data[i]; }
4872 }
4873
4874 float result = (float)(s/n);
4875// printf("cmean=%f\n",result);
4876 busy=false;
4877
4878 return result;
4879}
4880
4881
4883{
4884 if (!image) {
4885 LOGWARN("NULL Image");
4886 return 0;
4887 }
4888 float maxval = image->get_attr("maximum");
4889 float minval = image->get_attr("minimum");
4890 return (maxval + minval) / 2;
4891}
4892
4894{
4895 if (!image) {
4896 LOGWARN("NULL Image");
4897 return 0;
4898 }
4899 float maxval = image->get_attr("maximum");
4900 float minval = image->get_attr("minimum");
4901 return (maxval - minval) / 2;
4902}
4903
4905{
4906 if (!image) {
4907 LOGWARN("NULL Image");
4908 return 0;
4909 }
4910 double sum = 0;
4911 int nx = image->get_xsize();
4912 int ny = image->get_ysize();
4913 int nz = image->get_zsize();
4914 float *d = image->get_data();
4915 size_t nyz = ny * nz;
4916
4917 for (size_t i = 0; i < nyz; i++) {
4918 size_t l = i * nx;
4919 size_t r = l + nx - 2;
4920 sum += d[l] + d[l + 1] + d[r] + d[r + 1];
4921 }
4922 float mean = (float) sum / (4 * nyz);
4923 return mean;
4924}
4925
4927{
4928 if (!image) {
4929 LOGWARN("NULL Image");
4930 return;
4931 }
4932
4933
4934
4935
4936 float *rdata = image->get_data();
4937 int nx = image->get_xsize();
4938 int ny = image->get_ysize();
4939 int nz = image->get_zsize();
4940
4941 if (nz > 1) {
4942 // Muyuan 08/2018: normalize by slice when nz>1
4943 // since this processor is not used anyways..
4944 for (int z = 0; z < nz; z++) {
4945 double row_sum = 0;
4946 double row_sqr = 0;
4947 for (int y = 0; y < ny; y++) {
4948 for (int x = 0; x < nx; x++) {
4949 float d = rdata[x + y * nx + z*nx*ny];
4950 row_sum += d;
4951 d*=d;
4952 row_sqr += d;
4953 }
4954 }
4955 double row_mean = row_sum / nx / ny;
4956 double row_std = row_sqr / nx / ny;
4957 row_std = sqrt(row_std - row_mean*row_mean);
4958 for (int y = 0; y < ny; y++) {
4959 for (int x = 0; x < nx; x++) {
4960 rdata[x + y * nx+ z*nx*ny] -= (float)row_mean;
4961 rdata[x + y * nx+ z*nx*ny] /= (float)row_std;
4962 }
4963 }
4964
4965 }
4966
4967
4968// LOGERR("row normalize only works for 2D image");
4969// return;
4970 }
4971
4972 else {
4973 if (params.has_key("unitlen")) {
4974 for (int y = 0; y < ny; y++) {
4975 double row_len = 0;
4976 for (int x = 0; x < nx; x++) {
4977 row_len += pow((double)rdata[x + y * nx],2.0);
4978 }
4979 row_len=sqrt(row_len);
4980 if (row_len==0) row_len=1.0;
4981
4982 for (int x = 0; x < nx; x++) {
4983 rdata[x + y * nx] /= (float)row_len;
4984 }
4985 }
4986 image->update();
4987 return;
4988 }
4989
4990 for (int y = 0; y < ny; y++) {
4991 double row_sum = 0;
4992 for (int x = 0; x < nx; x++) {
4993 row_sum += rdata[x + y * nx];
4994 }
4995
4996 double row_mean = row_sum / nx;
4997 if (row_mean <= 0) {
4998 row_mean = 1;
4999 }
5000
5001 for (int x = 0; x < nx; x++) {
5002 rdata[x + y * nx] /= (float)row_mean;
5003 }
5004 }
5005 }
5006 image->update();
5007}
5008
5010{
5011 if (!image) {
5012 LOGWARN("NULL Image");
5013 return 0;
5014 }
5015 return image->get_attr("mean");
5016}
5017
5019{
5020 if (!image) {
5021 LOGWARN("NULL Image");
5022 return 0;
5023 }
5024 float mean = image->get_attr("mean");
5025 float sig = image->get_attr("sigma");
5026 size_t n=image->get_size();
5027
5028 // We want at least 100 values per bin on average
5029 int hist_size = image->get_size()/100;
5030 if (hist_size>1000) hist_size=1000;
5031 if (hist_size<5) hist_size=5;
5032 vector<float> hist(hist_size,0.0f);
5033
5034 float histmin=mean-2.0f*sig;
5035 float histmax=mean+2.0f*sig;
5036 float step=(histmax-histmin)/(hist_size-1);
5037 for (size_t i=0; i<n; i++) {
5038 int bin = (image->get_value_at_index(i)-histmin)/step;
5039 bin=bin<0?0:(bin>=hist_size?hist_size-1:bin);
5040 hist[bin]++;
5041 }
5042
5043 // yes, probably could use fancy vector methods...
5044 int maxv=hist[1],maxn=1;
5045 for (int i=2; i<hist_size-1; i++) {
5046 if (hist[i]>maxv) { maxv=hist[i]; maxn=i; }
5047 }
5048
5049 // weighted average position of the peak and nearest neighbors
5050 float v1=hist[maxn-1],v2=hist[maxn],v3=hist[maxn+1];
5051 float ret= (v1*(maxn-1)+v2*maxn+v3*(maxn+1))/(v1+v2+v3)*step+histmin;
5052 printf("%f %f %f %f %f %f\n",v1,v2,v3,mean,sig,ret);
5053
5054 return ret;
5055}
5056
5057
5058
5060{
5061 if (!image) {
5062 LOGWARN("NULL Image");
5063 return NULL;
5064 }
5065
5066 EMData *refr = params["ref"];
5067 EMData *actual = params.set_default("actual",(EMData*)NULL);
5068 EMData *ref;
5069 bool return_radial = params.set_default("return_radial",false);
5070 bool return_fft = params.set_default("return_fft",false);
5071 bool ctfweight = params.set_default("ctfweight",false);
5072 bool return_presigma = params.set_default("return_presigma",false);
5073 bool return_subim = params.set_default("return_subim",false);
5074 int si0=(int)floor(params.set_default("low_cutoff_frequency",0.0f)*image->get_ysize());
5075 int si1=(int)ceil(params.set_default("high_cutoff_frequency",0.7071f)*image->get_ysize()); // include the corners unless explicitly excluded
5076
5077 // We will be modifying imf, so it needs to be a copy
5078 EMData *imf;
5079 if (image->is_complex()) imf=image->copy();
5080 else imf=image->do_fft();
5081
5082 if (ctfweight) {
5083 EMData *ctfi=imf->copy_head();
5084 Ctf *ctf;
5085// if (image->has_attr("ctf"))
5086 ctf=(Ctf *)(image->get_attr("ctf"));
5087// else ctf=(Ctf *)(ref->get_attr("ctf"));
5089 imf->mult(*ctfi);
5090 delete ctfi;
5091 }
5092
5093 // Make sure ref is complex
5094 if (refr->is_complex()) ref=refr;
5095 else ref=refr->do_fft();
5096
5097 EMData *actf;
5098 if (actual==NULL) actf=ref;
5099 else {
5100 if (ctfweight) throw InvalidCallException("math.sub.optimal: Sorry, cannot use ctfweight in combination with actual");
5101 if (actual->is_complex()) actf=actual;
5102 else actf=actual->do_fft();
5103 }
5104
5105 int ny2=(int)(image->get_ysize()*sqrt(2.0)/2);
5106 vector <double>rad(ny2+1);
5107 vector <double>norm(ny2+1);
5108
5109 // We are essentially computing an FSC here, but while the reference (the image
5110 // we plan to subtract) is normalized, the other image is not. This gives us a filter
5111 // to apply to the reference to optimally eliminate its contents from 'image'.
5112 for (int y=-ny2; y<ny2; y++) {
5113 for (int x=0; x<ny2; x++) {
5114 int r=int(Util::hypot_fast(x,y));
5115 if (r>ny2) continue;
5116 std::complex<float> v1=imf->get_complex_at(x,y);
5117 std::complex<float> v2=ref->get_complex_at(x,y);
5118 rad[r]+=(double)(v1.real()*v2.real()+v1.imag()*v2.imag());
5119// norm[r]+=v2.real()*v2.real()+v2.imag()*v2.imag()+v1.real()*v1.real()+v1.imag()*v1.imag();
5120 norm[r]+=(double)(v2.real()*v2.real()+v2.imag()*v2.imag());
5121 }
5122 }
5123 for (int i=1; i<ny2; i++) rad[i]/=norm[i];
5124 rad[0]=0;
5125// FILE *out=fopen("dbug.txt","w");
5126// for (int i=0; i<ny2; i++) fprintf(out,"%lf\t%lf\t%lf\n",(float)i,rad[i],norm[i]);
5127// fclose(out);
5128
5129 float oldsig=-1.0;
5130 // This option computes the real-space sigma on the input-image after the specified filter
5131 // This is an expensive option, but more efficient than computing the same using other means
5132 if (return_presigma) {
5133 for (int y=-ny2; y<ny2; y++) {
5134 for (int x=0; x<imf->get_xsize()/2; x++) {
5135 int r=int(Util::hypot_fast(x,y));
5136 if (r>=ny2 || r>=si1 || r<si0) {
5137 imf->set_complex_at(x,y,0);
5138 continue;
5139 }
5140 std::complex<float> v1=imf->get_complex_at(x,y);
5141 imf->set_complex_at(x,y,v1);
5142 }
5143 }
5144 EMData *tmp=imf->do_ift();
5145 oldsig=(float)tmp->get_attr("sigma");
5146 delete tmp;
5147 }
5148
5149 for (int y=-ny2; y<ny2; y++) {
5150 for (int x=0; x<imf->get_xsize()/2; x++) {
5151 int r=int(Util::hypot_fast(x,y));
5152 if (r>=ny2 || r>=si1 || r<si0) {
5153 imf->set_complex_at(x,y,0);
5154 continue;
5155 }
5156 std::complex<float> v1=imf->get_complex_at(x,y);
5157 std::complex<float> v2=actf->get_complex_at(x,y);
5158 v2*=(float)rad[r];
5159 if (return_subim) imf->set_complex_at(x,y,v2);
5160 else imf->set_complex_at(x,y,v1-v2);
5161 }
5162 }
5163
5164 if (!refr->is_complex()) delete ref;
5165 if (actual!=NULL && !actual->is_complex()) delete actf;
5166
5167 vector <float>radf;
5168 if (return_radial) {
5169 radf.resize(ny2);
5170 for (int i=0; i<ny2; i++) radf[i]=(float)rad[i];
5171 }
5172
5173 if (!return_fft) {
5174 EMData *ret=imf->do_ift();
5175 delete imf;
5176 if (return_radial) ret->set_attr("filter_curve",radf);
5177 if (return_presigma) {
5178 ret->set_attr("sigma_presub",oldsig);
5179// printf("Set %f\n",(float)image->get_attr("sigma_presub"));
5180 }
5181 return ret;
5182 }
5183 if (return_radial) imf->set_attr("filter_curve",radf);
5184 if (return_presigma) imf->set_attr("sigma_presub",oldsig);
5185 return imf;
5186}
5187
5189{
5190 if (!image) {
5191 LOGWARN("NULL image");
5192 return;
5193 }
5194
5195 EMData *tmp=process(image);
5196 memcpy(image->get_data(),tmp->get_data(),(size_t)image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
5197 delete tmp;
5198 image->update();
5199 return;
5200}
5201
5202
5204{
5205 if (!image) {
5206 LOGWARN("NULL Image");
5207 return;
5208 }
5209
5210 EMData *to = params["to"];
5211
5212 bool ignore_zero = params.set_default("ignore_zero",true);
5213 bool fourieramp = params.set_default("fourieramp",false);
5214 bool debug = params.set_default("debug",false);
5215 float ignore_lowsig = params.set_default("ignore_lowsig",-1.0);
5216 float low_threshold = params.set_default("low_threshold",-FLT_MAX);
5217 float high_threshold = params.set_default("high_threshold",FLT_MAX);
5218
5219 int nx = image->get_xsize();
5220 int ny = image->get_ysize();
5221 int nz = image->get_zsize();
5222 size_t size = (size_t)nx * ny * nz;
5223 size_t size2 = 0;
5224
5225 EMData *fim = NULL;
5226 EMData *fto = NULL;
5227 float *dimage; // unthresholded image data
5228 float *dto;
5229 int step=1; // used in Fourier mode
5230
5231 float meani=(float)image->get_attr("mean");
5232 float meant=(float)to->get_attr("mean");
5233 float sigi=(float)image->get_attr("sigma")*ignore_lowsig;
5234 float sigt=(float)to->get_attr("sigma")*ignore_lowsig;
5235
5236 if (fourieramp) {
5237 fim=image->do_fft();
5238 fto=to->do_fft();
5239 fim->ri2ap();
5240 fto->ri2ap();
5241 dimage=fim->get_data();
5242 dto=fto->get_data();
5243 step=2;
5244 size2=(size_t)(nx+2) * ny * nz;
5245
5246 // sigma for thresholding
5247 meani=meant=0; // Fourier amplitude >=0, so we reference everything to this point
5248 sigi=sigt=0;
5249 for (size_t i=0; i<size2; i+=2) { sigi+=pow(dimage[i],2.0f); sigt+=pow(dto[i],2.0f); }
5250 sigi=ignore_lowsig*sqrt(sigi/(size2/2));
5251 sigt=ignore_lowsig*sqrt(sigt/(size2/2));
5252 }
5253 else {
5254 dimage = image->get_data();
5255 dto = to->get_data();
5256 size2=size;
5257 }
5258
5259
5260 // rewrote this to just use GSL and get rid of David's old code.
5261 // The two passes are just to make sure we don't eat too much RAM if we do 3D
5262 if (ignore_lowsig<0) ignore_lowsig=0;
5263
5264 size_t count=0;
5265 for (size_t i = 0; i < size2; i+=step) {
5266 if (dto[i] >= low_threshold && dto[i] <= high_threshold
5267 && (dto[i]>=meant+sigt || dto[i]<=meant-sigt)
5268 && (dimage[i]>=meani+sigi || dimage[i]<=meani-sigi)
5269 && (!ignore_zero ||(dto[i] != 0.0f && dimage[i] != 0.0f))) {
5270 count++;
5271 }
5272 }
5273
5274
5275 double *x=(double *)malloc(count*sizeof(double));
5276 double *y=(double *)malloc(count*sizeof(double));
5277 count=0;
5278 for (size_t i = 0; i < size2; i+=step) {
5279 if (dto[i] >= low_threshold && dto[i] <= high_threshold
5280 && (dto[i]>=meant+sigt || dto[i]<=meant-sigt)
5281 && (dimage[i]>=meani+sigi || dimage[i]<=meani-sigi)
5282 && (!ignore_zero ||(dto[i] != 0.0f && dimage[i] != 0.0f))) {
5283 x[count]=dimage[i];
5284 y[count]=dto[i];
5285 count++;
5286 }
5287 }
5288 double c0,c1;
5289 double cov00,cov01,cov11,sumsq;
5290 gsl_fit_linear (x, 1, y, 1, count, &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
5291
5292 if (debug) {
5293 FILE*out=fopen("debug.txt","w");
5294 for (size_t i = 0; i < count; i++) {
5295 fprintf(out,"%lf\t%lf\n",x[i],y[i]);
5296 }
5297 fclose(out);
5298 printf("add %lf\tmul %lf\t%lf\t%lf\t%lf\t%lf\n",c0,c1,cov00,cov01,cov11,sumsq);
5299 }
5300
5301 free(x);
5302 free(y);
5303 if (fim!=NULL) delete fim;
5304 if (fto!=NULL) delete fto;
5305
5306 if (fourieramp) c0=0; // c0 makes no sense in this context. Really just a measure of noise
5307 dimage = image->get_data();
5308 for (size_t i = 0; i < size; ++i) dimage[i]=dimage[i]*c1+c0;
5309 image->update();
5310 image->set_attr("norm_mult",c1);
5311 image->set_attr("norm_add",c0);
5312}
5313
5315 ENTERFUNC;
5316 if (!image->is_complex()) throw ImageFormatException("Fourier binary thresholding processor only works for complex images");
5317
5318 float threshold = params.set_default("value",0.0f);
5319 image->ri2ap(); // works for cuda
5320
5321 float* d = image->get_data();
5322 for( size_t i = 0; i < image->get_size()/2; ++i, d+=2) {
5323 if ( *d < threshold ) {
5324 *d = 0;
5325 *(d+1) = 0;
5326 }
5327 }
5328 image->ap2ri();
5329 image->set_ri(true); // So it can be used for fourier multiplaction, for example
5330 image->update();
5331 EXITFUNC;
5332}
5333
5335{
5336 if (!image) {
5337 LOGWARN("NULL Image");
5338 return;
5339 }
5340
5341 float distance_sigma = params["distance_sigma"];
5342 float value_sigma = params["value_sigma"];
5343 int max_iter = params["niter"];
5344 int half_width = params["half_width"];
5345
5346 if (half_width < distance_sigma) {
5347 LOGWARN("localwidth(=%d) should be larger than distance_sigma=(%f)\n",
5348 half_width, distance_sigma);
5349 }
5350
5351 distance_sigma *= distance_sigma;
5352
5353 float image_sigma = image->get_attr("sigma");
5354 if (image_sigma > value_sigma) {
5355 LOGWARN("image sigma(=%f) should be smaller than value_sigma=(%f)\n",
5356 image_sigma, value_sigma);
5357 }
5358 value_sigma *= value_sigma;
5359
5360 int nx = image->get_xsize();
5361 int ny = image->get_ysize();
5362 int nz = image->get_zsize();
5363
5364 if(nz==1) { //for 2D image
5365 int width=nx, height=ny;
5366
5367 int i,j,m,n;
5368
5369 float tempfloat1,tempfloat2,tempfloat3;
5370 int index1,index2,index;
5371 int Iter;
5372 int tempint1,tempint3;
5373
5374 tempint1=width;
5375 tempint3=width+2*half_width;
5376
5377 float* mask=(float*)calloc((2*half_width+1)*(2*half_width+1),sizeof(float));
5378 float* OrgImg=(float*)calloc((2*half_width+width)*(2*half_width+height),sizeof(float));
5379 float* NewImg=image->get_data();
5380
5381 for(m=-(half_width);m<=half_width;m++)
5382 for(n=-(half_width);n<=half_width;n++) {
5383 index=(m+half_width)*(2*half_width+1)+(n+half_width);
5384 mask[index]=exp((float)(-(m*m+n*n)/distance_sigma/2.0));
5385 }
5386
5387 //printf("entering bilateral filtering process \n");
5388
5389 Iter=0;
5390 while(Iter<max_iter) {
5391 for(i=0;i<height;i++)
5392 for(j=0;j<width;j++) {
5393 index1=(i+half_width)*tempint3+(j+half_width);
5394 index2=i*tempint1+j;
5395 OrgImg[index1]=NewImg[index2];
5396 }
5397
5398 // Mirror Padding
5399 for(i=0;i<height;i++){
5400 for(j=0;j<half_width;j++) OrgImg[(i+half_width)*tempint3+(j)]=OrgImg[(i+half_width)*tempint3+(2*half_width-j)];
5401 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)];
5402 }
5403 for(i=0;i<half_width;i++){
5404 for(j=0;j<(width+2*half_width);j++) OrgImg[i*tempint3+j]=OrgImg[(2*half_width-i)*tempint3+j];
5405 for(j=0;j<(width+2*half_width);j++) OrgImg[(i+height+half_width)*tempint3+j]=OrgImg[(height+half_width-2-i)*tempint3+j];
5406 }
5407
5408 //printf("finish mirror padding process \n");
5409 //now mirror padding have been done
5410
5411 for(i=0;i<height;i++){
5412 //printf("now processing the %d th row \n",i);
5413 for(j=0;j<width;j++){
5414 tempfloat1=0.0; tempfloat2=0.0;
5415 for(m=-(half_width);m<=half_width;m++)
5416 for(n=-(half_width);n<=half_width;n++){
5417 index =(m+half_width)*(2*half_width+1)+(n+half_width);
5418 index1=(i+half_width)*tempint3+(j+half_width);
5419 index2=(i+half_width+m)*tempint3+(j+half_width+n);
5420 tempfloat3=(OrgImg[index1]-OrgImg[index2])*(OrgImg[index1]-OrgImg[index2]);
5421
5422 tempfloat3=mask[index]*(1.0f/(1+tempfloat3/value_sigma)); // Lorentz kernel
5423 //tempfloat3=mask[index]*exp(tempfloat3/Sigma2/(-2.0)); // Guassian kernel
5424 tempfloat1+=tempfloat3;
5425
5426 tempfloat2+=tempfloat3*OrgImg[(i+half_width+m)*tempint3+(j+half_width+n)];
5427 }
5428 NewImg[i*width+j]=tempfloat2/tempfloat1;
5429 }
5430 }
5431 Iter++;
5432 }
5433
5434 //printf("have finished %d th iteration\n ",Iter);
5435// doneData();
5436 free(mask);
5437 free(OrgImg);
5438 // end of BilaFilter routine
5439
5440 }
5441 else { //3D case
5442 int width = nx;
5443 int height = ny;
5444 int slicenum = nz;
5445
5446 int slice_size = width * height;
5447 int new_width = width + 2 * half_width;
5448 int new_slice_size = (width + 2 * half_width) * (height + 2 * half_width);
5449
5450 int width1 = 2 * half_width + 1;
5451 int mask_size = width1 * width1;
5452 int old_img_size = (2 * half_width + width) * (2 * half_width + height);
5453
5454 int zstart = -half_width;
5455 int zend = -half_width;
5456 int is_3d = 0;
5457 if (nz > 1) {
5458 mask_size *= width1;
5459 old_img_size *= (2 * half_width + slicenum);
5460 zend = half_width;
5461 is_3d = 1;
5462 }
5463
5464 float *mask = (float *) calloc(mask_size, sizeof(float));
5465 float *old_img = (float *) calloc(old_img_size, sizeof(float));
5466
5467 float *new_img = image->get_data();
5468
5469 for (int p = zstart; p <= zend; p++) {
5470 int cur_p = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
5471
5472 for (int m = -half_width; m <= half_width; m++) {
5473 int cur_m = (m + half_width) * (2 * half_width + 1) + half_width;
5474
5475 for (int n = -half_width; n <= half_width; n++) {
5476 int l = cur_p + cur_m + n;
5477 mask[l] = exp((float) (-(m * m + n * n + p * p * is_3d) / distance_sigma / 2.0f));
5478 }
5479 }
5480 }
5481
5482 int iter = 0;
5483 while (iter < max_iter) {
5484 for (int k = 0; k < slicenum; k++) {
5485 size_t cur_k1 = (size_t)(k + half_width) * new_slice_size * is_3d;
5486 int cur_k2 = k * slice_size;
5487
5488 for (int i = 0; i < height; i++) {
5489 int cur_i1 = (i + half_width) * new_width;
5490 int cur_i2 = i * width;
5491
5492 for (int j = 0; j < width; j++) {
5493 size_t k1 = cur_k1 + cur_i1 + (j + half_width);
5494 int k2 = cur_k2 + cur_i2 + j;
5495 old_img[k1] = new_img[k2];
5496 }
5497 }
5498 }
5499
5500 for (int k = 0; k < slicenum; k++) {
5501 size_t cur_k = (k + half_width) * new_slice_size * is_3d;
5502
5503 for (int i = 0; i < height; i++) {
5504 int cur_i = (i + half_width) * new_width;
5505
5506 for (int j = 0; j < half_width; j++) {
5507 size_t k1 = cur_k + cur_i + j;
5508 size_t k2 = cur_k + cur_i + (2 * half_width - j);
5509 old_img[k1] = old_img[k2];
5510 }
5511
5512 for (int j = 0; j < half_width; j++) {
5513 size_t k1 = cur_k + cur_i + (width + half_width + j);
5514 size_t k2 = cur_k + cur_i + (width + half_width - j - 2);
5515 old_img[k1] = old_img[k2];
5516 }
5517 }
5518
5519
5520 for (int i = 0; i < half_width; i++) {
5521 int i2 = i * new_width;
5522 int i3 = (2 * half_width - i) * new_width;
5523 for (int j = 0; j < (width + 2 * half_width); j++) {
5524 size_t k1 = cur_k + i2 + j;
5525 size_t k2 = cur_k + i3 + j;
5526 old_img[k1] = old_img[k2];
5527 }
5528
5529 i2 = (height + half_width + i) * new_width;
5530 i3 = (height + half_width - 2 - i) * new_width;
5531 for (int j = 0; j < (width + 2 * half_width); j++) {
5532 size_t k1 = cur_k + i2 + j;
5533 size_t k2 = cur_k + i3 + j;
5534 old_img[k1] = old_img[k2];
5535 }
5536 }
5537 }
5538
5539 size_t idx;
5540 for (int k = 0; k < slicenum; k++) {
5541 size_t cur_k = (k + half_width) * new_slice_size;
5542
5543 for (int i = 0; i < height; i++) {
5544 int cur_i = (i + half_width) * new_width;
5545
5546 for (int j = 0; j < width; j++) {
5547 float f1 = 0;
5548 float f2 = 0;
5549 size_t k1 = cur_k + cur_i + (j + half_width);
5550
5551 for (int p = zstart; p <= zend; p++) {
5552 size_t cur_p1 = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
5553 size_t cur_p2 = (k + half_width + p) * new_slice_size;
5554
5555 for (int m = -half_width; m <= half_width; m++) {
5556 size_t cur_m1 = (m + half_width) * (2 * half_width + 1);
5557 size_t cur_m2 = cur_p2 + cur_i + m * new_width + j + half_width;
5558
5559 for (int n = -half_width; n <= half_width; n++) {
5560 size_t k = cur_p1 + cur_m1 + (n + half_width);
5561 size_t k2 = cur_m2 + n;
5562 float f3 = Util::square(old_img[k1] - old_img[k2]);
5563
5564 f3 = mask[k] * (1.0f / (1 + f3 / value_sigma));
5565 f1 += f3;
5566 size_t l1 = cur_m2 + n;
5567 f2 += f3 * old_img[l1];
5568 }
5569
5570 idx = (size_t)k * height * width + i * width + j;
5571 new_img[idx] = f2 / f1;
5572 }
5573 }
5574 }
5575 }
5576 }
5577 iter++;
5578 }
5579 if( mask ) {
5580 free(mask);
5581 mask = 0;
5582 }
5583
5584 if( old_img ) {
5585 free(old_img);
5586 old_img = 0;
5587 }
5588 }
5589
5590 image->update();
5591}
5592
5593
5594
5596{
5597 int isinten=image->get_attr_default("is_intensity",0);
5598 if (!image || ((image->is_complex() && image->get_ndim() > 2))){
5599 LOGWARN("only works on real or 2D intensity images. do nothing.");
5600 return;
5601 }
5602
5603 if (image->get_ndim() <= 0 || image->get_ndim() > 3) throw ImageDimensionException("radial average processor only works for real and 2D intensity images");
5604
5605 float *rdata = image->get_data();
5606 int nx = image->get_xsize();
5607 int ny = image->get_ysize();
5608
5609 vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1, 1);
5610
5611 if ((!image->is_complex()) && (isinten == 1)) {
5612 std::reverse(dist.begin(),dist.end());
5613 }
5614
5615 float midx = (float)((int)nx/2);
5616 float midy = (float)((int)ny/2);
5617
5618 size_t c = 0;
5619 if (image->is_complex() && image->get_ndim() == 2) {
5620 for (int y = -ny/2; y < ny/2; y++) {
5621 for (int x = -ny/2-1; x < nx/2+1; x++) {
5622 float r = (float) hypot(x,y);
5623 int i = (int) floor(r);
5624 r -= i;
5625 if (i >= 0 && i < nx / 2 - 1) {
5626 image->set_complex_at(x, y, dist[i] * (1.0f - r) + dist[i + 1] * r);
5627 }
5628 else if (i < 0) {
5629 image->set_complex_at(x, y, dist[0]);
5630 }
5631 else {
5632 image->set_complex_at(x, y, 0);
5633 }
5634 }
5635 }
5636 }
5637 else if (image->get_ndim() == 2) {
5638 for (int y = 0; y < ny; y++) {
5639 for (int x = 0; x < nx; x++, c++) {
5640 float r = (float) hypot(x - midx, y - midy);
5641
5642 int i = (int) floor(r);
5643 r -= i;
5644 if (i >= 0 && i < nx / 2 - 1) {
5645 rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
5646 }
5647 else if (i < 0) {
5648 rdata[c] = dist[0];
5649 }
5650 else {
5651 rdata[c] = 0;
5652 }
5653 }
5654 }
5655 }
5656 else if (image->get_ndim() == 3) {
5657 int nz = image->get_zsize();
5658 float midz = (float)((int)nz/2);
5659 float r;
5660 int i;
5661 for (int z = 0; z < nz; ++z) {
5662 for (int y = 0; y < ny; ++y) {
5663 for (int x = 0; x < nx; ++x, ++c) {
5664
5665 r = (float) Util::hypot3(x - midx, y - midy, z - midz);
5666
5667 i = Util::fast_floor(r);
5668 r -= i;
5669 if (i >= 0 && i < nx / 2 - 1) {
5670 rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
5671 }
5672 else if (i < 0) {
5673 rdata[c] = dist[0];
5674 }
5675 else {
5676 rdata[c] = 0;
5677 }
5678 }
5679 }
5680 }
5681 }
5682
5683 image->update();
5684}
5685
5686
5687
5689{
5690 if (!image || image->is_complex()) {
5691 LOGWARN("only works on real image. do nothing.");
5692 return;
5693 }
5694
5695 if (image->get_ndim() != 2) throw ImageDimensionException("This processor works only for 2D images");
5696
5697 float *rdata = image->get_data();
5698 int nx = image->get_xsize();
5699 int ny = image->get_ysize();
5700
5701 vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
5702
5703 int c = 0;
5704 for (int y = 0; y < ny; y++) {
5705 for (int x = 0; x < nx; x++, c++) {
5706 float r = (float) hypot(x - nx / 2, y - ny / 2);
5707 int i = (int) floor(r);
5708 r -= i;
5709 if (i >= 0 && i < nx / 2 - 1) {
5710 rdata[c] -= dist[i] * (1.0f - r) + dist[i + 1] * r;
5711 }
5712 else {
5713 rdata[c] = 0;
5714 }
5715 }
5716 }
5717
5718 image->update();
5719}
5720
5721
5723 if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
5724 if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
5725
5726 EMData* ret = new EMData(image->get_ysize(),image->get_xsize(),1); // transpose dimensions
5727
5728 for(int j = 0; j< image->get_ysize();++j) {
5729 for(int i = 0; i< image->get_xsize();++i) {
5730 ret->set_value_at(j,i,image->get_value_at(i,j));
5731 }
5732 }
5733
5734 return ret;
5735
5736}
5737
5739 if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
5740 if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
5741
5742 float* data = (float*)malloc(image->get_ysize()*image->get_xsize()*sizeof(float));
5743
5744 int nx = image->get_ysize(); // note tranpose
5745 for(int j = 0; j< image->get_ysize();++j) {
5746 for(int i = 0; i< image->get_xsize();++i) {
5747 data[i*nx+j] = image->get_value_at(i,j);
5748 }
5749 }
5750
5751 image->set_data(data,image->get_ysize(),image->get_xsize(),1);
5752
5753}
5754
5756{
5757 ENTERFUNC;
5758 if (!image) {
5759 LOGWARN("NULL Image");
5760 return;
5761 }
5762 string axis = (const char*)params["axis"];
5763
5764#ifdef EMAN2_USING_CUDA
5765 if (EMData::usecuda == 1 && image->getcudarwdata()) {
5766 //cout << "flip processor" << endl;
5767 float array[12] = {1.0, 0.0, 0.0, 0.0,
5768 0.0, 1.0, 0.0, 0.0,
5769 0.0, 0.0, 1.0, 0.0};
5770 if (axis == "x" || axis == "X") { // horizontal flip
5771 array[0] = -1.0;
5772 }else if (axis == "y" || axis == "Y") { // vertical flip
5773 array[5] = -1.0;
5774 }
5775 else if (axis == "z" || axis == "Z") { // vertical flip
5776 array[10] = -1.0;
5777 }
5778 Transform t(array);
5779 Dict params("transform",(Transform*)&t);
5780 image->process_inplace("xform",params);
5781
5782 EXITFUNC;
5783 return;
5784 }
5785#endif
5786
5787
5788 float *d = image->get_data();
5789 int nx = image->get_xsize();
5790 int ny = image->get_ysize();
5791 int nz = image->get_zsize();
5792
5793 size_t nxy = nx * ny;
5794
5795
5796 // Note in all cases the origin is nx/2, ny/2 and nz/2
5797 // This means when flipping even sized dimensions that some pixels are redundant.
5798 // Here redundant pixels are set to zero, however, should this change to something
5799 // like the mean.
5800 if (axis == "x" || axis == "X") { // Horizontal flip
5801 int offset = (nx%2 == 0);
5802 size_t idx1, idx2;
5803 for(int z = 0; z < nz; ++z) {
5804 for(int y = 0; y < ny; ++y) {
5805 if (offset != 0 ) {
5806 idx1 = z*nxy + y*nx;
5807 d[idx1] = 0; // Here's where you'd make it the mean
5808 }
5809 for(int x = offset; x < nx / 2; ++x) {
5810 idx1 = z*nxy + y*nx + x;
5811 idx2 = z*nxy + y*nx + (nx-x-1+offset);
5812 std::swap(d[idx1], d[idx2]);
5813 }
5814
5815 }
5816 }
5817 }
5818
5819 else if (axis == "y" || axis == "Y") { // vertical flip
5820 int offset = (ny%2 == 0);
5821 for(int z=0; z<nz; ++z) {
5822 if (offset != 0) {
5823 std::fill(d+z*nxy,d+(size_t)z*nxy+nx,0); // So if we have change it to the mean it's easy to do so. (instead of using memset)
5824 }
5825 for(int y=offset; y<ny/2; ++y) {
5826 for(int x=0; x<nx; ++x) {
5827 std::swap(d[(size_t)z*nxy + y*nx +x], d[(size_t)z*nxy + (ny -y -1+offset)*nx +x]);
5828 }
5829 }
5830 }
5831 }
5832 else if (axis == "z" || axis == "Z") { //z axis flip
5833 int offset = (nz%2 == 0);
5834 if (offset != 0) {
5835 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)
5836 }
5837 size_t idx1, idx2;
5838 for(int z=offset; z<nz/2; ++z) {
5839 for(int y=0; y<ny; ++y) {
5840 for(int x=0; x<nx; ++x) {
5841 idx1 = (size_t)z*nxy + y*nx + x;
5842 idx2 = (size_t)(nz-z-1+offset)*nxy + y*nx + x;
5843 std::swap(d[idx1], d[idx2]);
5844 }
5845 }
5846 }
5847 }
5848
5849 image->update();
5850 EXITFUNC;
5851}
5852
5854{
5855 if (!image) {
5856 LOGWARN("NULL Image");
5857 return;
5858 }
5859
5860 Randnum * randnum = Randnum::Instance();
5861 if(params.has_key("seed")) {
5862 randnum->set_seed((int)params["seed"]);
5863 }
5864
5865 float addnoise = params["noise"];
5866 addnoise *= get_sigma(image);
5867 float *dat = image->get_data();
5868
5869 for (size_t j = 0; j < image->get_size(); ++j) {
5870 dat[j] += randnum->get_gauss_rand(addnoise, addnoise / 2);
5871 }
5872
5873 image->update();
5874}
5875
5877{
5878 if (!image) {
5879 LOGWARN("NULL Image");
5880 return 0;
5881 }
5882 return image->get_attr("sigma");
5883}
5884
5886{
5887 if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
5888
5889 int nx=image->get_xsize();
5890 int ny=image->get_ysize();
5891 int nz=image->get_zsize();
5892
5893 int nxy = nx*ny;
5894
5895 if ( ny == 1 && nz == 1 ){
5896 cout << "Warning- attempted Fourier origin shift a 1D image - no action taken" << endl;
5897 return;
5898 }
5899 int yodd = (ny%2==1);
5900 int zodd = (nz%2==1);
5901
5902 float* rdata = image->get_data();
5903
5904 float tmp[2];
5905 float* p1;
5906 float* p2;
5907
5908 if (yodd){
5909 // Swap the middle slice (with respect to the y direction) with the bottom slice
5910 // shifting all slices above the middles slice upwards by one pixel, stopping
5911 // at the middle slice, not if nz = 1 we are not talking about slices, we are
5912 // talking about rows
5913 float prev[2];
5914 size_t idx;
5915 for( int s = 0; s < nz; s++ ) {
5916 for( int c =0; c < nx; c += 2 ) {
5917 idx = (size_t)s*nxy+ny/2*nx+c;
5918 prev[0] = rdata[idx];
5919 prev[1] = rdata[idx+1];
5920 for( int r = 0; r <= ny/2; ++r ) {
5921 idx = (size_t)s*nxy+r*nx+c;
5922 float* p1 = &rdata[idx];
5923 tmp[0] = p1[0];
5924 tmp[1] = p1[1];
5925
5926 p1[0] = prev[0];
5927 p1[1] = prev[1];
5928
5929 prev[0] = tmp[0];
5930 prev[1] = tmp[1];
5931 }
5932 }
5933 }
5934 }
5935
5936 // Shift slices (3D) or rows (2D) correctly in the y direction
5937 size_t idx1, idx2;
5938 for( int s = 0; s < nz; ++s ) {
5939 for( int r = 0 + yodd; r < ny/2+yodd; ++r ) {
5940 for( int c =0; c < nx; c += 2 ) {
5941 idx1 = (size_t)s*nxy+r*nx+c;
5942 idx2 = (size_t)s*nxy+(r+ny/2)*nx+c;
5943 p1 = &rdata[idx1];
5944 p2 = &rdata[idx2];
5945
5946 tmp[0] = p1[0];
5947 tmp[1] = p1[1];
5948
5949 p1[0] = p2[0];
5950 p1[1] = p2[1];
5951
5952 p2[0] = tmp[0];
5953 p2[1] = tmp[1];
5954 }
5955 }
5956 }
5957
5958 if ( nz != 1 )
5959 {
5960
5961 if (zodd){
5962 // Swap the middle slice (with respect to the z direction) and the front slice
5963 // shifting all behind the front slice towards the middle a distance of 1 voxel,
5964 // stopping at the middle slice.
5965 float prev[2];
5966 size_t idx;
5967 for( int r = 0; r < ny; ++r ) {
5968 for( int c =0; c < nx; c += 2 ) {
5969 idx = (size_t)nz/2*nxy+r*nx+c;
5970 prev[0] = rdata[idx];
5971 prev[1] = rdata[idx+1];
5972 for( int s = 0; s <= nz/2; ++s ) {
5973 idx = (size_t)s*nxy+r*nx+c;
5974 float* p1 = &rdata[idx];
5975 tmp[0] = p1[0];
5976 tmp[1] = p1[1];
5977
5978 p1[0] = prev[0];
5979 p1[1] = prev[1];
5980
5981 prev[0] = tmp[0];
5982 prev[1] = tmp[1];
5983 }
5984 }
5985 }
5986 }
5987
5988 // Shift slices correctly in the z direction
5989 size_t idx1, idx2;
5990 for( int s = 0+zodd; s < nz/2 + zodd; ++s ) {
5991 for( int r = 0; r < ny; ++r ) {
5992 for( int c =0; c < nx; c += 2 ) {
5993 idx1 = (size_t)s*nxy+r*nx+c;
5994 idx2 = (size_t)(s+nz/2)*nxy+r*nx+c;
5995 p1 = &rdata[idx1];
5996 p2 = &rdata[idx2];
5997
5998 tmp[0] = p1[0];
5999 tmp[1] = p1[1];
6000
6001 p1[0] = p2[0];
6002 p1[1] = p2[1];
6003
6004 p2[0] = tmp[0];
6005 p2[1] = tmp[1];
6006 }
6007 }
6008 }
6009 }
6010 image->set_shuffled(false);
6011}
6012
6014{
6015// if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
6016
6017 int nx=image->get_xsize();
6018 int ny=image->get_ysize();
6019 int nz=image->get_zsize();
6020
6021 int nxy = nx*ny;
6022
6023 if ( ny == 1 && nz == 1 ){
6024 cout << "Warning- attempted Fourier origin shift a 1D image - no action taken" << endl;
6025 return;
6026 }
6027
6028 int yodd = (ny%2==1);
6029 int zodd = (nz%2==1);
6030
6031 float* rdata = image->get_data();
6032
6033 float tmp[2];
6034 float* p1;
6035 float* p2;
6036
6037 // This will tackle the 'normalization' images which come out of the Fourier reconstructor.
6038 // ie- real-space 1/2 FFt images centered on the corner
6039 if ( !image->is_complex() ) {
6040 if (nz!=1 && !yodd && !zodd) {
6041 for (int x=0; x<nx; x++) {
6042 for (int y=0; y<ny; y++) {
6043 for (int z=0; z<nz/2; z++) {
6044 int y2=(y+ny/2)%ny;
6045 int z2=(z+nz/2)%nz; // %nz should be redundant here
6046 size_t i=x+y*nx+(size_t)z*nxy;
6047 size_t i2=x+y2*nx+(size_t)z2*nxy;
6048 float swp=rdata[i];
6049 rdata[i]=rdata[i2];
6050 rdata[i2]=swp;
6051 }
6052 }
6053 }
6054
6055 return;
6056 }
6057 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");
6058 }
6059
6060 if (yodd){
6061 // In 3D this is swapping the bottom slice (with respect to the y direction) and the middle slice,
6062 // shifting all slices below the middle slice down one. In 2D it is equivalent, but in terms of rows.
6063 float prev[2];
6064 size_t idx;
6065 for( int s = 0; s < nz; s++ ) {
6066 for( int c =0; c < nx; c += 2 ) {
6067 idx = (size_t)s*nxy+c;
6068 prev[0] = rdata[idx];
6069 prev[1] = rdata[idx+1];
6070 for( int r = ny/2; r >= 0; --r ) {
6071 idx = (size_t)s*nxy+r*nx+c;
6072 float* p1 = &rdata[idx];
6073 tmp[0] = p1[0];
6074 tmp[1] = p1[1];
6075
6076 p1[0] = prev[0];
6077 p1[1] = prev[1];
6078
6079 prev[0] = tmp[0];
6080 prev[1] = tmp[1];
6081 }
6082 }
6083 }
6084 }
6085
6086 // 3D - Shift slices correctly in the y direction, 2D - shift rows
6087 size_t idx1, idx2;
6088 for( int s = 0; s < nz; ++s ) {
6089 for( int r = 0; r < ny/2; ++r ) {
6090 for( int c =0; c < nx; c += 2 ) {
6091 idx1 = (size_t)s*nxy+r*nx+c;
6092 idx2 = (size_t)s*nxy+(r+ny/2+yodd)*nx+c;
6093 p1 = &rdata[idx1];
6094 p2 = &rdata[idx2];
6095
6096 tmp[0] = p1[0];
6097 tmp[1] = p1[1];
6098
6099 p1[0] = p2[0];
6100 p1[1] = p2[1];
6101
6102 p2[0] = tmp[0];
6103 p2[1] = tmp[1];
6104 }
6105 }
6106 }
6107
6108 if ( nz != 1 ) {
6109 if (zodd){
6110 // Swap the front slice (with respect to the z direction) and the middle slice
6111 // shifting all slices behind the middles slice towards the front slice 1 voxel.
6112 float prev[2];
6113 size_t idx;
6114 for( int r = 0; r < ny; ++r ) {
6115 for( int c =0; c < nx; c += 2 ) {
6116 prev[0] = rdata[r*nx+c];
6117 prev[1] = rdata[r*nx+c+1];
6118 for( int s = nz/2; s >= 0; --s ) {
6119 idx = (size_t)s*nxy+r*nx+c;
6120 float* p1 = &rdata[idx];
6121 tmp[0] = p1[0];
6122 tmp[1] = p1[1];
6123
6124 p1[0] = prev[0];
6125 p1[1] = prev[1];
6126
6127 prev[0] = tmp[0];
6128 prev[1] = tmp[1];
6129 }
6130 }
6131 }
6132 }
6133
6134 // Shift slices correctly in the y direction
6135 size_t idx1, idx2;
6136 for( int s = 0; s < nz/2; ++s ) {
6137 for( int r = 0; r < ny; ++r ) {
6138 for( int c =0; c < nx; c += 2 ) {
6139 idx1 = (size_t)s*nxy+r*nx+c;
6140 idx2 = (size_t)(s+nz/2+zodd)*nxy+r*nx+c;
6141 p1 = &rdata[idx1];
6142 p2 = &rdata[idx2];
6143
6144 tmp[0] = p1[0];
6145 tmp[1] = p1[1];
6146
6147 p1[0] = p2[0];
6148 p1[1] = p2[1];
6149
6150 p2[0] = tmp[0];
6151 p2[1] = tmp[1];
6152 }
6153 }
6154 }
6155 }
6156 image->set_shuffled(true);
6157}
6158
6160{
6161 if ( !image->is_complex() ) throw ImageFormatException("Can not handle images that are not complex in fourier phase shift 180");
6162
6163 // The old code here was seriously broken. It inverted the contrast in some even sized images, and didn't work
6164 // at all for odd images. Ugg. We're calling Pawel's code now. fixed 7/28/18
6165 image->center_origin_fft();
6166
6167// int nx = image->get_xsize();
6168// int ny = image->get_ysize();
6169// int nz = image->get_zsize();
6170
6171// int nxy = nx * ny;
6172
6173
6174// for (int k=-nz/2; k<(nz==1?1:nz/2); k++) {
6175// for (int j=-ny/2; j<ny/2; j++) {
6176// for (int i=(k+j)%2+(j<0?2:0); i<nx/2; i+=2) {
6177// image->set_complex_at(i,j,k,image->get_complex_at(i,j,k)* -1.0f);
6178// }
6179// }
6180// }
6181
6182}
6183
6185{
6186 int nx = image->get_xsize();
6187 int ny = image->get_ysize();
6188 int nz = image->get_zsize();
6189
6190 int xodd = (nx % 2) == 1;
6191 int yodd = (ny % 2) == 1;
6192 int zodd = (nz % 2) == 1;
6193
6194 int nxy = nx * ny;
6195
6196 float *rdata = image->get_data();
6197
6198 if ( ny == 1 && nz == 1 ){
6199 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
6200 }
6201 else if ( nz == 1 ) {
6202
6203 // Swap the bottom left and top right corners
6204 for ( int r = 0; r < ny/2; ++r ) {
6205 for ( int c = 0; c < nx/2; ++c) {
6206 int idx1 = r*nx + c;
6207 int idx2 = (r+ny/2+yodd)*nx + c + nx/2+xodd;
6208 float tmp = rdata[idx1];
6209 rdata[idx1] = rdata[idx2];
6210 rdata[idx2] = tmp;
6211 }
6212 }
6213
6214 // Swap the top left and bottom right corners
6215 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
6216 for ( int c = 0; c < nx/2; ++c) {
6217 int idx1 = r*nx + c;
6218 int idx2 = (r-ny/2-yodd)*nx + c + nx/2+xodd;
6219 float tmp = rdata[idx1];
6220 rdata[idx1] = rdata[idx2];
6221 rdata[idx2] = tmp;
6222 }
6223 }
6224 }
6225 else // nx && ny && nz are greater than 1
6226 {
6227 float tmp;
6228 // Swap the bottom left front and back right top quadrants
6229 size_t idx1, idx2;
6230
6231 for ( int s = 0; s < nz/2; ++s ) {
6232 for ( int r = 0; r < ny/2; ++r ) {
6233 for ( int c = 0; c < nx/2; ++ c) {
6234 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6235 idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
6236 tmp = rdata[idx1];
6237 rdata[idx1] = rdata[idx2];
6238 rdata[idx2] = tmp;
6239 }
6240 }
6241 }
6242 // Swap the bottom right front and back left top quadrants
6243 for ( int s = 0; s < nz/2; ++s ) {
6244 for ( int r = 0; r < ny/2; ++r ) {
6245 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
6246 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6247 idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c-nx/2-xodd;
6248 tmp = rdata[idx1];
6249 rdata[idx1] = rdata[idx2];
6250 rdata[idx2] = tmp;
6251 }
6252 }
6253 }
6254 // Swap the top right front and back left bottom quadrants
6255 for ( int s = 0; s < nz/2; ++s ) {
6256 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
6257 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
6258 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6259 idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c-nx/2-xodd;
6260 tmp = rdata[idx1];
6261 rdata[idx1] = rdata[idx2];
6262 rdata[idx2] = tmp;
6263 }
6264 }
6265 }
6266 // Swap the top left front and back right bottom quadrants
6267 for ( int s = 0; s < nz/2; ++s ) {
6268 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
6269 for ( int c = 0; c < nx/2; ++c) {
6270 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6271 idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
6272 tmp = rdata[idx1];
6273 rdata[idx1] = rdata[idx2];
6274 rdata[idx2] = tmp;
6275 }
6276 }
6277 }
6278 }
6279}
6280
6282{
6283 int nx = image->get_xsize();
6284 int ny = image->get_ysize();
6285 int nz = image->get_zsize();
6286
6287 int xodd = (nx % 2) == 1;
6288 int yodd = (ny % 2) == 1;
6289 int zodd = (nz % 2) == 1;
6290
6291 int nxy = nx * ny;
6292
6293 float *rdata = image->get_data();
6294
6295 if ( ny == 1 && nz == 1 ){
6296 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
6297 }
6298 else if ( nz == 1 ) {
6299 float tmp;
6300 if ( yodd ) {
6301 // Iterate along middle row, swapping values where appropriate
6302 int r = ny/2;
6303 for ( int c = 0; c < nx/2; ++c ) {
6304 int idx1 = r*nx + c;
6305 int idx2 = r*nx + c + nx/2+ xodd;
6306 tmp = rdata[idx1];
6307 rdata[idx1] = rdata[idx2];
6308 rdata[idx2] = tmp;
6309 }
6310 }
6311
6312 if ( xodd ) {
6313 // Iterate along the central column, swapping values where appropriate
6314 int c = nx/2;
6315 for ( int r = 0; r < ny/2; ++r ) {
6316 int idx1 = r*nx + c;
6317 int idx2 = (r+ny/2+yodd)*nx + c;
6318 tmp = rdata[idx1];
6319 rdata[idx1] = rdata[idx2];
6320 rdata[idx2] = tmp;
6321 }
6322 }
6323 }
6324 else // nx && ny && nz are greater than 1
6325 {
6326 float tmp;
6327 if ( xodd ) {
6328 // Iterate along the x = nx/2 slice, swapping values where appropriate
6329 int c = nx/2;
6330 size_t idx1, idx2;
6331 for( int s = 0; s < nz/2; ++s ) {
6332 for ( int r = 0; r < ny/2; ++r ) {
6333 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6334 idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
6335 tmp = rdata[idx1];
6336 rdata[idx1] = rdata[idx2];
6337 rdata[idx2] = tmp;
6338 }
6339 }
6340
6341 for( int s = nz-1; s >= (nz/2+zodd); --s ) {
6342 for ( int r = 0; r < ny/2; ++r ) {
6343 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6344 idx2 = (s-nz/2-zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
6345 tmp = rdata[idx1];
6346 rdata[idx1] = rdata[idx2];
6347 rdata[idx2] = tmp;
6348 }
6349 }
6350 }
6351 if ( yodd ) {
6352 // Iterate along the y = ny/2 slice, swapping values where appropriate
6353 int r = ny/2;
6354 size_t idx1, idx2;
6355 for( int s = 0; s < nz/2; ++s ) {
6356 for ( int c = 0; c < nx/2; ++c ) {
6357 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6358 idx2 =(s+nz/2+zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
6359 tmp = rdata[idx1];
6360 rdata[idx1] = rdata[idx2];
6361 rdata[idx2] = tmp;
6362 }
6363 }
6364
6365 for( int s = nz-1; s >= (nz/2+zodd); --s ) {
6366 for ( int c = 0; c < nx/2; ++c ) {
6367 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6368 idx2 = (s-nz/2-zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
6369 tmp = rdata[idx1];
6370 rdata[idx1] = rdata[idx2];
6371 rdata[idx2] = tmp;
6372 }
6373 }
6374 }
6375 if ( zodd ) {
6376 // Iterate along the z = nz/2 slice, swapping values where appropriate
6377 int s = nz/2;
6378 size_t idx1, idx2;
6379 for( int r = 0; r < ny/2; ++r ) {
6380 for ( int c = 0; c < nx/2; ++c ) {
6381 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6382 idx2 = (size_t)s*nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
6383 tmp = rdata[idx1];
6384 rdata[idx1] = rdata[idx2];
6385 rdata[idx2] = tmp;
6386 }
6387 }
6388
6389 for( int r = ny-1; r >= (ny/2+yodd); --r ) {
6390 for ( int c = 0; c < nx/2; ++c ) {
6391 idx1 = (size_t)s*nxy+(size_t)r*nx+c;
6392 idx2 = (size_t)s*nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
6393 tmp = rdata[idx1];
6394 rdata[idx1] = rdata[idx2];
6395 rdata[idx2] = tmp;
6396 }
6397 }
6398 }
6399 }
6400}
6401
6403{
6404 if (!image) throw NullPointerException("Error: attempt to phase shift a null image");
6405
6406#ifdef EMAN2_USING_CUDA
6407 if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
6408 //cout << "CUDA tocorner " << image->getcudarwdata() << endl;
6409 emdata_phaseorigin_to_corner(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
6410 return;
6411 }
6412#endif // EMAN2_USING_CUDA
6413
6414 if (image->is_complex()) {
6415 fourier_phaseshift180(image);
6416 return;
6417 }
6418
6419 int nx = image->get_xsize();
6420 int ny = image->get_ysize();
6421 int nz = image->get_zsize();
6422
6423 if ( ny == 1 && nz == 1 && nx == 1) return;
6424
6425 int nxy = nx * ny;
6426
6427 float *rdata = image->get_data();
6428
6429 bool xodd = (nx % 2) == 1;
6430 bool yodd = (ny % 2) == 1;
6431 bool zodd = (nz % 2) == 1;
6432
6433 if ( ny == 1 && nz == 1 ){
6434 if (xodd){
6435 // Put the last pixel in the center, shifting the contents
6436 // to right of the center one step to the right
6437 float in_x = rdata[nx-1];
6438 float tmp;
6439 for ( int i = nx/2; i < nx; ++i ) {
6440 tmp = rdata[i];
6441 rdata[i] = in_x;
6442 in_x = tmp;
6443 }
6444 }
6445 // now the operation is straight forward
6446 for ( int i = 0; i < nx/2; ++i ) {
6447 int idx = i+nx/2+xodd;
6448 float tmp = rdata[i];
6449 rdata[i] = rdata[idx];
6450 rdata[idx] = tmp;
6451 }
6452
6453 }
6454 else if ( nz == 1 ) {
6455 if (yodd) {
6456 // Tranfer the top row into the middle row,
6457 // shifting all pixels above and including the current middle up one.
6458 for ( int c = 0; c < nx; ++c ) {
6459 // Get the value in the top row
6460 float last_val = rdata[(ny-1)*nx + c];
6461 float tmp;
6462 for ( int r = ny/2; r < ny; ++r ){
6463 int idx =r*nx+c;
6464 tmp = rdata[idx];
6465 rdata[idx] = last_val;
6466 last_val = tmp;
6467 }
6468 }
6469 }
6470
6471 if (xodd) {
6472 // Transfer the right most column into the center column
6473 // Shift all columns right of and including center to the right one pixel
6474 for ( int r = 0; r < ny; ++r ) {
6475 float last_val = rdata[(r+1)*nx -1];
6476 float tmp;
6477 for ( int c = nx/2; c < nx; ++c ){
6478 int idx =r*nx+c;
6479 tmp = rdata[idx];
6480 rdata[idx] = last_val;
6481 last_val = tmp;
6482 }
6483 }
6484 }
6485 // It is important central slice shifting come after the previous two operations
6487 // Now the corners of the image can be shifted...
6488 swap_corners_180(image);
6489
6490 }
6491 else
6492 {
6493 float tmp;
6494 if (zodd) {
6495 // Tranfer the back slice into the middle slice,
6496 // shifting all pixels beyond and including the middle slice back one.
6497 size_t idx = 0;
6498 for (int r = 0; r < ny; ++r){
6499 for (int c = 0; c < nx; ++c) {
6500 float last_val = rdata[(nz-1)*nxy+r*nx+c];
6501 for (int s = nz/2; s < nz; ++s) {
6502 idx = (size_t)s*nxy+r*nx+c;
6503 tmp = rdata[idx];
6504 rdata[idx] = last_val;
6505 last_val = tmp;
6506 }
6507 }
6508 }
6509 }
6510 if (yodd) {
6511 // Tranfer the top slice into the middle slice,
6512 // shifting all pixels above and including the middle slice up one.
6513 size_t idx = 0;
6514 for (int s = 0; s < nz; ++s) {
6515 for (int c = 0; c < nx; ++c) {
6516 float last_val = rdata[s*nxy+(ny-1)*nx+c];
6517 for (int r = ny/2; r < ny; ++r){
6518 idx = (size_t)s*nxy+r*nx+c;
6519 tmp = rdata[idx];
6520 rdata[idx] = last_val;
6521 last_val = tmp;
6522 }
6523 }
6524 }
6525 }
6526 if (xodd) {
6527 // Transfer the right most slice into the central slice
6528 // Shift all pixels to right of and including center slice to the right one pixel
6529 size_t idx = 0;
6530 for (int s = 0; s < nz; ++s) {
6531 for (int r = 0; r < ny; ++r) {
6532 float last_val = rdata[s*nxy+r*nx+nx-1];
6533 for (int c = nx/2; c < nx; ++c){
6534 idx = (size_t)s*nxy+r*nx+c;
6535 tmp = rdata[idx];
6536 rdata[idx] = last_val;
6537 last_val = tmp;
6538 }
6539 }
6540 }
6541 }
6542 // Now swap the various parts in the central slices
6544 // Now shift the corners
6545 swap_corners_180(image);
6546 }
6547}
6548
6549
6551{
6552 if (!image) throw NullPointerException("Error: attempt to phase shift a null image");
6553
6554#ifdef EMAN2_USING_CUDA
6555 if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
6556 //cout << "CUDA tocenter" << endl;
6557 emdata_phaseorigin_to_center(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
6558 return;
6559 }
6560#endif // EMAN2_USING_CUDA
6561
6562 if (image->is_complex()) {
6563 fourier_phaseshift180(image);
6564 return;
6565 }
6566
6567 int nx = image->get_xsize();
6568 int ny = image->get_ysize();
6569 int nz = image->get_zsize();
6570
6571 if ( ny == 1 && nz == 1 && nx == 1) return;
6572
6573 int nxy = nx * ny;
6574
6575 float *rdata = image->get_data();
6576
6577 bool xodd = (nx % 2) == 1;
6578 bool yodd = (ny % 2) == 1;
6579 bool zodd = (nz % 2) == 1;
6580
6581 if ( ny == 1 && nz == 1 ){
6582 if (xodd) {
6583 // Put the center pixel at the end, shifting the contents
6584 // to right of the center one step to the left
6585 float in_x = rdata[nx/2];
6586 float tmp;
6587 for ( int i = nx-1; i >= nx/2; --i ) {
6588 tmp = rdata[i];
6589 rdata[i] = in_x;
6590 in_x = tmp;
6591 }
6592 }
6593 // now the operation is straight forward
6594 for ( int i = 0; i < nx/2; ++i ) {
6595 int idx = i + nx/2;
6596 float tmp = rdata[i];
6597 rdata[i] = rdata[idx];
6598 rdata[idx] = tmp;
6599 }
6600 }
6601 else if ( nz == 1 ){
6602 // The order in which these operations occur literally undoes what the
6603 // PhaseToCornerProcessor did to the image.
6604 // First, the corners sections of the image are swapped appropriately
6605 swap_corners_180(image);
6606 // Second, central pixel lines are swapped
6608
6609 float tmp;
6610 // Third, appropriate sections of the image are cyclically shifted by one pixel
6611 if (xodd) {
6612 // Transfer the middle column to the far right
6613 // Shift all from the far right to (but not including the) middle one to the left
6614 for ( int r = 0; r < ny; ++r ) {
6615 float last_val = rdata[r*nx+nx/2];
6616 for ( int c = nx-1; c >= nx/2; --c ){
6617 int idx = r*nx+c;
6618 tmp = rdata[idx];
6619 rdata[idx] = last_val;
6620 last_val = tmp;
6621 }
6622 }
6623 }
6624 if (yodd) {
6625 // Tranfer the middle row to the top,
6626 // shifting all pixels from the top row down one, until but not including the) middle
6627 for ( int c = 0; c < nx; ++c ) {
6628 // Get the value in the top row
6629 float last_val = rdata[ny/2*nx + c];
6630 for ( int r = ny-1; r >= ny/2; --r ){
6631 int idx = r*nx+c;
6632 tmp = rdata[idx];
6633 rdata[idx] = last_val;
6634 last_val = tmp;
6635 }
6636 }
6637 }
6638 }
6639 else
6640 {
6641 // The order in which these operations occur literally undoes the
6642 // PhaseToCornerProcessor operation - in 3D.
6643 // First, the corner quadrants of the voxel volume are swapped
6644 swap_corners_180(image);
6645 // Second, appropriate parts of the central slices are swapped
6647
6648 float tmp;
6649 // Third, appropriate sections of the image are cyclically shifted by one voxel
6650 if (xodd) {
6651 // Transfer the central slice in the x direction to the far right
6652 // moving all slices on the far right toward the center one pixel, until
6653 // the center x slice is ecountered
6654 size_t idx = 0;
6655 for (int s = 0; s < nz; ++s) {
6656 for (int r = 0; r < ny; ++r) {
6657 float last_val = rdata[s*nxy+r*nx+nx/2];
6658 for (int c = nx-1; c >= nx/2; --c){
6659 idx = (size_t)s*nxy+r*nx+c;
6660 tmp = rdata[idx];
6661 rdata[idx] = last_val;
6662 last_val = tmp;
6663 }
6664 }
6665 }
6666 }
6667 if (yodd) {
6668 // Tranfer the central slice in the y direction to the top
6669 // shifting all pixels below it down on, until the center y slice is encountered.
6670 size_t idx = 0;
6671 for (int s = 0; s < nz; ++s) {
6672 for (int c = 0; c < nx; ++c) {
6673 float last_val = rdata[s*nxy+ny/2*nx+c];
6674 for (int r = ny-1; r >= ny/2; --r){
6675 idx = (size_t)s*nxy+r*nx+c;
6676 tmp = rdata[idx];
6677 rdata[idx] = last_val;
6678 last_val = tmp;
6679 }
6680 }
6681 }
6682 }
6683 if (zodd) {
6684 // Tranfer the central slice in the z direction to the back
6685 // shifting all pixels beyond and including the middle slice back one.
6686 size_t idx = 0;
6687 for (int r = 0; r < ny; ++r){
6688 for (int c = 0; c < nx; ++c) {
6689 float last_val = rdata[nz/2*nxy+r*nx+c];
6690 for (int s = nz-1; s >= nz/2; --s) {
6691 idx = (size_t)s*nxy+r*nx+c;
6692 tmp = rdata[idx];
6693 rdata[idx] = last_val;
6694 last_val = tmp;
6695 }
6696 }
6697 }
6698 }
6699 }
6700}
6701
6703 if (!image) {
6704 LOGWARN("NULL Image");
6705 return;
6706 }
6707
6708 int nx = image->get_xsize();
6709 int ny = image->get_ysize();
6710 int nz = image->get_zsize();
6711
6712 int ox = nx/2;
6713 int oy = ny/2;
6714 int oz = nz/2;
6715
6716 Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
6717 int au = params.set_default("au",0);
6718 int symavg = params.set_default("symavg",0);
6719
6720 if ((toupper(((string)params["sym"])[0])!='C' || au<0)&& symavg) throw InvalidParameterException("ERROR: symavg only works with Cn symmetry, and one au must be specified.");
6721
6722 if (symavg) {
6723 for(int k = 0; k < nz; ++k ) {
6724 for(int j = 0; j < ny; ++j ) {
6725 for (int i = 0; i< nx; ++i) {
6726 float az=atan2(float(j-ny/2),float(i-nx/2));
6727
6728 }
6729 }
6730 }
6731
6732 delete sym;
6733 }
6734
6735 float *d = image->get_data();
6736 for(int k = 0; k < nz; ++k ) {
6737 for(int j = 0; j < ny; ++j ) {
6738 for (int i = 0; i< nx; ++i, ++d) {
6739 //cout << i << " " << j << " " << k << endl;
6740 Vec3f v(i-ox,j-oy,k-oz);
6741// v.normalize();
6742 int a = sym->point_in_which_asym_unit(v);
6743 if (au == -1) {
6744 *d = (float)a;
6745 } else {
6746 if ( a == au ) *d = 1;
6747 else *d = 0;
6748 }
6749 }
6750 }
6751 }
6752
6753 delete sym;
6754
6755}
6756
6758{
6759 if (!image) {
6760 LOGWARN("NULL Image");
6761 return;
6762 }
6763
6764 if (image->get_ndim() != 2) {
6765 throw ImageDimensionException("This processor only supports 2D images.");
6766 }
6767
6768 /*
6769 The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
6770 To get around this just use the return_mask parameter.
6771 string mask_output = params.set_default("write_mask", "");
6772 if ( mask_output != "") {
6773 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.");
6774 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
6775 }
6776 */
6777
6778 int radius=params.set_default("radius",0);
6779 int nmaxseed=params.set_default("nmaxseed",0);
6780
6781 float threshold=0.0;
6782 if (params.has_key("sigma") || !params.has_key("threshold")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
6783 else threshold=params["threshold"];
6784
6785
6786 int nshells = params.set_default("nshells",0);
6787 int nshellsgauss = params.set_default("nshellsgauss",0);
6788 int verbose=params.set_default("verbose",0);
6789
6790 int nx = image->get_xsize();
6791 int ny = image->get_ysize();
6792
6793 EMData *amask = new EMData();
6794 amask->set_size(nx, ny);
6795
6796 float *dat = image->get_data();
6797 float *dat2 = amask->get_data();
6798 int i,j;
6799 size_t l = 0;
6800
6801 if (verbose) printf("%f\t%f\t%f\t%d\n",(float)image->get_attr("mean"),(float)image->get_attr("sigma"),threshold,nmaxseed);
6802
6803 // Seeds with the highest valued pixels
6804 if (nmaxseed>0) {
6805 EMData *peaks=image->process("mask.onlypeaks",Dict("npeaks",0)); // only find true peak values (pixels surrounded by lower values)
6806 vector<Pixel> maxs=peaks->calc_n_highest_locations(nmaxseed);
6807 delete peaks;
6808
6809 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
6810 if ((*i).x==0 || (*i).y==0 ) continue; // generally indicates a failed peak search, and regardless we don't really want edges
6811 amask->set_value_at((*i).x,(*i).y,0,1.0);
6812 if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
6813 }
6814 }
6815
6816 // Seeds with a circle
6817 if (radius>0) {
6818 // start with an initial circle
6819 l=0;
6820 for (j = -ny / 2; j < ny / 2; ++j) {
6821 for (i = -nx / 2; i < nx / 2; ++i,++l) {
6822 if ( abs(j) > radius || abs(i) > radius) continue;
6823 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
6824 if ( (j * j + i * i) > (radius*radius) ) continue;
6825 dat2[l] = 1.0f;
6826 }
6827 }
6828 }
6829
6830 // iteratively 'flood fills' the map... recursion would be better
6831 int done=0;
6832 int iter=0;
6833 while (!done) {
6834 iter++;
6835 done=1;
6836 if (verbose && iter%10==0) printf("%d iterations\n",iter);
6837 for (j=1; j<ny-1; ++j) {
6838 for (i=1; i<nx-1; ++i) {
6839 l=i+j*nx;
6840 if (dat2[l]) continue;
6841 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx])) {
6842 dat2[l]=1.0;
6843 done=0;
6844 }
6845 }
6846 }
6847 }
6848
6849 amask->update();
6850
6851 if (verbose) printf("extending mask\n");
6852 if (nshells>0 || nshellsgauss>0) amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
6853
6854 bool return_mask = params.set_default("return_mask",false);
6855 if (return_mask) {
6856 // 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.
6857 memcpy(dat,dat2,image->get_size()*sizeof(float));
6858 } else {
6859 image->mult(*amask);
6860 }
6861
6862 // EMAN2 policy is not to allow file io from with a processor
6863 //if (mask_output != "") {
6864 // amask->write_image(mask_output);
6865 //}
6866
6867
6868 delete amask;
6869}
6870
6872 EMData *tmp=process(image);
6873 memcpy(image->get_data(),tmp->get_data(),(size_t)image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
6874 delete tmp;
6875 image->update();
6876 return;
6877}
6878
6880 if (!image) {
6881 LOGWARN("NULL Image");
6882 return NULL;
6883 }
6884
6885 EMData *fft;
6886 if (!image->is_complex()) fft=image->do_fft();
6887 else fft=image->copy();
6888
6889 bool purectf=(bool)params.set_default("purectf",0);
6890 EMAN2Ctf ctf;
6891 ctf.defocus=params["defocus"];
6892 ctf.bfactor=params["bfactor"];
6893 ctf.ampcont=params.set_default("ampcont",10.0f);
6894 ctf.voltage=params.set_default("voltage",200.0f);
6895 ctf.cs=params.set_default("cs",2.0);
6896 ctf.apix=params.set_default("apix",image->get_attr_default("apix_x",1.0));
6897 if (image->has_attr("dsbg")) ctf.dsbg=image->get_attr("dsbg");
6898 else ctf.dsbg=1.0/(ctf.apix*fft->get_ysize()*4.0); //4x oversampling
6899 int doflip=(int)params.set_default("phaseflip",1); // whether to use the CTF or abs(CTF)
6900 float noiseamp=params.set_default("noiseamp",0.0f);
6901 float noiseampwhite=params.set_default("noiseampwhite",0.0f);
6902 int bsfp=(int)params.set_default("bispectrumfp",0); // special mode for bispectrum processing ... obsolete as of 8/16/18
6903
6904 // compute the CTF
6905 vector <float> ctfc = ctf.compute_1d(fft->get_ysize()*12,ctf.dsbg,ctf.CTF_AMP,NULL); // *6 goes to corner, remember you provide 2x the number of points you need
6906 if (!doflip) {
6907 for (vector<float>::iterator it=ctfc.begin(); it!=ctfc.end(); ++it) *it=fabs(*it);
6908 }
6909
6910// for (int i=0; i<ctfc.size(); i++) printf("%d\t%f\n",i,ctfc[i]);
6911// printf("apix %f\tdsbg %f\tdef %f\tbfac %f\tvol %f\tcs %f\n",ctf.apix,ctf.dsbg,ctf.defocus,ctf.bfactor,ctf.voltage,ctf.cs);
6912
6913// printf("%1.3f\t%1.3f\t%1.3f\t%1.3f\t%1.3f\t%d\n",ctf.defocus,ctf.bfactor,ctf.ampcont,ctf.dsbg,ctf.apix,fft->get_ysize());
6914// FILE *out=fopen("x.txt","w");
6915// for (int i=0; i<ctfc.size(); i++) fprintf(out,"%f\t%1.3g\n",0.25*i/(float)fft->get_ysize(),ctfc[i]);
6916// fclose(out);
6917
6918 if (bsfp) {
6919 int fp=fft->get_zsize();
6920 int nx=fft->get_xsize();
6921 int ny=fft->get_ysize();
6922 EMData *ret=new EMData((nx-2)/2,ny*fp,1);
6923// for (int j=ny*2-4; j<ctfc.size(); j++) ctfc[j]*=exp(-pow(j-ny*2+4,2.0)/8.0); // soft Gaussian falloff to CTF modification to avoid corner/edge effects
6924 for (int k=0; k<fp; k++) {
6925 EMData *plnf=fft->get_clip(Region(0,0,k,nx,ny,1));
6926 plnf->set_complex(1);
6927 plnf->set_ri(1);
6928 plnf->set_fftpad(1);
6929// plnf->apply_radial_func(0,0.25f/fft->get_ysize(),ctfc,1);
6930 for (int jy=-ny/2; jy<ny/2; jy++) {
6931 for (int jx=0; jx<nx/2; jx++) {
6932 if (jx==0 && jy<0) continue;
6933 int r1=Util::hypot_fast_int(jx*4,jy*4);
6934 int r2=(k+2)*4;
6935 int r3=Util::hypot_fast_int((jx+k+2)*4,jy*4);
6936 float ctfmod=ctfc[r1]*ctfc[r2]*ctfc[r3];
6937// if (jx==0|| jx==1) printf("%d %d\t%d %d %d\t%g %g %g\t%g\n",jx,jy,r1,r2,r3,ctfc[r1],ctfc[r2],ctfc[r3],ctfmod);
6938
6939 // Turns out that it shouldn't BE rotationally symmetric
6940// // To make this rotationally symmetric we have to integrate over the j+k vector
6941// float avgr=0.0f;
6942// float norm=0.0f;
6943// for (float ang=0.0f; ang<2.0*M_PI; ang+=2.0*M_PI/float(k*8)) {
6944// float jkx=jx*4+k*4.0*cos(ang);
6945// float jky=jy*4+k*4.0*sin(ang);
6946//
6947// int r3=int(hypot(jkx,jky)+0.5);
6948// avgr+=ctfc[r3];
6949// norm+=1.0;
6950// }
6951// ctfmod*=(avgr/norm);
6952
6953 if (purectf) plnf->set_complex_at(jx,jy,ctfmod);
6954 else plnf->set_complex_at(jx,jy,plnf->get_complex_at(jx,jy)*ctfmod);
6955// plnf->set_complex_at(jx,jy,plnf->get_complex_at(jx,jy);
6956// plnf->set_complex_at(jx,jy,ctfmod);
6957 }
6958 }
6959// plnf->write_image("tst.hdf",-1);
6960
6961 EMData *pln=plnf->do_ift();
6962 pln->process_inplace("xform.phaseorigin.tocenter");
6963 pln->process_inplace("normalize");
6964 ret->insert_clip(pln,IntPoint(-nx/2,k*ny,0));
6965 delete plnf;
6966 delete pln;
6967 }
6968 delete fft;
6969 return ret;
6970 }
6971 else {
6972 if (purectf) {
6973 for (size_t i=0; i<fft->get_size(); i++) fft->set_value_at_fast(i,i%2==0?1.0f:0.0f);
6974 }
6975 fft->apply_radial_func(0,0.25f/fft->get_ysize(),ctfc,1);
6976 }
6977
6978 // Add noise
6979 if (noiseamp!=0 || noiseampwhite!=0) {
6980 EMData *noise = new EMData(image->get_ysize(),image->get_ysize(),1);
6981 noise->process_inplace("testimage.noise.gauss");
6982 noise->do_fft_inplace();
6983
6984 // White noise
6985 if (noiseampwhite!=0) {
6986 noise->mult((float)noiseampwhite*15.0f); // The 15.0 is to roughly compensate for the stronger pink noise curve
6987 fft->add(*noise);
6988 noise->mult((float)1.0/(noiseampwhite*15.0f));
6989 }
6990
6991 // Pink noise
6992 if (noiseamp!=0) {
6993 vector <float> pinkbg;
6994 pinkbg.resize(500);
6995 float nyimg=0.5f/ctf.apix; // image nyquist
6996 // This pink curve came from a typical image in the GroEL 4A data set
6997 for (int i=0; i<500; i++) pinkbg[i]=noiseamp*(44.0f*exp(-5.0f*nyimg*i/250.0f)+10.0f*exp(-90.0f*nyimg*i/250.0f)); // compute curve to image Nyquist*2
6998 noise->apply_radial_func(0,.002f,pinkbg,1); // Image nyquist is at 250 -> 0.5
6999 fft->add(*noise);
7000 }
7001
7002 }
7003
7004 EMData *ret=fft->do_ift();
7005 delete fft;
7006
7007 return ret;
7008}
7009
7011{
7012 if (!image) {
7013 LOGWARN("NULL Image");
7014 return;
7015 }
7016
7017 if (!image->is_complex()) {
7018 LOGERR("AddRandomNoise Processor only works for complex image");
7019 throw ImageFormatException("only work for complex image");
7020 }
7021
7022 int n = params["n"];
7023 float x0 = params["x0"];
7024 float dx = params["dx"];
7025 vector < float >y = params["y"];
7026
7027 int interpolation = 1;
7028 if (params.has_key("interpolation")) {
7029 interpolation = params["interpolation"];
7030 }
7031
7032 Randnum * randnum = Randnum::Instance();
7033 if(params.has_key("seed")) {
7034 randnum->set_seed((int)params["seed"]);
7035 }
7036
7037 int nx = image->get_xsize();
7038 int ny = image->get_ysize();
7039 int nz = image->get_zsize();
7040
7041 image->ap2ri();
7042 float *rdata = image->get_data();
7043
7044 size_t k = 0;
7045 float half_nz = 0;
7046 if (nz > 1) {
7047 half_nz = nz / 2.0f;
7048 }
7049
7050 const float sqrt_2 = sqrt((float) 2);
7051
7052 float r;
7053 for (int h = 0; h < nz; h++) {
7054 for (int j = 0; j < ny; j++) {
7055 for (int i = 0; i < nx; i += 2, k += 2) {
7056 r = (Util::hypot3(i / 2.0f, j - ny / 2.0f, h - half_nz));
7057// 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
7058 r = (r - x0) / dx;
7059 int l = 0;
7060 if (interpolation) {
7061 l = Util::fast_floor(r);
7062 }
7063 else {
7064 l = Util::fast_floor(r + 0.5f);
7065 }
7066 r -= l;
7067 float f = 0;
7068 if (l >= n - 2) {
7069 f = y[n - 1];
7070 }
7071 else if (l < 0) {
7072 l = 0;
7073 }
7074 else {
7075 if (interpolation) {
7076 f = (y[l] * (1 - r) + y[l + 1] * r);
7077 }
7078 else {
7079 f = y[l];
7080 }
7081 }
7082 f = randnum->get_gauss_rand(sqrt(f), sqrt(f) / 3);
7083 float a = randnum->get_frand(0.0f, (float)(2 * M_PI));
7084 if (i == 0) {
7085 f *= sqrt_2;
7086 }
7087 rdata[k] += f * cos(a);
7088 rdata[k + 1] += f * sin(a);
7089 }
7090 }
7091 }
7092
7093 image->update();
7094}
7095
7097{
7098 if (!image) {
7099 LOGWARN("NULL Image");
7100 return;
7101 }
7102
7103 int nx = image->get_xsize();
7104 int ny = image->get_ysize();
7105 int nz = image->get_zsize();
7106
7107 if (ny == 1) {
7108 LOGERR("Error: mask.addshells.multilevel works only in 2/3-D");
7109 return;
7110 }
7111
7112 int num_shells = params.set_default("nshells",1);
7113
7114 // there are other strategies which might allow us to avoid the extra copy, but this will have to do for now
7115 EMData *image1=image;
7116 EMData *image2=image->copy();
7117 if (nz == 1) {
7118 for (int i = 0; i < num_shells; i++) {
7119 for (int y = 1; y < ny - 1; y++) {
7120 for (int x = 1; x < nx - 1; x++) {
7121 if (image1->get_value_at(x,y)>0) continue; // already part of a masked region
7122
7123 // Note that this produces a directional bias in the case of ambiguous pixels
7124 // While this could be improved upon slightly, there can be truly ambiguous cases
7125 // and at least this method is deterministic
7126 if (image1->get_value_at(x-1,y)>0) image2->set_value_at_fast(x,y,image1->get_value_at(x-1,y));
7127 else if (image1->get_value_at(x+1,y)>0) image2->set_value_at_fast(x,y,image1->get_value_at(x+1,y));
7128 else if (image1->get_value_at(x,y-1)>0) image2->set_value_at_fast(x,y,image1->get_value_at(x,y-1));
7129 else if (image1->get_value_at(x,y+1)>0) image2->set_value_at_fast(x,y,image1->get_value_at(x,y+1));
7130
7131 }
7132 }
7133 memcpy(image1->get_data(),image2->get_data(),image1->get_size()*sizeof(float));
7134 }
7135 }
7136 else {
7137 for (int i = 0; i < num_shells; i++) {
7138 for (int z = 1; z < nz - 1; z++) {
7139 for (int y = 1; y < ny - 1; y++) {
7140 for (int x = 1; x < nx - 1; x++) {
7141 if (image1->get_value_at(x,y,z)>0) continue; // already part of a masked region
7142
7143 // Note that this produces a directional bias in the case of ambiguous pixels
7144 // While this could be improved upon slightly, there can be truly ambiguous cases
7145 // and at least this method is deterministic
7146 if (image1->get_value_at(x-1,y,z)>0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x-1,y,z));
7147 else if (image1->get_value_at(x+1,y,z)>0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x+1,y,z));
7148 else if (image1->get_value_at(x,y-1,z)>0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y-1,z));
7149 else if (image1->get_value_at(x,y+1,z)>0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y+1,z));
7150 else if (image1->get_value_at(x,y,z-1)>0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y,z-1));
7151 else if (image1->get_value_at(x,y,z+1)>0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y,z+1));
7152
7153 }
7154 }
7155 }
7156 memcpy(image1->get_data(),image2->get_data(),image1->get_size()*sizeof(float));
7157 }
7158 }
7159
7160 delete image2;
7161 image->update();
7162}
7163
7164
7166{
7167 if (!image) {
7168 LOGWARN("NULL Image");
7169 return;
7170 }
7171
7172 int nx = image->get_xsize();
7173 int ny = image->get_ysize();
7174 int nz = image->get_zsize();
7175
7176 if (ny == 1) {
7177 LOGERR("Tried to add mask shell to 1d image");
7178 return;
7179 }
7180
7181 int num_shells = params.set_default("nshells",1);
7182
7183 float *d = image->get_data();
7184 float k = 0.99999f;
7185 int nxy = nx * ny;
7186
7187 if (nz == 1) {
7188 for (int i = 0; i < num_shells; i++) {
7189 for (int y = 1; y < ny - 1; y++) {
7190 int cur_y = y * nx;
7191
7192 for (int x = 1; x < nx - 1; x++) {
7193 int j = x + cur_y;
7194 if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k || d[j - nx] > k)) {
7195 d[j] = k;
7196 }
7197 }
7198 }
7199 k -= 0.00001f;
7200 }
7201 }
7202 else {
7203 for (int i = 0; i < num_shells; i++) {
7204 for (int z = 1; z < nz - 1; z++) {
7205 size_t cur_z = (size_t)z * nx * ny;
7206
7207 for (int y = 1; y < ny - 1; y++) {
7208 size_t cur_y = y * nx + cur_z;
7209
7210 for (int x = 1; x < nx - 1; x++) {
7211 size_t j = x + cur_y;
7212
7213 if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k ||
7214 d[j - nx] > k || d[j - nxy] > k || d[j + nxy] > k)) {
7215 d[j] = k;
7216 }
7217 }
7218 }
7219 }
7220
7221 k -= 0.00001f;
7222 }
7223 }
7224
7225 size_t size = (size_t)nx * ny * nz;
7226 for (size_t i = 0; i < size; ++i) {
7227 if (d[i]) {
7228 d[i] = 1;
7229 }
7230 else {
7231 d[i] = 0;
7232 }
7233 }
7234
7235 image->update();
7236}
7237
7239{
7240 if (!image) {
7241 LOGWARN("NULL Image");
7242 return;
7243 }
7244
7245 float thr = params["thr"];
7246 string symname=(string)params["sym"];
7247 Symmetry3D* sym = Factory<Symmetry3D>::get(symname);
7248
7249 int nx = image->get_xsize();
7250 int ny = image->get_ysize();
7251 int nz = image->get_zsize();
7252
7253 if (ny == 1 || nz==1) {
7254 LOGERR("Error: segment.subunit works only in 3-D");
7255 return;
7256 }
7257
7258 // there are other strategies which might allow us to avoid the extra copy, but this will have to do for now
7259 EMData *image1=new EMData(nx,ny,nz);
7260 image1->to_zero();
7261 EMData *image2=image->copy();
7262
7263 // We're using image2 here temporarily to seed image1. We will reinitialize it when done
7264 image2->process_inplace("mask.sharp",Dict("inner_radius",(int)nz/5)); // we don't want to seed too close to the middle
7265 IntPoint ml=image2->calc_max_location(); // highest pixel value, now we symmetrize
7266
7267 // Seed the multi-level mask
7268 int i=0;
7269 vector<Transform> transforms = sym->get_syms();
7270 for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
7271 Transform t = *trans_it;
7272 i++;
7273 Vec3f xf = t.transform(ml[0]-nx/2,ml[1]-ny/2,ml[2]-nz/2);
7274 image1->set_value_at((int)(xf[0]+nx/2),(int)(xf[1]+ny/2),(int)(xf[2]+nz/2),(float)i);
7275 }
7276 memcpy(image2->get_data(),image1->get_data(),image1->get_size()*sizeof(float)); // copy the seed from image 1 to image 2
7277
7278
7279
7280 // We progressively lower the threshold, sort of like a very coarse watershed
7281 float max=(float)image->get_attr("maximum");
7282 float gap=max-thr;
7283 if (gap<=0) throw InvalidParameterException("SegmentSubunitProcessor: threshold must be < max value");
7284
7285 for (int ti=0; ti<12; ti++) {
7286 float thr2=max-(ti+1)*gap/12.0;
7287 printf("threshold %1.4f\n",thr2);
7288 int change=1;
7289 while (change) {
7290 change=0;
7291 for (int z = 1; z < nz - 1; z++) {
7292 for (int y = 1; y < ny - 1; y++) {
7293 for (int x = 1; x < nx - 1; x++) {
7294 // Skip the voxel if already part of a mask or if below threshold
7295 if (image1->get_value_at(x,y,z)>0 || image->get_value_at(x,y,z)<thr2) continue;
7296
7297 // Note that this produces a directional bias in the case of ambiguous pixels
7298 // While this could be improved upon slightly, there can be truly ambiguous cases
7299 // and at least this method is deterministic
7300 if (image1->get_value_at(x-1,y,z)>0) { image2->set_value_at_fast(x,y,z,image1->get_value_at(x-1,y,z)); change=1; }
7301 else if (image1->get_value_at(x+1,y,z)>0) { image2->set_value_at_fast(x,y,z,image1->get_value_at(x+1,y,z)); change=1; }
7302 else if (image1->get_value_at(x,y-1,z)>0) { image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y-1,z)); change=1; }
7303 else if (image1->get_value_at(x,y+1,z)>0) { image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y+1,z)); change=1; }
7304 else if (image1->get_value_at(x,y,z-1)>0) { image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y,z-1)); change=1; }
7305 else if (image1->get_value_at(x,y,z+1)>0) { image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y,z+1)); change=1; }
7306
7307 }
7308 }
7309 }
7310 memcpy(image1->get_data(),image2->get_data(),image1->get_size()*sizeof(float));
7311 }
7312// char fs[20];
7313// sprintf(fs,"lvl%d.hdf",ti);
7314// image1->write_image(fs);
7315 }
7316
7317// image1->write_image("multilev.hdf");
7318// image1->process_inplace("threshold.abovetozero",Dict("maxval",(float)1.01f));
7319// image->mult(*image1);
7320
7321 // our final return value is the multilevel mask
7322 memcpy(image->get_data(),image1->get_data(),image1->get_size()*sizeof(float));
7323
7324 delete image1;
7325 delete image2;
7326 delete sym;
7327 image->update();
7328}
7329
7330
7332{
7333 if (!image) {
7334 LOGWARN("NULL Image");
7335 return;
7336 }
7337
7338 if ((float)image->get_attr("sigma")==0.0f) return; // Can't center a constant valued image
7339 int nx = image->get_xsize();
7340 int ny = image->get_ysize();
7341 int nz = image->get_zsize();
7342
7343 // Preprocess a copy of the image to better isolate the "bulk" of the object
7344 float gmw=(nx/16)>5?nx/16:5; // gaussian mask width
7345 EMData *image2=image->process("filter.highpass.gauss",Dict("cutoff_pixels",nx<50?nx/10:5)); // clear out large scale gradients
7346 image2->process_inplace("normalize.circlemean",Dict("radius",ny/2-4));
7347 image2->process_inplace("mask.gaussian",Dict("inner_radius",nx/2-gmw,"outer_radius",gmw/1.3)); // get rid of peripheral garbage
7348 image2->process_inplace("math.squared"); // exaggerate stronger density and includes strong negative density
7349 image2->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.05)); // get rid of peripheral garbage
7350 image2->process_inplace("normalize.circlemean",Dict("radius",ny/2-6));
7351
7352 // We compute a histogram so we can decide on a good threshold value
7353 float hmin=(float)image2->get_attr("mean");
7354 float hmax=(float)image2->get_attr("mean")+(float)image2->get_attr("sigma")*4.0;
7355 vector <float> hist = image2->calc_hist( 100,hmin,hmax);
7356 double tot=0;
7357 int i;
7358 for (i=99; i>=0; i--) {
7359 tot+=hist[i];
7360 if (tot>nx*ny*nz/10) break; // find a threshold encompassing a specific fraction of the total area/volume
7361 }
7362 float thr=(i*hmax+(99-i)*hmin)/99.0; // this should now be a threshold encompasing ~1/10 of the area in the image
7363// printf("mean %f sigma %f thr %f\n",(float)image2->get_attr("mean"),(float)image2->get_attr("sigma"),thr);
7364
7365 // threshold so we are essentially centering the object silhouette
7366 image2->process_inplace("threshold.belowtozero",Dict("minval",thr));
7367// image2->process_inplace("threshold.binary",Dict("value",thr));
7368// image2->write_image("dbg1.hdf",-1);
7369
7370 EMData *image3;
7371 if (nz==1) image3=image2->process("mask.auto2d",Dict("radius",nx/10,"threshold",thr*0.9,"nmaxseed",5));
7372 else image3=image2->process("mask.auto3d",Dict("radius",nx/10,"threshold",thr*0.9,"nmaxseed",5));
7373
7374 // if the mask failed, we revert to the thresholded, but unmasked image
7375 if (nz==1 && (float)image3->get_attr("sigma")==0) {
7376 delete image3;
7377 image3=image2->process("math.linearpyramid");
7378 image3->add(9.0f); // we comress the pyramid from .9-1
7379 image3->mult(0.9f);
7380 image3->process_inplace("mask.auto2d",Dict("threshold",0.5,"nmaxseed",5)); // should find seed points with a central bias
7381// image3->write_image("dbg3.hdf",-1);
7382 }
7383
7384 image3->process_inplace("threshold.binary",Dict("value",thr));
7385
7386 if ((float)image3->get_attr("sigma")==0) delete image3;
7387 else {
7388 delete image2;
7389 image2=image3;
7390 }
7391
7392// image2->write_image("dbg2.hdf",-1);
7393 FloatPoint com = image2->calc_center_of_mass(0.5);
7394 delete image2;
7395
7396 // actual centering is int translate only
7397 int dx = -(floor(com[0] + 0.5f) - nx / 2);
7398 int dy = -(floor(com[1] + 0.5f) - ny / 2);
7399 int dz = 0;
7400 if (nz > 1) {
7401 dz = -(floor(com[2] + 0.5f) - nz / 2);
7402 }
7403 if (abs(dx)>=nx-1 || abs(dy)>=ny-1 || abs(dz)>=nz) {
7404 printf("ERROR, center of mass outside image\n");
7405 }
7406 else {
7407 image->translate(dx, dy, dz);
7408
7409 Transform t;
7410 t.set_trans((float)dx,(float)dy,(float)dz);
7411
7412 if (nz > 1) {
7413 image->set_attr("xform.align3d",&t);
7414 } else {
7415 image->set_attr("xform.align2d",&t);
7416 }
7417 }
7418
7419
7420}
7421
7422
7424{
7425 if (!image) {
7426 LOGWARN("NULL Image");
7427 return;
7428 }
7429
7430 int int_shift_only = params.set_default("int_shift_only",1);
7431 int powercenter = params.set_default("powercenter",0);
7432 float threshold = params.set_default("threshold",0.0f);
7433// int positive = params.set_default("positive",0);
7434
7435 if ((float)image->get_attr("sigma")==0.0f) return; // Can't center a constant valued image
7436 if (threshold>(float)image->get_attr("maximum")) {
7437 printf("Warning, centering threshold %1.2f, but image max %1.2f. Adjusting.",threshold,(float)image->get_attr("maximum"));
7438 threshold=(float)image->get_attr("mean")+(float)image->get_attr("sigma");
7439 }
7440
7441 EMData *tmp = 0;
7442 if (powercenter) { tmp=image; image=tmp->process("math.squared"); } // yes, I know, not very efficient
7443 FloatPoint com = image->calc_center_of_mass(threshold);
7444 if (powercenter) { delete image; image=tmp; }
7445
7446 int nx = image->get_xsize();
7447 int ny = image->get_ysize();
7448 int nz = image->get_zsize();
7449
7450 if (int_shift_only) {
7451 int dx = -(floor(com[0] + 0.5f) - nx / 2);
7452 int dy = -(floor(com[1] + 0.5f) - ny / 2);
7453 int dz = 0;
7454 if (nz > 1) {
7455 dz = -(floor(com[2] + 0.5f) - nz / 2);
7456 }
7457 if (abs(dx)>=nx-1 || abs(dy)>=ny-1 || abs(dz)>=nz) {
7458 printf("ERROR, center of mass outside image\n");
7459 }
7460 else {
7461 image->translate(dx, dy, dz);
7462
7463 Transform t;
7464 t.set_trans((float)dx,(float)dy,(float)dz);
7465
7466 if (nz > 1) {
7467 image->set_attr("xform.align3d",&t);
7468 } else {
7469 image->set_attr("xform.align2d",&t);
7470 }
7471 }
7472 }
7473 else {
7474 float dx = -(com[0] - nx / 2);
7475 float dy = -(com[1] - ny / 2);
7476 float dz = 0;
7477 if (nz > 1) {
7478 dz = -(com[2] - nz / 2);
7479 }
7480 if (fabs(dx)>=nx-1 || fabs(dy)>=ny-2 || fabs(dz)>=nz) {
7481 printf("ERROR, center of mass outside image\n");
7482 }
7483 else {
7484 image->translate(dx, dy, dz);
7485
7486 Transform t;
7487 t.set_trans(dx,dy,dz);
7488
7489 if (nz > 1) {
7490 image->set_attr("xform.align3d",&t);
7491 } else {
7492 image->set_attr("xform.align2d",&t);
7493 }
7494 }
7495 }
7496}
7497
7499{
7500 if (!image) {
7501 LOGWARN("NULL Image");
7502 return;
7503 }
7504
7505 int int_shift_only = params.set_default("int_shift_only",1);
7506
7507 vector<float> pcog = image->phase_cog();
7508
7509 int dims = image->get_ndim();
7510
7511 if (int_shift_only) {
7512 int dx=-int(pcog[0]+0.5f),dy=0,dz=0;
7513 if ( dims >= 2 ) dy = -int(pcog[1]+0.5);
7514 if ( dims == 3 ) dz = -int(pcog[2]+0.5);
7515
7516 Transform t;
7517 t.set_trans((float)dx,(float)dy,(float)dz);
7518 if (dims == 3) image->set_attr("xform.align3d",&t);
7519 else if (dims == 2) image->set_attr("xform.align2d",&t);
7520
7521 image->translate(dx,dy,dz);
7522 } else {
7523 float dx=-pcog[0],dy=0.0,dz=0.0;
7524 if ( dims >= 2 ) dy = -pcog[1];
7525 if ( dims == 3 ) dz = -pcog[2];
7526 image->translate(dx,dy,dz);
7527
7528 Transform t;
7529 t.set_trans(dx,dy,dz);
7530 if (dims == 3) image->set_attr("xform.align3d",&t);
7531 else if (dims == 2) image->set_attr("xform.align2d",&t);
7532 }
7533}
7534
7536{
7537 if (!image) {
7538 LOGWARN("NULL Image");
7539 return;
7540 }
7541
7542 Dict params1;
7543 params1["intonly"] = 1;
7544 params1["maxshift"] = image->get_xsize() / 4;
7545 EMData* aligned = image->align("translational", 0, params1);
7546 if ( image->get_ndim() == 3 ) {
7547 Transform* t = aligned->get_attr("xform.align3d");
7548 image->translate(t->get_trans());
7549 image->set_attr("xform.align3d",t);
7550 delete t;
7551 }
7552 else {
7553 // assumption is the image is 2D which may be false
7554 Transform* t = aligned->get_attr("xform.align2d");
7555 image->translate(t->get_trans());
7556 image->set_attr("xform.align2d",t);
7557 delete t;
7558 }
7559
7560 delete aligned;
7561
7562}
7563
7565{
7566 EMData *tmp=process(image);
7567 size_t n = (size_t)image->get_xsize()*image->get_ysize()*image->get_zsize();
7568 memcpy(image->get_data(),tmp->get_data(),n*sizeof(float));
7569 image->update();
7570 delete tmp;
7571}
7572
7574{
7575 const char *fsp = params["fscfile"];
7576 float snrmult = params.set_default("snrmult",1.5f);
7577 float sscale = params.set_default("sscale",1.0f);
7578 float maxfreq = params.set_default("maxfreq",1.0f);
7579
7580 XYData fsc;
7581 fsc.read_file(fsp);
7582 float nyquist=1.0/(2.0f*(float)image->get_attr("apix_x"));
7583
7584 float lf=1.0f;
7585 int N=(int)fsc.get_size();
7586 int localav=0; // once triggered, this uses a local average of 5 points instead of the point itself
7587 // While this could all be in one equation, the compiler will optimize it, and this is much more transparent
7588 for (int i=0; i<N; i++) {
7589 float s=i*nyquist/N;
7590 float f=fsc.get_y(i);
7591 float snr;
7592 if (s>=maxfreq && lf<f) f=lf*.9;
7593 if (f<0 && i>2) localav=1;
7594 if (localav==1 && i>N-3) f=lf;
7595 else if (localav==1) f=(fsc.get_y(i-2)+fsc.get_y(i-1)+fsc.get_y(i)+fsc.get_y(i+1)+fsc.get_y(i+2))/5.0f;
7596 else if (localav==2) f=.00001;
7597
7598 if (f>=1.0) f=.9999;
7599 if (f<0) { localav=2; f=.00001; }
7600
7601 snr=snrmult*f/(1.0-f); // if FSC==1, we just set it to 1000, which is large enough to make the Wiener filter effectively 1
7602 float wiener=snr*snr/(snr*snr+1);
7603 if (wiener<.001) wiener=.001; // we don't want to go all the way to zero. We leave behind just just a touch to preserve potential phase info
7604
7605 fsc.set_y(i,wiener);
7606 lf=f;
7607 }
7608 fsc.set_x(0,0); // just to make sure we have values to the origin.
7609// fsc.write_file("wiener.txt");
7610 FILE *out=fopen("wiener.txt","w");
7611 vector<float> wienerary(image->get_ysize());
7612 for (int i=0; i<image->get_ysize(); i++) {
7613 wienerary[i]=fsc.get_yatx(i*nyquist/image->get_ysize());
7614 fprintf(out,"%f\t%f\n",sscale*i*nyquist/image->get_ysize(),wienerary[i]);
7615 }
7616 fclose(out);
7617
7618 EMData *fft=image->do_fft();
7619 fft->apply_radial_func(0,sscale*0.5/(float)image->get_ysize(),wienerary);
7620
7621 EMData *ret=fft->do_ift();
7622 delete fft;
7623
7624 return ret;
7625}
7626
7628{
7629 if (!image) {
7630 return;
7631 }
7632
7633 int wiener = params["wiener"];
7634 const char *snrfile = params["snrfile"];
7635
7636 XYData sf;
7637 int err = sf.read_file(snrfile);
7638 if (err) {
7639 LOGERR("couldn't read structure factor file!");
7640 return;
7641 }
7642
7643
7644 for (size_t i = 0; i < sf.get_size(); i++) {
7645 if (sf.get_y(i) <= 0) {
7646 sf.set_y(i, -4.0f);
7647 }
7648 else {
7649 sf.set_y(i, log10(sf.get_y(i)));
7650 }
7651 }
7652 sf.update();
7653
7654 Ctf *image_ctf = image->get_ctf();
7655
7656 vector < float >ctf;
7657 if (wiener) {
7658 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_WIENER_FILTER, &sf);
7659 }
7660 else {
7661 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR, &sf);
7662 }
7663
7664 if(image_ctf) {delete image_ctf; image_ctf=0;}
7665
7666 image->process_inplace("normalize.circlemean");
7667
7668 int nx = image->get_xsize();
7669 int ny = image->get_ysize();
7670
7671 Region clip_r(-nx / 2, -ny / 2, nx * 2, ny * 2);
7672 EMData *d3 = image->get_clip(clip_r);
7673 EMData *d2 = d3->do_fft();
7674
7675// d2->apply_radial_func(0, 2.0f / Ctf::CTFOS, ctf, 0); // this is troubling! only EMAN1 CTF used CTFOS, and then, not correctly...
7676 d2->apply_radial_func(0, 2.0f, ctf, 0);
7677
7678 if( d3 )
7679 {
7680 delete d3;
7681 d3 = 0;
7682 }
7683
7684 if( image )
7685 {
7686 delete image;
7687 image = 0;
7688 }
7689
7690 EMData *d1 = d2->do_ift();
7691 int d1_nx = d1->get_xsize();
7692 int d1_ny = d1->get_ysize();
7693 Region d1_r(d1_nx / 4, d1_ny / 4, d1_nx / 2, d1_ny / 2);
7694
7695 image = d1->get_clip(d1_r);
7696
7697 if( d1 )
7698 {
7699 delete d1;
7700 d1 = 0;
7701 }
7702
7703 if( d2 )
7704 {
7705 delete d2;
7706 d2 = 0;
7707 }
7708}
7709
7711{
7712 if (!image) {
7713 return;
7714 }
7715
7716 float defocus = params.set_default("defocus",3.0);
7717 float ac = params.set_default("ac",10.0);
7718 float cs = params.set_default("cs",2.7);
7719 float voltage = params.set_default("voltage",300.0);
7720 float apix = params.set_default("apix",image->get_attr("apix_x"));
7721 float hppix = params.set_default("hppix",-1.0f);
7722 int useheader = params.set_default("useheader",0);
7723 int phaseflip = params.set_default("phaseflip",0);
7724
7725 int ny = image->get_ysize();
7726 EMAN2Ctf ctf;
7727 if (image->has_attr("ctf") && useheader){
7728
7729 ctf.copy_from((Ctf *)(image->get_attr("ctf")));
7730// printf("CTF %f\t%f\t%f\t%f\n",ctf.defocus,ctf.ampcont,ctf.voltage,ctf.apix);
7731 }
7732 else {
7733 ctf.defocus=defocus;
7734 ctf.voltage=voltage;
7735 ctf.cs=cs;
7736
7737 ctf.ampcont=ac;
7738 ctf.dfdiff=0;
7739 ctf.bfactor=200.0;
7740 }
7741 ctf.apix=apix;
7742 ctf.dsbg=1.0/(ctf.apix*ny);
7743
7744 int np=(int)ceil(ny*1.73)+1;
7745 vector <float> filter = ctf.compute_1d(np,ctf.dsbg,Ctf::CTF_AMP);
7746
7747 // reciprocal until the first CTF maximum, then no filter after that
7748 int i;
7749 filter[0]=1.0;
7750 for (i=1; i<np/2-1; i++) {
7751 if (filter[i+1]<filter[i]) {
7752 filter[i]=1.0/filter[i];
7753 break;
7754 }
7755 filter[i]=1.0/filter[i];
7756 }
7757 int gi=i;
7758 while (i<np/2) {
7759 if (phaseflip) filter[i]=filter[gi]*(filter[i]<0?-1.0f:1.0f);
7760 else filter[i]=filter[gi];
7761 i++;
7762 }
7763
7764 if (hppix>0) {
7765 for (int i=0; i<(int)hppix*3.0; i++) filter[i]*=tanh((float)i/hppix);
7766 }
7767
7768// for (i=0; i<np/2; i++) printf("%d\t%1.3g\n",i,filter[i]);
7769 image->process_inplace("filter.radialtable",Dict("table",filter));
7770
7771}
7772
7774{
7775 if (!image) {
7776 LOGWARN("NULL Image");
7777 return;
7778 }
7779 const char *filename = params["filename"];
7780 float apix = params["apix"];
7781
7782 FILE *in = fopen(filename, "rb");
7783 if (!in) {
7784 LOGERR("FileFourierProcessor: cannot open file '%s'", filename);
7785 return;
7786 }
7787
7788 float f = 0;
7789 int n = 0;
7790 while (fscanf(in, " %f %f", &f, &f) == 2) {
7791 n++;
7792 }
7793 rewind(in);
7794
7795 vector < float >xd(n);
7796 vector < float >yd(n);
7797
7798 float sf = apix * image->get_xsize();
7799
7800 for (int i = 0; fscanf(in, " %f %f", &xd[i], &yd[i]) == 2; i++) {
7801 xd[i] *= sf;
7802 }
7803
7804 if (xd[2] - xd[1] != xd[1] - xd[0]) {
7805 LOGWARN("Warning, x spacing appears nonuniform %g!=%g\n",
7806 xd[2] - xd[1], xd[1] - xd[0]);
7807 }
7808
7809 EMData *d2 = image->do_fft();
7810 if( image )
7811 {
7812 delete image;
7813 image = 0;
7814 }
7815
7816 d2->apply_radial_func(xd[0], xd[1] - xd[0], yd, 1);
7817 image = d2->do_ift();
7818}
7819
7821{
7822 if (!image) {
7823 LOGWARN("NULL Image");
7824 return;
7825 }
7826
7827 if (image->get_zsize()>1) throw ImageDimensionException("Error: math.xybadlines works only on 2D images");
7828
7829 int nx=image->get_xsize();
7830 int ny=image->get_ysize();
7831
7832 vector <int> cols = params.set_default("cols",vector <int> ());
7833 vector <int> rows = params.set_default("rows",vector <int> ());
7834 float nnorm = params.set_default("neighbornorm",1.0f);//sqrt(2.0f));
7835
7836 int mincol = *min_element(cols.begin(),cols.end());
7837 int maxcol = *max_element(cols.begin(),cols.end());
7838
7839 int minrow = *min_element(rows.begin(),rows.end());
7840 int maxrow = *max_element(rows.begin(),rows.end());
7841
7842 int start;
7843 int ogl;
7844 int ngl;
7845 bool inflag;
7846 int pos;
7847
7848 ogl = 0;
7849 for (int x=mincol-1; x<=maxcol+1; x++) {
7850 inflag = false;
7851 for (int i=0; i<=cols.size(); i++) if (x==cols[i]) inflag = true;
7852 if (inflag == true) continue;
7853 else {
7854 inflag = false;
7855 for (int i=0; i<=cols.size(); i++) if ((x-1)==cols[i]) inflag = true;
7856 if (inflag == true){
7857 ngl = x;
7858 start = ogl+1;
7859 for (int c=start; c<ngl; c++) {
7860 //printf("Fixing column %d\n",c);
7861 pos = c-ogl;
7862 for (int y=0; y<ny; y++) {
7863 float val = ((image->get_value_at(ogl,y)*(ngl-ogl-pos)+image->get_value_at(ngl,y)*pos)) / (nnorm*(ngl-ogl));
7864 image->set_value_at(c,y,val);
7865 }
7866 }
7867 ogl = x;
7868 }
7869 else ogl = x;
7870 }
7871 }
7872
7873 ogl = 0;
7874 for (int y=minrow-1; y<=maxrow+1; y++) {
7875 inflag = false;
7876 for (int i=0; i<=rows.size(); i++) if (y==rows[i]) inflag = true;
7877 if (inflag == true) continue;
7878 else {
7879 inflag = false;
7880 for (int i=0; i<=rows.size(); i++) if ((y-1)==rows[i]) inflag = true;
7881 if (inflag == true){
7882 ngl = y;
7883 for (int r=ogl+1; r<ngl; r++) {
7884 //printf("Fixing row %d\n",r);
7885 pos = r-ogl;
7886 for (int x=0; x<nx; x++) {
7887 float val = ((image->get_value_at(x,ogl)*(ngl-ogl-pos)+image->get_value_at(x,ngl)*pos)) / (nnorm*(ngl-ogl));
7888 image->set_value_at(x,r,val);
7889 }
7890 }
7891 ogl = y;
7892 }
7893 else ogl = y;
7894 }
7895 }
7896}
7897
7898
7900{
7901 if (!image) {
7902 LOGWARN("NULL Image");
7903 return;
7904 }
7905 int xlen = params.set_default("xlen",10);
7906 int ylen = params.set_default("ylen",10);
7907
7908 int nx=image->get_attr("nx");
7909 int ny=image->get_attr("ny");
7910 EMData *tmp=new EMData(nx,ny,1);
7911
7912 // we do this in real-space, since the integration size is small, and we don't want Fourier edge effects
7913 // we use a 'moving window' to avoid summing the same points multiple times
7914 // start with y
7915 if (ylen>0) {
7916 for (int x=0; x<nx; x++) {
7917 float sum=0.0;
7918 float sumn=0.0;
7919 for (int y=0; y<(ylen<ny?ylen:ny); y++) { sum+=image->get_value_at(x,y); sumn+=1.0; } // we seed the process with a 1/2 stripe
7920 // now loop over each final pixel
7921 for (int y=0; y<ny; y++) {
7922 if (y+ylen<ny) { sum+=image->get_value_at(x,y+ylen); sumn+=1.0; }
7923 if (y-ylen-1>=0) { sum-=image->get_value_at(x,y-ylen-1); sumn-=1.0; }
7924 tmp->set_value_at_fast(x,y,sum/sumn);
7925 }
7926 }
7927 tmp->write_image("tmp.hdf",0);
7928 image->sub(*tmp);
7929 }
7930
7931 // now x
7932 if (xlen>0) {
7933 for (int y=0; y<ny; y++) {
7934 float sum=0.0;
7935 float sumn=0.0;
7936 for (int x=0; x<(xlen<nx?xlen:nx); x++) { sum+=image->get_value_at(x,y); sumn+=1.0; } // we seed the process with a 1/2 stripe
7937 // now loop over each final pixel
7938 for (int x=0; x<nx; x++) {
7939 if (x+xlen<nx) { sum+=image->get_value_at(x+xlen,y); sumn+=1.0; }
7940 if (x-xlen-1>=0) { sum-=image->get_value_at(x-xlen-1,y); sumn-=1.0; }
7941 tmp->set_value_at_fast(x,y,sum/sumn);
7942 }
7943 }
7944 tmp->write_image("tmp.hdf",1);
7945 image->sub(*tmp);
7946 }
7947
7948 delete tmp;
7949}
7950
7951
7953{
7954 if (!image) {
7955 LOGWARN("NULL Image");
7956 return;
7957 }
7958 float apix = params["apix"];
7959 float threshold = params["threshold"];
7960 float radius = params["radius"];
7961
7962 if (apix > 0) {
7963 int ny = image->get_ysize();
7964 radius = ny * apix / radius;
7965 //printf("Norm filter radius=%1.1f\n", radius);
7966 }
7967
7968 EMData *blur = image->copy();
7969 EMData *maskblur = image->copy();
7970
7971 maskblur->process_inplace("threshold.binary", Dict("value", threshold));
7972 maskblur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
7973// maskblur->process_inplace("filter.highpass.tanh", Dict("highpass", -10.0f));
7974 maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
7975// maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
7976
7977
7978 blur->process_inplace("threshold.belowtozero", Dict("minval", threshold));
7979 blur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
7980// blur->process_inplace("filter.highpass.tanh", Dict("cutoff_abs", -10.0f));
7981
7982 maskblur->div(*blur);
7983 image->mult(*maskblur);
7984// maskblur->write_image("norm.mrc", 0, EMUtil::IMAGE_MRC);
7985
7986 if( maskblur )
7987 {
7988 delete maskblur;
7989 maskblur = 0;
7990 }
7991
7992 if( blur )
7993 {
7994 delete blur;
7995 blur = 0;
7996 }
7997}
7998
7999
8001{
8002 if (!image) {
8003 LOGWARN("NULL Image");
8004 return;
8005 }
8006 float thresh = params["thresh"];
8007 int output_symlabel = params["output_symlabel"];
8008
8009 // set up all the symmetry transforms for all the searched symmetries
8010 const vector<string> sym_list = params["sym"];
8011 int sym_num = sym_list.size();
8012 vector< vector< Transform > > transforms(sym_num);
8013 vector< float* > symvals(sym_num);
8014 for (int i =0; i < sym_num; i++) {
8015 vector<Transform> sym_transform = Symmetry3D::get_symmetries(sym_list[i]);
8016 transforms[i] = sym_transform;
8017 symvals[i] = new float[sym_transform.size()]; // new float(nsym);
8018 }
8019
8020 EMData *orig = image->copy();
8021
8022 image->to_zero();
8023
8024 int nx= image->get_xsize();
8025 int ny= image->get_ysize();
8026 int nz= image->get_zsize();
8027 int xy = nx * ny;
8028 float * data = image->get_data();
8029 float * sdata = orig->get_data();
8030
8031 EMData *symlabel = 0;
8032 float * ldata = symlabel->get_data();
8033 if (output_symlabel) {
8034 symlabel = image->copy();
8035 symlabel->to_zero();
8036 ldata = symlabel->get_data();
8037 }
8038
8039 for (int k = 0; k < nz; k++) {
8040 for (int j = 0; j < ny; j++) {
8041 for(int i = 0; i < nx; i++) {
8042 size_t index = (size_t)k * nx * ny + j * nx + i;
8043 float val = sdata[ index ];
8044 float bestmean = val, bestsymlevel = FLT_MAX;
8045 int bestsym = 0;
8046 for( int sym = 0; sym< sym_num; sym++) {
8047 int cur_sym_num = transforms[sym].size();
8048 float *symval = symvals[sym];
8049 // first find out all the symmetry related location values
8050 for( int s = 0; s < cur_sym_num; s++){
8051 Transform r = transforms[sym][s];
8052 float x2 = (float)(r[0][0] * (i-nx/2) + r[0][1] * (j-ny/2) + r[0][2] * (k-nz/2) + nx / 2);
8053 float y2 = (float)(r[1][0] * (i-nx/2) + r[1][1] * (j-ny/2) + r[1][2] * (k-nz/2) + ny / 2);
8054 float z2 = (float)(r[2][0] * (i-nx/2) + r[2][1] * (j-ny/2) + r[2][2] * (k-nz/2) + nz / 2);
8055
8056 if (x2 >= 0 && y2 >= 0 && z2 >= 0 && x2 < (nx - 1) && y2 < (ny - 1)
8057 && z2 < (nz - 1)) {
8058 float x = (float)Util::fast_floor(x2);
8059 float y = (float)Util::fast_floor(y2);
8060 float z = (float)Util::fast_floor(z2);
8061
8062 float t = x2 - x;
8063 float u = y2 - y;
8064 float v = z2 - z;
8065
8066 size_t ii = x + y * nx + z * (size_t)xy;
8067
8068 symval[s]=
8069 Util::trilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],
8070 sdata[ii + nx + 1], sdata[ii + nx * ny],
8071 sdata[ii + xy + 1], sdata[ii + xy + nx],
8072 sdata[ii + xy + nx + 1], t, u, v);
8073 }
8074 else {
8075 symval[s] = 0.0 ;
8076 }
8077 }
8078 float tmean=0, tsigma=0;
8079 for( int s = 0; s < cur_sym_num; s++) {
8080 tmean += symval[s];
8081 tsigma += symval[s] * symval[s];
8082 }
8083 tmean /= cur_sym_num;
8084 tsigma = tsigma/cur_sym_num - tmean*tmean;
8085 if (tsigma < bestsymlevel ) {
8086 bestsymlevel = tsigma;
8087 bestmean = tmean;
8088 bestsym = sym;
8089 }
8090 }
8091 if ( bestsymlevel > thresh) {
8092 if (output_symlabel) ldata[index] = (float)bestsym;
8093 data[index] = bestmean;
8094 }
8095 else {
8096 if (output_symlabel) ldata[index] = -1;
8097 data[index] = val;
8098 }
8099 }
8100 }
8101 }
8102 if( orig )
8103 {
8104 delete orig;
8105 orig = 0;
8106 }
8107 for (int i =0; i < sym_num; i++) {
8108 if( symvals[i] )
8109 {
8110 delete symvals[i];
8111 symvals[i] = 0;
8112 }
8113 }
8114 if (symlabel) params.put("symlabel_map", EMObject(symlabel));
8115}
8116
8117
8119{
8120 if (!image) {
8121 LOGWARN("NULL Image");
8122 return;
8123 }
8124 EMData* mask = params.set_default("image",(EMData*)0);
8125
8126 if (mask==0) {
8127 const char *filename = params["filename"];
8128 mask=new EMData(filename,0);
8129 if (!EMUtil::is_same_size(image, mask)) {
8130 delete mask;
8131 LOGERR("IndexMaskFileProcessor: Mask size different than image");
8132 return;
8133 }
8134 }
8135 else mask=mask->copy();
8136
8137 int maskset=params.set_default("maskset",-1);
8138 if (maskset>=0) {
8139 mask->process_inplace("threshold.binaryrange", Dict("low", (float)(maskset-0.5), "high", (float)(maskset+0.5)));
8140 }
8141
8142 image->mult(*mask);
8143 delete mask;
8144}
8145
8146
8147// void CoordinateMaskFileProcessor::process_inplace(EMData * image)
8148// {
8149// if (!image) {
8150// LOGWARN("NULL Image");
8151// return;
8152// }
8153//
8154// const char *filename = params["filename"];
8155// EMData *msk = new EMData();
8156// msk->read_image(filename);
8157//
8158// int nx = image->get_xsize();
8159// int ny = image->get_ysize();
8160// int nz = image->get_zsize();
8161//
8162// int xm = msk->get_xsize();
8163// int ym = msk->get_ysize();
8164// int zm = msk->get_zsize();
8165//
8166// float apix = image->get_attr("apix_x");
8167// float apixm = msk->get_attr("apix_x");
8168//
8169// float xo = image->get_attr_default("origin_x",0.0);
8170// float yo = image->get_attr_default("origin_y",0.0);
8171// float zo = image->get_attr_default("origin_z",0.0);
8172//
8173// float xom = msk->get_attr_default("origin_x",0.0);
8174// float yom = msk->get_attr_default("origin_y",0.0);
8175// float zom = msk->get_attr_default("origin_z",0.0);
8176//
8177// float *dp = image->get_data();
8178// float *dpm = msk->get_data();
8179// int nxy = nx * ny;
8180//
8181// for (int k = 0; k < nz; k++) {
8182// float zc = zo + k * apix;
8183// if (zc <= zom || zc >= zom + zm * apixm) {
8184// memset(&(dp[k * nxy]), 0, sizeof(float) * nxy);
8185// }
8186// else {
8187// int km = (int) ((zc - zom) / apixm);
8188//
8189// for (int j = 0; j < ny; j++) {
8190// float yc = yo + j * apix;
8191// if (yc <= yom || yc >= yom + ym * apixm) {
8192// memset(&(dp[k * nxy + j * nx]), 0, sizeof(float) * nx);
8193// }
8194// else {
8195// int jm = (int) ((yc - yom) / apixm);
8196// size_t idx = 0;
8197// float xc;
8198// int im;
8199// for (int i = 0; i < nx; i++) {
8200// xc = xo + i * apix;
8201// idx = (size_t)k * nxy + j * nx + i;
8202// if (xc <= xom || xc >= xom + xm * apixm) {
8203// dp[idx] = 0;
8204// }
8205// else {
8206// im = (int) ((xc - xom) / apixm);
8207// if (dpm[km * xm * ym + jm * xm + im] <= 0) {
8208// dp[idx] = 0;
8209// }
8210// }
8211// }
8212// }
8213// }
8214// }
8215// }
8216//
8217// image->update();
8218// msk->update();
8219// if( msk )
8220// {
8221// delete msk;
8222// msk = 0;
8223// }
8224// }
8225
8226void MatchSFProcessor::create_radial_func(vector < float >&rad,EMData *image) const {
8227 // The radial mask comes in with the existing radial image profile
8228 // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
8229
8230 EMData *to = params["to"];
8231 float apixto = to->get_attr("apix_x");
8232 bool bydot = params.set_default("bydot",false);
8233 float keephires = params.set_default("keephires",false);
8234
8235 if (to->get_ysize() != image->get_ysize()) throw ImageDimensionException("Fatal Error: filter.matchto - image sizes must match");
8236
8237 // This method is similar to that used by math.sub.optimal
8238 // It scales such that the average dot product at each resolution is matched,
8239 // but negative values (phase flips) are set to zero.
8240 if (bydot) {
8241 // Note that 'image' is guaranteed to be the FFT already
8242 EMData *tofft;
8243 if (to->is_complex()) tofft=to;
8244 else tofft=to->do_fft();
8245
8246 float cornerscale;
8247 if (image->get_zsize()>1) cornerscale=sqrt(3.0);
8248 else cornerscale=sqrt(2.0);
8249
8250 int ny=image->get_ysize();
8251 int ny2=(int)floor(image->get_ysize()*cornerscale/2);
8252 vector <float>norm(ny2+1);
8253 for (int i=0; i<ny2; i++) norm[i]=rad[i]=0;
8254
8255 for (int y=-ny; y<ny; y++) {
8256 for (int x=0; x<ny; x++) { // intentionally skipping the final pixel in x
8257 int r=int(Util::hypot_fast(x,y));
8258 if (r>ny2) continue;
8259 std::complex<float> v1=image->get_complex_at(x,y);
8260 std::complex<float> v2=tofft->get_complex_at(x,y);
8261 rad[r]+=(double)(v1.real()*v2.real()+v1.imag()*v2.imag());
8262 norm[r]+=(double)(v2.real()*v2.real()+v2.imag()*v2.imag());
8263 }
8264 }
8265 float radmean=0.0f;
8266 for (int i=0; i<ny2; i++) {
8267 rad[i]=(rad[i]/norm[i]<0)?0.0:rad[i]/norm[i];
8268 radmean+=rad[i];
8269 }
8270 radmean/=ny2;
8271
8272 if (keephires) {
8273 for (int i=0; i<ny2; i++) {
8274 if (rad[i]<radmean/100.0) rad[i]=radmean/100.0;
8275 }
8276 }
8277
8278 if (!to->is_complex()) delete tofft;
8279 return;
8280 }
8281
8282 // This simply divides one radial intensity profile by the other
8283 if (to->is_complex()) {
8284 vector<float> rd=to->calc_radial_dist(rad.size(),0,1.0f,1);
8285 for (size_t i=0; i<rd.size(); ++i) {
8286 if (rad[i]>0) rad[i]=sqrt(rd[i]/rad[i]);
8287 }
8288 }
8289 else {
8290 EMData *tmp=to->do_fft();
8291 vector<float> rd=tmp->calc_radial_dist(rad.size(),0,1.0f,1);
8292 for (size_t i=0; i<rd.size(); ++i) {
8293 if (rad[i]>0) rad[i]=sqrt(rd[i]/rad[i]);
8294 }
8295 delete tmp;
8296 }
8297
8298 // This makes sure that the filter never falls below 0.01 of the mean filter value so we keep something at all resolutions
8299 if (keephires) {
8300 float radmean=0.0f;
8301 for (int i=0; i<rad.size(); i++) radmean+=rad[i];
8302 radmean/=rad.size();
8303 for (int i=0; i<rad.size(); i++) {
8304 if (rad[i]<radmean/100.0) rad[i]=radmean/100.0;
8305 }
8306 }
8307
8308
8309}
8310
8312
8313 EMData *tmp = 0;
8314 if (!image->is_complex()) { tmp=image; image=tmp->do_fft(); }
8315
8316 XYData *tmpsf = params["strucfac"];
8317 XYData *sf = new XYData();
8318 sf->set_state(tmpsf->get_state());
8319 for (int i=0; i<sf->get_size(); i++) sf->set_y(i,sqrt(sf->get_y(i)));
8320
8321 if(params.has_key("apix")) {
8322 image->set_attr("apix_x", (float)params["apix"]);
8323 image->set_attr("apix_y", (float)params["apix"]);
8324 image->set_attr("apix_z", (float)params["apix"]);
8325 if (image->has_attr("ctf")) {
8326 Ctf *ctf=image->get_attr("ctf");
8327 ctf->apix=(float)params["apix"];
8328 image->set_attr("ctf",ctf);
8329 delete(ctf);
8330 }
8331 }
8332
8333 float apix=image->get_attr("apix_x");
8334 int nx=image->get_xsize();
8335 int ny=image->get_ysize();
8336 int nz=image->get_zsize();
8337
8338 if (nz==1) {
8339 for (int j=-ny/2; j<ny/2; j++) {
8340 for (int i=0; i<nx/2; i++) {
8341 float r=Util::hypot2(i/(float)(nx-2),j/(float)ny)/apix; // radius in terms of Nyquist=0.5
8342 float a=sf->get_yatx(r);
8343 std::complex<float> v=image->get_complex_at(i,j);
8344 if (v!=0.0f) v*=a/abs(v);
8345 else v=std::complex<float>(a,0);
8346 image->set_complex_at(i,j,v);
8347 }
8348 }
8349 }
8350 else {
8351 for (int k=-nz/2; k<nz/2; k++) {
8352 for (int j=-ny/2; j<ny/2; j++) {
8353 for (int i=0; i<nx/2; i++) {
8354 float r=Util::hypot3(i/(float)(nx-2),j/(float)ny,k/(float)nz)/apix; // radius in terms of Nyquist=0.5
8355 float a=sf->get_yatx(r);
8356 std::complex<float> v=image->get_complex_at(i,j,k);
8357 if (v!=0.0f) v*=a/abs(v);
8358 else v=std::complex<float>(a,0);
8359 image->set_complex_at(i,j,k,v);
8360 }
8361 }
8362 }
8363 }
8364
8365 if (tmp!=0) {
8366 EMData *tmp2=image->do_ift();
8367 memcpy(tmp->get_data(),tmp2->get_data(),tmp2->get_size()*sizeof(float));
8368 delete tmp2;
8369 delete image;
8370 }
8371 delete sf;
8372
8373}
8374
8375
8376void SetSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
8377 // The radial mask comes in with the existing radial image profile
8378 // The radial mask runs from 0 to the corner in Fourier space
8379
8380 XYData *sf = 0;
8381 if (params.has_key("filename")) {
8382 sf=new XYData;
8383 sf->read_file((const char *)params["filename"]);
8384 }
8385 else sf = params["strucfac"];
8386 if(params.has_key("apix")) {
8387 image->set_attr("apix_x", (float)params["apix"]);
8388 image->set_attr("apix_y", (float)params["apix"]);
8389 image->set_attr("apix_z", (float)params["apix"]);
8390 if (image->has_attr("ctf")) {
8391 Ctf *ctf=image->get_attr("ctf");
8392 ctf->apix=(float)params["apix"];
8393 image->set_attr("ctf",ctf);
8394 delete(ctf);
8395 }
8396 }
8397 float scale=params.set_default("scale",1.0f);
8398
8399 float apix=image->get_attr("apix_x");
8400 int ny=image->get_ysize();
8401 int n = radial_mask.size();
8402 int nmax=(int)floor(sf->get_x(sf->get_size()-1)*apix*ny); // This is the radius at which we have our last valid value from the curve
8403 if (nmax>n) nmax=n;
8404
8405 if ((nmax)<3) throw InvalidParameterException("Insufficient structure factor data for SetSFProcessor to be meaningful");
8406
8407 int i;
8408 radial_mask[0]=1;
8409 for (i=1; i<nmax; i++) {
8410// if (radial_mask[i]>0)
8411// {
8412// radial_mask[i]= sqrt(n*sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
8413// }
8414 if (radial_mask[i]>0) {
8415 radial_mask[i]= sqrt((ny*ny*ny)*scale*sf->get_yatx(i/(apix*ny))/radial_mask[i]);
8416 }
8417 else if (i>0) radial_mask[i]=radial_mask[i-1]; // For points where the existing power spectrum was 0
8418
8419 }
8420
8421 // Continue to use a fixed factor after we run out of 'sf' values
8422
8423 while (i<n) {
8424 radial_mask[i]=radial_mask[nmax-1];
8425 i++;
8426 }
8427
8428 if (params.has_key("filename")) delete sf;
8429}
8430
8432{
8433 if (!image) {
8434 LOGWARN("NULL Image");
8435 return;
8436 }
8437
8438 float mask = params["mask"];
8439
8440 int nx = image->get_xsize();
8441 int ny = image->get_ysize();
8442 int nz = image->get_zsize();
8443
8444 float *dat = image->get_data();
8445 double sma = 0;
8446 size_t smn = 0;
8447 float r = 0.0f;
8448 for (int k = 0; k < nz; ++k) {
8449 for (int j = 0; j < ny; ++j) {
8450 for (int i = 0; i < nx; ++i, ++dat) {
8451 r =
8452 sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
8453 Util::square(k - nz / 2));
8454 if (r > mask - 1.5f && r < mask - 0.5f) {
8455 sma += *dat;
8456 smn++;
8457 }
8458 }
8459 }
8460 }
8461
8462 float smask = (float) (sma / smn);
8463 image->update();
8464
8465 dat = image->get_data();
8466 for (int k = 0; k < nz; ++k) {
8467 for (int j = 0; j < ny; ++j) {
8468 for (int i = 0; i < nx; ++i, ++dat) {
8469 r =
8470 sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
8471 Util::square(k - nz / 2));
8472 if (r > mask - .5) {
8473 *dat = 0;
8474 }
8475 else {
8476 *dat -= smask;
8477 }
8478 }
8479 }
8480 }
8481
8482 image->update();
8483}
8484
8485// updated 2018-06-26 by Muyuan
8487{
8488 if (!image) {
8489 LOGWARN("NULL Image");
8490 return;
8491 }
8492
8493
8494 float sig = image->get_attr("sigma");
8495 float mean = image->get_attr("mean");
8496
8497 float thr1 = params.set_default("threshold1",mean + sig * 2);
8498 float thr2 = params.set_default("threshold2",mean + sig * 1);
8499
8500 EMData *mask=image->copy();
8501 mask->process_inplace("threshold.binary",Dict("value",thr1));
8502
8503 EMData *mask2=image->copy();
8504 mask2->process_inplace("threshold.binary",Dict("value",thr2));
8505 float maskmean=mask->get_attr("mean");
8506 for (int i=0; i<1000; i++){
8507 mask->process_inplace("mask.addshells",Dict("nshells",2));
8508 mask->mult(*mask2);
8509 if (float(mask->get_attr("mean"))==maskmean)
8510 break;
8511 maskmean=mask->get_attr("mean");
8512// printf("%d\t%f\n", i, maskmean);
8513 }
8514
8515
8516 // below copied from mask.auto3d
8517 int nshells = params["nshells"];
8518 int nshellsgauss = params["nshellsgauss"];
8519
8520 mask->process_inplace("mask.addshells.gauss", Dict("val1", (int)(nshells+nshellsgauss/2),"val2",0));
8521 if (nshellsgauss>0)
8522 mask->process_inplace("filter.lowpass.gauss", Dict("cutoff_abs", (float)(1.0f/(float)nshellsgauss)));
8523
8524 mask->process_inplace("threshold.belowtozero", Dict("minval",(float)0.002)); // this makes the value exactly 0 beyond ~2.5 sigma
8525
8526 bool return_mask = params.set_default("return_mask",false);
8527 if (return_mask) {
8528 // 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.
8529 float *dat = image->get_data();
8530 float *dat2 = mask->get_data();
8531 memcpy(dat,dat2,image->get_size()*sizeof(float));
8532 } else {
8533 image->mult(*mask);
8534 }
8535
8536 delete mask;
8537 delete mask2;
8538}
8539
8540// Originally this was done recursively, but there were issues with exceeding the maximum recursion depth,
8541// so switched to a vector-style algorithm instead
8543{
8544 if (!imagein) {
8545 LOGWARN("NULL Image");
8546 return;
8547 }
8548 image=imagein;
8549
8550 int nx = image->get_xsize();
8551 int ny = image->get_ysize();
8552 int nz = image->get_zsize();
8553
8554 int verbose=params.set_default("verbose",0);
8555 unsigned int voxels=params.set_default("voxels",27);
8556 float threshold=params.set_default("threshold",1.5);
8557
8558 mask = new EMData();
8559 mask->set_size(nx, ny, nz);
8560 mask->to_one();
8561
8562 for (int zz = 0; zz < nz; zz++) {
8563 for (int yy = 0; yy < ny; yy++) {
8564 for (int xx = 0; xx < nx; xx++) {
8565 if (image->get_value_at(xx,yy,zz)>threshold && mask->get_value_at(xx,yy,zz)==1.0) {
8566 vector<Vec3i> pvec;
8567 pvec.push_back(Vec3i(xx,yy,zz));
8568 for (uint i=0; i<pvec.size(); i++) {
8569 // Duplicates will occur the way the algorithm is constructed, so we eliminate them as we encounter them
8570 if (mask->sget_value_at(pvec[i])==0.0f) {
8571 pvec.erase(pvec.begin()+i);
8572 i--;
8573 continue;
8574 }
8575
8576 // mask out the points in the volume
8577 mask->set_value_at(pvec[i],0.0f);
8578
8579 int x=pvec[i][0];
8580 int y=pvec[i][1];
8581 int z=pvec[i][2];
8582 // Any neighboring values above threshold we haven't already set get added to the list
8583 if (image->sget_value_at(x-1,y,z)>threshold && mask->get_value_at(x-1,y,z)==1.0) pvec.push_back(Vec3i(x-1,y,z));
8584 if (image->sget_value_at(x+1,y,z)>threshold && mask->get_value_at(x+1,y,z)==1.0) pvec.push_back(Vec3i(x+1,y,z));
8585 if (image->sget_value_at(x,y-1,z)>threshold && mask->get_value_at(x,y-1,z)==1.0) pvec.push_back(Vec3i(x,y-1,z));
8586 if (image->sget_value_at(x,y+1,z)>threshold && mask->get_value_at(x,y+1,z)==1.0) pvec.push_back(Vec3i(x,y+1,z));
8587 if (image->sget_value_at(x,y,z-1)>threshold && mask->get_value_at(x,y,z-1)==1.0) pvec.push_back(Vec3i(x,y,z-1));
8588 if (image->sget_value_at(x,y,z+1)>threshold && mask->get_value_at(x,y,z+1)==1.0) pvec.push_back(Vec3i(x,y,z+1));
8589 }
8590
8591 // If the blob is too big, then we don't mask it out after all, but we set the value
8592 // to 2.0 so we know the voxels have already been examined, and don't check them again
8593 if (pvec.size()>voxels) {
8594 if (verbose) printf("%d\t%d\t%d\tvoxels: %d\n",xx,yy,zz,(int)pvec.size());
8595 for (uint i=0; i<pvec.size(); i++) mask->set_value_at(pvec[i],2.0);
8596 }
8597 }
8598 }
8599 }
8600 }
8601
8602 mask->process_inplace("threshold.binary",Dict("value",0.5));
8603
8604 // Now we expand the mask by 1 pixel and blur the edge
8605 mask->mult(-1.0f);
8606 mask->add(1.0f);
8607 mask->process_inplace("mask.addshells",Dict("nshells",2)); // expand by 1 shell
8608 mask->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.25f));
8609 mask->mult(-1.0f);
8610 mask->add(1.0f);
8611 mask->update();
8612
8613 // apply the mask
8614 image->mult(*mask);
8615 if (verbose>1) mask->write_image("mask.hdf", 0, EMUtil::IMAGE_HDF);
8616
8617 delete mask;
8618}
8619
8620
8622{
8623 if (!image) {
8624 LOGWARN("NULL Image");
8625 return;
8626 }
8627
8628 if (image->get_ndim() != 3) {
8629 throw ImageDimensionException("This processor was only ever designed to work on 3D images.");
8630 }
8631
8632 /*
8633 The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
8634 To get around this just use the return_mask parameter.
8635 string mask_output = params.set_default("write_mask", "");
8636 if ( mask_output != "") {
8637 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.");
8638 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
8639 }
8640 */
8641
8642 int radius=0;
8643 if (params.has_key("radius")) {
8644 radius = params["radius"];
8645 }
8646 int nmaxseed=0;
8647 if (params.has_key("nmaxseed")) {
8648 nmaxseed = params["nmaxseed"];
8649 }
8650
8651 float threshold=0.0;
8652 if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
8653 else threshold=params["threshold"];
8654
8655 int nshells = params["nshells"];
8656 int nshellsgauss = params["nshellsgauss"];
8657 int verbose=params.set_default("verbose",0);
8658
8659 int nx = image->get_xsize();
8660 int ny = image->get_ysize();
8661 int nz = image->get_zsize();
8662 int nxy=nx*ny;
8663
8664 EMData *amask = new EMData();
8665 amask->set_size(nx, ny, nz);
8666
8667 float *dat = image->get_data();
8668 float *dat2 = amask->get_data();
8669 int i,j,k;
8670 size_t l = 0;
8671
8672 // Seeds with the highest valued pixels
8673 if (nmaxseed>0) {
8674 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
8675
8676 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
8677 amask->set_value_at((*i).x,(*i).y,(*i).z,1.0);
8678 if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
8679 }
8680 }
8681
8682 // Seeds with a sphere
8683 if (radius>0) {
8684 // start with an initial sphere
8685 for (k = -nz / 2; k < nz / 2; ++k) {
8686 for (j = -ny / 2; j < ny / 2; ++j) {
8687 for (i = -nx / 2; i < nx / 2; ++i,++l) {
8688 if (abs(k) > radius || abs(j) > radius || abs(i) > radius) continue;
8689 if ( (k * k + j * j + i * i) > (radius*radius) || dat[l] < threshold) continue;
8690 dat2[l] = 1.0f;
8691 }
8692 }
8693 }
8694 }
8695
8696
8697 // iteratively 'flood fills' the map... recursion would be better
8698 int done=0;
8699 int iter=0;
8700 while (!done) {
8701 iter++;
8702 done=1;
8703 if (verbose && iter%10==0) printf("%d iterations\n",iter);
8704 for (k=1; k<nz-1; ++k) {
8705 for (j=1; j<ny-1; ++j) {
8706 for (i=1; i<nx-1; ++i) {
8707 l=i+j*nx+k*nx*ny;
8708 if (dat2[l]) continue;
8709 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx]||dat2[l-nxy]||dat2[l+nxy])) {
8710 dat2[l]=1.0;
8711 done=0;
8712 }
8713 }
8714 }
8715 }
8716 }
8717
8718 amask->update();
8719
8720 if (verbose) printf("expanding mask\n");
8721 amask->process_inplace("mask.addshells.gauss", Dict("val1", (int)(nshells+nshellsgauss/2),"val2",0));
8722 if (verbose) printf("filtering mask\n");
8723 if (nshellsgauss>0) amask->process_inplace("filter.lowpass.gauss", Dict("cutoff_abs", (float)(1.0f/(float)nshellsgauss)));
8724 amask->process_inplace("threshold.belowtozero", Dict("minval",(float)0.002)); // this makes the value exactly 0 beyond ~2.5 sigma
8725
8726 bool return_mask = params.set_default("return_mask",false);
8727 if (return_mask) {
8728 // 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.
8729 dat = image->get_data();
8730 dat2 = amask->get_data();
8731 memcpy(dat,dat2,image->get_size()*sizeof(float));
8732 } else {
8733 image->mult(*amask);
8734 }
8735
8736 // EMAN2 policy is not to allow file io from with a processor
8737 //if (mask_output != "") {
8738 // amask->write_image(mask_output);
8739 //}
8740
8741
8742 delete amask;
8743}
8744
8746{
8747 if (!image) {
8748 LOGWARN("NULL Image");
8749 return;
8750 }
8751
8752 float val1 = params["val1"];
8753 float val2 = params["val2"];
8754
8755 int nx = image->get_xsize();
8756 int ny = image->get_ysize();
8757 int nz = image->get_zsize();
8758 EMData *image2 = new EMData(nx,ny,nz);
8759
8760 // Got a compile warning complaining that these things were never used. Hope I didn't break anything - apologies if so (d.woolford)
8761// float *dat = image->get_data();
8762// float *dat2 = image2->get_data();
8763
8764
8765 float *d = image->get_data();
8766 float *d2 = image2->get_data();
8767
8768 const int nxy = nx * ny;
8769 size_t size = (size_t)nx * ny * nz;
8770
8771 // TODO: THIS IS EXTREMELY INEFFICIENT
8772 if (nz != 1) {
8773 for (int l = 1; l <= (int) val1+val2; ++l) {
8774 for (size_t i=0; i<size; i++) d2[i]=d[i];
8775 for (int k = 1; k < nz - 1; ++k) {
8776 for (int j = 1; j < ny - 1; ++j) {
8777 for (int i = 1; i < nx - 1; ++i) {
8778 size_t t = i + j*nx+(size_t)k*nx*ny;
8779 if (d[t]) continue;
8780 if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx] || d2[t + nxy] || d2[t - nxy]) d[t] = (float) l + 1;
8781 }
8782 }
8783 }
8784 }
8785 }
8786 else {
8787 for (int l = 1; l <= (int) val1+val2; ++l) {
8788 for (size_t i=0; i<size; i++) d2[i]=d[i];
8789 for (int j = 1; j < ny - 1; ++j) {
8790 for (int i = 1; i < nx - 1; ++i) {
8791 size_t t = i + j * nx;
8792 if (d[t]) continue;
8793 if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx]) d[t] = (float) l + 1;
8794 }
8795 }
8796 }
8797 }
8798
8799 vector<float> vec;
8800 for (int i=0; i<val1+2; i++) vec.push_back(1.0);
8801 for (int i=0; i<val2; i++) {
8802 vec.push_back(exp(-pow(2.0f*i/(val2),2.0f)));
8803// printf("%f\n",exp(-pow(2.0*i/(val1-val2),2.0)));
8804 }
8805 for (size_t i = 0; i < size; ++i) if (d[i]) d[i]=vec[(int)d[i]];
8806
8807 image->update();
8808 delete image2;
8809}
8810
8812 string dir = params.set_default("axis", "");
8813 if ( dir == "" || ( dir != "x" && dir != "y" && dir != "z" ) )
8814 throw InvalidParameterException("The direction parameter must be either x, y, or z");
8815
8816 int nx = image->get_xsize();
8817 int ny = image->get_ysize();
8818 int nz = image->get_zsize();
8819 EMData* ret = new EMData;
8820 if (image->has_attr("ptcl_repr")) ret->set_attr("ptcl_repr",image->get_attr("ptcl_repr"));
8821 if (image->has_attr("xform_align2d")) ret->set_attr("xform_align2d",image->get_attr("xform_align2d"));
8822 if (image->has_attr("xform_align3d")) ret->set_attr("xform_align3d",image->get_attr("xform_align3d"));
8823 ret->set_attr("apix_y",image->get_attr("apix_y")); // potentially meaningless, may get overwritten, but better to be self-consistent
8824 ret->set_attr("apix_z",image->get_attr("apix_z")); // meaningless, but better to be self-consistent
8825
8826
8827 if (nz==1) {
8828 if (dir=="x") {
8829 ret->set_size(ny,1,1);
8830 ret->set_attr("apix_x",image->get_attr("apix_y"));
8831 for (int y=0; y<ny; y++) {
8832 double sm=0;
8833 for (int x=0; x<nx; x++) sm+=image->get_value_at(x,y);
8834 ret->set_value_at(y,0,0,sm/nx);
8835 }
8836 return ret;
8837 }
8838 else if (dir=="y") {
8839 ret->set_size(nx,1,1);
8840 ret->set_attr("apix_x",image->get_attr("apix_x"));
8841 for (int x=0; x<nx; x++) {
8842 double sm=0;
8843 for (int y=0; y<ny; y++) sm+=image->get_value_at(x,y);
8844 ret->set_value_at(x,0,0,sm/ny);
8845 }
8846 return ret;
8847 }
8848 else throw InvalidParameterException("The direction parameter must be either x, y for 2-D images");
8849 }
8850
8851 int a0 = params.set_default("first", 0);
8852 int a1 = params.set_default("last", -1);
8853
8854 // compress one of the dimensions
8855 if ( dir == "x" ) {
8856 ret->set_size(nz,ny);
8857 ret->set_attr("apix_x",image->get_attr("apix_z"));
8858 ret->set_attr("apix_y",image->get_attr("apix_y"));
8859
8860 // bounds checks
8861 if (a0<0) a0+=nx;
8862 if (a1<0) a1+=nx;
8863 if (a0<0) a0=0;
8864 if (a1<0) a1=0;
8865 if (a0>=nx) a0=nx-1;
8866 if (a1>=nx) a1=nx-1;
8867
8868 for (int y=0; y<ny; y++) {
8869 for (int z=0; z<nz; z++) {
8870 double sum=0.0;
8871 for (int x=a0; x<=a1; x++) sum+=image->get_value_at(x,y,z);
8872 ret->set_value_at(z,y,(float)sum);
8873 }
8874 }
8875 }
8876 else if ( dir == "y" ) {
8877 ret->set_size(nx,nz);
8878 ret->set_attr("apix_x",image->get_attr("apix_x"));
8879 ret->set_attr("apix_y",image->get_attr("apix_z"));
8880
8881 // bounds checks
8882 if (a0<0) a0+=ny;
8883 if (a1<0) a1+=ny;
8884 if (a0<0) a0=0;
8885 if (a1<0) a1=0;
8886 if (a0>=ny) a0=ny-1;
8887 if (a1>=ny) a1=ny-1;
8888
8889 for (int x=0; x<nx; x++) {
8890 for (int z=0; z<nz; z++) {
8891 double sum=0.0;
8892 for (int y=a0; y<=a1; y++) sum+=image->get_value_at(x,y,z);
8893 ret->set_value_at(x,z,(float)sum);
8894 }
8895 }
8896 }
8897 else if ( dir == "z" ) {
8898 ret->set_size(nx,ny);
8899 ret->set_attr("apix_x",image->get_attr("apix_x"));
8900 ret->set_attr("apix_y",image->get_attr("apix_y"));
8901
8902 // bounds checks
8903 if (a0<0) a0+=nz;
8904 if (a1<0) a1+=nz;
8905 if (a0<0) a0=0;
8906 if (a1<0) a1=0;
8907 if (a0>=nz) a0=nz-1;
8908 if (a1>=nz) a1=nz-1;
8909
8910 for (int y=0; y<ny; y++) {
8911 for (int x=0; x<nx; x++) {
8912 double sum=0.0;
8913 for (int z=a0; z<=a1; z++) sum+=image->get_value_at(x,y,z);
8914 ret->set_value_at(x,y,(float)sum);
8915 }
8916 }
8917 }
8918
8919 ret->update();
8920 return ret;
8921}
8922
8924{
8925 if (!image) {
8926 LOGWARN("NULL Image");
8927 return;
8928 }
8929
8930 nx = image->get_xsize();
8931 ny = image->get_ysize();
8932 nz = image->get_zsize();
8933}
8934
8936{
8937 if (!image->is_complex()) {
8938 int nx = image->get_xsize();
8939 int offset = 2 - nx%2;
8940
8941 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
8942 image->set_complex(true);
8943 if (1 == offset) image->set_fftodd(true);
8944 else image->set_fftodd(false);
8945 image->set_fftpad(true);
8946 }
8947 image->set_ri(true);
8948 image->to_zero();
8949
8950 float center = params.set_default("center",ny/4);
8951 float width = params.set_default("width",sqrt(2.0f));
8952
8953 int nx = image->get_xsize();
8954 int ny = image->get_ysize();
8955 int nz = image->get_zsize();
8956 int w3 = floor(width*3);
8957 float l0 = pow(center-w3,2.0f);
8958 float l1 = pow(center+w3,2.0f);
8959
8960 if (nz==1) {
8961 // 1D
8962 if (ny==1) {
8963 for (int x=0; x<nx/2; x++) {
8964 if (abs(x-center)>w3) continue;
8965 image->set_complex_at(x,0,exp(-pow((x-center)/width,2.0f)));
8966 }
8967 }
8968 // 2D
8969 else {
8970 for (int y=-ny/2; y<ny/2; y++) {
8971 for (int x=0; x<nx/2; x++) {
8972 float r=Util::hypot_fast(x,y);
8973 if (r<center-w3 || r>center+w3) continue;
8974 image->set_complex_at(x,y,exp(-pow((r-center)/width,2.0f)));
8975 }
8976 }
8977 }
8978 }
8979 else {
8980 // 3D
8981 for (int z=-nz/2; z<nz/2; z++) {
8982 for (int y=-ny/2; y<ny/2; y++) {
8983 for (int x=0; x<nx/2; x++) {
8984 float r=Util::hypot3(x,y,z);
8985 if (r<center-w3 || r>center+w3) continue;
8986 image->set_complex_at(x,y,z,exp(-pow((r-center)/width,2.0f)));
8987 }
8988 }
8989 }
8990 }
8991}
8992
8993
8995{
8996 if (!image->is_complex()) {
8997 int nx = image->get_xsize();
8998 int offset = 2 - nx%2;
8999
9000 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
9001 image->set_complex(true);
9002 if (1 == offset) image->set_fftodd(true);
9003 else image->set_fftodd(false);
9004 image->set_fftpad(true);
9005 }
9006 image->ri2ap();
9007
9008 float sigma = params.set_default("sigma",.25f);
9009
9010 float * d = image->get_data();
9011 int nx = image->get_xsize();
9012 int ny = image->get_ysize();
9013 int nxy = image->get_ysize()*nx;
9014 int nzon2 = image->get_zsize()/2;
9015 int nyon2 = image->get_ysize()/2;
9016 float rx, ry, rz, length, amp, phase;
9017 int twox;
9018 for (int z = 0; z< image->get_zsize(); ++z) {
9019 for (int y = 0; y < image->get_ysize(); ++y) {
9020 for (int x = 0; x < image->get_xsize()/2; ++x) {
9021 rx = (float)x;
9022 ry = (float)nyon2 - (float)y;
9023 rz = (float)nzon2 - (float)z;
9024 length = sqrt(rx*rx + ry*ry + rz*rz);
9025 amp = exp(-sigma*length);
9026 phase = Util::get_frand(0,1)*2*M_PI;
9027
9028 twox = 2*x;
9029 size_t idx1 = twox + y*nx+(size_t)z*nxy;
9030 size_t idx2 = idx1 + 1;
9031 d[idx1] = amp;
9032 d[idx2] = phase;
9033
9034 }
9035 }
9036 }
9037
9038 image->ap2ri();
9039 if (image->get_ndim() == 2) {
9040 bool yodd = image->get_ysize() % 2 == 1;
9041
9042 int yit = image->get_ysize()/2-1;
9043 int offset = 1;
9044 if (yodd) {
9045 offset = 0;
9046 }
9047 for (int y = 0; y < yit; ++y) {
9048 int bot_idx = (y+offset)*nx;
9049 int top_idx = (ny-1-y)*nx;
9050 float r1 = d[bot_idx];
9051 float i1 = d[bot_idx+1];
9052 float r2 = d[top_idx];
9053 float i2 = d[top_idx+1];
9054 float r = (r1 + r2)/2.0f;
9055 float i = (i1 + i2)/2.0f;
9056 d[bot_idx] = r;
9057 d[top_idx] = r;
9058 d[bot_idx+1] = i;
9059 d[top_idx+1] = -i;
9060
9061 bot_idx = (y+offset)*nx+nx-2;
9062 top_idx = (ny-1-y)*nx+nx-2;
9063 r1 = d[bot_idx];
9064 i1 = d[bot_idx+1];
9065 r2 = d[top_idx];
9066 i2 = d[top_idx+1];
9067 r = (r1 + r2)/2.0f;
9068 i = (i1 + i2)/2.0f;
9069 d[bot_idx] = r;
9070 d[top_idx] = r;
9071 d[bot_idx+1] = i;
9072 d[top_idx+1] = -i;
9073 }
9074
9075 d[1] = 0; // 0 phase for this componenet
9076 d[nx-1] = 0; // 0 phase for this component
9077 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
9078 d[ny/2*nx+1] = 0;// 0 phase for this component
9079 }
9080
9081 if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
9082 image->do_ift_inplace();
9083 image->depad();
9084}
9085
9086#include <iostream>
9087using std::ostream_iterator;
9088
9090 if (params.has_key("noise")==false) throw InvalidParameterException("You must supply the noise argument");
9091 if (params.has_key("snr")==false) throw InvalidParameterException("You must supply the snr argument");
9092
9093 float boost = params.set_default("boost",1.0f);
9094
9095 if (!image->is_complex()) {
9096 image->do_fft_inplace();
9097 }
9098 EMData* cpy = image->copy();
9099 cpy->ri2inten();
9100 vector<float> sf = cpy->calc_radial_dist(cpy->get_ysize()/2,0.0,1.0,1);
9101 transform(sf.begin(),sf.end(),sf.begin(),sqrtf);
9102 delete cpy;
9103
9104 image->ri2ap();
9105
9106 vector<float> noise = params["noise"];
9107 vector<float> snr = params["snr"];
9108
9109// copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
9110// copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
9111
9112 for(vector<float>::iterator it = noise.begin(); it != noise.end(); ++it){
9113 if ((*it) == 0) *it = 1;
9114 }
9115 for(vector<float>::iterator it = snr.begin(); it != snr.end(); ++it){
9116 if ((*it) < 0) *it = 0;
9117 }
9118 // Subtract the mean from the data and store it in data_mm
9119 transform(snr.begin(),snr.end(),noise.begin(),snr.begin(),std::multiplies<float>());
9120 transform(snr.begin(),snr.end(),snr.begin(),sqrtf);
9121// copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
9122// copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
9123
9124 int i = static_cast<int>(snr.size());
9125
9126 float * d = image->get_data();
9127 int nx = image->get_xsize();
9128// int ny = image->get_ysize();
9129 int nxy = image->get_ysize()*nx;
9130 int nzon2 = image->get_zsize()/2;
9131 int nyon2 = image->get_ysize()/2;
9132 float rx, ry, rz, amp;
9133 int length;
9134 int twox;
9135 image->process_inplace("xform.fourierorigin.tocenter");
9136 for (int z = 0; z< image->get_zsize(); ++z) {
9137 for (int y = 0; y < image->get_ysize(); ++y) {
9138 for (int x = 0; x < image->get_xsize()/2; ++x) {
9139 rx = (float)x;
9140 ry = (float)nyon2 - (float)y;
9141 rz = (float)nzon2 - (float)z;
9142 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
9143
9144 twox = 2*x;
9145 size_t idx1 = twox + y*nx+(size_t)z*nxy;
9146 if (length >= i || length >= (int)sf.size()) {
9147 d[idx1] = 0;
9148 continue;
9149 } else {
9150 amp = boost*snr[length];
9151// if (amp > 0) amp =sqrtf(amp);
9152// else amp = 0;
9153 }
9154
9155 if (sf[length] == 0) {
9156 d[idx1] = 0;
9157 continue;
9158 }
9159
9160// size_t idx2 = idx1 + 1;
9161// cout << d[idx1] << " " << sf[length] << endl;
9162 d[idx1] /= sf[length];
9163 if (d[idx1] < 0) {
9164 d[idx1] *= amp;
9165 }else {
9166 d[idx1] *= -amp;
9167 }
9168// d[idx2] = phase;
9169
9170 }
9171 }
9172 }
9173
9174 image->ap2ri();
9175 if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
9176 image->do_ift_inplace();
9177 image->depad();
9178}
9179
9181
9182 if (params.has_key("profile")==false) throw InvalidParameterException("You must supply the profile argument");
9183
9184 if (!image->is_complex()) {
9185 int nx = image->get_xsize();
9186 int offset = 2 - nx%2;
9187
9188 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
9189 image->set_complex(true);
9190 if (1 == offset) image->set_fftodd(true);
9191 else image->set_fftodd(false);
9192 image->set_fftpad(true);
9193 }
9194 image->to_zero();
9195 image->ri2ap();
9196
9197 vector<float> profile = params["profile"];
9198 transform(profile.begin(),profile.end(),profile.begin(),sqrtf);
9199
9200 int i = static_cast<int>(profile.size());
9201
9202 float * d = image->get_data();
9203 int nx = image->get_xsize();
9204 int ny = image->get_ysize();
9205 int nxy = image->get_ysize()*nx;
9206 int nzon2 = image->get_zsize()/2;
9207 int nyon2 = image->get_ysize()/2;
9208 float rx, ry, rz, amp, phase;
9209 int length;
9210 int twox;
9211 for (int z = 0; z< image->get_zsize(); ++z) {
9212 for (int y = 0; y < image->get_ysize(); ++y) {
9213 for (int x = 0; x < image->get_xsize()/2; ++x) {
9214 rx = (float)x;
9215 ry = (float)nyon2 - (float)y;
9216 rz = (float)nzon2 - (float)z;
9217 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
9218
9219 twox = 2*x;
9220 size_t idx1 = twox + y*nx+(size_t)z*nxy;
9221 size_t idx2 = idx1 + 1;
9222
9223
9224 if (length >= i) {
9225 d[idx1] = 0;
9226 d[idx2] = 0;
9227 continue;
9228 }
9229 amp = profile[length];
9230 phase = Util::get_frand(0,1)*2*M_PI;
9231
9232
9233 d[idx1] = amp;
9234 d[idx2] = phase;
9235
9236 }
9237 }
9238 }
9239
9240 image->ap2ri();
9241 if (image->get_ndim() == 2) {
9242 bool yodd = image->get_ysize() % 2 == 1;
9243
9244 int yit = image->get_ysize()/2-1;
9245 int offset = 1;
9246 if (yodd) {
9247 offset = 0;
9248 }
9249 for (int y = 0; y < yit; ++y) {
9250 int bot_idx = (y+offset)*nx;
9251 int top_idx = (ny-1-y)*nx;
9252 float r1 = d[bot_idx];
9253 float i1 = d[bot_idx+1];
9254 float r2 = d[top_idx];
9255 float i2 = d[top_idx+1];
9256 float r = (r1 + r2)/2.0f;
9257 float i = (i1 + i2)/2.0f;
9258 d[bot_idx] = r;
9259 d[top_idx] = r;
9260 d[bot_idx+1] = i;
9261 d[top_idx+1] = -i;
9262
9263 bot_idx = (y+offset)*nx+nx-2;
9264 top_idx = (ny-1-y)*nx+nx-2;
9265 r1 = d[bot_idx];
9266 i1 = d[bot_idx+1];
9267 r2 = d[top_idx];
9268 i2 = d[top_idx+1];
9269 r = (r1 + r2)/2.0f;
9270 i = (i1 + i2)/2.0f;
9271 d[bot_idx] = r;
9272 d[top_idx] = r;
9273 d[bot_idx+1] = i;
9274 d[top_idx+1] = -i;
9275 }
9276
9277 d[1] = 0; // 0 phase for this componenet
9278 d[nx-1] = 0; // 0 phase for this component
9279 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
9280 d[ny/2*nx+1] = 0;// 0 phase for this component
9281 }
9282
9283 if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
9284 image->do_ift_inplace();
9285 image->depad();
9286}
9287
9289{
9290 preprocess(image);
9291
9292 float period = params.set_default("period",10.0f);
9293 size_t n = (size_t)image->get_xsize()*image->get_ysize()*image->get_zsize();
9294
9295 for(size_t i = 0; i < n; ++i) {
9296 float x = fmod((float)i,period);
9297 x /= period;
9298 x = (float)sin(x*EMConsts::pi*2.0);
9299 image->set_value_at_fast(i,x);
9300 }
9301}
9302
9304{
9305 preprocess(image);
9306
9307 float sigma = params["sigma"];
9308 string axis = (const char*)params["axis"];
9309 float c = params["c"];
9310
9311 float *dat = image->get_data();
9312 float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
9313 float x2, y2, z2; //this is the coordinates of this pixel from image center
9314 for (int k = 0; k < nz; ++k) {
9315 for (int j = 0; j < ny; ++j) {
9316 for (int i = 0; i < nx; ++i, ++dat) {
9317 x2 = (float)( i - nx/2 );
9318 y2 = (float)( j - ny/2 );
9319 z2 = (float)( k - nz/2 );
9320
9321 if(axis==""){
9322 r = (float)sqrt(x2*x2+y2*y2+z2*z2);
9323 }
9324 else if(axis == "x"){
9325 float lc = -c;
9326 float rc = c;
9327 r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
9328 (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
9329 }
9330 else if(axis == "y"){
9331 float lc = -c;
9332 float rc = c;
9333 r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
9334 (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
9335 }
9336 else if(axis == "z"){
9337 if( nz == 1 ){
9338 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
9339 }
9340 float lc = -c;
9341 float rc = c;
9342 r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
9343 (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
9344 }
9345 else{
9346 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
9347 }
9348 //the amplitude of the pixel is proportional to the distance of this pixel from the center
9349 *dat = (float)gsl_ran_gaussian_pdf((double)r,(double)sigma);
9350 }
9351 }
9352 }
9353
9354 image->update();
9355}
9356
9358{
9359 string axis = params.set_default("axis", "x");
9360
9361 float m = params.set_default("m", 1.0f);
9362 float b = params.set_default("b", 0.0f);
9363
9364 if ( axis != "z" && axis != "y" && axis != "x") throw InvalidParameterException("Axis must be x,y or z");
9365
9366 preprocess(image);
9367
9368 if ( axis == "x")
9369 {
9370 for(int k=0; k<nz;++k) {
9371 for(int j=0; j<ny; ++j) {
9372 for(int i=0; i <nx; ++i) {
9373 image->set_value_at(i,j,k,m*i+b);
9374 }
9375 }
9376 }
9377 }
9378 else if ( axis == "y")
9379 {
9380 for(int k=0; k<nz;++k) {
9381 for(int j=0; j<ny; ++j) {
9382 for(int i=0; i <nx; ++i) {
9383 image->set_value_at(i,j,k,m*j+b);
9384 }
9385 }
9386 }
9387 }
9388 else if ( axis == "z")
9389 {
9390 for(int k=0; k<nz;++k) {
9391 for(int j=0; j<ny; ++j) {
9392 for(int i=0; i <nx; ++i) {
9393 image->set_value_at(i,j,k,m*k+b);
9394 }
9395 }
9396 }
9397 }
9398 image->update();
9399}
9400
9402{
9403 preprocess(image);
9404
9405 float fill = params.set_default("fill", 1.0f);
9406 // get the central coordinates
9407 int cx = nx/2;
9408 int cy = ny/2;
9409 int cz = nz/2;
9410
9411 // Offsets are used to detect when "the extra pixel" needs to be filled in
9412 // They are implemented on the assumption that for odd dimensions
9413 // the "center pixel" is the center pixel, but for even dimensions the "center
9414 // pixel" is displaced in the positive direction by 1
9415 int xoffset = (nx % 2 == 0? 1:0);
9416 int yoffset = (ny % 2 == 0? 1:0);
9417 int zoffset = (nz % 2 == 0? 1:0);
9418
9419 // This should never occur - but if indeed it did occur, the code in this function
9420 // would break - the function would proceed into the final "else" and seg fault
9421 // It is commented out but left for clarity
9422// if ( nx < 1 || ny < 1 || nz < 1 ) throw ImageDimensionException("Error: one of the image dimensions was less than zero");
9423
9424 if ( nx == 1 && ny == 1 && nz == 1 )
9425 {
9426 (*image)(0) = fill;
9427 }
9428 else if ( ny == 1 && nz == 1 )
9429 {
9430 int radius = params.set_default("radius", cx );
9431 if ( radius > cx ) radius = cx;
9432
9433 (*image)(cx) = fill;
9434 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i) = fill;
9435 for ( int i = 1; i <= radius; ++i ) (*image)(cx-i) = fill;
9436 }
9437 else if ( nz == 1 )
9438 {
9439 int min = ( nx < ny ? nx : ny );
9440 min /= 2;
9441
9442 int radius = params.set_default("radius", min );
9443 if ( radius > min ) radius = min;
9444
9445 (*image)(cx,cy) = fill;
9446
9447 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i,cy) = fill;
9448 for ( int i = 1; i <= radius-yoffset; ++i )(*image)(cx,cy+i) = fill;
9449
9450 for ( int i = 1; i <= radius; ++i )
9451 {
9452 (*image)(cx-i,cy) = fill;
9453 (*image)(cx,cy-i) = fill;
9454 }
9455
9456 }
9457 else
9458 {
9459 // nx > 1 && ny > 1 && nz > 1
9460 int min = ( nx < ny ? nx : ny );
9461 if (nz < min ) min = nz;
9462 min /= 2;
9463
9464 int radius = params.set_default("radius", min);
9465 if ( radius > min ) radius = min;
9466
9467
9468 (*image)(cx,cy,cz) = fill;
9469 for ( int i = 1; i <=radius-xoffset; ++i ) (*image)(cx+i,cy,cz) = fill;
9470 for ( int i = 1; i <=radius-yoffset; ++i ) (*image)(cx,cy+i,cz) = fill;
9471 for ( int i = 1; i <=radius-zoffset; ++i ) (*image)(cx,cy,cz+i) = fill;
9472 for ( int i = 1; i <= radius; ++i )
9473 {
9474 (*image)(cx-i,cy,cz) = fill;
9475 (*image)(cx,cy-i,cz) = fill;
9476 (*image)(cx,cy,cz-i) = fill;
9477 }
9478 }
9479
9480 image->update();
9481}
9482
9484{
9485 preprocess(image);
9486
9487 int dim_size = image->get_ndim();
9488 if( 2 != dim_size ) {
9489 throw ImageDimensionException("works for 2D images only");
9490 }
9491
9492 int nx = image->get_xsize();
9493 int ny = image->get_ysize();
9494 image->to_zero();
9495
9496 for (int i=0; i<100; i++) {
9497 int x=static_cast<int>( nx/2+nx/6.0*sin(i*2.0*3.14159/100.0) );
9498 int y=ny/4+i*ny/200;
9499 for (int xx=x-nx/10; xx<x+nx/10; xx++) {
9500 for (int yy=y-ny/10; yy<y+ny/10; yy++) {
9501 (*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);
9502 }
9503 }
9504 }
9505
9506 image->update();
9507}
9508
9510{
9511 preprocess(image);
9512
9513 float x_sigma = params["x_sigma"];
9514 float y_sigma = params["y_sigma"];
9515 float z_sigma = params["z_sigma"];
9516
9517 float x_center = params["x_center"];
9518 float y_center = params["y_center"];
9519 float z_center = params["z_center"];
9520
9521 int nx = image->get_xsize();
9522 int ny = image->get_ysize();
9523 int nz = image->get_zsize();
9524
9525 float x_twosig2 = 2*x_sigma*x_sigma;
9526 float y_twosig2 = 2*y_sigma*y_sigma;
9527 float z_twosig2 = 2*z_sigma*z_sigma;
9528
9529 float sr2pi = sqrt( 2.0f*(float)pi );
9530 float norm = 1.0f/ ( x_sigma*sr2pi );
9531 if (ny > 1) {
9532 norm *= 1.0f/ ( y_sigma*sr2pi );
9533 if (nz > 1) norm *= 1.0f/ ( z_sigma*sr2pi );
9534 }
9535
9536 float z, y, x, sum, val;
9537 for (int iz=0; iz < nz; ++iz) {
9538 z = static_cast<float>(iz) - z_center;
9539 for (int iy=0; iy < ny; ++iy) {
9540 y = static_cast<float>(iy) - y_center;
9541 for (int ix=0; ix < nx; ++ix) {
9542 x = static_cast<float>(ix) - x_center;
9543 sum = x*x/x_twosig2 + y*y/y_twosig2 + z*z/z_twosig2;
9544 val = norm*exp(-sum);
9545 (*image)(ix,iy,iz) = val;
9546 }
9547 }
9548 }
9549 image->update();
9550}
9551
9553{
9554 preprocess(image);
9555
9556 if(!params.has_key("wavelength")) {
9557 LOGERR("%s wavelength is required parameter", get_name().c_str());
9558 throw InvalidParameterException("wavelength parameter is required.");
9559 }
9560 float wavelength = params["wavelength"];
9561
9562 float phase = 0;
9563 if(params.has_key("phase")) {
9564 phase = params["phase"];
9565 }
9566
9567 float x = (float)(nx/2);
9568 if (params.has_key("x")) x=params["x"];
9569 float y = (float)(ny/2);
9570 if (params.has_key("y")) y=params["y"];
9571 float z = (float)(nz/2);
9572 if (params.has_key("z")) z=params["z"];
9573
9574 int ndim = image->get_ndim();
9575
9576 if(ndim==2) { //2D
9577 for(int j=0; j<ny; ++j) {
9578 for(int i=0; i<nx; ++i) {
9579 float r=hypot(x-(float)i,y-(float)j);
9580 if (r<.5) continue;
9581 image->set_value_at(i,j,cos(2*(float)pi*r/wavelength+phase)/r);
9582 }
9583 }
9584 }
9585 else { //3D
9586 for(int k=0; k<nz; ++k) {
9587 for(int j=0; j<ny; ++j) {
9588 for(int i=0; i<nx; ++i) {
9589 float r=Util::hypot3(x-(float)i,y-(float)j,z-(float)k);
9590 if (r<.5) continue;
9591 image->set_value_at(i,j,k,cos(2*(float)pi*r/wavelength+phase)/(r*r));
9592 }
9593 }
9594 }
9595 }
9596
9597 image->update();
9598}
9599
9600
9602{
9603 preprocess(image);
9604
9605 if(!params.has_key("wavelength")) {
9606 LOGERR("%s wavelength is required parameter", get_name().c_str());
9607 throw InvalidParameterException("wavelength parameter is required.");
9608 }
9609 float wavelength = params["wavelength"];
9610
9611 string axis = "";
9612 if(params.has_key("axis")) {
9613 axis = (const char*)params["axis"];
9614 }
9615
9616 float phase = 0;
9617 if(params.has_key("phase")) {
9618 phase = params["phase"];
9619 }
9620
9621 int ndim = image->get_ndim();
9622 float * dat = image->get_data();
9623
9624 if(ndim==1) { //1D
9625 for(int i=0; i<nx; ++i, ++dat) {
9626 *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
9627 }
9628 }
9629 else if(ndim==2) { //2D
9630 float alpha = 0;
9631 if(params.has_key("az")) {
9632 alpha = params["az"];
9633 }
9634 for(int j=0; j<ny; ++j) {
9635 for(int i=0; i<nx; ++i, ++dat) {
9636 if(alpha != 0) {
9637 *dat = sin((i*sin((180-alpha)*M_PI/180)+j*cos((180-alpha)*M_PI/180))*(2.0f*M_PI/wavelength) + phase);
9638 }
9639 else if(axis.compare("y")==0 || axis.compare("Y")==0) {
9640 *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
9641 }
9642 else {
9643 *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
9644 }
9645 }
9646 }
9647 }
9648 else { //3D
9649 float az = 0;
9650 if(params.has_key("az")) {
9651 az = params["az"];
9652 }
9653 float alt = 0;
9654 if(params.has_key("alt")) {
9655 alt = params["alt"];
9656 }
9657 float phi = 0;
9658 if(params.has_key("phi")) {
9659 phi = params["phi"];
9660 }
9661
9662 for(int k=0; k<nz; ++k) {
9663 for(int j=0; j<ny; ++j) {
9664 for(int i=0; i<nx; ++i, ++dat) {
9665 if(axis.compare("z")==0 || axis.compare("Z")==0) {
9666 *dat = sin(k*(2.0f*M_PI/wavelength) + phase);
9667 }
9668 else if(axis.compare("y")==0 || axis.compare("Y")==0) {
9669 *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
9670 }
9671 else {
9672 *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
9673 }
9674 }
9675 }
9676 }
9677
9678 if(az != 0 || alt != 0 || phi != 0) {
9679 Dict d("type","eman");
9680 d["az"] = az; d["phi"] = phi; d["alt"] = alt;
9681 image->transform(Transform(d));
9682 }
9683 }
9684
9685 image->update();
9686}
9687
9689{
9690 preprocess(image);
9691
9692 float wavelength = params["wavelength"];
9693 string axis = (const char*)params["axis"];
9694 float c = params["c"];
9695 float phase = params["phase"];
9696
9697 float *dat = image->get_data();
9698 float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
9699 float x2, y2, z2; //this is the coordinates of this pixel from image center
9700 for (int k = 0; k < nz; ++k) {
9701 for (int j = 0; j < ny; ++j) {
9702 for (int i = 0; i < nx; ++i, ++dat) {
9703 x2 = (float)( i - nx/2 );
9704 y2 = (float)( j - ny/2 );
9705 z2 = (float)( k - nz/2 );
9706 if(axis == ""){
9707 r = (float)sqrt(x2*x2+y2*y2+z2*z2);
9708 }
9709 else if(axis == "x"){
9710 float lc = -c;
9711 float rc = c;
9712 r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
9713 (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
9714 }
9715 else if(axis == "y"){
9716 float lc = -c;
9717 float rc = c;
9718 r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
9719 (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
9720 }
9721 else if(axis == "z"){
9722 if( nz == 1 ){
9723 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
9724 }
9725 float lc = -c;
9726 float rc = c;
9727 r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
9728 (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
9729 }
9730 else{
9731 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
9732 }
9733 *dat = sin( r * (2.0f*M_PI/wavelength) - phase*180/M_PI);
9734 }
9735 }
9736 }
9737
9738 image->update();
9739}
9740
9742{
9743 preprocess(image);
9744
9745 float edge_length = params["edge_length"];
9746 string axis = (const char*)params["axis"];
9747 float odd_edge = params["odd_edge"];
9748 int fill = 1;
9749 if(params.has_key("fill")) {
9750 fill = (int)params["fill"];
9751 }
9752
9753 float *dat = image->get_data();
9754 float x2, y2, z2; //this coordinates of this pixel from center
9755 float xEdge, yEdge, zEdge; //half of edge length for this cube
9756 if(axis == ""){
9757 xEdge = edge_length/2.0f;
9758 yEdge = edge_length/2.0f;
9759 zEdge = edge_length/2.0f;
9760 }
9761 else if(axis == "x"){
9762 xEdge = odd_edge/2.0f;
9763 yEdge = edge_length/2.0f;
9764 zEdge = edge_length/2.0f;
9765 }
9766 else if(axis == "y"){
9767 xEdge = edge_length/2.0f;
9768 yEdge = odd_edge/2.0f;
9769 zEdge = edge_length/2.0f;
9770 }
9771 else if(axis == "z"){
9772 if( nz == 1 ){
9773 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
9774 }
9775 xEdge = edge_length/2.0f;
9776 yEdge = edge_length/2.0f;
9777 zEdge = odd_edge/2.0f;
9778 }
9779 else{
9780 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
9781 }
9782 for (int k = 0; k < nz; ++k) {
9783 for (int j = 0; j < ny; ++j) {
9784 for (int i = 0; i < nx; ++i, ++dat) {
9785 x2 = (float)fabs((float)i - nx/2);
9786 y2 = (float)fabs((float)j - ny/2);
9787 z2 = (float)fabs((float)k - nz/2);
9788 if( x2<=xEdge && y2<=yEdge && z2<=zEdge ) {
9789 if( !fill) {
9790 *dat = 0;
9791 }
9792 else {
9793 *dat = 1;
9794 }
9795 }
9796 else {
9797 if( !fill ) {
9798 *dat = 1;
9799 }
9800 else {
9801 *dat = 0;
9802 }
9803 }
9804 }
9805 }
9806 }
9807
9808 image->update();
9809}
9810
9812{
9813 preprocess(image);
9814
9815 float radius = params.set_default("radius",nx/2.0f);
9816 string axis = (const char*)params["axis"];
9817 float c = params.set_default("c",nx/2.0f);
9818 int fill = params.set_default("fill",1);
9819
9820 float *dat = image->get_data();
9821 float x2, y2, z2; //this is coordinates of this pixel from center
9822 float r = 0.0f;
9823 float asy = 0.0f;
9824 if(axis == ""){
9825 asy = radius;
9826 }
9827 else if(axis == "x" || axis == "y"){
9828 asy = c;
9829 }
9830 else if(axis=="z"){
9831 if( nz == 1 ){
9832 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
9833 }
9834 asy = c;
9835 }
9836 else{
9837 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
9838 }
9839
9840 for (int k = 0; k < nz; ++k) {
9841 for (int j = 0; j < ny; ++j) {
9842 for (int i = 0; i < nx; ++i, ++dat) {
9843 x2 = fabs((float)i - nx/2);
9844 y2 = fabs((float)j - ny/2);
9845 z2 = fabs((float)k - nz/2);
9846 if( axis == "" ){
9847 r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
9848 }
9849 else if (axis == "x"){
9850 r = (x2*x2)/(asy*asy) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
9851 }
9852 else if(axis == "y"){
9853 r = (x2*x2)/(radius*radius) + (y2*y2)/(asy*asy) + (z2*z2)/(radius*radius);
9854 }
9855 else if(axis=="z"){
9856 r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(asy*asy);
9857 }
9858 if( r<=1 ) {
9859 if( !fill) {
9860 *dat = 0;
9861 }
9862 else {
9863 *dat = 1;
9864 }
9865 }
9866 else {
9867 if( !fill ) {
9868 *dat = 1;
9869 }
9870 else {
9871 *dat = 0;
9872 }
9873 }
9874 }
9875 }
9876 }
9877
9878 image->update();
9879}
9880
9882{
9883 preprocess(image);
9884 image->to_zero(); // The testimage processors are supposed to replace the image contents
9885
9886 float width = params.set_default("width",2.0f);
9887
9888 float a2 = params.set_default("a",nx/2.0f-1.0f);
9889 float b2 = params.set_default("b",ny/2.0f-1.0f);
9890 float c2 = params.set_default("c",nz/2.0f-1.0f);
9891
9892 float a1 = params.set_default("xwidth",a2-width);
9893 float b1 = params.set_default("ywidth",b2-width);
9894 float c1 = params.set_default("zwidth",c2-width);
9895
9896 float fill = params.set_default("fill",1.0f);
9897 Transform* t;
9898 if (params.has_key("transform")) {
9899 t = params["transform"];
9900 } else {
9901 t = new Transform;
9902 }
9903
9904
9905 int mz = 2*(int)c2+1;
9906 if ( nz < mz ) mz = nz;
9907 int my = 2*(int)b2+1;
9908 if ( ny < my ) my = ny;
9909 int mx = 2*(int)a2+1;
9910 if ( nx < mx ) mx = nx;
9911
9912 float ai1 = 1/(a1*a1);
9913 float bi1 = 1/(b1*b1);
9914 float ci1 = 1/(c1*c1);
9915
9916 float ai2 = 1/(a2*a2);
9917 float bi2 = 1/(b2*b2);
9918 float ci2 = 1/(c2*c2);
9919
9920 Vec3f origin(nx/2,ny/2,nz/2);
9921
9922 float x2, y2, z2, r1,r2;
9923 int xl, yl, zl;
9924 for (int k = 0; k < mz; ++k) {
9925 for (int j = 0; j < my; ++j) {
9926 for (int i = 0; i < mx; ++i) {
9927 x2 = (float)(i - mx/2);
9928 y2 = (float)(j - my/2);
9929 z2 = (float)(k - mz/2);
9930 r1 = (x2*x2)*ai1 + (y2*y2)*bi1 + (z2*z2)*ci1;
9931 r2 = (x2*x2)*ai2 + (y2*y2)*bi2 + (z2*z2)*ci2;
9932 if (r2 <= 1 && r1 >= 1) {
9933
9934 if (t != 0) {
9935 Vec3f v(x2,y2,z2);
9936 v = (*t)*v;
9937 v += origin;
9938
9939 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
9940 // I fill in 3x3 cubes to make sure there are no gaps...
9941
9942 for( int kk = -1; kk <= 1; ++kk)
9943 for( int jj = -1; jj <= 1; ++jj)
9944 for( int ii = -1; ii <= 1; ++ii) {
9945 xl = (int)v[0]+ii;
9946 yl = (int)v[1]+jj;
9947 zl = (int)v[2]+kk;
9948 if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
9949 image->set_value_at(xl,yl,zl,1.0);
9950 }
9951 } else {
9952 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
9953 }
9954 }
9955 }
9956 }
9957 }
9958
9959 delete t;
9960
9961 image->update();
9962}
9963
9965{
9966 preprocess(image);
9967 image->to_zero(); // The testimage processors are supposed to replace the image contents
9968
9969
9970 float a = params.set_default("a",nx/2.0f-1.0f);
9971 float b = params.set_default("b",ny/2.0f-1.0f);
9972 float c = params.set_default("c",nz/2.0f-1.0f);
9973 float fill = params.set_default("fill",1.0f);
9974 //bool hollow = params.set_default("hollow",false);
9975 Transform* t;
9976 if (params.has_key("transform")) {
9977 t = params["transform"];
9978 } else {
9979 t = new Transform;
9980 }
9981
9982
9983 int mz = 2*(int)c+1;
9984 if ( nz < mz ) mz = nz;
9985 int my = 2*(int)b+1;
9986 if ( ny < my ) my = ny;
9987 int mx = 2*(int)a+1;
9988 if ( nx < mx ) mx = nx;
9989
9990
9991 float ai = 1/(a*a);
9992 float bi = 1/(b*b);
9993 float ci = 1/(c*c);
9994
9995 Vec3f origin(nx/2,ny/2,nz/2);
9996
9997 float x2, y2, z2, r;
9998 int xl, yl, zl;
9999 for (int k = 0; k < mz; ++k) {
10000 for (int j = 0; j < my; ++j) {
10001 for (int i = 0; i < mx; ++i) {
10002 x2 = (float)(i - mx/2);
10003 y2 = (float)(j - my/2);
10004 z2 = (float)(k - mz/2);
10005 r = (x2*x2)*ai + (y2*y2)*bi + (z2*z2)*ci;
10006 if (r <= 1) {
10007
10008 if (t != 0) {
10009 Vec3f v(x2,y2,z2);
10010 v = (*t)*v;
10011 v += origin;
10012
10013 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
10014 // I fill in 3x3 cubes to make sure there are no gaps...
10015
10016 for( int kk = -1; kk <= 1; ++kk)
10017 for( int jj = -1; jj <= 1; ++jj)
10018 for( int ii = -1; ii <= 1; ++ii) {
10019 xl = (int)v[0]+ii;
10020 yl = (int)v[1]+jj;
10021 zl = (int)v[2]+kk;
10022 if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
10023 image->set_value_at(xl,yl,zl,fill);
10024 }
10025 } else {
10026 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
10027 }
10028 }
10029 }
10030 }
10031 }
10032
10033 delete t;
10034
10035 image->update();
10036}
10037
10039{
10040 preprocess(image);
10041
10042 Randnum * r = Randnum::Instance();
10043 if(params.has_key("seed")) {
10044 r->set_seed((int)params["seed"]);
10045 }
10046
10047 float *dat = image->get_data();
10048 size_t size = (size_t)nx*ny*nz;
10049 for (size_t i=0; i<size; ++i) {
10050 dat[i] = r->get_frand();
10051 }
10052
10053 image->update();
10054}
10055
10057{
10058 preprocess(image);
10059
10060 float sigma = params["sigma"];
10061 if (sigma<=0) { sigma = 1.0; }
10062 float mean = params["mean"];
10063
10064 Randnum * r = Randnum::Instance();
10065 if (params.has_key("seed")) {
10066 r->set_seed((int)params["seed"]);
10067 }
10068
10069 float *dat = image->get_data();
10070 size_t size = (size_t)nx*ny*nz;
10071 for (size_t i=0; i<size; ++i) {
10072 dat[i] = r->get_gauss_rand(mean, sigma);
10073 }
10074
10075 image->update();
10076}
10077
10079{
10080 preprocess(image);
10081
10082 int nx = image->get_xsize();
10083 int ny = image->get_ysize();
10084 int nz = image->get_zsize();
10085
10086 if(nz == 1) {
10087 throw ImageDimensionException("This processor only apply to 3D image");
10088 }
10089
10090 float radius = params["radius"];
10091
10092 if(radius > Util::get_min(nx, ny)/2.0) {
10093 throw InvalidValueException(radius, "radius must be <= min(nx, ny)/2");
10094 }
10095
10096 float height;
10097 if(params.has_key("height")) {
10098 height = params["height"];
10099 if(height > nz) {
10100 throw InvalidValueException(radius, "height must be <= nz");
10101 }
10102 }
10103 else {
10104 height = static_cast<float>(nz);
10105 }
10106
10107 float *dat = image->get_data();
10108 float x2, y2; //this is coordinates of this pixel from center axle
10109 float r = 0.0f;
10110 for (int k = 0; k < nz; ++k) {
10111 for (int j = 0; j < ny; ++j) {
10112 for (int i = 0; i < nx; ++i, ++dat) {
10113 x2 = fabs((float)i - nx/2);
10114 y2 = fabs((float)j - ny/2);
10115 r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius);
10116
10117 if(r<=1 && k>=(nz-height)/2 && k<=(nz+height)/2) {
10118 *dat = 1;
10119 }
10120 else {
10121 *dat = 0;
10122 }
10123 }
10124 }
10125 }
10126
10127 image->update();
10128}
10129
10131{
10132 preprocess(image);
10133
10134 int nx = image->get_xsize();
10135 int ny = image->get_ysize();
10136 int nz = image->get_zsize();
10137
10138 if(nz == 1) {
10139 throw ImageDimensionException("This processor only works on 3D images");
10140 }
10141
10142 float a = params["major"];
10143
10144 if(a > Util::get_min(nx, ny)/2.0) {
10145 throw InvalidValueException(a, "major must be <= min(nx, ny)/2");
10146 }
10147
10148 float b = params["minor"];
10149
10150 if(b > Util::get_min(nx, ny)/2.0) {
10151 throw InvalidValueException(b, "minor must be <= min(nx, ny)/2");
10152 }
10153
10154 float h;
10155 if(params.has_key("height")) {
10156 h = params["height"];
10157 if(h > nz) {
10158 throw InvalidValueException(h, "height must be <= nz");
10159 }
10160 }
10161 else {
10162 h = static_cast<float>(nz);
10163 }
10164
10165 float *dat = image->get_data();
10166 float x2, y2; //this is coordinates of this pixel from center axle
10167 float r = 0.0f;
10168 for (int k = 0; k < nz; ++k) {
10169 for (int j = 0; j < ny; ++j) {
10170 for (int i = 0; i < nx; ++i, ++dat) {
10171 x2 = fabs((float)i - nx/2);
10172 y2 = fabs((float)j - ny/2);
10173 r = (x2*x2)/(a*a) + (y2*y2)/(b*b);
10174 if(r<=1 && k>=(nz-h)/2 && k<=(nz+h)/2) {
10175 *dat = 1;
10176 }
10177 else {
10178 *dat = 0;
10179 }
10180 }
10181 }
10182 }
10183
10184 image->update();
10185}
10186
10188{
10189 if (!image) {
10190 return;
10191 }
10192
10193 int nz = image->get_zsize();
10194 if (nz > 1) {
10195 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
10196 throw ImageDimensionException("3D model not supported");
10197 }
10198
10199 int nsam = image->get_xsize();
10200 int nrow = image->get_ysize();
10201 int n1 = nsam / 2;
10202 double sx1 = double(n1)*double(nsam+1);
10203 if ( nsam % 2 == 1 )
10204 sx1 += 1 + n1;
10205 sx1 *= nrow;
10206 int n2 = nrow / 2;
10207 double sx2 = double(n2)*double(nrow+1);
10208 if ( nrow % 2 == 1 )
10209 sx2 += 1 + n2;
10210 sx2 *= nsam;
10211 float *data = image->get_data();
10212 float *row = NULL; // handy pointer for values in a specific row of the data
10213 // statistical sums
10214 double syx1 = 0, syx2 = 0, sy = 0, sx1q = 0, sx2q = 0, syq = 0;
10215 for (int j=1; j <= nrow; j++) {
10216 row = data + (j-1)*nsam - 1; // "-1" so that we can start counting at 1
10217 for (int i=1; i<=nsam; i++) {
10218 syx1 += row[i]*i;
10219 syx2 += row[i]*j;
10220 sy += row[i];
10221 sx1q += i*i;
10222 sx2q += j*j;
10223 syq += row[i]*double(row[i]);
10224 }
10225 }
10226 // least-squares
10227 float dn = float(nsam)*float(nrow);
10228 double qyx1 = syx1 - sx1*sy / dn;
10229 double qyx2 = syx2 - sx2*sy / dn;
10230 double qx1x2 = 0.0;
10231 double qx1 = sx1q - sx1*sx1 / dn;
10232 double qx2 = sx2q - sx2*sx2 / dn;
10233 double qy = syq - sy*sy / dn;
10234 double c = qx1*qx2 - qx1x2*qx1x2;
10235 if ( c > FLT_EPSILON ) {
10236 double b1 = (qyx1*qx2 - qyx2*qx1x2) / c;
10237 double b2 = (qyx2*qx1 - qyx1*qx1x2) / c;
10238 double a = (sy - b1*sx1 - b2*sx2) / dn;
10239 double d = a + b1 + b2;
10240 for (int i=1; i<=nrow; i++) {
10241 qy = d;
10242 row = data + (i-1)*nsam - 1;
10243 for (int k=1; k<=nsam; k++) {
10244 row[k] -= static_cast<float>(qy);
10245 qy += b1;
10246 }
10247 d += b2;
10248 }
10249 } // image not altered if c is zero
10250
10251 image->update();
10252}
10253
10254
10256{
10257 if (!image) {
10259 Log::logger()->error("Null image during call to CCDNorm\n");
10260 return;
10261 }
10262 if (image->get_zsize() > 1) {
10264 Log::logger()->error("CCDNorm does not support 3d images\n");
10265 return;
10266 }
10267
10268 int xs = image->get_xsize();
10269 int ys = image->get_ysize();
10270
10271 // width of sample area on either side of the seams
10272 int width = params["width"];
10273
10274 width%=(xs > ys ? xs/2 : ys/2); // make sure width is a valid value
10275 if (width==0) {
10276 width=1;
10277 }
10278
10279 // get the 4 "seams" of the image
10280 float *left, *right, *top, *bottom;
10281
10282 double *temp;
10283 temp= (double*)malloc((xs > ys ? xs*width : ys*width)*sizeof(double));
10284 if (temp==NULL) {
10286 Log::logger()->error("Could not allocate enough memory during call to CCDNorm\n");
10287 return;
10288 }
10289
10290 int x, y, z;
10291
10292 // the mean values of each seam and the average
10293 double mL,mR,mT,mB;
10294
10295 // how much to shift each seam
10296 double nl,nr,nt,nb;
10297
10298 // quad. shifting amount
10299 double q1,q2,q3,q4;
10300
10301 // calc. the mean for each quadrant
10302 for (z=0; z<width; z++) {
10303 left = image->get_col(xs/2 -1-z)->get_data();
10304 for (y=0; y<ys; y++)
10305 temp[z*ys+y]=left[y];
10306 }
10307 mL=gsl_stats_mean(temp,1,ys*width);
10308
10309 for (z=0; z<width; z++) {
10310 right = image->get_col(xs/2 +z)->get_data();
10311 for (y=0; y<ys; y++)
10312 temp[z*ys+y]=right[y];
10313 }
10314 mR=gsl_stats_mean(temp,1,ys*width);
10315
10316 for (z=0; z<width; z++) {
10317 top = image->get_row(ys/2 -1-z)->get_data();
10318 for (x=0; x<xs; x++)
10319 temp[z*xs+x]=top[x];
10320 }
10321 mT=gsl_stats_mean(temp,1,xs*width);
10322
10323 for (z=0; z<width; z++) {
10324 bottom = image->get_row(ys/2 +z)->get_data();
10325 for (x=0; x<xs; x++)
10326 temp[z*xs+x]=bottom[x];
10327 }
10328 mB=gsl_stats_mean(temp,1,xs*width);
10329
10330 free(temp);
10331
10332 nl=(mL+mR)/2-mL;
10333 nr=(mL+mR)/2-mR;
10334 nt=(mT+mB)/2-mT;
10335 nb=(mT+mB)/2-mB;
10336
10337 q1=nl+nt;
10338 q2=nr+nt;
10339 q3=nr+nb;
10340 q4=nl+nb;
10341
10342 // change the pixel values
10343 for (x = 0; x < xs / 2; x++)
10344 for (y = 0; y < ys / 2; y++) {
10345 image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q1));
10346 }
10347 for (x = xs / 2; x < xs; x++)
10348 for (y = 0; y < ys / 2; y++) {
10349 image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q2));
10350 }
10351 for (x = xs / 2; x < xs; x++)
10352 for (y = ys / 2; y < ys; y++) {
10353 image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q3));
10354 }
10355 for (x = 0; x < xs / 2; x++)
10356 for (y = ys / 2; y < ys; y++) {
10357 image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q4));
10358 }
10359
10360}
10361
10363{
10364 int nx=image->get_xsize();
10365 int nz=image->get_xsize();
10366 EMData * result = image->process("filter.highpass.gauss",Dict("cutoff_freq",0.01f));
10367 if (nz==1) result->process_inplace("mask.decayedge2d",Dict("width",nx/50));
10368 result->add(-float(result->get_attr("minimum")));
10369 result->process_inplace("filter.lowpass.tophat",Dict("cutoff_freq",0.05));
10370 result->process_inplace("math.squared");
10371 result->process_inplace("filter.lowpass.gauss",Dict("cutoff_freq",10.0f/(nx/40*(float)image->get_attr("apix_x"))));
10372 result->process_inplace("normalize.edgemean");
10373
10374 return result;
10375}
10376
10378{
10379 // slightly inefficient, but best we can easily do
10380 EMData *tmp = process(image);
10381 memcpy(image->get_data(),tmp->get_data(),image->get_size()*sizeof(float));
10382 delete tmp;
10383 return;
10384}
10385
10386
10388{
10389 if (image->get_zsize() != 1) {
10390 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
10391 throw ImageDimensionException("3D model not supported");
10392 }
10393
10394 int i,nx,ny;
10395 const gsl_wavelet_type * T;
10396 nx=image->get_xsize();
10397 ny=image->get_ysize();
10398
10399 if (nx != ny && ny!=1) throw ImageDimensionException("Wavelet transform only supports square images");
10400// float l=log((float)nx)/log(2.0f);
10401// if (l!=floor(l)) throw ImageDimensionException("Wavelet transform size must be power of 2");
10402 if( !Util::IsPower2(nx) ) throw ImageDimensionException("Wavelet transform size must be power of 2");
10403
10404 // Unfortunately GSL works only on double() arrays
10405 // eventually we should put our own wavelet code in here
10406 // but this will work for now
10407 double *cpy = (double *)malloc(nx*ny*sizeof(double));
10408
10409 for (i=0; i<nx*ny; i++) cpy[i]=image->get_value_at(i,0,0);
10410
10411 string tp = (const char*)params["type"];
10412 if (tp=="daub") T=gsl_wavelet_daubechies;
10413 else if (tp=="harr") T=gsl_wavelet_haar;
10414 else if (tp=="bspl") T=gsl_wavelet_bspline;
10415 else throw InvalidStringException(tp,"Invalid wavelet name, 'daub', 'harr' or 'bspl'");
10416
10417 int K=(int)params["ord"];
10418 gsl_wavelet_direction dir;
10419
10420 if ((int)params["dir"]==1) dir=(gsl_wavelet_direction)1; // defined as 'forward', but name is broken on mac
10421 else dir=(gsl_wavelet_direction)-1; // backward
10422
10423 gsl_wavelet *w = gsl_wavelet_alloc(T, K);
10424 gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(nx);
10425
10426 if (ny==1) gsl_wavelet_transform (w,cpy, 1, nx, dir, work);
10427 else gsl_wavelet2d_transform (w, cpy, nx,nx,ny, dir, work);
10428
10429 gsl_wavelet_workspace_free (work);
10430 gsl_wavelet_free (w);
10431
10432 for (i=0; i<nx*ny; i++) image->set_value_at_fast(i,0,0,static_cast<float>(cpy[i]));
10433
10434 free(cpy);
10435}
10436
10438{
10439 if( params.has_key("dir") ) {
10440 if ((int)params["dir"]==-1||(image->is_complex() && (int)params["dir"]==0)) {
10441 image->do_ift_inplace();
10442 }
10443 else {
10444 image->do_fft_inplace();
10445 }
10446 }
10447}
10448/*
10449void RadialProcessor::process_inplace(EMData * image)
10450{
10451 if (!image) {
10452 LOGWARN("NULL Image");
10453 return;
10454 }
10455
10456 //Note : real image only!
10457 if(image->is_complex()) {
10458 LOGERR("%s Processor only operates on real images", get_name().c_str());
10459 throw ImageFormatException("apply to real image only");
10460 }
10461
10462 vector<float> table = params["table"];
10463 vector<float>::size_type tsize = table.size();
10464
10465 int nx = image->get_xsize();
10466 int ny = image->get_ysize();
10467 int nz = image->get_zsize();
10468 int nx2 = nx / 2;
10469 int ny2 = ny / 2;
10470 int nz2 = nz / 2;
10471 float sz[3];
10472 sz[0] = static_cast<float>(nx2);
10473 sz[1] = static_cast<float>(ny2);
10474 sz[2] = static_cast<float>(nz2);
10475 float szmax = *std::max_element(&sz[0], &sz[3]);
10476 float maxsize;
10477 if(nz>1) {
10478 maxsize = (float)(1.8f * szmax);
10479 }
10480 else{
10481 maxsize = (float)(1.5f * szmax);
10482 }
10483 for(int i=tsize+1; i<maxsize; i++) {
10484 table.push_back(0.0f);
10485 }
10486
10487 float dx = 1.0f / (float)nx;
10488 float dy = 1.0f / (float)ny;
10489 float dz = 1.0f / (float)nz;
10490 float dx2 = dx * dx;
10491 float dy2 = dy * dy;
10492 float dz2 = dz * dz;
10493 int iz, iy, ix, jz, jy, jx;
10494 float argx, argy, argz;
10495 float rf, df, f;
10496 int ir;
10497 for(iz=1; iz<=nz; iz++) {
10498 jz = iz - 1;
10499 if(jz > nz2) {
10500 jz -= nz;
10501 }
10502 argz = float(jz*jz) * dz2;
10503
10504 for(iy=1; iy<=ny; iy++) {
10505 jy = iy - 1;
10506 if(jy > ny2) {
10507 jy -= ny;
10508 }
10509 argy = argz + float(jy*jy) * dy2;
10510
10511 for(ix=1; ix<=nx; ix++) {
10512 jx = ix -1;
10513 argx = argy + float(jx*jx)*dx2;
10514
10515 rf = sqrt(argx)*2.0f*nx2;
10516 ir = int(rf);
10517 df = rf - float(ir);
10518 f = table[ir] + df*(table[ir+1]-table[ir]);
10519
10520 (*image)(ix-1,iy-1,iz-1) *= f;
10521 }
10522 }
10523 }
10524
10525 image->update();
10526}
10527*/
10528
10529
10530
10532{
10533 if (!image) {
10534 LOGWARN("NULL Image");
10535 return;
10536 }
10537
10538 string axis = (const char*)params["axis"];
10539
10540 float* data = image->EMData::get_data();
10541
10542 int nx = image->get_xsize();
10543 int ny = image->get_ysize();
10544 int nz = image->get_zsize();
10545 size_t nxy = nx*ny;
10546
10547 int x_start = 0;
10548 int y_start = 0;
10549 int z_start = 0;
10550
10551 if (axis == "x" || axis == "X") {
10552 int offset = 0;
10553 for (int iz = 0; iz < nz; iz++){
10554 for (int iy = 0; iy < ny; iy++) {
10555 offset = nx*iy + nxy*iz;
10556 reverse(&data[x_start+offset],&data[offset+nx]);
10557 }
10558 }
10559 } else if (axis == "y" || axis == "Y") {
10560 float *tmp = new float[nx];
10561 int nhalf = ny/2;
10562 size_t beg = 0;
10563 for (int iz = 0; iz < nz; iz++) {
10564 beg = iz*nxy;
10565 for (int iy = y_start; iy < nhalf; iy++) {
10566 memcpy(tmp, &data[beg+iy*nx], nx*sizeof(float));
10567 memcpy(&data[beg+iy*nx], &data[beg+(y_start+ny-iy-1)*nx], nx*sizeof(float));
10568 memcpy(&data[beg+(y_start+ny-iy-1)*nx], tmp, nx*sizeof(float));
10569 }
10570 }
10571 delete[] tmp;
10572 } else if (axis == "z" || axis == "Z") {
10573 if(1-z_start) {
10574 int nhalf = nz/2;
10575 float *tmp = new float[nxy];
10576 for(int iz = 0;iz<nhalf;iz++){
10577 memcpy(tmp,&data[iz*nxy],nxy*sizeof(float));
10578 memcpy(&data[iz*nxy],&data[(nz-iz-1)*nxy],nxy*sizeof(float));
10579 memcpy(&data[(nz-iz-1)*nxy],tmp,nxy*sizeof(float));
10580 }
10581 delete[] tmp;
10582 } else {
10583 float *tmp = new float[nx];
10584 int nhalf = nz/2;
10585 size_t beg = 0;
10586 for (int iy = 0; iy < ny; iy++) {
10587 beg = iy*nx;
10588 for (int iz = z_start; iz < nhalf; iz++) {
10589 memcpy(tmp, &data[beg+ iz*nxy], nx*sizeof(float));
10590 memcpy(&data[beg+iz*nxy], &data[beg+(nz-iz-1+z_start)*nxy], nx*sizeof(float));
10591 memcpy(&data[beg+(nz-iz-1+z_start)*nxy], tmp, nx*sizeof(float));
10592 }
10593 }
10594 delete[] tmp;
10595 }
10596 }
10597
10598 image->update();
10599}
10600
10602{
10603 if (!image) {
10604 LOGWARN("NULL Image");
10605 return;
10606 }
10607
10608 string axis = (const char*)params["axis"];
10609
10610 float* data = image->EMData::get_data();
10611
10612 int nx = image->get_xsize();
10613 int ny = image->get_ysize();
10614 int nz = image->get_zsize();
10615 size_t nxy = nx*ny;
10616
10617 int x_start = 1-nx%2;
10618 int y_start = 1-ny%2;
10619 int z_start = 1-nz%2;
10620
10621 if (axis == "x" || axis == "X") {
10622 if(image->is_complex()) {
10623 if(nz>1 || ny%2 == 1 || image->is_fftodd() ) throw ImageFormatException("Error: Mirror works only on 2D even complex images");
10624 for (int iy = 1; iy < ny/2; iy++) {
10625 int offset = nx*iy;
10626 int off2 = nx*(ny-iy);
10627 for (int ix = 0; ix < nx; ix++) {
10628 float tmp = data[ix+offset];
10629 data[ix+offset] = data[ix+off2];
10630 data[ix+off2] = tmp;
10631 }
10632 }
10633 // conjugate
10634 for (int ix = 1; ix < nxy; ix += 2) data[ix] = -data[ix];
10635 } else {
10636 for (int iz = 0; iz < nz; iz++)
10637 for (int iy = 0; iy < ny; iy++) {
10638 int offset = nx*iy + nxy*iz;
10639 reverse(&data[offset+x_start],&data[offset+nx]);
10640 }
10641 }
10642 } else if (axis == "y" || axis == "Y") {
10643 float *tmp = new float[nx];
10644 int nhalf = ny/2;
10645 size_t beg = 0;
10646 for (int iz = 0; iz < nz; iz++) {
10647 beg = iz*nxy;
10648 for (int iy = y_start; iy < nhalf; iy++) {
10649 memcpy(tmp, &data[beg+iy*nx], nx*sizeof(float));
10650 memcpy(&data[beg+iy*nx], &data[beg+(ny-iy-1+y_start)*nx], nx*sizeof(float));
10651 memcpy(&data[beg+(ny-iy-1+y_start)*nx], tmp, nx*sizeof(float));
10652 }
10653 }
10654 delete[] tmp;
10655 } else if (axis == "z" || axis == "Z") {
10656 if(1-z_start) {
10657 int nhalf = nz/2;
10658 float *tmp = new float[nxy];
10659 for(int iz = 0;iz<nhalf;iz++){
10660 memcpy(tmp,&data[iz*nxy],nxy*sizeof(float));
10661 memcpy(&data[iz*nxy],&data[(nz-iz-1)*nxy],nxy*sizeof(float));
10662 memcpy(&data[(nz-iz-1)*nxy],tmp,nxy*sizeof(float));
10663 }
10664 delete[] tmp;
10665 } else {
10666 float *tmp = new float[nx];
10667 int nhalf = nz/2;
10668 size_t beg = 0;
10669 for (int iy = 0; iy < ny; iy++) {
10670 beg = iy*nx;
10671 for (int iz = z_start; iz < nhalf; iz++) {
10672 memcpy(tmp, &data[beg+ iz*nxy], nx*sizeof(float));
10673 memcpy(&data[beg+iz*nxy], &data[beg+(nz-iz-1+z_start)*nxy], nx*sizeof(float));
10674 memcpy(&data[beg+(nz-iz-1+z_start)*nxy], tmp, nx*sizeof(float));
10675 }
10676 }
10677 delete[] tmp;
10678 }
10679 }
10680
10681 image->update();
10682}
10683
10684
10685int EMAN::multi_processors(EMData * image, vector < string > processornames)
10686{
10687 Assert(image != 0);
10688 Assert(processornames.size() > 0);
10689
10690 for (size_t i = 0; i < processornames.size(); i++) {
10691 image->process_inplace(processornames[i]);
10692 }
10693 return 0;
10694}
10695
10696float* TransformProcessor::transform(const EMData* const image, const Transform& t) const {
10697
10698 ENTERFUNC;
10699
10700 Transform inv = t.inverse();
10701 int nx = image->get_xsize();
10702 int ny = image->get_ysize();
10703 int nz = image->get_zsize();
10704 int nxy = nx*ny;
10705 int N = ny;
10706
10707 int zerocorners = params.set_default("zerocorners",0);
10708
10709
10710 const float * const src_data = image->get_const_data();
10711 float *des_data = (float *) EMUtil::em_calloc(sizeof(float)*nx,ny*nz);
10712
10713 if ((nz == 1)&&(image -> is_real())) {
10714 Vec2f offset(nx/2,ny/2);
10715 for (int j = 0; j < ny; j++) {
10716 for (int i = 0; i < nx; i++) {
10717 Vec2f coord(i-nx/2,j-ny/2);
10718 Vec2f soln = inv*coord;
10719 soln += offset;
10720
10721 float x2 = soln[0];
10722 float y2 = soln[1];
10723
10724 if (x2 < 0 || x2 >= nx || y2 < 0 || y2 >= ny ) {
10725 des_data[i + j * nx] = 0; // It may be tempting to set this value to the
10726 // mean but in fact this is not a good thing to do. Talk to S.Ludtke about it.
10727 }
10728 else {
10729 int ii = Util::fast_floor(x2);
10730 int jj = Util::fast_floor(y2);
10731 int k0 = ii + jj * nx;
10732 int k1 = k0 + 1;
10733 int k2 = k0 + nx;
10734 int k3 = k0 + nx + 1;
10735
10736 if (ii == nx - 1) {
10737 k1--;
10738 k3--;
10739 }
10740 if (jj == ny - 1) {
10741 k2 -= nx;
10742 k3 -= nx;
10743 }
10744
10745 float t = x2 - ii;
10746 float u = y2 - jj;
10747
10748 des_data[i + j * nx] = Util::bilinear_interpolate(src_data[k0],src_data[k1], src_data[k2], src_data[k3],t,u);
10749 }
10750 }
10751 }
10752 }
10753 if ((nz == 1)&&(image -> is_complex())&&(nx%2==0)&&((2*(nx-ny)-3)*(2*(nx-ny)-3)==1)&&(zerocorners==0) ) {
10754 //printf("Hello 2-d complex TransformProcessor \n");
10755 // make sure there was a realImage.process('xform.phaseorigin.tocorner')
10756 // before transformation to Fourier Space
10757// This rotates a complex image that is a FT of a real space image: it has Friedel symmetries
10758// An arbitrary complex image, F, can be decomposed into two Friedel images
10759// G(k) = (F(k) + F*(-k))/2 , H(k) = (-i(F(k) - F*(k)))/2;
10760// via F(k) = G(k) + i H(k); notice G and H are Friedel symmetric (not necessarily real)
10761// But g,h are real, using f=g+ih.
10762// First make sure that image has proper size;
10763// if 2N is side of real image, then sizes of FFT are (2N+2,2N)
10764// if 2N+1 is side of real image, then sizes of FFT are (2N+2,2N+1)
10765// so we need nx =ny+2, and ny even
10766// or nx = ny+1 and ny odd
10767// so nx even, and 2 *(nx -ny) -3= +- 1; So abs(2*(nx-ny)-3) == 1
10768 float theta = t.get_rotation("eman").get("phi"); theta=theta*pi/180;
10769 Vec3f transNow= t.get_trans();
10770 float xshift= transNow[0]; float yshift= transNow[1];
10771 float tempR; float tempI;float tempW;
10772// int kNy= ny; //size of the real space image
10773// int kNx= nx/2; //
10774 Vec2f offset(nx/2,ny/2);
10775 float Mid =(N+1.0)/2.0; // Check this
10776 for (int kyN = 0; kyN < ny; kyN++) {
10777 int kyNew = kyN;
10778 if (kyN>=nx/2) kyNew=kyN-ny; // Step 0 Unalias
10779 float kxOldPre= - sin(theta)* kyNew;
10780 float kyOldPre= cos(theta)* kyNew;
10781 float phaseY = -2*pi*kyNew*yshift/ny;
10782
10783 for (int kxN = 0; kxN < (nx/2); kxN++) {
10784 int kxNew=kxN;
10785 if (kxN >= nx/2) kxNew=kxN-ny;// Step 0 Unalias
10786 // Step 1, Do rotation and find 4 nn
10787 float kxOld= kxOldPre + cos(theta)* kxNew ;
10788 float kyOld= kyOldPre + sin(theta)* kxNew ;
10789 //
10790 int kxLower= floor(kxOld); int kxUpper= kxLower+1; // All these values
10791 int kyLower= floor(kyOld); int kyUpper= kyLower+1; // may be neg
10792 float dkxLower= (kxUpper-kxOld); float dkxUpper= (kxOld-kxLower);
10793 float dkyLower= (kyUpper-kyOld); float dkyUpper= (kyOld-kyLower);
10794//
10795 int kxL= kxLower; int kyL=kyLower;
10796 float dataLL_R= 0; float dataLL_I=0; int flag=1;
10797 if ((abs(kxL)<Mid) && (abs(kyL)<Mid)) { // Step 2 Make sure to be in First BZ
10798 kxL = (N+kxL)%N; kyL = (N+kyL)%N;
10799 if (kxL> N/2){ kxL=(N-kxL)%N; kyL=(N-kyL)%N ;flag=-1;} // Step 3: if nec, use Friedel paired
10800 dataLL_R= src_data[2*kxL+ kyL*nx]; // image -> get_value_at(2*kxL,kyL);
10801 dataLL_I= flag*src_data[2*kxL+1+ kyL*nx]; // image -> get_value_at(2*kxL+1,kyL);
10802 }
10803
10804 kxL=kxLower; int kyU=kyUpper;
10805 float dataLU_R= 0; float dataLU_I=0; flag=1;
10806 if ((abs(kxL)<Mid) && (abs(kyU)<Mid)){ // Step 2 Make sure to be in First BZ
10807 kxL = (N+kxL)%N; kyU = (N+kyU)%N;
10808 if (kxL> N/2){ kxL=(N-kxL)%N; kyU=(N-kyU)%N;flag=-1;} // Step 3
10809 dataLU_R= src_data[2*kxL+ kyU*nx];// image -> get_value_at(2*kxL,kyU);
10810 dataLU_I= flag*src_data[2*kxL+1+ kyU*nx];// flag*image -> get_value_at(2*kxL+1,kyU);
10811 }
10812
10813 int kxU= kxUpper; kyL=kyLower;
10814 float dataUL_R= 0; float dataUL_I=0; flag=1;
10815 if ((abs(kxU)<Mid) && (abs(kyL)<Mid)) { // Step 2
10816 kxU = (N+kxU)%N; kyL = (N+kyL)%N;
10817 if (kxU> N/2) { kxU=(N-kxU)%N; kyL=(N-kyL)%N;flag=-1;} // Step 3
10818 dataUL_R= src_data[2*kxU + kyL*nx]; // image -> get_value_at(2*kxU,kyL);
10819 dataUL_I= flag*src_data[2*kxU+1 + kyL*nx]; // flag*image -> get_value_at(2*kxU+1,kyL);
10820 }
10821
10822 kxU= kxUpper; kyU=kyUpper;
10823 float dataUU_R= 0; float dataUU_I=0; flag=1;
10824 if ((abs(kxU)<Mid) & (abs(kyU)<Mid)){ // Step 2
10825 kxU = (N+kxU)%N; kyU = (N+kyU)%N;
10826 if (kxU> N/2) { kxU=(N-kxU)%N; kyU=(N-kyU)%N;flag=-1;} // Step 3
10827 dataUU_R= src_data[2*kxU + kyU*nx]; // image -> get_value_at(2*kxU,kyU);
10828 dataUU_I= flag*src_data[2*kxU+1 + kyU*nx]; //flag*image -> get_value_at(2*kxU+1,kyU);
10829 }
10830 // Step 4 Assign Weights
10831 float WLL = dkxLower*dkyLower ;
10832 float WLU = dkxLower*dkyUpper ;// make more intricated weightings here
10833 float WUL = dkxUpper*dkyLower ;// WLL(dkxLower,dkyLower)
10834 float WUU = dkxUpper*dkyUpper ;// etc
10835 tempW = WLL + WLU + WUL + WUU ;
10836
10837 // Step 5 Assign Real, then Imaginar Values
10838 tempR = WLL*dataLL_R + WLU*dataLU_R + WUL* dataUL_R + WUU * dataUU_R ;
10839 tempI = WLL*dataLL_I + WLU*dataLU_I + WUL* dataUL_I + WUU * dataUU_I ;
10840 //
10841 float phase = phaseY -2*pi*kxNew*xshift/ny;
10842 float tempRb=tempR*cos(phase) - tempI*sin(phase);
10843 float tempIb=tempR*sin(phase) + tempI*cos(phase);
10844 //
10845 des_data[2*kxN + nx* kyN] = tempRb/tempW;
10846 des_data[2*kxN+1 + nx* kyN] = tempIb/tempW;
10847 //printf(" kxNew = %d, kyNew = %d,kxOld = %3.2f, kyOld = %3.2f, xl = %d,xU = %d,yl = %d,yu = %d, tempR = %3.2f, tempI=%3.2f, \n",
10848 // kxNew,kyNew, kxOld, kyOld, kxLower,kxUpper,kyLower,kyUpper, tempR, tempI);
10849 }
10850 }
10851 }
10852
10853 if ((nz == 1)&&(image -> is_complex())&&(nx%2==0)&&((2*(nx-ny)-3)*(2*(nx-ny)-3)==1)&&(zerocorners==1) ) {
10854 //printf("Hello 2-d complex TransformProcessor \n");
10855 // make sure there was a realImage.process('xform.phaseorigin.tocorner')
10856 // before transformation to Fourier Space
10857// This rotates a complex image that is a FT of a real space image: it has Friedel symmetries
10858// An arbitrary complex image, F, can be decomposed into two Friedel images
10859// G(k) = (F(k) + F*(-k))/2 , H(k) = (-i(F(k) - F*(k)))/2;
10860// via F(k) = G(k) + i H(k); notice G and H are Friedel symmetric (not necessarily real)
10861// But g,h are real, using f=g+ih.
10862// First make sure that image has proper size;
10863// if 2N is side of real image, then sizes of FFT are (2N+2,2N)
10864// if 2N+1 is side of real image, then sizes of FFT are (2N+2,2N+1)
10865// so we need nx =ny+2, and ny even
10866// or nx = ny+1 and ny odd
10867// so nx even, and 2 *(nx -ny) -3= +- 1; So abs(2*(nx-ny)-3) == 1
10868 float theta = t.get_rotation("2d").get("alpha"); theta=theta*pi/180;
10869 float Ctheta= cos(theta);
10870 float Stheta= sin(theta);
10871 int mirror= t.get_mirror()?(-1.0f):1.0f; // added by steve on 11/7/16
10872 Vec3f transNow= t.get_trans();
10873 float xshift= transNow[0]; float yshift= transNow[1];
10874// printf("%f\t%f\t%f\t%d\n",theta,xshift,yshift,mirror);
10875 float tempR; float tempI; // float tempW;
10876 float Mid =N*N/4; // steve changed to N^2
10877// int kNy= ny; //size of the real space image
10878// int kNx= nx/2; //
10879 Vec2f offset(nx/2,ny/2);
10880 float phaseConstx = -2*pi*xshift/ny ;
10881 float k1= cos(phaseConstx); float k2= sin(phaseConstx);
10882 float k3= 1.0/k1; float k4= k2/k1; // that is 1/cos and tan()
10883 int nxy=nx*ny;
10884
10885 for (int kyN = 0; kyN < ny; kyN++) {
10886 int kyNew = kyN;
10887 if (kyN>=nx/2) kyNew=kyN-ny; // Step 0 Unalias
10888 float kxOld= - Stheta* kyNew - Ctheta;
10889 float kyOld= Ctheta* kyNew - Stheta;
10890 float phase = -2*pi*kyNew*yshift/ny - phaseConstx ;
10891 float Cphase = cos(phase);
10892 float Sphase = sin(phase);
10893 int kx,ky;
10894 int IndexOut;
10895 if (mirror==-1.0) {
10896 if (kyN>0) IndexOut = -2 + nx * (ny-kyN); // Added by steve on 11/7/16
10897 else IndexOut = -2+ nx* kyN;
10898 }
10899 else IndexOut = -2+ nx* kyN;
10900 for (int kxN = 0; kxN < (nx/2); kxN++) {
10901 IndexOut += 2;
10902 // int kxNew=kxN;
10903 // if (kxN >= nx/2) kxNew=kxN-ny;// Step 0 Unalias, but this won't happen
10904 // Step 1, Do rotation and find 4 nn
10905 kxOld += Ctheta ;// was using kxNew instead of kxN
10906 kyOld += Stheta ;
10907 phase += phaseConstx;
10908 Cphase = Cphase*k1 -Sphase*k2; //update using trig addition; this is cos = cos cos -sin sin
10909 Sphase = Sphase*k3+ Cphase*k4; // and sin = sin (1/ cos) + cos * tan;
10910
10911// if ((abs(kxOld)>=Mid) || (abs(kyOld)>=Mid)) { // out of bounds
10912 if (Util::square_sum(kxOld,kyOld)>=Mid) {
10913 des_data[IndexOut] = 0;
10914 des_data[IndexOut+1] = 0;
10915 continue;}
10916
10917 //
10918 int kxLower= floor(kxOld); // All these values
10919 int kyLower= floor(kyOld); // may be neg
10920 //float dkxLower= (kxLower+1-kxOld);
10921 float dkxUpper= (kxOld-kxLower);
10922 //float dkyLower= (kyLower+1-kyOld);
10923 float dkyUpper= (kyOld-kyLower);
10924//
10925 kx= kxLower; ky =kyLower;
10926 int flagLL=1;
10927 if (kx<0) kx += N;
10928 if (ky<0) ky += N;
10929 if (kx> N/2){ kx=(N-kx) ; ky=(N-ky) ;flagLL=-1;} // Step 3: if nec, use Friedel paired
10930 int kLL =2*kx+ky*nx;
10931
10932 kx = kxLower; ky = kyLower+1;
10933 int flagLU =1;
10934 if (kx<0) kx += N;
10935 if (ky<0) ky += N;
10936 if (kx> N/2){ kx=(N-kx) ; ky=(N-ky) ;flagLU=-1;} // Step 3: if nec, use Friedel paired
10937 int kLU =2*kx+ky*nx;
10938
10939 kx = kxLower+1; ky=kyLower;
10940 int flagUL=1;
10941 if (kx<0) kx += N;
10942 if (ky<0) ky += N;
10943 if (kx> N/2){ kx=(N-kx) ; ky=(N-ky) ;flagUL=-1;} // Step 3: if nec, use Friedel paired
10944 int kUL =2*kx+ky*nx;
10945
10946 kx = kxLower+1; ky = kyLower+1;
10947 int flagUU =1;
10948 if (kx<0) kx += N;
10949 if (ky<0) ky += N;
10950 if (kx> N/2){ kx=(N-kx) ; ky=(N-ky) ;flagUU=-1;} // Step 3: if nec, use Friedel paired
10951 int kUU =2*kx+ky*nx;
10952
10953 // Step 4 Assign Weights
10954// float WLL = dkxLower*dkyLower ;
10955// float WLU = dkxLower*dkyUpper ;// make more intricated weightings here
10956// float WUL = dkxUpper*dkyLower ;// WLL(dkxLower,dkyLower)
10957// float WUU = dkxUpper*dkyUpper ;// etc
10958// tempW = WLL + WLU + WUL + WUU ;
10959
10960 // Added by steve. MAJOR limit checking issues here! Hope this doesn't cause any other problems
10961 if (kLL<0||kUL<0||kLU<0||kUU<0||kLL>=nxy||kUL>=nxy||kLU>=nxy||kUU>=nxy) continue;
10962 //printf("%d %d %d %d\n",kLL,kUL,kLU,kUU);
10963
10964 // Step 5 Assign Real, then Imaginary Values
10965 tempR = Util::bilinear_interpolate(src_data[kLL],src_data[kUL], src_data[kLU], src_data[kUU],dkxUpper,dkyUpper);//
10966 //WLL*dataLL_R + WLU*dataLU_R + WUL* dataUL_R + WUU * dataUU_R ;
10967 tempI = Util::bilinear_interpolate(flagLL* src_data[kLL+1],flagUL*src_data[kUL+1],
10968 flagLU*src_data[kLU+1], flagUU*src_data[kUU+1],dkxUpper,dkyUpper);
10969 //WLL*dataLL_I + WLU*dataLU_I + WUL* dataUL_I + WUU * dataUU_I ;
10970 //
10971
10972 float tempRb=tempR*Cphase - tempI*Sphase;
10973 float tempIb=tempR*Sphase + tempI*Cphase;
10974 //
10975 des_data[IndexOut] = tempRb;
10976// des_data[IndexOut+1] = tempIb;
10977 des_data[IndexOut+1] = tempIb*mirror;
10978 //printf(" kxNew = %d, kyNew = %d,kxOld = %3.2f, kyOld = %3.2f, xl = %d,xU = %d,yl = %d,yu = %d, tempR = %3.2f, tempI=%3.2f, \n",
10979 // kxNew,kyNew, kxOld, kyOld, kxLower,kxUpper,kyLower,kyUpper, tempR, tempI);
10980 }
10981 }
10982 }
10983
10984 if ((nz > 1)&&(image -> is_complex())&&(zerocorners==3)) {
10985 //printf("Hello 3-d complex TransformProcessor \n");
10986 float phi = t.get_rotation("eman").get("phi"); phi=pi*phi/180;
10987 float alt = t.get_rotation("eman").get("alt"); alt=pi*alt/180;
10988 float az = t.get_rotation("eman").get("az"); az=pi*az /180;
10989 Vec3f transNow= t.get_trans();
10990 float xshift= transNow[0]; float yshift= transNow[1];float zshift= transNow[2];
10991
10992 float phaseConstx = -2*pi*xshift/ny ;
10993 float k1= cos(phaseConstx); float k2= sin(phaseConstx);
10994 float k3= 1.0/k1; float k4= k2/k1; // that is 1/cos and tan()
10995
10996 float MatXX = (cos(az)*cos(phi) - sin(az)*cos(alt)*sin(phi) );
10997 float MatXY = (- cos(az)*sin(phi) - sin(az)*cos(alt)*cos(phi) ) ;
10998 float MatXZ = sin(az)*sin(alt) ;
10999 float MatYX = (sin(az)*cos(phi) + cos(az)*cos(alt)*sin(phi) );
11000 float MatYY = (- sin(az)*sin(phi) + cos(az)*cos(alt)*cos(phi) ) ;
11001 float MatYZ = - cos(az)*sin(alt) ;
11002 float MatZX = sin(alt)*sin(phi);
11003 float MatZY = sin(alt)*cos(phi);
11004 float MatZZ = cos(alt) ;
11005 float tempR; float tempI; float tempW;
11006 float Mid =(N+1.0)/2.0; // Check this
11007 int nxny = nx*ny;
11008
11009 for (int kzN = 0; kzN < ny; kzN++) {
11010 int kzNew=kzN;
11011 if (kzN >= nx/2) kzNew=kzN-N; // Step 0 Unalias new coords;
11012 for (int kyN = 0; kyN < ny; kyN++) {// moves them to lesser mag
11013 int kyNew=kyN;
11014 if (kyN>=nx/2) kyNew=kyN-ny; // Step 0 Unalias
11015 float kxPre = MatXY * kyNew + MatXZ *kzNew;
11016 float kyPre = MatYY * kyNew + MatYZ*kzNew;
11017 float kzPre = MatZY * kyNew + MatZZ*kzNew;
11018 float phase = -2*pi*kzNew*zshift/ny-2*pi*kyNew*yshift/ny - phaseConstx ;
11019 float Cphase = cos(phase);
11020 float Sphase = sin(phase);
11021
11022 float OutBounds2= (2*Mid*Mid- (kyNew*kyNew+kzNew*kzNew)) ;
11023 int kxNewMax= nx/2;
11024 if (OutBounds2< 0) kxNewMax=0;
11025 else if (OutBounds2<(nx*nx/4)) kxNewMax=sqrt(OutBounds2);
11026 for (int kxN = kxNewMax; kxN < nx/2 ; kxN++ ) {
11027 des_data[2*kxN + nx* kyN +nxny*kzN] = 0;
11028 des_data[2*kxN + nx* kyN +nxny*kzN+1] = 0;
11029 }
11030
11031
11032 for (int kxN = 0; kxN < kxNewMax; kxN++ ) {
11033 Cphase = Cphase*k1 -Sphase*k2; //update using trig addition; this is cos = cos cos -sin sin
11034 Sphase = Sphase*k3+ Cphase*k4; // and sin = sin (1/ cos) + cos * tan;
11035 // Step 1: Do inverse Rotation to get former values, and alias Step1
11036 float kxOld= MatXX * kxN + kxPre;
11037 float kyOld= MatYX * kxN + kyPre;
11038 float kzOld= MatZX * kxN + kzPre;
11039 //
11040 if ((abs(kxOld)>=Mid) || (abs(kyOld)>=Mid) || (abs(kzOld)>=Mid) ) { // out of bounds
11041 des_data[2*kxN + nx* kyN +nxny*kzN] = 0;
11042 des_data[2*kxN + nx* kyN +nxny*kzN+1] = 0;
11043 continue;}
11044 //
11045 int kxLower= floor(kxOld); int kxUpper= kxLower+1;
11046 int kyLower= floor(kyOld); int kyUpper= kyLower+1;
11047 int kzLower= floor(kzOld); int kzUpper= kzLower+1;
11048 //
11049 float dkxLower= (kxUpper-kxOld); float dkxUpper= (kxOld-kxLower);
11050 float dkyLower= (kyUpper-kyOld); float dkyUpper= (kyOld-kyLower);
11051 float dkzLower= (kzUpper-kzOld); float dkzUpper= (kzOld-kzLower);
11052 // LLL 1
11053 int kxL= kxLower; int kyL=kyLower; int kzL=kzLower;
11054 float dataLLL_R= 0; float dataLLL_I=0; int flag=1;
11055 if ( (abs(kxL)<Mid) && (abs(kyL)<Mid) && (abs(kzL)<Mid) ) { // Step 2 Make sure to be in First BZ
11056 kxL = (N+kxL)%N; kyL = (N+kyL)%N; kzL = (N+kzL)%N;
11057 if (kxL> N/2){kxL=(N-kxL)%N; kyL=(N-kyL)%N ; kzL=(N-kzL)%N ;flag=-1;} // Step 3: use Friedel paired
11058 dataLLL_R= src_data[ 2*kxL + nx*kyL+ nxny*kzL ]; //get_value_at(2*kxL,kyL,kzL);
11059 dataLLL_I=flag*src_data[ 2*kxL+1 + nx*kyL+ nxny*kzL ];//get_value_at(2*kxL+1,kyL,kzL);
11060 }
11061 // LLU 2
11062 kxL= kxLower; kyL=kyLower; int kzU=kzUpper;
11063 float dataLLU_R= 0; float dataLLU_I=0; flag=1;
11064 if ( (abs(kxL)<Mid) && (abs(kyL)<Mid) && (abs(kzU)<Mid) ) {// Step 2 Make sure to be in First BZ
11065 kxL = (N+kxL)%N; kyL = (N+kyL)%N; kzU = (N+kzU)%N;
11066 if (kxL> N/2){kxL=(N-kxL)%N; kyL=(N-kyL)%N ; kzU=(N-kzU)%N ;flag=-1;} // Step 3: use Friedel paired
11067 dataLLU_R= src_data[ 2*kxL + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxL ,kyL,kzU);
11068 dataLLU_I= flag*src_data[ 2*kxL+1 + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxL+1,kyL,kzU);
11069 }
11070 // LUL 3
11071 kxL= kxLower; int kyU=kyUpper; kzL=kzLower;
11072 float dataLUL_R= 0; float dataLUL_I=0; flag=1;
11073 if ( (abs(kxL)<Mid) && (abs(kyU)<Mid)&& (abs(kzL)<Mid) ) {// Step 2 Make sure to be in First BZ
11074 kxL = (N+kxL)%N; kyU = (N+kyU)%N; kzL = (N+kzL)%N;
11075 if (kxL> N/2){ kxL=(N-kxL)%N; kyU=(N-kyU)%N; kzL=(N-kzL)%N ;flag=-1;}// Step 3
11076 dataLUL_R= src_data[ 2*kxL + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxL ,kyU,kzL);
11077 dataLUL_I=flag*src_data[ 2*kxL+1 + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxL+1,kyU,kzL);
11078 }
11079 // LUU 4
11080 kxL= kxLower; kyU=kyUpper; kzL=kzUpper;
11081 float dataLUU_R= 0; float dataLUU_I=0; flag=1;
11082 if ( (abs(kxL)<Mid) && (abs(kyU)<Mid)&& (abs(kzU)<Mid)) {// Step 2 Make sure to be in First BZ
11083 kxL = (N+kxL)%N; kyU = (N+kyU)%N; kzU = (N+kzU)%N;
11084 if (kxL> N/2){kxL=(N-kxL)%N; kyU=(N-kyU)%N; kzL=(N-kzL)%N ;flag=-1;} // Step 3
11085 dataLUU_R= src_data[ 2*kxL + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxL ,kyU,kzU);
11086 dataLUU_I=flag*src_data[ 2*kxL+1 + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxL+1,kyU,kzU);
11087 }
11088 // ULL 5
11089 int kxU= kxUpper; kyL=kyLower; kzL=kzLower;
11090 float dataULL_R= 0; float dataULL_I=0; flag=1;
11091 if ( (abs(kxU)<Mid) && (abs(kyL)<Mid) && (abs(kzL)<Mid) ) {// Step 2
11092 kxU = (N+kxU)%N; kyL = (N+kyL)%N; kzL = (N+kzL)%N;
11093 if (kxU> N/2){kxU=(N-kxU)%N; kyL=(N-kyL)%N; kzL=(N-kzL)%N ;flag=-1;} // Step 3
11094 dataULL_R= src_data[ 2*kxU + nx*kyL+ nxny*kzL ]; // image -> get_value_at(2*kxU ,kyL,kzL);
11095 dataULL_I=flag*src_data[ 2*kxU+1 + nx*kyL+ nxny*kzL ]; // image -> get_value_at(2*kxU+1,kyL,kzL);
11096 }
11097 // ULU 6
11098 kxU= kxUpper; kyL=kyLower; kzU=kzUpper;
11099 float dataULU_R= 0; float dataULU_I=0; flag=1;
11100 if ( (abs(kxU)<Mid) && (abs(kyL)<Mid)&& (abs(kzU)<Mid) ) {// Step 2
11101 kxU = (N+kxU)%N; kyL = (N+kyL)%N; kzU = (N+kzU)%N;
11102 if (kxU> N/2){kxU=(N-kxU)%N; kyL=(N-kyL)%N; kzU=(N-kzU)%N ;flag=-1;} // Step 3
11103 dataULU_R= src_data[ 2*kxU + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxU ,kyL,kzU);
11104 dataULU_I=flag*src_data[ 2*kxU+1 + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxU+1,kyL,kzU);
11105 }
11106 // UUL 7
11107 kxU= kxUpper; kyU=kyUpper; kzL=kzLower;
11108 float dataUUL_R= 0; float dataUUL_I=0; flag=1;
11109 if ( (abs(kxU)<Mid) && (abs(kyU)<Mid) && (abs(kzL)<Mid) ) {// Step 2
11110 kxU = (N+kxU)%N; kyU = (N+kyU)%N; kzL = (N+kzL)%N;
11111 if (kxU> N/2){kxU=(N-kxU)%N; kyU=(N-kyU)%N; kzL=(N-kzL)%N ;flag=-1;} // Step 3
11112 dataUUL_R= src_data[ 2*kxU + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxU ,kyU,kzL);
11113 dataUUL_I=flag*src_data[ 2*kxU+1 + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxU+1,kyU,kzL);
11114 }
11115 // UUU 8
11116 kxU= kxUpper; kyU=kyUpper; kzU=kzUpper;
11117 float dataUUU_R= 0; float dataUUU_I=0; flag=1;
11118 if ( (abs(kxU)<Mid) && (abs(kyU)<Mid) && (abs(kzU)<Mid) ) { // Step 2
11119 kxU = (N+kxU)%N; kyU = (N+kyU)%N; kzU = (N+kzU)%N;
11120 if (kxU> N/2) {kxU=(N-kxU)%N; kyU=(N-kyU)%N; kzU=(N-kzU)%N ;flag=-1;} // Step 3
11121 dataUUU_R= src_data[ 2*kxU + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxU ,kyU,kzU);
11122 dataUUU_I=flag*src_data[ 2*kxU+1 + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxU+1,kyU,kzU);
11123 }
11124 // Step 4 Assign Weights
11125 float WLLL = dkxLower*dkyLower*dkzLower ;
11126 // WLLL = sqrt(pow(dkxUpper,2)+ pow(dkyUpper,2) + pow(dkzUpper,2)) ;
11127 // WLLL = sin(pi* WLLL+.00000001)/(pi* WLLL+.00000001);
11128 float WLLU = dkxLower*dkyLower*dkzUpper ;
11129 float WLUL = dkxLower*dkyUpper*dkzLower ;
11130 float WLUU = dkxLower*dkyUpper*dkzUpper ;
11131 float WULL = dkxUpper*dkyLower*dkzLower ;
11132 float WULU = dkxUpper*dkyLower*dkzUpper ;
11133 float WUUL = dkxUpper*dkyUpper*dkzLower;
11134 float WUUU = dkxUpper*dkyUpper*dkzUpper;
11135 tempW = WLLL + WLLU + WLUL + WLUU + WULL + WULU + WUUL + WUUU ;
11136 // Step 5 Assign Real, then Imaginary Values
11137 tempR = WLLL*dataLLL_R + WLLU*dataLLU_R + WLUL*dataLUL_R + WLUU*dataLUU_R ;
11138 tempR += WULL*dataULL_R + WULU*dataULU_R + WUUL*dataUUL_R + WUUU*dataUUU_R ;
11139 //
11140 tempI = WLLL*dataLLL_I + WLLU*dataLLU_I + WLUL*dataLUL_I + WLUU*dataLUU_I ;
11141 tempI += WULL*dataULL_I + WULU*dataULU_I + WUUL*dataUUL_I + WUUU*dataUUU_I ;
11142 //
11143// float phase = -2*pi*(kxNew*xshift+kyNew*yshift+kzNew*zshift)/ny;
11144 float tempRb=tempR*Cphase - tempI*Sphase;
11145 float tempIb=tempR*Sphase + tempI*Cphase;
11146 //
11147 des_data[2*kxN + nx* kyN +nxny*kzN] = tempRb/tempW;
11148 des_data[2*kxN+1 + nx* kyN +nxny*kzN] = tempIb/tempW;
11149 }}} // end z, y, x loops through new coordinates
11150 } // end rotations in Fourier Space 3D
11151 // Steve trying for more optimization
11152 if ((nz > 1)&&(image -> is_complex())&&(zerocorners==2)) {
11153 //printf("Hello 3-d complex TransformProcessor \n");
11154 float phi = t.get_rotation("eman").get("phi"); phi=pi*phi/180;
11155 float alt = t.get_rotation("eman").get("alt"); alt=pi*alt/180;
11156 float az = t.get_rotation("eman").get("az"); az=pi*az /180;
11157 Vec3f transNow= t.get_trans();
11158 float xshift= transNow[0]; float yshift= transNow[1];float zshift= transNow[2];
11159
11160 float phaseConstx = -2*pi*xshift/ny ;
11161 float k1= cos(phaseConstx); float k2= sin(phaseConstx);
11162 float k3= 1.0/k1; float k4= k2/k1; // that is 1/cos and tan()
11163
11164 float MatXX = (cos(az)*cos(phi) - sin(az)*cos(alt)*sin(phi) );
11165 float MatXY = (- cos(az)*sin(phi) - sin(az)*cos(alt)*cos(phi) ) ;
11166 float MatXZ = sin(az)*sin(alt) ;
11167 float MatYX = (sin(az)*cos(phi) + cos(az)*cos(alt)*sin(phi) );
11168 float MatYY = (- sin(az)*sin(phi) + cos(az)*cos(alt)*cos(phi) ) ;
11169 float MatYZ = - cos(az)*sin(alt) ;
11170 float MatZX = sin(alt)*sin(phi);
11171 float MatZY = sin(alt)*cos(phi);
11172 float MatZZ = cos(alt) ;
11173 //float tempR; float tempI; float tempW; # commented because variables were unused and produced warnings during compilation.
11174 float Mid =(N+1.0)/2.0; // Check this
11175 int lim=(N/2)*(N/2); // this is NOT N*N/4 !
11176 int nxny = nx*ny;
11177
11178 for (int kzN = 0; kzN < ny; kzN++) {
11179 int kzNew=kzN;
11180 if (kzN >= nx/2) kzNew=kzN-N; // Step 0 Unalias new coords;
11181 for (int kyN = 0; kyN < ny; kyN++) {// moves them to lesser mag
11182 int kyNew=kyN;
11183 if (kyN>=nx/2) kyNew=kyN-ny; // Step 0 Unalias
11184
11185 // Establish limits for this row and skip if necessary
11186 int kyz2=kyNew*kyNew+kzNew*kzNew;
11187 if (kyz2>lim) continue; // Whole y,z row is 'missing'
11188 int kxNewMax=(int)floor(sqrt((float)(lim-kyz2)));
11189 float kxPre = MatXY * kyNew + MatXZ *kzNew;
11190 float kyPre = MatYY * kyNew + MatYZ*kzNew;
11191 float kzPre = MatZY * kyNew + MatZZ*kzNew;
11192 float phase = -2*pi*kzNew*zshift/ny-2*pi*kyNew*yshift/ny - phaseConstx ;
11193 float Cphase = cos(phase);
11194 float Sphase = sin(phase);
11195
11196// for (int kxN = kxNewMax; kxN < nx/2 ; kxN++ ) {
11197// des_data[2*kxN + nx* kyN +nxny*kzN] = 0;
11198// des_data[2*kxN + nx* kyN +nxny*kzN+1] = 0;
11199// }
11200
11201
11202 for (int kxN = 0; kxN < kxNewMax; kxN++ ) {
11203 Cphase = Cphase*k1 -Sphase*k2; //update using trig addition; this is cos = cos cos -sin sin
11204 Sphase = Sphase*k3+ Cphase*k4; // and sin = sin (1/ cos) + cos * tan;
11205 // Step 1: Do inverse Rotation to get former values, and alias Step1
11206 float kxOld= MatXX * kxN + kxPre;
11207 float kyOld= MatYX * kxN + kyPre;
11208 float kzOld= MatZX * kxN + kzPre;
11209 //
11210 // This is impossible
11211// if ((abs(kxOld)>=Mid) || (abs(kyOld)>=Mid) || (abs(kzOld)>=Mid) ) { // out of bounds
11212// des_data[2*kxN + nx* kyN +nxny*kzN] = 0;
11213// des_data[2*kxN + nx* kyN +nxny*kzN+1] = 0;
11214// continue;}
11215 //
11216 int kx0= floor(kxOld);
11217 int ky0= floor(kyOld);
11218 int kz0= floor(kzOld);
11219 //
11220 float dkx0= (kxOld-kx0);
11221 float dky0= (kyOld-ky0);
11222 float dkz0= (kzOld-kz0);
11223
11224 std::complex<float> c0 = image->get_complex_at(kx0 ,ky0 ,kz0 );
11225 std::complex<float> c1 = image->get_complex_at(kx0+1,ky0 ,kz0 );
11226 std::complex<float> c2 = image->get_complex_at(kx0 ,ky0+1,kz0 );
11227 std::complex<float> c3 = image->get_complex_at(kx0+1,ky0+1,kz0 );
11228 std::complex<float> c4 = image->get_complex_at(kx0 ,ky0 ,kz0+1);
11229 std::complex<float> c5 = image->get_complex_at(kx0+1,ky0 ,kz0+1);
11230 std::complex<float> c6 = image->get_complex_at(kx0 ,ky0+1,kz0+1);
11231 std::complex<float> c7 = image->get_complex_at(kx0+1,ky0+1,kz0+1);
11232
11233 std::complex<float> nwv = Util::trilinear_interpolate_complex(c0,c1,c2,c3,c4,c5,c6,c7,dkx0,dky0,dkz0);
11234
11235 des_data[2*kxN + nx* kyN +nxny*kzN] = nwv.real()*Cphase - nwv.imag()*Sphase;
11236 des_data[2*kxN+1 + nx* kyN +nxny*kzN] = nwv.real()*Sphase + nwv.imag()*Cphase;
11237
11238// // LLL 1
11239// int kxL= kxLower; int kyL=kyLower; int kzL=kzLower;
11240// float dataLLL_R= 0; float dataLLL_I=0; int flag=1;
11241// if ( (abs(kxL)<Mid) && (abs(kyL)<Mid) && (abs(kzL)<Mid) ) { // Step 2 Make sure to be in First BZ
11242// kxL = (N+kxL)%N; kyL = (N+kyL)%N; kzL = (N+kzL)%N;
11243// if (kxL> N/2){kxL=(N-kxL)%N; kyL=(N-kyL)%N ; kzL=(N-kzL)%N ;flag=-1;} // Step 3: use Friedel paired
11244// dataLLL_R= src_data[ 2*kxL + nx*kyL+ nxny*kzL ]; //get_value_at(2*kxL,kyL,kzL);
11245// dataLLL_I=flag*src_data[ 2*kxL+1 + nx*kyL+ nxny*kzL ];//get_value_at(2*kxL+1,kyL,kzL);
11246// }
11247// // LLU 2
11248// kxL= kxLower; kyL=kyLower; int kzU=kzUpper;
11249// float dataLLU_R= 0; float dataLLU_I=0; flag=1;
11250// if ( (abs(kxL)<Mid) && (abs(kyL)<Mid) && (abs(kzU)<Mid) ) {// Step 2 Make sure to be in First BZ
11251// kxL = (N+kxL)%N; kyL = (N+kyL)%N; kzU = (N+kzU)%N;
11252// if (kxL> N/2){kxL=(N-kxL)%N; kyL=(N-kyL)%N ; kzU=(N-kzU)%N ;flag=-1;} // Step 3: use Friedel paired
11253// dataLLU_R= src_data[ 2*kxL + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxL ,kyL,kzU);
11254// dataLLU_I= flag*src_data[ 2*kxL+1 + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxL+1,kyL,kzU);
11255// }
11256// // LUL 3
11257// kxL= kxLower; int kyU=kyUpper; kzL=kzLower;
11258// float dataLUL_R= 0; float dataLUL_I=0; flag=1;
11259// if ( (abs(kxL)<Mid) && (abs(kyU)<Mid)&& (abs(kzL)<Mid) ) {// Step 2 Make sure to be in First BZ
11260// kxL = (N+kxL)%N; kyU = (N+kyU)%N; kzL = (N+kzL)%N;
11261// if (kxL> N/2){ kxL=(N-kxL)%N; kyU=(N-kyU)%N; kzL=(N-kzL)%N ;flag=-1;}// Step 3
11262// dataLUL_R= src_data[ 2*kxL + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxL ,kyU,kzL);
11263// dataLUL_I=flag*src_data[ 2*kxL+1 + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxL+1,kyU,kzL);
11264// }
11265// // LUU 4
11266// kxL= kxLower; kyU=kyUpper; kzL=kzUpper;
11267// float dataLUU_R= 0; float dataLUU_I=0; flag=1;
11268// if ( (abs(kxL)<Mid) && (abs(kyU)<Mid)&& (abs(kzU)<Mid)) {// Step 2 Make sure to be in First BZ
11269// kxL = (N+kxL)%N; kyU = (N+kyU)%N; kzU = (N+kzU)%N;
11270// if (kxL> N/2){kxL=(N-kxL)%N; kyU=(N-kyU)%N; kzL=(N-kzL)%N ;flag=-1;} // Step 3
11271// dataLUU_R= src_data[ 2*kxL + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxL ,kyU,kzU);
11272// dataLUU_I=flag*src_data[ 2*kxL+1 + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxL+1,kyU,kzU);
11273// }
11274// // ULL 5
11275// int kxU= kxUpper; kyL=kyLower; kzL=kzLower;
11276// float dataULL_R= 0; float dataULL_I=0; flag=1;
11277// if ( (abs(kxU)<Mid) && (abs(kyL)<Mid) && (abs(kzL)<Mid) ) {// Step 2
11278// kxU = (N+kxU)%N; kyL = (N+kyL)%N; kzL = (N+kzL)%N;
11279// if (kxU> N/2){kxU=(N-kxU)%N; kyL=(N-kyL)%N; kzL=(N-kzL)%N ;flag=-1;} // Step 3
11280// dataULL_R= src_data[ 2*kxU + nx*kyL+ nxny*kzL ]; // image -> get_value_at(2*kxU ,kyL,kzL);
11281// dataULL_I=flag*src_data[ 2*kxU+1 + nx*kyL+ nxny*kzL ]; // image -> get_value_at(2*kxU+1,kyL,kzL);
11282// }
11283// // ULU 6
11284// kxU= kxUpper; kyL=kyLower; kzU=kzUpper;
11285// float dataULU_R= 0; float dataULU_I=0; flag=1;
11286// if ( (abs(kxU)<Mid) && (abs(kyL)<Mid)&& (abs(kzU)<Mid) ) {// Step 2
11287// kxU = (N+kxU)%N; kyL = (N+kyL)%N; kzU = (N+kzU)%N;
11288// if (kxU> N/2){kxU=(N-kxU)%N; kyL=(N-kyL)%N; kzU=(N-kzU)%N ;flag=-1;} // Step 3
11289// dataULU_R= src_data[ 2*kxU + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxU ,kyL,kzU);
11290// dataULU_I=flag*src_data[ 2*kxU+1 + nx*kyL+ nxny*kzU ]; // image -> get_value_at(2*kxU+1,kyL,kzU);
11291// }
11292// // UUL 7
11293// kxU= kxUpper; kyU=kyUpper; kzL=kzLower;
11294// float dataUUL_R= 0; float dataUUL_I=0; flag=1;
11295// if ( (abs(kxU)<Mid) && (abs(kyU)<Mid) && (abs(kzL)<Mid) ) {// Step 2
11296// kxU = (N+kxU)%N; kyU = (N+kyU)%N; kzL = (N+kzL)%N;
11297// if (kxU> N/2){kxU=(N-kxU)%N; kyU=(N-kyU)%N; kzL=(N-kzL)%N ;flag=-1;} // Step 3
11298// dataUUL_R= src_data[ 2*kxU + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxU ,kyU,kzL);
11299// dataUUL_I=flag*src_data[ 2*kxU+1 + nx*kyU+ nxny*kzL ]; // image -> get_value_at(2*kxU+1,kyU,kzL);
11300// }
11301// // UUU 8
11302// kxU= kxUpper; kyU=kyUpper; kzU=kzUpper;
11303// float dataUUU_R= 0; float dataUUU_I=0; flag=1;
11304// if ( (abs(kxU)<Mid) && (abs(kyU)<Mid) && (abs(kzU)<Mid) ) { // Step 2
11305// kxU = (N+kxU)%N; kyU = (N+kyU)%N; kzU = (N+kzU)%N;
11306// if (kxU> N/2) {kxU=(N-kxU)%N; kyU=(N-kyU)%N; kzU=(N-kzU)%N ;flag=-1;} // Step 3
11307// dataUUU_R= src_data[ 2*kxU + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxU ,kyU,kzU);
11308// dataUUU_I=flag*src_data[ 2*kxU+1 + nx*kyU+ nxny*kzU ]; // image -> get_value_at(2*kxU+1,kyU,kzU);
11309// }
11310// // Step 4 Assign Weights
11311// float WLLL = dkxLower*dkyLower*dkzLower ;
11312// // WLLL = sqrt(pow(dkxUpper,2)+ pow(dkyUpper,2) + pow(dkzUpper,2)) ;
11313// // WLLL = sin(pi* WLLL+.00000001)/(pi* WLLL+.00000001);
11314// float WLLU = dkxLower*dkyLower*dkzUpper ;
11315// float WLUL = dkxLower*dkyUpper*dkzLower ;
11316// float WLUU = dkxLower*dkyUpper*dkzUpper ;
11317// float WULL = dkxUpper*dkyLower*dkzLower ;
11318// float WULU = dkxUpper*dkyLower*dkzUpper ;
11319// float WUUL = dkxUpper*dkyUpper*dkzLower;
11320// float WUUU = dkxUpper*dkyUpper*dkzUpper;
11321// tempW = WLLL + WLLU + WLUL + WLUU + WULL + WULU + WUUL + WUUU ;
11322// // Step 5 Assign Real, then Imaginary Values
11323// tempR = WLLL*dataLLL_R + WLLU*dataLLU_R + WLUL*dataLUL_R + WLUU*dataLUU_R ;
11324// tempR += WULL*dataULL_R + WULU*dataULU_R + WUUL*dataUUL_R + WUUU*dataUUU_R ;
11325// //
11326// tempI = WLLL*dataLLL_I + WLLU*dataLLU_I + WLUL*dataLUL_I + WLUU*dataLUU_I ;
11327// tempI += WULL*dataULL_I + WULU*dataULU_I + WUUL*dataUUL_I + WUUU*dataUUU_I ;
11328// //
11329// // float phase = -2*pi*(kxNew*xshift+kyNew*yshift+kzNew*zshift)/ny;
11330// float tempRb=tempR*Cphase - tempI*Sphase;
11331// float tempIb=tempR*Sphase + tempI*Cphase;
11332// //
11333// des_data[2*kxN + nx* kyN +nxny*kzN] = tempRb/tempW;
11334// des_data[2*kxN+1 + nx* kyN +nxny*kzN] = tempIb/tempW;
11335 }}} // end z, y, x loops through new coordinates
11336 } // end rotations in Fourier Space 3D
11337 if ((nz > 1)&&(image -> is_complex())&&(zerocorners<=1)) {
11338 //printf("Hello 3-d complex TransformProcessor \n");
11339 float phi = t.get_rotation("eman").get("phi"); phi=pi*phi/180;
11340 float alt = t.get_rotation("eman").get("alt"); alt=pi*alt/180;
11341 float az = t.get_rotation("eman").get("az"); az=pi*az /180;
11342 Vec3f transNow= t.get_trans();
11343 float xshift= transNow[0]; float yshift= transNow[1];float zshift= transNow[2];
11344
11345 float MatXX = (cos(az)*cos(phi) - sin(az)*cos(alt)*sin(phi) );
11346 float MatXY = (- cos(az)*sin(phi) - sin(az)*cos(alt)*cos(phi) ) ;
11347 float MatXZ = sin(az)*sin(alt) ;
11348 float MatYX = (sin(az)*cos(phi) + cos(az)*cos(alt)*sin(phi) );
11349 float MatYY = (- sin(az)*sin(phi) + cos(az)*cos(alt)*cos(phi) ) ;
11350 float MatYZ = - cos(az)*sin(alt) ;
11351 float MatZX = sin(alt)*sin(phi);
11352 float MatZY = sin(alt)*cos(phi);
11353 float MatZZ = cos(alt) ;
11354 float tempR=0; float tempI=0;
11355 float Mid =(N+1.0)/2.0; // Check this
11356 float phaseConstx = -2*pi*xshift/ny ;
11357 float k1= cos(phaseConstx); float k2= sin(phaseConstx);
11358 float k3= 1.0/k1; float k4= k2/k1; // that is 1/cos and tan()
11359// float dataRLLL, dataRLLU, dataRLUL, dataRLUU;
11360// float dataRULL, dataRULU, dataRUUL, dataRUUU;
11361// float dataILLL, dataILLU, dataILUL, dataILUU;
11362// float dataIULL, dataIULU, dataIUUL, dataIUUU;
11363 int nxny = nx*ny;
11364
11365 for (int kzN = 0; kzN < ny; kzN++) {
11366 int kzNew=kzN;
11367 if (kzN >= nx/2) kzNew=kzN-N; // Step 0 Unalias new coords;
11368 for (int kyN = 0; kyN < ny; kyN++) {// moves them to lesser mag
11369 int kyNew=kyN;
11370 if (kyN>=nx/2) kyNew=kyN-ny; // Step 0 Unalias
11371 // Step 1: Do inverse Rotation to get former values, and alias Step1
11372 float kxOld = MatXY * kyNew + MatXZ *kzNew - MatXX;
11373 float kyOld = MatYY * kyNew + MatYZ*kzNew - MatYX;
11374 float kzOld = MatZY * kyNew + MatZZ*kzNew - MatZX;
11375 float phase = -2*pi*kzNew*zshift/ny-2*pi*kyNew*yshift/ny - phaseConstx ;
11376 float Cphase = cos(phase);
11377 float Sphase = sin(phase);
11378 int kx, ky,kz, II;
11379
11380 int IndexOut= -2+ nx* kyN +nxny*kzN;
11381 float OutBounds2 = (Mid*Mid- (kyOld*kyOld+kzOld*kzOld)) ;
11382
11383 int kxNewMax= nx/2;
11384 if (OutBounds2< 0) kxNewMax=0;
11385 else if (OutBounds2<(nx*nx/4)) kxNewMax=sqrt(OutBounds2);
11386 for (int kxN = kxNewMax; kxN < nx/2 ; kxN++ ) {
11387 des_data[2*kxN + nx* kyN +nxny*kzN] = 0;
11388 des_data[2*kxN + nx* kyN +nxny*kzN+1] = 0;
11389 }
11390
11391
11392 for (int kxNew = 0; kxNew < kxNewMax; kxNew++ ) {
11393/* printf(" kxNew = %d, kyNew = %d, kzNew = %d,kxOld = %3.2f, kyOld = %3.2f, kzOld = %3.2f \n",
11394 kxNew,kyNew,kzNew, kxOld, kyOld, kzOld);*/
11395
11396 IndexOut +=2;
11397
11398 kxOld += MatXX ;
11399 kyOld += MatYX ;
11400 kzOld += MatZX ;
11401 phase += phaseConstx;
11402 Cphase = Cphase*k1 -Sphase*k2; //update using trig addition; this is cos = cos cos -sin sin
11403 Sphase = Sphase*k3+ Cphase*k4; // and sin = sin (1/ cos) + cos * tan;
11404
11405 //
11406 if ((abs(kxOld)>=Mid) || (abs(kyOld)>=Mid) || (abs(kzOld)>=Mid) ) { // out of bounds
11407 des_data[IndexOut] = 0;
11408 des_data[IndexOut+1] = 0;
11409 continue;}
11410/* if (kxOld*kxOld+OutBounds> 2*Mid*Mid){ // out of bounds
11411 des_data[IndexOut] = 0;
11412 des_data[IndexOut+1] = 0;
11413 continue;} */
11414 //
11415 int kxLower= floor(kxOld);
11416 int kyLower= floor(kyOld);
11417 int kzLower= floor(kzOld);
11418 //
11419 float dkxUpper= (kxOld-kxLower);
11420 float dkyUpper= (kyOld-kyLower);
11421 float dkzUpper= (kzOld-kzLower);
11422
11423 // LLL 1
11424 kx= kxLower; ky =kyLower; kz=kzLower;
11425// dataRLLL=0; dataILLL=0;
11426// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11427 int flagLLL=1;
11428 if (kx<0) kx += N; if (ky<0) ky += N; if (kz<0) kz += N;
11429 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagLLL=-1;} // Step 3: if nec, use Friedel paired
11430 int kLLL =2*kx + nx*ky+ nxny*kz ;
11431// dataRLLL = src_data[ kLLL ];
11432// dataILLL = flagLLL*src_data[ 1 + kLLL ]; //
11433// }
11434
11435 // LLU 2
11436 kx= kxLower; ky =kyLower; kz=kzLower+1;
11437// dataRLLU=0; dataILLU=0;
11438// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11439 int flagLLU=1;
11440 if (kx<0) kx += N; if (ky<0) ky += N; if (kz<0) kz += N;
11441 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagLLU=-1;} // Step 3: if nec, use Friedel paired
11442 int kLLU =2*kx + nx*ky+ nxny*kz ;
11443// dataRLLU = src_data[ kLLU];
11444// dataILLU = flagLLU*src_data[1+kLLU];
11445// }
11446
11447 // LUL 3
11448 kx= kxLower; ky =kyLower+1; kz=kzLower;
11449// dataRLUL=0; dataILUL=0;
11450// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11451 int flagLUL=1;
11452 if (kx<0) kx += N; if (ky<0) ky += N; if (kz<0) kz += N;
11453 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagLUL=-1;} // Step 3: if nec, use Friedel paired
11454 int kLUL =2*kx + nx*ky+ nxny*kz ;
11455// dataRLUL = src_data[ kLUL];
11456// dataILUL = flagLUL*src_data[1+kLUL];
11457// }
11458
11459 // LUU 4
11460 kx= kxLower; ky =kyLower+1; kz=kzLower+1;
11461// dataRLUU=0; dataILUU=0;
11462// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11463 int flagLUU=1;
11464 if (kx<0) kx += N; if (ky<0) ky += N; if (kz<0) kz += N;
11465 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagLUU=-1;} // Step 3: if nec, use Friedel paired
11466 int kLUU =2*kx + nx*ky+ nxny*kz ;
11467// dataRLUU = src_data[ kLUU];
11468// dataILUU = flagLUU*src_data[1+kLUU];
11469// }
11470
11471 // ULL 5
11472 kx= kxLower+1; ky =kyLower; kz=kzLower;
11473// dataRULL=0; dataIULL=0;
11474// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11475 int flagULL=1;
11476 if (kx<0) kx += N; if (ky<0) ky += N; if (kz<0) kz += N;
11477 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagULL=-1;} // Step 3: if nec, use Friedel paired
11478 int kULL =2*kx + nx*ky+ nxny*kz ;
11479// dataRULL = src_data[ kULL];
11480// dataIULL = flagULL*src_data[1+kULL];
11481// }
11482
11483 // ULU 6
11484 kx= kxLower+1; ky =kyLower; kz=kzLower+1;
11485// dataRULU=0; dataIULU=0;
11486// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11487 int flagULU=1;
11488 if (kx<0) kx += N; if (ky<0) ky += N;if (kz<0) kz += N;
11489 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagULU=-1;} // Step 3: if nec, use Friedel paired
11490 int kULU =2*kx + nx*ky+ nxny*kz ;
11491// dataRULU = src_data[ kULU];
11492// dataIULU = flagULU*src_data[1+kULU];
11493// }
11494
11495 // UUL 7
11496 kx= kxLower+1; ky =kyLower+1; kz=kzLower;
11497// dataRUUL=0; dataIUUL=0;
11498// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11499 int flagUUL=1;
11500 if (kx<0) kx += N; if (ky<0) ky += N;if (kz<0) kz += N;
11501 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagUUL=-1;} // Step 3: if nec, use Friedel paired
11502 int kUUL =2*kx + nx*ky+ nxny*kz ;
11503// dataRUUL = src_data[ kUUL];
11504// dataIUUL = flagUUL*src_data[1+kUUL];
11505// }
11506
11507 // UUU 8
11508 kx= kxLower+1; ky =kyLower+1; kz=kzLower+1;
11509// dataRUUU=0; dataIUUU=0;
11510// if ( (abs(kx)<Mid) && (abs(ky)<Mid) && (abs(kz)<Mid) ) { // Step 2 Make sure to be in First BZ
11511 int flagUUU=1;
11512 if (kx<0) kx += N; if (ky<0) ky += N;if (kz<0) kz += N;
11513 if (kx> N/2){kx=N-kx;ky=(N-ky)%N;kz=(N-kz)%N; flagUUU=-1;} // Step 3: if nec, use Friedel paired
11514 int kUUU =2*kx + nx*ky+ nxny*kz ;
11515// dataRUUU = src_data[ kUUU];
11516// dataIUUU = flagUUU*src_data[1+kUUU];
11517// }
11518
11519 // Step 4 Assign Real, then Imaginary Values
11520/* printf(" kxNew = %d, kyNew = %d, kzNew = %d,kxOld = %3.2f, kyOld = %3.2f, kzOld = %3.2f \n",
11521 kxNew,kyNew,kzNew, kxOld, kyOld, kzOld);
11522 printf(" dataRLLL= %f, dataRULL = %f, dataRLUL = %f,dataRUUL = %f, dataRLLU = %f, dataRULU = %f, dataRLUU = %f, dataRUUU = %f \n",
11523 dataRLLL,dataRULL,dataRLUL, dataRUUL,dataRLLU, dataRULU,dataRLUU, dataRUUU);
11524 printf(" dataILLL= %f, dataIULL = %f, dataILUL = %f,dataIUUL = %f, dataILLU = %f, dataIULU = %f, dataILUU = %f, dataIUUU = %f \n",
11525 dataILLL,dataIULL,dataILUL, dataIUUL,dataILLU, dataIULU,dataILUU, dataIUUU);*/
11526/* printf(" kLLL= %f, kULL = %d, kLUL = %d,kUUL = %d, kLLU = %d, kULU = %d, kLUU = %d, kUUU = %d \n",
11527 kLLL,kULL,kLUL, kUUL,kLLU, kULU,kLUU, kUUU);*/
11528
11530 src_data[kLLL] , src_data[kULL],
11531 src_data[kLUL] , src_data[kUUL],
11532 src_data[kLLU] , src_data[kULU],
11533 src_data[kLUU] , src_data[kUUU],
11534 dkxUpper,dkyUpper,dkzUpper);
11535
11537 flagLLL*src_data[kLLL+1], flagULL*src_data[kULL+1],
11538 flagLUL*src_data[kLUL+1], flagUUL*src_data[kUUL+1],
11539 flagLLU*src_data[kLLU+1], flagULU*src_data[kULU+1],
11540 flagLUU*src_data[kLUU+1], flagUUU*src_data[kUUU+1],
11541 dkxUpper,dkyUpper,dkzUpper);
11542
11543 // Step 5 Apply translation
11544 float tempRb=tempR*Cphase - tempI*Sphase;
11545 float tempIb=tempR*Sphase + tempI*Cphase;
11546 //
11547 des_data[IndexOut] = tempRb;
11548 des_data[IndexOut+1] = tempIb;
11549 }}} // end z, y, x loops through new coordinates
11550 } // end rotations in Fourier Space 3D
11551 if ((nz > 1)&&(image -> is_real())) {
11552 size_t l=0, ii, k0, k1, k2, k3, k4, k5, k6, k7;
11553 Vec3f offset(nx/2,ny/2,nz/2);
11554 float x2, y2, z2, tuvx, tuvy, tuvz;
11555 int ix, iy, iz;
11556 for (int k = 0; k < nz; ++k) {
11557 for (int j = 0; j < ny; ++j) {
11558 for (int i = 0; i < nx; ++i,++l) {
11559 Vec3f coord(i-nx/2,j-ny/2,k-nz/2);
11560 Vec3f soln = inv*coord;
11561 soln += offset;
11562
11563 x2 = soln[0];
11564 y2 = soln[1];
11565 z2 = soln[2];
11566
11567 if (x2 < 0 || y2 < 0 || z2 < 0 || x2 >= nx || y2 >= ny || z2>= nz ) {
11568 des_data[l] = 0;
11569 }
11570 else {
11571 ix = Util::fast_floor(x2);
11572 iy = Util::fast_floor(y2);
11573 iz = Util::fast_floor(z2);
11574 tuvx = x2-ix;
11575 tuvy = y2-iy;
11576 tuvz = z2-iz;
11577 ii = ix + iy * nx + iz * nxy;
11578
11579 k0 = ii;
11580 k1 = k0 + 1;
11581 k2 = k0 + nx;
11582 k3 = k0 + nx+1;
11583 k4 = k0 + nxy;
11584 k5 = k1 + nxy;
11585 k6 = k2 + nxy;
11586 k7 = k3 + nxy;
11587
11588 if (ix == nx - 1) {
11589 k1--;
11590 k3--;
11591 k5--;
11592 k7--;
11593 }
11594 if (iy == ny - 1) {
11595 k2 -= nx;
11596 k3 -= nx;
11597 k6 -= nx;
11598 k7 -= nx;
11599 }
11600 if (iz == nz - 1) {
11601 k4 -= nxy;
11602 k5 -= nxy;
11603 k6 -= nxy;
11604 k7 -= nxy;
11605 }
11606
11607 des_data[l] = Util::trilinear_interpolate(src_data[k0],
11608 src_data[k1], src_data[k2], src_data[k3], src_data[k4],
11609 src_data[k5], src_data[k6], src_data[k7], tuvx, tuvy, tuvz);
11610 }
11611 }
11612 }
11613 }
11614 }
11615
11616 EXITFUNC;
11617 return des_data;
11618}
11619
11620void TransformProcessor::assert_valid_aspect(const EMData* const image) const {
11621 int ndim = image->get_ndim();
11622 if (ndim != 2 && ndim != 3) throw ImageDimensionException("Transforming an EMData only works if it's 2D or 3D");
11623
11624// if (! params.has_key("transform") ) throw InvalidParameterException("You must specify a Transform in order to perform this operation");
11625}
11626
11627//void TransformProcessor::update_emdata_attributes(EMData* const p, const Dict& attr_dict, const float& scale) const {
11628//
11629// float inv_scale = 1.0f/scale;
11630//
11631// p->scale_pixel(1.0f/scale);
11632//
11633// // According to Baker the origin attributes remain unchanged
11644//
11645// vector<string> scale_attrs;
11646// scale_attrs.push_back("apix_x");
11647// scale_attrs.push_back("apix_y");
11648// scale_attrs.push_back("apix_z");
11649//
11650//
11651// for(vector<string>::const_iterator it = scale_attrs.begin(); it != scale_attrs.end(); ++it) {
11652// if (attr_dict.has_key(*it)) {
11653// p->set_attr(*it,(float) attr_dict[*it] * inv_scale);
11654// }
11655// }
11656//
11657//}
11658
11660 ENTERFUNC;
11661
11662 assert_valid_aspect(image);
11663
11664 Transform t;
11665 if (params.has_key("transform")) t=*(Transform *)params["transform"];
11666 else {
11667 if (params.has_key("alpha")) params["phi"]=params["alpha"];
11668 float az=params.set_default("az",0.0f);
11669 float alt=params.set_default("alt",0.0f);
11670 float phi=params.set_default("phi",0.0f);
11671 float tx=params.set_default("tx",0.0f);
11672 float ty=params.set_default("ty",0.0f);
11673 float tz=params.set_default("tz",0.0f);
11674
11675 t.set_rotation(Dict("type","eman","az",az,"alt",alt,"phi",phi));
11676 t.set_trans(tx,ty,tz);
11677 }
11678
11679 EMData* p = 0;
11680#ifdef EMAN2_USING_CUDA
11681 if(EMData::usecuda == 1 && image->isrodataongpu()){
11682 //cout << "using CUDA xform" << endl;
11683 p = new EMData(0,0,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict());
11684 float * m = new float[12];
11685 Transform inv = t.inverse();
11687 image->bindcudaarrayA(true);
11688 p->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
11689 image->unbindcudaarryA();
11690 delete [] m;
11691 p->update();
11692 }
11693#endif
11694
11695 if ( p == 0 ) {
11696 float* des_data = transform(image,t);
11697 p = new EMData(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict());
11698 }
11699
11700 // all_translation += transform.get_trans();
11701
11702 float scale = t.get_scale();
11703 if (scale != 1.0) {
11704 p->scale_pixel(1.0f/scale);
11705// update_emdata_attributes(p,image->get_attr_dict(),scale);
11706 }
11707
11708 EXITFUNC;
11709 return p;
11710}
11711
11713 ENTERFUNC;
11714
11715 assert_valid_aspect(image);
11716
11717 Transform t;
11718 if (params.has_key("transform")) t=*(Transform *)params["transform"];
11719 else {
11720 if (params.has_key("alpha")) params["phi"]=params["alpha"];
11721 float az=params.set_default("az",0.0f);
11722 float alt=params.set_default("alt",0.0f);
11723 float phi=params.set_default("phi",0.0f);
11724 float tx=params.set_default("tx",0.0f);
11725 float ty=params.set_default("ty",0.0f);
11726 float tz=params.set_default("tz",0.0f);
11727
11728 t.set_rotation(Dict("type","eman","az",az,"alt",alt,"phi",phi));
11729 t.set_trans(tx,ty,tz);
11730 }
11731
11732 // all_translation += transform.get_trans();
11733 bool use_cpu = true;
11734
11735#ifdef EMAN2_USING_CUDA
11736 if(EMData::usecuda == 1 && image->isrodataongpu()){
11737 //cout << "CUDA xform inplace" << endl;
11738 image->bindcudaarrayA(false);
11739 float * m = new float[12];
11740 Transform inv = t.inverse();
11742 image->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
11743 image->unbindcudaarryA();
11744 delete [] m;
11745 use_cpu = false;
11746 image->update();
11747 }
11748#endif
11749 if ( use_cpu ) {
11750 float* des_data = transform(image,t);
11751 image->set_data(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize());
11752 image->update();
11753 }
11754 float scale = t.get_scale();
11755 if (scale != 1.0f) {
11756 image->scale_pixel(1.0f/scale);
11757// update_emdata_attributes(image,image->get_attr_dict(),scale);
11758 }
11759
11760 EXITFUNC;
11761}
11762
11763
11764void IntTranslateProcessor::assert_valid_aspect(const vector<int>& translation, const EMData* const) const {
11765 if (translation.size() == 0 ) throw InvalidParameterException("You must specify the trans argument");
11766}
11767
11768Region IntTranslateProcessor::get_clip_region(vector<int>& translation, const EMData* const image) const {
11769 unsigned int dim = static_cast<unsigned int> (image->get_ndim());
11770
11771 if ( translation.size() != dim ) {
11772 for(unsigned int i = translation.size(); i < dim; ++i ) translation.push_back(0);
11773 }
11774
11775 Region clip_region;
11776 if (dim == 1) {
11777 clip_region = Region(-translation[0],image->get_xsize());
11778 } else if ( dim == 2 ) {
11779 clip_region = Region(-translation[0],-translation[1],image->get_xsize(),image->get_ysize());
11780 } else if ( dim == 3 ) {
11781 clip_region = Region(-translation[0],-translation[1],-translation[2],image->get_xsize(),image->get_ysize(),image->get_zsize());
11782 } else throw ImageDimensionException("Only 1,2 and 3D images are supported");
11783
11784 return clip_region;
11785}
11786
11788
11789 vector<int> translation = params.set_default("trans",vector<int>() );
11790
11791
11792 assert_valid_aspect(translation,image);
11793
11794 Region clip_region = get_clip_region(translation,image);
11795
11796 image->clip_inplace(clip_region,0);
11797 // clip_inplace does the update!
11798}
11799
11801
11802 vector<int> translation = params.set_default("trans",vector<int>() );
11803
11804 assert_valid_aspect(translation,image);
11805
11806 Region clip_region = get_clip_region(translation,image);
11807
11808 return image->get_clip(clip_region,0);
11809 // clip_inplace does the update!
11810}
11811
11812
11814 int ndim = image->get_ndim();
11815 if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
11816
11817 if ( image->get_xsize() != image->get_ysize()) {
11818 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
11819 }
11820 if ( ndim == 3 ) {
11821 if ( image->get_xsize() != image->get_zsize()) {
11822 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
11823 }
11824 }
11825
11826 float scale = params.set_default("scale",0.0f);
11827 if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
11828
11829 int clip = 0;
11830
11831 if(params.has_key("clip"))
11832 {
11833 clip = params["clip"];
11834 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
11835 }
11836 else
11837 {
11838 clip = (int)(scale*image->get_xsize());
11839 }
11840
11841 Region r;
11842 if (ndim == 3) {
11843 r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
11844 } else { // ndim == 2 guaranteed by check at beginning of function
11845 r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
11846 }
11847
11848 if (scale > 1) {
11849 if ( clip != 0) {
11850 image->clip_inplace(r);
11851 }
11852 Transform t;
11853 t.set_scale(scale);
11854 image->process_inplace("xform",Dict("transform",&t));
11855 } else if (scale < 1) {
11856 Transform t;
11857 t.set_scale(scale);
11858 image->process_inplace("xform",Dict("transform",&t));
11859 if ( clip != 0) {
11860 image->clip_inplace(r);
11861 }
11862 } else {
11863 if ( clip != 0) {
11864 image->clip_inplace(r);
11865 }
11866 }
11867}
11868
11870 float pix;
11871 short x,y,z;
11872
11873 friend bool operator<(const WSsortlist& l, const WSsortlist& r) {
11874 return l.pix < r.pix;
11875 }
11876};
11877
11878// inefficient since a copy was probably already made, but best we can do
11880 EMData *tmp=process(image);
11881 memcpy(image->get_data(),tmp->get_data(),image->get_size()*sizeof(float));
11882 delete tmp;
11883}
11884
11886 //unsigned int nseg = params.set_default("nseg",12);
11887 int nseg = params.set_default("nseg",12);
11888 float thr = params.set_default("thr",0.5f);
11889 int segbymerge = params.set_default("segbymerge",0);
11890 vector<float> centers;
11891 int verbose = params.set_default("verbose",0);
11892 if (nseg<=1) throw InvalidValueException(nseg,"nseg must be greater than 1");
11893
11894 if (segbymerge) { segbymerge=nseg; nseg=4096; } // set max number of segments to a large (but not infinite) value. Too many will make connectivity matrix too big
11895
11896 EMData *ret=new EMData(image->get_xsize(),image->get_ysize(),image->get_zsize());
11897 ret->to_zero();
11898
11899
11900 int nx=image->get_xsize();
11901 int ny=image->get_ysize();
11902 int nz=image->get_zsize();
11903 if (nz==1) throw ImageDimensionException("Only 3-D data supported");
11904
11905 // Count the number of above threshold pixels
11906 size_t n2seg = 0;
11907 for (int z=1; z<nz-1; z++) {
11908 for (int y=1; y<ny-1; y++) {
11909 for (int x=1; x<nx-1; x++) {
11910 if (image->get_value_at(x,y,z)>=thr) n2seg++;
11911 }
11912 }
11913 }
11914 if (verbose) printf("%ld voxels above threshold\n",n2seg);
11915
11916 // Extract the pixels for sorting
11917 vector<WSsortlist> srt(n2seg);
11918 size_t i=0;
11919 for (int z=1; z<nz-1; z++) {
11920 for (int y=1; y<ny-1; y++) {
11921 for (int x=1; x<nx-1; x++) {
11922 if (image->get_value_at(x,y,z)>=thr) {
11923 srt[i].pix=image->get_value_at(x,y,z);
11924 srt[i].x=x;
11925 srt[i].y=y;
11926 srt[i].z=z;
11927 i++;
11928 }
11929 }
11930 }
11931 }
11932 if (verbose) printf("Voxels extracted, sorting\n");
11933
11934 // actual sort
11935 sort(srt.begin(), srt.end());
11936 if (verbose) printf("Voxels sorted (%1.4g max), starting watershed\n",srt[0].pix);
11937
11938 // now we start with the highest value and fill in the segments
11939 float cseg=1.0;
11940 int start=n2seg;
11941 for (i=0; i<n2seg; i++) {
11942 int x=srt[i].x;
11943 int y=srt[i].y;
11944 int z=srt[i].z;
11945 float lvl=0;
11946 for (int zz=z-1; zz<=z+1; zz++) {
11947 for (int yy=y-1; yy<=y+1; yy++) {
11948 for (int xx=x-1; xx<=x+1; xx++) {
11949 float v=ret->get_value_at(xx,yy,zz);
11950 if (v>lvl) lvl=v; // use the highest numbered border segment (arbitrary)
11951 }
11952 }
11953 }
11954 if (lvl==0) {
11955 if (verbose) printf("%d %d %d\t%1.0f\t%1.3g\n",x,y,z,cseg,srt[i].pix);
11956 lvl=cseg;
11957 centers.push_back(x);
11958 centers.push_back(y);
11959 centers.push_back(z);
11960 cseg+=1.0;
11961 }
11962 if (lvl>nseg) {
11963 start=i;
11964 if (verbose) printf("Requested number of segments achieved at density %1.4g\n",srt[i].pix);
11965 break;
11966 } // This means we've made as many segments as we need, so we switch to flood-filling
11967 ret->set_value_at_fast(x,y,z,lvl);
11968 }
11969
11970 // We have as many segments as we'll get, but not all voxels have been segmented, so we do a progressive flood fill in density order
11971 size_t chg=1;
11972 while (chg) {
11973 chg=0;
11974 for (i=start; i<n2seg; i++) {
11975 int x=srt[i].x;
11976 int y=srt[i].y;
11977 int z=srt[i].z;
11978 if (ret->get_value_at(x,y,z)!=0) continue; // This voxel is already done
11979
11980 float lvl=0;
11981 for (int zz=z-1; zz<=z+1; zz++) {
11982 for (int yy=y-1; yy<=y+1; yy++) {
11983 for (int xx=x-1; xx<=x+1; xx++) {
11984 float v=ret->get_value_at(xx,yy,zz);
11985 if (v>lvl) lvl=v; // use the highest numbered border segment (arbitrary)
11986 }
11987 }
11988 }
11989 if (lvl==0) continue; // we just skip voxels without any segmented neighbors
11990 ret->set_value_at_fast(x,y,z,lvl);
11991 chg+=1;
11992 }
11993 if (verbose) printf("%ld voxels changed\n",chg);
11994 }
11995 ret->set_attr("segment_centers",centers);
11996
11997 if (segbymerge) {
11998 if (cseg<segbymerge) return ret;
11999 }
12000 else if (cseg<=nseg) return ret; // We don't have too many segments, so we just return now
12001
12002 if (verbose) printf("Merging segments\n");
12003 // If requested, we now merge segments with the most surface contact until we have the correct final number
12004 if (segbymerge) {
12005 int nsegstart=(int)cseg; // Number of segments we actually generated
12006 nseg=(int)cseg;
12007 EMData *mx=new EMData(nsegstart,nsegstart,1); // This will be a "contact matrix" among segments
12008 float *mxd=mx->get_data();
12009
12010 // each cycle of the while loop, we eliminate one segment by merging
12011 int sub1=-1,sub2=-1; // sub2 will be merged into sub1
12012 nseg++; // since we don't actually remove one on the first pass, but decrement the counter
12013 while (segbymerge<nseg) {
12014 mx->to_zero();
12015
12016 for (i=0; i<n2seg; i++) {
12017 int x=srt[i].x;
12018 int y=srt[i].y;
12019 int z=srt[i].z;
12020
12021 int v1=(int)ret->get_value_at(x,y,z);
12022 if (v1==sub2) { ret->set_value_at_fast(x,y,z,sub1); v1=sub1; }
12023 mxd[v1+v1*nsegstart]++; // the diagonal is a count of the number of voxels in the segment
12024 for (int zz=z-1; zz<=z+1; zz++) {
12025 for (int yy=y-1; yy<=y+1; yy++) {
12026 for (int xx=x-1; xx<=x+1; xx++) {
12027 int v2=(int)ret->get_value_at(xx,yy,zz);
12028 if (v2==sub2) v2=sub1; // pretend that any sub2 values are actually sub1
12029 if (v1==v2) continue;
12030 mxd[v1+v2*nsegstart]+=image->get_value_at(xx,yy,zz); // We weight the connectivity by the image value
12031 }
12032 }
12033 }
12034 }
12035 mx->update();
12036 nseg--; // number of segments left
12037 if (verbose && sub1==-1) { mx->write_image("contactmx.hdf",0); } // for debugging
12038
12039 sub1=-1;
12040 sub2=-1;
12041 // contact matrix complete, now figure out which 2 segments to merge
12042 // diagonal of matrix is a count of the 'volume' of the segment. off-diagonal elements are surface area of contact region (roughly)
12043 // we want to normalize the surface area elements so they are roughly proportional to the size of the segment, so we don't merge
12044 // based on total contact area, but contact area as a fraction of the total area.
12045 float bestv=-1.0;
12046 for (int s1=1; s1<nsegstart; s1++) {
12047 for (int s2=1; s2<nsegstart; s2++) {
12048 if (s1==s2) continue; // ignore the diagonal
12049 float v=mxd[s1+s2*nsegstart];
12050 if (v==0) continue; // empty segment
12051// v/=(pow(mxd[s1+s1*nsegstart],0.6667f)+pow(mxd[s2+s2*nsegstart],0.6667f)); // normalize by the sum of the estimated surface areas (no shape effects)
12052 v/=max(mxd[s1+s1*nsegstart],mxd[s2+s2*nsegstart]); // normalize by the sum of the estimated surface areas (no shape effects)
12053 if (v>bestv) { bestv=v; sub1=s1; sub2=s2; }
12054 }
12055 }
12056 float mv=0;
12057 int mvl=0;
12058 for (i=nsegstart+1; i<nsegstart*nsegstart; i+=nsegstart+1)
12059 if (mxd[i]>mv) { mv=mxd[i]; mvl=i/nsegstart; }
12060 if (verbose) printf("Merging %d to %d (%1.0f, %d)\n",sub2,sub1,mv,mvl);
12061 if (sub1==-1) {
12062 if (verbose) printf("Unable to find segments to merge, aborting\n");
12063 break;
12064 }
12065 }
12066
12067 }
12068
12069 return ret;
12070}
12071
12073 int ndim = image->get_ndim();
12074 if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
12075
12076 if ( image->get_xsize() != image->get_ysize()) {
12077 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
12078 }
12079 if ( ndim == 3 ) {
12080 if ( image->get_xsize() != image->get_zsize()) {
12081 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
12082 }
12083 }
12084
12085 float scale = params.set_default("scale",0.0f);
12086 if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
12087
12088 int clip = 0;
12089
12090 if(params.has_key("clip"))
12091 {
12092 clip = params["clip"];
12093 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
12094 }
12095 else
12096 {
12097 clip = (int)(scale*image->get_xsize());
12098 }
12099
12100 Region r;
12101 if (ndim == 3) {
12102 r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
12103 } else { // ndim == 2 guaranteed by check at beginning of function
12104 r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
12105 }
12106
12107 EMData* ret = 0;
12108 if (scale > 1) {
12109 if ( clip != 0) {
12110 ret = image->get_clip(r);
12111 }
12112 Transform t;
12113 t.set_scale(scale);
12114 if (ret != 0) {
12115 ret->process_inplace("xform",Dict("transform",&t));
12116 } else {
12117 ret = image->process("xform",Dict("transform",&t));
12118 }
12119 } else if (scale < 1) {
12120 Transform t;
12121 t.set_scale(scale);
12122 ret = image->process("xform",Dict("transform",&t));
12123 if ( clip != 0) {
12124 ret->clip_inplace(r);
12125 }
12126 } else {
12127 if ( clip != 0) {
12128 ret = image->get_clip(r);
12129 } else {
12130 ret = image->copy();
12131 }
12132 }
12133 return ret;
12134
12135}
12136
12138 ENTERFUNC;
12139
12140
12141 if (image->get_ndim() != 2) {
12142 throw ImageDimensionException("2D only");
12143 }
12144
12145#ifdef EMAN2_USING_CUDA
12146 if (EMData::usecuda == 1 && image->getcudarwdata()) {
12147 //cout << "CUDA rotate 180" << endl;
12148 emdata_rotate_180(image->getcudarwdata(), image->get_xsize(), image->get_ysize());
12149 EXITFUNC;
12150 return;
12151 }
12152#endif
12153
12154 float *d = image->get_data();
12155 int nx = image->get_xsize();
12156 int ny = image->get_ysize();
12157
12158 // x and y offsets are used to handle even vs odd cases
12159 int x_offset = 0;
12160 if (nx % 2 == 1) x_offset=1;
12161 int y_offset = 0;
12162 if (ny % 2 == 1) y_offset=1;
12163
12164 bool stop = false;
12165 for (int x = 1; x <= (nx/2+x_offset); x++) {
12166 int y = 0;
12167 for (y = 1; y < (ny+y_offset); y++) {
12168 if (x == (nx / 2+x_offset) && y == (ny / 2+y_offset)) {
12169 stop = true;
12170 break;
12171 }
12172 int i = (x-x_offset) + (y-y_offset) * nx;
12173 int k = nx - x + (ny - y) * nx;
12174
12175 float t = d[i];
12176 d[i] = d[k];
12177 d[k] = t;
12178 }
12179 if (stop) break;
12180 }
12181
12182 /* Here we guard against irregularites that occur at the boundaries
12183 * of even dimensioned images. The basic policy is to replace the pixel
12184 * in row 0 and/or column 0 with those in row 1 and/or column 1, respectively.
12185 * The pixel at 0,0 is replaced with the pixel at 1,1 if both image dimensions
12186 * are even. FIXME - it may be better to use an average at the corner, in
12187 * this latter case, using pixels (1,1), (0,1) and (1,0). I am not sure. (dsawoolford)
12188 */
12189 if (x_offset == 0) {
12190 for (int y = 0; y < ny; y++) {
12191 image->set_value_at_fast(0,y,image->get_value_at(1,y));
12192 }
12193 }
12194
12195 if (y_offset == 0) {
12196 for (int x = 0; x < nx; x++) {
12197 image->set_value_at_fast(x,0,image->get_value_at(x,1));
12198 }
12199 }
12200
12201 if (y_offset == 0 && x_offset == 0) {
12202 image->set_value_at_fast(0,0,image->get_value_at(1,1));
12203 }
12204
12205 image->update();
12206 EXITFUNC;
12207}
12208
12209
12211{
12212
12213 if ( image->is_complex() ) throw ImageFormatException("Error: clamping processor does not work on complex images");
12214
12215 float min = params.set_default("minval",default_min);
12216 float max = params.set_default("maxval",default_max);
12217 bool tomean = params.set_default("tomean",false);
12218 bool tozero = params.set_default("tozero",false);
12219 float new_min_vals = min;
12220 float new_max_vals = max;
12221 if (tomean) new_min_vals = new_max_vals = image->get_attr("mean");
12222 if (tozero) new_min_vals = new_max_vals = 0.0;
12223
12224 // Okay, throwing such an error is probably overkill - but atleast the user will get a loud message
12225 // saying what went wrong.
12226 if ( max < min ) throw InvalidParameterException("Error: minval was greater than maxval, aborting");
12227
12228 size_t size = image->get_size();
12229 for(size_t i = 0; i < size; ++i )
12230 {
12231 float * data = &image->get_data()[i];
12232 if ( *data < min ) *data = new_min_vals;
12233 else if ( *data > max ) *data = new_max_vals;
12234 }
12235 image->update();
12236}
12237
12238void TestTomoImage::insert_rectangle( EMData* image, const Region& region, const float& value, const Transform& t3d )
12239{
12240 int startx = (int)region.origin[0] - (int)region.size[0]/2;
12241 int starty = (int)region.origin[1] - (int)region.size[1]/2;
12242 int startz = (int)region.origin[2] - (int)region.size[2]/2;
12243
12244 int endx = (int)region.origin[0] + (int)region.size[0]/2;
12245 int endy = (int)region.origin[1] + (int)region.size[1]/2;
12246 int endz = (int)region.origin[2] + (int)region.size[2]/2;
12247
12248 if ( ! t3d.is_identity() ) {
12249 float xt, yt, zt;
12250 for ( float z = (float)startz; z < (float)endz; z += 0.25f ) {
12251 for ( float y = (float)starty; y < (float)endy; y += 0.25f ) {
12252 for ( float x = (float)startx; x < (float)endx; x += 0.25f ) {
12253 xt = (float) x - region.origin[0];
12254 yt = (float) y - region.origin[1];
12255 zt = (float) z - region.origin[2];
12256 Vec3f v((float)xt,(float)yt,(float)zt);
12257 v = t3d*v;
12258 image->set_value_at((int)(v[0]+region.origin[0]),(int)(v[1]+region.origin[1]),(int)(v[2]+region.origin[2]), value);
12259 }
12260 }
12261 }
12262 } else {
12263 for ( int z = startz; z < endz; ++z ) {
12264 for ( int y = starty; y < endy; ++y ) {
12265 for ( int x = startx; x < endx; ++x ) {
12266 image->set_value_at(x,y,z, value);
12267 }
12268 }
12269 }
12270 }
12271}
12272
12274{
12275 //float nx = 240;
12276 //float ny = 240;
12277 //float nz = 60;
12278
12279 //image->set_size((int)nx,(int)ny,(int)nz);
12280 float nx = (float) image->get_xsize();
12281 float ny = (float) image->get_ysize();
12282 float nz = (float) image->get_zsize();
12283
12284 // This increment is used to simplified positioning
12285 // It's an incremental factor that matches the grid size of the paper
12286 // that I drew this design on before implementing it in code
12287 float inc = 1.0f/22.0f;
12288 float xinc = inc;
12289 float yinc = inc;
12290 float zinc = inc;
12291
12292 Dict d;
12293 d["a"] = (float) .4*nx+3;
12294 d["b"] = (float) .4*ny+3;
12295 d["c"] = (float) .4*nz+3;
12296 d["fill"] = 0.2;
12297 image->process_inplace("testimage.ellipsoid",d);
12298
12299 d["a"] = (float) .4*nx;
12300 d["b"] = (float) .4*ny;
12301 d["c"] = (float) .4*nz;
12302 d["fill"] = 0.1;
12303 image->process_inplace("testimage.ellipsoid",d);
12304
12305 // Center x, center z, bottom y ellipsoids that grow progessively smaller
12306 {
12307 Transform t;
12308 t.set_trans(0.,ny*4.0f*yinc-ny/2,0);
12309 Dict d;
12310 d["transform"] = &t;
12311 d["a"] = (float) 2.*xinc*nx;
12312 d["b"] = (float)0.5*yinc*ny;
12313 d["c"] = (float) 1.*zinc*nz;
12314 d["fill"] = 0.3;
12315 image->process_inplace("testimage.ellipsoid",d);
12316 }
12317
12318 {
12319 Transform t;
12320 t.set_trans(0.,ny*5.5f*yinc-ny/2,0);
12321 Dict d;
12322 d["transform"] = &t;
12323 d["a"] = (float) 1.5*xinc*nx;
12324 d["b"] = (float)0.5*yinc*ny;
12325 d["c"] = (float) 1.*zinc*nz;
12326 d["fill"] = 0.0;
12327 image->process_inplace("testimage.ellipsoid",d);
12328 }
12329 {
12330 Transform t;
12331 t.set_trans(0.,ny*7*yinc-ny/2,0);
12332 Dict d;
12333 d["transform"] = &t;
12334 d["a"] = (float) 1.*xinc*nx;
12335 d["b"] = (float)0.5*yinc*ny;
12336 d["c"] = (float) 1.*zinc*nz;
12337 d["fill"] = 0.3;
12338 image->process_inplace("testimage.ellipsoid",d);
12339 }
12340
12341
12342 {
12343 Transform t;
12344 t.set_trans(0.,ny*8.5f*yinc-ny/2,0);
12345 Dict d;
12346 d["transform"] = &t;
12347 d["a"] = (float) .75*xinc*nx;
12348 d["b"] = (float)0.5*yinc*ny;
12349 d["c"] = (float) 1.*zinc*nz;
12350 d["fill"] = 0.0;
12351 image->process_inplace("testimage.ellipsoid",d);
12352 }
12353
12354 // Center x, center z, bottom y ellipsoids that grow progessively smaller
12355 {
12356 Transform t;
12357 t.set_trans(0.,ny*18*yinc-ny/2,0);
12358 Dict d;
12359 d["transform"] = &t;
12360 d["a"] = (float) 2*xinc*nx;
12361 d["b"] = (float)0.5*yinc*ny;
12362 d["c"] = (float) 1.*zinc*nz;
12363 d["fill"] = 0.3;
12364 image->process_inplace("testimage.ellipsoid",d);
12365 }
12366
12367 {
12368 Transform t;
12369 t.set_trans(0.,ny*16.5f*yinc-ny/2,0);
12370 Dict d;
12371 d["transform"] = &t;
12372 d["a"] = (float) 1.5*xinc*nx;
12373 d["b"] = (float)0.5*yinc*ny;
12374 d["c"] = (float) 1.*zinc*nz;
12375 d["fill"] = 0.3;
12376 image->process_inplace("testimage.ellipsoid",d);
12377 }
12378
12379 {
12380 Transform t;
12381 t.set_trans(0.,ny*15*yinc-ny/2,0);
12382 Dict d;
12383 d["transform"] = &t;
12384 d["a"] = (float) 1*xinc*nx;
12385 d["b"] = (float)0.5*yinc*ny;
12386 d["c"] = (float) 1.*zinc*nz;
12387 d["fill"] = 0.3f;
12388 image->process_inplace("testimage.ellipsoid",d);
12389 }
12390
12391 {
12392 Transform t;
12393 t.set_trans(0.,ny*13.5f*yinc-ny/2,0);
12394 Dict d;
12395 d["transform"] = &t;
12396 d["a"] = (float).75*xinc*nx;
12397 d["b"] = (float)0.5*yinc*ny;
12398 d["c"] = (float) 1.*zinc*nz;
12399 d["fill"] = 0.3;
12400 image->process_inplace("testimage.ellipsoid",d);
12401 }
12402
12403 // Left ellipsoids from the bottom up
12404 {
12405
12406 Transform t;
12407 t.set_trans(nx*6*xinc-nx/2,ny*5*yinc-ny/2,0);
12408 Dict d;
12409 d["transform"] = &t;
12410 d["a"] = (float)1*xinc*nx;
12411 d["b"] = (float).75*yinc*ny;
12412 d["c"] = (float) .75*zinc*nz;
12413 d["fill"] = 0.25;
12414 image->process_inplace("testimage.ellipsoid",d);
12415 }
12416
12417 {
12418 Transform t;
12419 t.set_trans(nx*6*xinc-nx/2,ny*7*yinc-ny/2,0);
12420 Dict d;
12421 d["transform"] = &t;
12422 d["a"] = (float)1.5*xinc*nx;
12423 d["b"] = (float).75*yinc*ny;
12424 d["c"] = (float) .75*zinc*nz;
12425 d["fill"] = 0.25;
12426 image->process_inplace("testimage.ellipsoid",d);
12427 }
12428
12429 {
12430 Transform t;
12431 t.set_trans(nx*6*xinc-nx/2,ny*9*yinc-ny/2,0);
12432 Dict d;
12433 d["transform"] = &t;
12434 d["a"] = (float)2*xinc*nx;
12435 d["b"] = (float).75*yinc*ny;
12436 d["c"] = (float) .75*zinc*nz;
12437 d["fill"] = 0.25;
12438 image->process_inplace("testimage.ellipsoid",d);
12439 }
12440
12441 {
12442 Transform t;
12443 t.set_trans(nx*6*xinc-nx/2,ny*11*yinc-ny/2,0);
12444 Dict d;
12445 d["transform"] = &t;
12446 d["a"] = (float)2.5*xinc*nx;
12447 d["b"] = (float).75*yinc*ny;
12448 d["c"] = (float) 1*zinc*nz;
12449 d["fill"] = 0.25;
12450 image->process_inplace("testimage.ellipsoid",d);
12451 }
12452
12453 {
12454 Transform t;
12455 t.set_trans(nx*6*xinc-nx/2,ny*13*yinc-ny/2,0);
12456 Dict d;
12457 d["transform"] = &t;
12458 d["a"] = (float) 3*xinc*nx;
12459 d["b"] = (float).75*yinc*ny;
12460 d["c"] = (float) 1*zinc*nz;
12461 d["fill"] = 0.25;
12462 image->process_inplace("testimage.ellipsoid",d);
12463 }
12464
12465 // Right rectangle from the top down
12466 {
12467 Region region(nx*15.*inc,ny*17.*inc,nz/2.,1.*inc*nx,1.5*inc*ny,1.5*inc*nz);
12468 insert_rectangle(image, region, 0.25);
12469 }
12470 {
12471 Region region(nx*15.*inc,ny*15.*inc,nz/2.,1.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
12472 insert_rectangle(image, region, 0.25);
12473 }
12474 {
12475 Region region(nx*15.*inc,ny*13.*inc,nz/2.,2.*inc*nx,1.5*inc*ny,1.5*inc*nz);
12476 insert_rectangle(image, region, 0.25);
12477 }
12478 {
12479 Region region(nx*15.*inc,ny*11.*inc,nz/2.,2.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
12480 insert_rectangle(image, region, 0.25);
12481 }
12482 {
12483 Region region(nx*15.*inc,ny*9.*inc,nz/2.,3.*inc*nx,1.5*inc*ny,1.5*inc*nz);
12484 insert_rectangle(image, region, 0.25);
12485 }
12486
12487 // Center rotated rectangle
12488 {
12489 Region region(nx/2.,ny/2.,nz/2.,2.*inc*nx,2.5*inc*ny,1.*inc*nz);
12490 Transform t3d(Dict("type","eman","az",(float)-25.0));
12491 insert_rectangle(image, region, 0.4f, t3d);
12492 }
12493
12494 // Rotated ellipsoids
12495 {
12496 Transform t;
12497 t.set_trans(nx*6.8f*xinc-nx/2,ny*16*yinc-ny/2,0);
12498 Dict rot;
12499 rot["type"] = "eman";
12500 rot["az"] = 43.0f;
12501 t.set_rotation(rot);
12502 Dict d;
12503 d["transform"] = &t;
12504 d["a"] = (float) 1.5*xinc*nx;
12505 d["b"] = (float) .5*yinc*ny;
12506 d["c"] = (float) .5*zinc*nz;
12507 d["fill"] = 0.2;
12508 image->process_inplace("testimage.ellipsoid",d);
12509 }
12510 {
12511 Transform t;
12512 t.set_trans(nx*7.2f*xinc-nx/2,ny*16*yinc-ny/2,0);
12513 Dict rot;
12514 rot["type"] = "eman";
12515 rot["az"] = 135.0f;
12516 t.set_rotation(rot);
12517 Dict d;
12518 d["transform"] = &t;
12519 d["a"] = (float) 1.5*xinc*nx;
12520 d["b"] = (float) .5*yinc*ny;
12521 d["c"] = (float) .5*zinc*nz;
12522 d["fill"] = 0.3;
12523 image->process_inplace("testimage.ellipsoid",d);
12524 }
12525
12526 // Dense small ellipsoids
12527 {
12528 Transform t;
12529 t.set_trans(nx*3.5f*xinc-nx/2,ny*8*yinc-ny/2,0);
12530 Dict d;
12531 d["transform"] = &t;
12532 d["a"] = (float) .5*xinc*nx;
12533 d["b"] = (float) .5*yinc*ny;
12534 d["c"] = (float) .5*zinc*nz;
12535 d["fill"] = 2.05;
12536 image->process_inplace("testimage.ellipsoid",d);
12537
12538 t.set_trans(nx*8*xinc-nx/2,ny*18*yinc-ny/2,0);
12539 image->process_inplace("testimage.ellipsoid",d);
12540
12541 t.set_trans(nx*14*xinc-nx/2,ny*18.2f*yinc-ny/2,0);
12542 image->process_inplace("testimage.ellipsoid",d);
12543
12544 t.set_trans(nx*18*xinc-nx/2,ny*14*yinc-ny/2,0);
12545 image->process_inplace("testimage.ellipsoid",d);
12546
12547 t.set_trans(nx*17*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
12548 image->process_inplace("testimage.ellipsoid",d);
12549 }
12550
12551
12552 // Dense small rectangles
12553 {
12554 Region region(nx*18.*inc,ny*11.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
12555 Transform t3d(Dict("type","eman","az",(float)45.0));
12556 insert_rectangle(image, region, 1.45f, t3d);
12557 }
12558 {
12559 Region region(nx*3.*inc,ny*10.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
12560 Transform t3d(Dict("type","eman","az",(float)45.0));
12561 insert_rectangle(image, region, 1.45f, t3d);
12562 }
12563
12564 // Insert small cluster of spheres
12565 {
12566 Transform t;
12567 t.set_trans(nx*14*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
12568 Dict d;
12569 d["transform"] = &t;
12570 d["a"] = (float) .5*xinc*nx;
12571 d["b"] = (float) .5*yinc*ny;
12572 d["c"] = (float) .5*zinc*nz;
12573 d["fill"] = .35;
12574 image->process_inplace("testimage.ellipsoid",d);
12575 }
12576 {
12577 Transform t;
12578 t.set_trans(nx*15*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
12579 Dict d;
12580 d["transform"] = &t;
12581 d["a"] = (float) .25*xinc*nx;
12582 d["b"] = (float) .25*yinc*ny;
12583 d["c"] = (float) .25*zinc*nz;
12584 d["fill"] = .35;
12585 image->process_inplace("testimage.ellipsoid",d);
12586
12587 t.set_trans(nx*13.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
12588 image->process_inplace("testimage.ellipsoid",d);
12589
12590 t.set_trans(nx*14.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
12591 image->process_inplace("testimage.ellipsoid",d);
12592
12593 t.set_trans(nx*15.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
12594 image->process_inplace("testimage.ellipsoid",d);
12595
12596 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
12597 image->process_inplace("testimage.ellipsoid",d);
12598
12599 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
12600 image->process_inplace("testimage.ellipsoid",d);
12601
12602 t.set_trans(nx*15*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
12603 image->process_inplace("testimage.ellipsoid",d);
12604
12605 t.set_trans(nx*16*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
12606 image->process_inplace("testimage.ellipsoid",d);
12607
12608 t.set_trans(nx*14.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
12609 image->process_inplace("testimage.ellipsoid",d);
12610
12611 t.set_trans(nx*15.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
12612 image->process_inplace("testimage.ellipsoid",d);
12613 }
12614 // Insert feducials around the outside of the "cell"
12615// for ( float i = 0.; i < 3.; i += 1. ) {
12616// for ( float j = 0.; j < 3.; j += 1. ) {
12617// Region region(nx*2.+i*inc,ny*2.+j*inc,nz/2.,0.05*inc*nx,0.05*inc*ny,0.05*inc*nz);
12618// insert_solid_ellipse(image, region, 2.0);
12619// }
12620// }
12621
12622}
12623
12625{
12626 float nsigma = params.set_default("nsigma",default_sigma);
12627 float sigma = image->get_attr("sigma");
12628 float mean = image->get_attr("mean");
12629 params.put("minval",mean - nsigma*sigma);
12630 params.put("maxval",mean + nsigma*sigma);
12631
12633}
12634
12636{
12637 float min = image->get_attr("minimum");
12638 float max = image->get_attr("maximum");
12639 float nbins = (float)params.set_default("nbins",default_bins);
12640 bool debug = params.set_default("debug",false);
12641
12642 vector<int> debugscores;
12643 if ( debug ) {
12644 debugscores = vector<int>((int)nbins, 0);
12645 }
12646
12647 if ( nbins < 0 ) throw InvalidParameterException("nbins must be greater than 0");
12648
12649 float bin_width = (max-min)/nbins;
12650 float bin_val_offset = bin_width/2.0f;
12651
12652 size_t size = image->get_size();
12653 float* dat = image->get_data();
12654
12655 for(size_t i = 0; i < size; ++i ) {
12656 float val = dat[i];
12657 val -= min;
12658 int bin = (int) (val/bin_width);
12659
12660 // This makes the last interval [] and not [)
12661 if (bin == nbins) bin -= 1;
12662
12663 dat[i] = min + bin*bin_width + bin_val_offset;
12664 if ( debug ) {
12665 debugscores[bin]++;
12666 }
12667 }
12668
12669 if ( debug ) {
12670 int i = 0;
12671 for( vector<int>::const_iterator it = debugscores.begin(); it != debugscores.end(); ++it, ++i)
12672 cout << "Bin " << i << " has " << *it << " pixels in it" << endl;
12673 }
12674
12675}
12677{
12678 //bool complexflag = false;
12679 EMData* null = 0;
12680 EMData* with = params.set_default("with", null);
12681 if ( with == NULL ) throw InvalidParameterException("Error - the image required for the convolution is null");
12682
12683 EMData* newimage = fourierproduct(image, with, CIRCULANT, CONVOLUTION, false);
12684
12685 float* orig = image->get_data();
12686 float* work = newimage->get_data();
12687 int nx = image->get_xsize();
12688 int ny = image->get_ysize();
12689 int nz = image->get_zsize();
12690 memcpy(orig,work,nx*ny*nz*sizeof(float));
12691 image->update();
12692
12693 delete newimage;
12694}
12695
12697{
12698 if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
12699
12700 EMData* e = new EMData();
12701 int nx = image->get_xsize();
12702 int ny = image->get_ysize();
12703 int nz = image->get_zsize();
12704
12705 if ( nz == 1 && ny == 1 ) {
12706 if ( nx < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
12707
12708 e->set_size(3,1,1);
12709 e->set_value_at(0,-1);
12710 e->set_value_at(2, 1);
12711
12712 Region r = Region(-nx/2+1,nx);
12713 e->clip_inplace(r);
12714 } else if ( nz == 1 ) {
12715 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
12716 e->set_size(3,3,1);
12717 e->set_value_at(0,0,-1);
12718 e->set_value_at(0,1,-2);
12719 e->set_value_at(0,2,-1);
12720
12721 e->set_value_at(2,0,1);
12722 e->set_value_at(2,1,2);
12723 e->set_value_at(2,2,1);
12724 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
12725 e->clip_inplace(r);
12726 } else {
12727 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
12728 e->set_size(3,3,3);
12729 e->set_value_at(0,0,0,-1);
12730 e->set_value_at(0,1,0,-1);
12731 e->set_value_at(0,2,0,-1);
12732 e->set_value_at(0,0,1,-1);
12733 e->set_value_at(0,1,1,-8);
12734 e->set_value_at(0,2,1,-1);
12735 e->set_value_at(0,0,2,-1);
12736 e->set_value_at(0,1,2,-1);
12737 e->set_value_at(0,2,2,-1);
12738
12739 e->set_value_at(2,0,0,1);
12740 e->set_value_at(2,1,0,1);
12741 e->set_value_at(2,2,0,1);
12742 e->set_value_at(2,0,1,1);
12743 e->set_value_at(2,1,1,8);
12744 e->set_value_at(2,2,1,1);
12745 e->set_value_at(2,0,2,1);
12746 e->set_value_at(2,1,2,1);
12747 e->set_value_at(2,2,2,1);
12748
12749 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
12750 e->clip_inplace(r);
12751 }
12752
12753 Dict conv_parms;
12754 conv_parms["with"] = e;
12755 image->process_inplace("math.convolution", conv_parms);
12756 image->process_inplace("xform.phaseorigin.tocenter");
12757
12758 delete e;
12759}
12760
12761
12763{
12764 bool fim = params.set_default("angle_fim", false);
12765 float alt;
12766 if ( fim ) {
12767 alt = image->get_attr("euler_alt");
12768 }
12769 else alt = params.set_default("angle", 0.0f);
12770
12771 float cosine = cos(alt*M_PI/180.0f);
12772 float mult_fac = 1.0f/(cosine);
12773 image->mult( mult_fac );
12774}
12775
12777{
12778 bool biedgemean = params.set_default("biedgemean", false);
12779 bool edgemean = params.set_default("edgemean", false);
12780 // You can only do one of these - so if someone specifies them both the code complains loudly
12781 if (biedgemean && edgemean) throw InvalidParameterException("The edgemean and biedgemean options are mutually exclusive");
12782
12783 bool fim = params.set_default("angle_fim", false);
12784 float alt;
12785 if ( fim ) {
12786 Transform* t = (Transform*)image->get_attr("xform.projection");
12787 Dict d = t->get_params("eman");
12788 alt = (float) d["alt"];
12789 if(t) {delete t; t=0;}
12790 }
12791 else alt = params.set_default("angle", 0.0f);
12792
12793
12794 float cosine = cos(alt*M_PI/180.0f);
12795
12796 // Zero the edges
12797 int nx = image->get_xsize();
12798 int ny = image->get_ysize();
12799 int x_clip = static_cast<int>( (float) nx * ( 1.0 - cosine ) / 2.0);
12800
12801 float x1_edge_mean = 0.0;
12802 float x2_edge_mean = 0.0;
12803
12804 if ( biedgemean )
12805 {
12806 float edge_mean = 0.0;
12807
12808 // Accrue the pixel densities on the side strips
12809 for ( int i = 0; i < ny; ++i ) {
12810 edge_mean += image->get_value_at(x_clip, i );
12811 edge_mean += image->get_value_at(nx - x_clip-1, i );
12812 }
12813 // Now make it so the mean is stored
12814 edge_mean /= 2*ny;
12815
12816 // Now shift pixel values accordingly
12817 for ( int i = 0; i < ny; ++i ) {
12818 for ( int j = nx-1; j >= nx - x_clip; --j) {
12819 image->set_value_at(j,i,edge_mean);
12820 }
12821 for ( int j = 0; j < x_clip; ++j) {
12822 image->set_value_at(j,i,edge_mean);
12823 }
12824 }
12825 x1_edge_mean = edge_mean;
12826 x2_edge_mean = edge_mean;
12827 }
12828 else if (edgemean)
12829 {
12830 for ( int i = 0; i < ny; ++i ) {
12831 x1_edge_mean += image->get_value_at(x_clip, i );
12832 x2_edge_mean += image->get_value_at(nx - x_clip-1, i );
12833 }
12834 x1_edge_mean /= ny;
12835 x2_edge_mean /= ny;
12836
12837 for ( int i = 0; i < ny; ++i ) {
12838 for ( int j = 0; j < x_clip; ++j) {
12839 image->set_value_at(j,i,x1_edge_mean);
12840 }
12841 for ( int j = nx-1; j >= nx - x_clip; --j) {
12842 image->set_value_at(j,i,x2_edge_mean);
12843 }
12844 }
12845 }
12846 else
12847 {
12848 // The edges are just zeroed -
12849 Dict zero_dict;
12850 zero_dict["x0"] = x_clip;
12851 zero_dict["x1"] = x_clip;
12852 zero_dict["y0"] = 0;
12853 zero_dict["y1"] = 0;
12854 image->process_inplace( "mask.zeroedge2d", zero_dict );
12855 }
12856
12857 int gauss_rad = params.set_default("gauss_falloff", 0);
12858 if ( gauss_rad != 0)
12859 {
12860 // If the gaussian falloff distance is greater than x_clip, it will technically
12861 // go beyond the image boundaries. Thus we clamp gauss_rad so this cannot happen.
12862 // Therefore, there is potential here for (benevolent) unexpected behavior.
12863 if ( gauss_rad > x_clip ) gauss_rad = x_clip;
12864
12865 float gauss_sigma = params.set_default("gauss_sigma", 3.0f);
12866 if ( gauss_sigma < 0 ) throw InvalidParameterException("Error - you must specify a positive, non-zero gauss_sigma");
12867 float sigma = (float) gauss_rad/gauss_sigma;
12868
12869 GaussianFunctoid gf(sigma);
12870
12871 for ( int i = 0; i < ny; ++i ) {
12872
12873 float left_value = image->get_value_at(x_clip, i );
12874 float scale1 = left_value-x1_edge_mean;
12875
12876 float right_value = image->get_value_at(nx - x_clip - 1, i );
12877 float scale2 = right_value-x2_edge_mean;
12878
12879 for ( int j = 1; j < gauss_rad; ++j )
12880 {
12881 image->set_value_at(x_clip-j, i, scale1*gf((float)j)+x1_edge_mean );
12882 image->set_value_at(nx - x_clip + j-1, i, scale2*gf((float)j)+x2_edge_mean);
12883 }
12884 }
12885 }
12886
12887 image->update();
12888}
12889
12891{
12892 if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
12893
12894 EMData* e = new EMData();
12895 int nx = image->get_xsize();
12896 int ny = image->get_ysize();
12897 int nz = image->get_zsize();
12898
12899 if ( nz == 1 && ny == 1 ) {
12900 throw ImageDimensionException("Error - cannot detect Y edges for an image that that is 1D!");
12901 } else if ( nz == 1 ) {
12902 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
12903 e->set_size(3,3,1);
12904 e->set_value_at(0,0,-1);
12905 e->set_value_at(1,0,-2);
12906 e->set_value_at(2,0,-1);
12907
12908 e->set_value_at(0,2,1);
12909 e->set_value_at(1,2,2);
12910 e->set_value_at(2,2,1);
12911 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
12912 e->clip_inplace(r);
12913 } else {
12914 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
12915 e->set_size(3,3,3);
12916 e->set_value_at(0,0,0,-1);
12917 e->set_value_at(1,0,0,-1);
12918 e->set_value_at(2,0,0,-1);
12919 e->set_value_at(0,0,1,-1);
12920 e->set_value_at(1,0,1,-8);
12921 e->set_value_at(2,0,1,-1);
12922 e->set_value_at(0,0,2,-1);
12923 e->set_value_at(1,0,2,-1);
12924 e->set_value_at(2,0,2,-1);
12925
12926 e->set_value_at(0,2,0,1);
12927 e->set_value_at(1,2,0,1);
12928 e->set_value_at(2,2,0,1);
12929 e->set_value_at(0,2,1,1);
12930 e->set_value_at(1,2,1,8);
12931 e->set_value_at(2,2,1,1);
12932 e->set_value_at(0,2,2,1);
12933 e->set_value_at(1,2,2,1);
12934 e->set_value_at(2,2,2,1);
12935
12936 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
12937 e->clip_inplace(r);
12938 }
12939
12940 Dict conv_parms;
12941 conv_parms["with"] = e;
12942 image->process_inplace("math.convolution", conv_parms);
12943 image->process_inplace("xform.phaseorigin.tocenter");
12944
12945 delete e;
12946}
12947
12949{
12950 if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
12951
12952 EMData* e = new EMData();
12953 int nx = image->get_xsize();
12954 int ny = image->get_ysize();
12955 int nz = image->get_zsize();
12956
12957 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");
12958
12959 e->set_size(3,3,3);
12960 e->set_value_at(0,0,0,-1);
12961 e->set_value_at(1,0,0,-1);
12962 e->set_value_at(2,0,0,-1);
12963 e->set_value_at(0,1,0,-1);
12964 e->set_value_at(1,1,0,-8);
12965 e->set_value_at(2,1,0,-1);
12966 e->set_value_at(0,2,0,-1);
12967 e->set_value_at(1,2,0,-1);
12968 e->set_value_at(2,2,0,-1);
12969
12970 e->set_value_at(0,0,2,1);
12971 e->set_value_at(1,0,2,1);
12972 e->set_value_at(2,0,2,1);
12973 e->set_value_at(0,1,2,1);
12974 e->set_value_at(1,1,2,8);
12975 e->set_value_at(2,1,2,1);
12976 e->set_value_at(0,2,2,1);
12977 e->set_value_at(1,2,2,1);
12978 e->set_value_at(2,2,2,1);
12979
12980 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
12981 e->clip_inplace(r);
12982
12983 Dict conv_parms;
12984 conv_parms["with"] = e;
12985 image->process_inplace("math.convolution", conv_parms);
12986 image->process_inplace("xform.phaseorigin.tocenter");
12987
12988 delete e;
12989}
12990
12992{
12993 EMData* d = new EMData();
12994 d = image->process("math.edge.xgradient");
12995 image->process_inplace("math.edge.ygradient");
12996 image->add(*d);
12997 image->process_inplace("normalize");
12998 delete d;
12999}
13000
13002{
13003 EMData* d = new EMData();
13004 image->process_inplace("math.edge.xgradient");
13005 image->process_inplace("math.squared");
13006 d = image->process("math.edge.ygradient");
13007 image->addsquare(*d);
13008 image->process_inplace("math.sqrt");
13009 delete d;
13010}
13011
13013{
13014 EMData* d = new EMData();
13015 int size = image->get_xsize() * image->get_ysize();
13016 image->process_inplace("math.edge.xgradient");
13017 d = image->process("math.edge.ygradient");
13018 for ( int i = 0; i < size; ++i ) {
13019 image->set_value_at_index(i,atan2(d->get_value_at_index(i),image->get_value_at_index(i)));
13020 }
13021 delete d;
13022}
13023
13025{
13026 EMData* d = new EMData();
13027 image->process_inplace("math.edge.xgradient");
13028 image->process_inplace("math.edge.xgradient");
13029 image->process_inplace("math.squared");
13030 d = image->process("math.edge.ygradient");
13031 d->process_inplace("math.edge.ygradient");
13032 image->addsquare(*d);
13033 image->process_inplace("math.sqrt");
13034 delete d;
13035}
13036
13038{
13039 EMData* d = new EMData();
13040 int size = image->get_xsize() * image->get_ysize();
13041 image->process_inplace("math.edge.xgradient");
13042 image->process_inplace("math.edge.xgradient");
13043 image->process_inplace("math.squared");
13044 d = image->process("math.edge.ygradient");
13045 d->process_inplace("math.edge.ygradient");
13046 for ( int i = 0; i < size; ++i ) {
13047 image->set_value_at_index(i,atan2(d->get_value_at_index(i),image->get_value_at_index(i)));
13048 }
13049 delete d;
13050}
13051
13053{
13054 EMData* dx = new EMData();
13055 EMData* dy = new EMData();
13056 EMData* dxdx = new EMData();
13057 EMData* dxdy = new EMData();
13058 EMData* dydy = new EMData();
13059
13060 dx = image->process("math.edge.xgradient");
13061 dy = image->process("math.edge.ygradient");
13062 dxdx = dx->process("math.edge.xgradient");
13063 dxdy = dx->process("math.edge.ygradient");
13064 dydy = dy->process("math.edge.ygradient");
13065
13066 dxdx->mult(*dx);
13067 dxdx->mult(*dx);
13068
13069 dxdy->mult(2);
13070 dxdy->mult(*dx);
13071 dxdy->mult(*dy);
13072
13073 dydy->mult(*dx);
13074 dydy->mult(*dy);
13075
13076 dx->mult(*dx);
13077 dx->addsquare(*dy);
13078
13079 image->to_zero();
13080 image->add(*dxdx);
13081 image->add(*dxdy);
13082 image->add(*dydy);
13083 image->div(*dx);
13084}
13085
13087{
13088 dump_factory < Processor > ();
13089}
13090
13091map<string, vector<string> > EMAN::dump_processors_list()
13092{
13093 return dump_factory_list < Processor > ();
13094}
13095
13096map<string, vector<string> > EMAN::group_processors()
13097{
13098 map<string, vector<string> > processor_groups;
13099
13100 vector <string> processornames = Factory<Processor>::get_list();
13101
13102 for (size_t i = 0; i < processornames.size(); i++) {
13103 Processor * f = Factory<Processor>::get(processornames[i]);
13104 if (dynamic_cast<RealPixelProcessor*>(f) != 0) {
13105 processor_groups["RealPixelProcessor"].push_back(f->get_name());
13106 }
13107 else if (dynamic_cast<BoxStatProcessor*>(f) != 0) {
13108 processor_groups["BoxStatProcessor"].push_back(f->get_name());
13109 }
13110 else if (dynamic_cast<ComplexPixelProcessor*>(f) != 0) {
13111 processor_groups["ComplexPixelProcessor"].push_back(f->get_name());
13112 }
13113 else if (dynamic_cast<CoordinateProcessor*>(f) != 0) {
13114 processor_groups["CoordinateProcessor"].push_back(f->get_name());
13115 }
13116 else if (dynamic_cast<FourierProcessor*>(f) != 0) {
13117 processor_groups["FourierProcessor"].push_back(f->get_name());
13118 }
13119 else if (dynamic_cast<NewFourierProcessor*>(f) != 0) {
13120 processor_groups["FourierProcessor"].push_back(f->get_name());
13121 }
13122 else if (dynamic_cast<NormalizeProcessor*>(f) != 0) {
13123 processor_groups["NormalizeProcessor"].push_back(f->get_name());
13124 }
13125 else {
13126 processor_groups["Others"].push_back(f->get_name());
13127 }
13128 }
13129
13130 return processor_groups;
13131}
13132
13133
13134
13135float ModelHelixProcessor::radprofile(float r, int type)
13136//Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
13137{
13138 // r in angstrom
13139 double ret = 0;//iterations ==> rounding is problematic with float types if 15 < r < 20 and really bad if 20 < r < 30
13140 if (type == 0) { // pure Gaussian falloff
13141 r /= 2;
13142 ret = exp(-r * r);
13143 } else if (type == 1) { // pure Gaussian falloff + negative dip, so mean is 0
13144 r /= 2;
13145 ret = (1 - r * r / 4) * exp(-r * r / 4);
13146 } else if (type == 2) {
13147 // polynomial fitting to the radial profile of real helix density
13148 // f=a0*x^n+a1+x^(n-1)+ ... +a[n-1]*x+an
13149 //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};
13150
13151 // now the fitting to the original profile
13152 if (r >= 12.2)
13153 return 0; //We don't want that part of the polynomial --> goes way below zero
13154 static float an[15] = { -3.9185246832229140e-16f,
13155 3.3957205298900993e-14f, 2.0343351971222658e-12f,
13156 -4.4935965816879751e-10f, 3.0668169835080933e-08f,
13157 -1.1904544689091790e-06f, 2.9753088549414953e-05f,
13158 -4.9802112876220150e-04f, 5.5900917825309360e-03f,
13159 -4.0823714462925299e-02f, 1.8021733669148599e-01f,
13160 -4.0992557296268717e-01f, 3.3980328566901458e-01f,
13161 -3.6062024812411908e-01f, 1.0000000000000000e+00f };
13162
13163 ret = an[0];
13164 for (int i = 1; i < 15; i++) {
13165 ret = ret * r + an[i];
13166 }
13167 }
13168 return (float)ret;
13169}
13170
13172//Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
13173{
13174 // synthesize model alpha helix, len is Angstrom, default to 2 turns
13175 //The helical axis is parallel to the z axis.
13176 EMData * cyl = in;
13177 int nx = cyl->get_xsize();
13178 int ny = cyl->get_ysize();
13179 int nz = cyl->get_zsize();
13180
13181 int type = params.set_default("type", 2);
13182 float len = params.set_default("length", 16.2f); //in angstroms
13183 int x0 = params.set_default("x0", -1); //in voxels -- default value changed a few lines down
13184 int y0 = params.set_default("y0", -1); //in voxels
13185 int z0 = params.set_default("z0", -1); //in voxels
13186 //TODO: check with Matt about default values
13187
13188 if (x0 < 0 || x0 >= nx)
13189 x0 = nx / 2;
13190 if (y0 < 0 || y0 >= ny)
13191 y0 = ny / 2;
13192 if (z0 < 0 || z0 >= nz)
13193 z0 = nz / 2;
13194
13195 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
13196 float apix_y = cyl->get_attr("apix_y");
13197 float apix_z = cyl->get_attr("apix_z");
13198
13199 float * dat = cyl->get_data();
13200 int cyl_voxel_len = (int) (len / apix_z);
13201 int cyl_k_min = z0 - cyl_voxel_len / 2;
13202 int cyl_k_max = z0 + cyl_voxel_len / 2;
13203
13204 int x, y;
13205 for (int k = 0; k < nz; ++k) {
13206 for (int j = 0; j < ny; ++j) {
13207 for (int i = 0; i < nx; ++i, ++dat) {
13208 x = i - x0;//coordinate sys centered on cylinder
13209 y = j - y0;//coordinate sys centered on cylinder
13210 float radius = (float)hypot(x * apix_x, y * apix_y);
13211 if ((k > cyl_k_min) && (k < cyl_k_max))
13212 *dat += radprofile(radius, type); //pointer arithmetic for array done in loop
13213 //else
13214 //continue;
13215
13216 }
13217 }
13218 }
13219}
13220
13222{
13223 EMData * cyl = in;
13224 int nx = cyl->get_xsize();
13225 int ny = cyl->get_ysize();
13226 int nz = cyl->get_zsize();
13227 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
13228 float apix_y = cyl->get_attr("apix_y");
13229 float apix_z = cyl->get_attr("apix_z");
13230 float lengthAngstroms = params["length"];
13231 int z0 = params.set_default("z0", -1); //in voxels
13232
13233 if (z0 < 0 || z0 >= nz)
13234 z0 = nz / 2;
13235
13236 int z_start = Util::round( z0 - 0.5*lengthAngstroms/apix_z );
13237 int z_stop = Util::round( z0 + 0.5*lengthAngstroms/apix_z );
13238
13239 float * dat = cyl->get_data();
13240 double rho_x_sum, rho_y_sum, rho_sum, x_cm, y_cm, radius;
13241
13242 for (int k = 0; k < nz; ++k) //taking slices along z axis
13243 {
13244 rho_x_sum = rho_y_sum = rho_sum = 0; //Set to zero for a new slice
13245
13246 if (k >= z_start && k <= z_stop)
13247 //Apply the radial profile only between z_start and z_stop on the z axis
13248 {
13249 //Calculating CM for the slice...
13250 for (int j = 0; j < ny; ++j)
13251 {
13252 for (int i = 0; i < nx; ++i, ++dat)
13253 {
13254 rho_x_sum += (*dat)*i;
13255 rho_y_sum += (*dat)*j;
13256 rho_sum += *dat;
13257 }
13258 }
13259 if (rho_sum != 0)
13260 {
13261 dat -= nx*ny;//going back to the beginning of the dat array
13262 x_cm = rho_x_sum/rho_sum;
13263 y_cm = rho_y_sum/rho_sum;
13264
13265 //Applying radial profile...
13266 for (int j=0; j<ny;++j)
13267 {
13268 for (int i=0;i<nx;++i,++dat)
13269 {
13270 radius = hypot( (i-x_cm)*apix_x, (j-y_cm)*apix_y );
13271 *dat = radprofile((float)radius, 2);//Type 2 is the polynomial radial profile.
13272 }
13273 }
13274 }
13275 }
13276 else
13277 //Clear the map, setting the density to zero everywhere else.
13278 {
13279 for (int j=0; j<ny; j++)
13280 for(int i=0; i<nx; i++)
13281 {
13282 *dat = 0;
13283 dat++;
13284 }
13285 }
13286
13287 }
13288}
13289
13290//Do NOT use this code as an example, (const EMData* const image) needs to be used otherwise process_inplace is called and the params are throw out!
13292{
13293 using namespace wustl_mm::GraySkeletonCPP;
13294 using namespace wustl_mm::SkeletonMaker;
13295
13296 Volume * vimage = new Volume(image);
13297 float threshold = params["threshold"];
13298 int min_curvew = params.set_default("min_curve_width", 4);
13299 int min_srfcw = params.set_default("min_surface_width", 4);
13300 bool mark_surfaces = params.set_default("mark_surfaces", true);
13301 Volume* vskel = VolumeSkeletonizer::PerformPureJuSkeletonization(vimage, "unused", static_cast<double>(threshold), min_curvew, min_srfcw);
13302 //VolumeSkeletonizer::CleanUpSkeleton(vskel, 4, 0.01f);
13303 if (mark_surfaces) {
13304 VolumeSkeletonizer::MarkSurfaces(vskel);
13305 }
13306
13307 vskel->getVolumeData()->owns_emdata = false; //ensure the EMData object will remain when the Volume and its VolumeData object are freed
13308 EMData* skel = vskel->get_emdata();
13309 skel->update();
13310 return skel;
13311}
13312
13314{
13315 EMData* em_skel = this->process(image);
13316 //TODO: use memcpy and copy metadata explicitly
13317 *image = *em_skel; //Deep copy performed by EMData::operator=
13318 image->update();
13319 delete em_skel;
13320 em_skel = NULL;
13321 return;
13322}
13323
13325 if (image->get_zsize()!=1) throw ImageDimensionException("Only 2-D images supported");
13326
13327 EMData *cimage = NULL;
13328 if (image->is_complex()) cimage = image->copy();
13329 else cimage = image->do_fft();
13330 cimage->process_inplace("xform.phaseorigin.tocorner");
13331
13332 // Decide how large the bispectrum will be
13333 int nky=params.set_default("size",0)/2;
13334
13335 int nkx=nky+1;
13336 if (nky<4 || nky>=cimage->get_ysize()/2) nky=cimage->get_ysize()/8;
13337 if (nkx<5 || nky>=cimage->get_xsize()/2) nkx=cimage->get_xsize()/8+1;
13338 //if (image->get_xsize()<nky*2) throw ImageDimensionException("Image size smaller than requested footprint size, this is invalid.");
13339
13340 EMData* ret=new EMData(nkx*2,nky*2,1);
13341 ret->set_complex(1);
13342 ret->set_fftpad(1);
13343 ret->to_zero();
13344// printf("apix %f\tnx %d\n",(float)image->get_attr("apix_x"),(int)image->get_xsize());
13345
13346 // Fourier footprint mode, produces a 3-D image using n rotational invariants, real values from Fourier space
13347 if (params.has_key("ffp")) {
13348 // We need to save this so CTF can be applied accurately later on.
13349 float dsbg=1.0/(float(image->get_attr("apix_x"))*image->get_xsize()*4.0);
13350 int fp=(int)params.set_default("ffp",8);
13351 EMData *ret2=new EMData(nkx*2,nky*2,fp);
13352// ret2->to_zero();
13353 ret2->set_complex(1);
13354 ret2->set_ri(1);
13355 ret2->set_fftpad(1);
13356
13357 // We are doing a lot of rotations, so we make the image as small as possible first
13358 EMData *tmp=cimage;
13359 size_t laysize=nkx*2*nky*2;
13360 cimage=new EMData((nkx+fp+2)*2,(nky+fp+2)*2,1);
13361 cimage->set_complex(1);
13362 cimage->set_ri(1);
13363 cimage->set_fftpad(1);
13364
13365 for (int k=-cimage->get_ysize()/2; k<cimage->get_ysize()/2; k++) {
13366 for (int j=0; j<cimage->get_xsize()/2; j++) {
13367 cimage->set_complex_at(j,k,tmp->get_complex_at(j,k));
13368 }
13369 }
13370 delete tmp;
13371
13372 // now we compute the actual rotationally integrated "footprint"
13373 for (int k=2; k<2+fp; k++) {
13374// int jkx=k;
13375// int jky=0;
13376 int kx=k;
13377 int ky=0;
13378 ret->to_zero();
13379
13380 for (float ang=0; ang<360.0; ang+=360.0/(nky*M_PI) ) {
13381 EMData *cimage2=cimage->process("xform",Dict("alpha",ang));
13382
13383 for (int jy=-nky; jy<nky; jy++) {
13384 for (int jx=0; jx<nkx; jx++) {
13385 if (jx==0 && jy<0) continue; // this is critical! it avoids double-computation along kx=0
13386// int kx=jkx-jx;
13387// int ky=jky-jy;
13388 int jkx=jx+kx;
13389 int jky=jy+ky;
13390
13391// if (abs(jkx)>nkx || abs(jky)>nky) continue; // we go outside this range
13392 complex<double> v1 = (complex<double>)cimage2->get_complex_at(jx,jy);
13393 complex<double> v2 = (complex<double>)cimage2->get_complex_at(kx,ky);
13394 complex<double> v3 = (complex<double>)cimage2->get_complex_at(jkx,jky);
13395 ret->add_complex_at(jx,jy,0,(complex<float>)(v1*v2*std::conj(v3)));
13396 }
13397 }
13398 delete cimage2;
13399 }
13400
13401 // this fixes an issue with adding in the "special" Fourier locations ... sort of
13402// for (int jy=-nky; jy<nky; jy++) {
13403// ret->set_complex_at(0,jy,ret->get_complex_at(0,jy)/sqrt(2.0f));
13404// ret->set_complex_at(nkx-1,jy,ret->get_complex_at(nkx-1,jy)/sqrt(2.0f));
13405// }
13406 // simple fixed high-pass filter to get rid of gradient effects
13407 for (int jy=-2; jy<=2; jy++) {
13408 for (int jx=0; jx<=2; jx++) {
13409 ret->set_complex_at(jx,jy,0.0f);
13410 }
13411 }
13412 memcpy(ret2->get_data()+laysize*(k-2),ret->get_data(),laysize*sizeof(float));
13413 }
13414 delete ret;
13415 delete cimage;
13416 ret2->set_attr("dsbg",dsbg);
13417 return ret2;
13418 }
13419 // footprint mode, produces a 2-D image containing n veritcally arranged rotational invariants
13420 else if (params.has_key("fp")) {
13421 int fp=(int)params.set_default("fp",8);
13422 //EMData *ret2=new EMData(nkx*2-2,nky*2*fp,1);
13423 EMData *ret2=new EMData(nkx-1,nky*2*fp,1);
13424
13425 // We are doing a lot of rotations, so we make the image as small as possible first
13426 // note that 'step' is actually downsampling the image in Fourier space based
13427 // on the size of the desired bispectrum 9/1/18
13428 EMData *tmp=cimage;
13429// cimage=new EMData((nkx*2+fp+2)*2,(nky*2+fp+2)*2,1);
13430 cimage=new EMData((nkx*2+fp)*2-2,(nky*2+fp)*2,1);
13431 cimage->set_complex(1);
13432 cimage->set_ri(1);
13433 cimage->set_fftpad(1);
13434 int step=int(floor(tmp->get_ysize()/(2.0f*cimage->get_ysize())));
13435// int step=int(floor(tmp->get_ysize()/(cimage->get_ysize())));
13436 if (step==0) step=1;
13437// printf("%d\n",step);
13438
13439 for (int k=-cimage->get_ysize()/2; k<cimage->get_ysize()/2; k++) {
13440 for (int j=0; j<cimage->get_xsize()/2; j++) {
13441 cimage->set_complex_at(j,k,tmp->get_complex_at(j*step,k*step));
13442 }
13443 }
13444 delete tmp;
13445
13446// int mjkx=0,mjx=0,mkx=0;
13447 // now we compute the actual rotationally integrated "footprint"
13448 for (int dk=0; dk<fp; dk++) {
13449// int jkx=k;
13450// int jky=0;
13451// int kx=k;
13452// int ky=0;
13453 ret->to_zero();
13454
13455 for (float ang=0; ang<360.0; ang+=360.0/(nky*M_PI) ) {
13456 EMData *cimage2=cimage->process("xform",Dict("alpha",ang,"zerocorners",1));
13457
13458 for (int jy=-nky; jy<nky; jy++) {
13459 for (int jx=0; jx<nkx; jx++) {
13460 if ((jx==0 && jy<0) || (jx+dk<4)) continue; // first avoids double-computation along kx=0, second eliminates low resolution artifacts
13461// int kx=jkx-jx;
13462// int ky=jky-jy;
13463 int kx=jx+dk;
13464 int ky=0;
13465 int jkx=jx+kx;
13466 int jky=jy+ky;
13467// if (jkx>mjkx) { mjkx=jkx; mjx=jx; mkx=kx; }
13468 //int jkx2=jx-kx;
13469 //int jky2=jy-ky;
13470
13471// if (abs(jkx)>nkx || abs(jky)>nky) continue;
13472 complex<double> v1 = (complex<double>)cimage2->get_complex_at(jx,jy);
13473 complex<double> v2 = (complex<double>)cimage2->get_complex_at(kx,ky);
13474 complex<double> v3 = (complex<double>)cimage2->get_complex_at(jkx,jky);
13475// if (jx<4&&jy<4&&Util::hypot_fast(jx,jy)<4.0) v1=0.0; // we "filter" out the very low resolution
13476 ret->add_complex_at(jx,jy,0,(complex<float>)(v1*v2*std::conj(v3)));
13477
13478 //complex<double> v4 = (complex<double>)cimage2->get_complex_at(jkx2,jky2); // This is based on Phil's point that the v1,v2,v3 computation lacks Friedel symmetry
13479 //ret->add_complex_at(jx,jy,0,(complex<float>)(v1*(v2*std::conj(v3)+std::conj(v2)*std::conj(v4))));
13480
13481 }
13482 }
13483 delete cimage2;
13484 }
13485// printf("%d\t%d\t%d\t%d\n",dk,mjkx,mjx,mkx);
13486
13487 // this fixes an issue with adding in the "special" Fourier locations ... sort of
13488// for (int jy=-nky; jy<nky; jy++) {
13489// ret->set_complex_at(0,jy,ret->get_complex_at(0,jy)/sqrt(2.0f));
13490// ret->set_complex_at(nkx-1,jy,ret->get_complex_at(nkx-1,jy)/sqrt(2.0f));
13491// }
13492 // simple fixed high-pass filter to get rid of gradient effects
13493// for (int jy=-2; jy<=2; jy++) {
13494// for (int jx=0; jx<=2; jx++) {
13495// ret->set_complex_at(jx,jy,0.0f);
13496// }
13497// }
13498// ret->write_image("tst2.hdf",-1);
13499// EMData *pln=ret->do_ift();
13500// pln->process_inplace("xform.phaseorigin.tocenter");
13501// pln->process_inplace("normalize");
13502// ret2->insert_clip(ret,IntPoint(0,dk*nky*2,0));
13503 //ret2->insert_clip(pln,IntPoint(-nkx,(k-2)*nky*2,0));
13504// delete pln;
13505 for (int x=0; x<nkx-1; x++) {
13506 for (int y=-nky; y<nky; y++) {
13507 complex<float> val=ret->get_complex_at(x,y);
13508 if (x<=2&&abs(y)<=2&&Util::hypot_fast(x,y)<2.0) val=0.0; // We filter out the very low resolution
13509 ret2->set_value_at(x,y+nky+nky*dk*2,cbrt(std::real(val)));
13510// ret2->set_value_at(x,y+nky+nky*dk*2,std::real(val));
13511 }
13512 }
13513 }
13514// printf("%d\t%d\t%d\t%d\t%d\n",fp,nkx,nky,cimage->get_xsize(),cimage->get_ysize());
13515 delete ret;
13516 delete cimage;
13517 ret2->set_attr("is_bispec_fp",(int)fp);
13518 return ret2;
13519 }
13520 // In this mode we are making a translational invariant with information we can use for rotational alignment
13521 // It is not actually a bispectrum, but is based on a 2-point method instead
13522 else if (params.has_key("rfp")) {
13523// if (cimage->get_ysize()/2<nky*2) throw ImageDimensionException("Image size smaller than requested footprint size, this is invalid.");
13524 int rfp=(int)params.set_default("rfp",4);
13525 const int minr=4; // lowest frequency considered in the calculation (in pixels)
13526 int rsize=cimage->get_ysize()/4-minr-2;
13527 if (rsize>nky) rsize=nky;
13528// int nang=Util::calc_best_fft_size(int(M_PI*cimage->get_ysize())); // this gives basically 1 pixel precision at Nyquist. Accuracy is another question
13529 int nang=Util::calc_best_fft_size(int(M_PI*0.6*cimage->get_ysize())); // one pixel at 0.6 Nyquist. Refine alignment is probably necessary anyway
13530
13531 EMData *ret2=new EMData(nang,rsize*rfp*2,1);
13532 EMData *line=new EMData(minr*2+rsize*2,1,1); // one complex line
13533 line->set_complex(1);
13534 line->set_ri(1);
13535 line->set_fftpad(1); //correct?
13536
13537 for (int angi=0; angi<nang; angi++) { // this is x
13538 float ofs=M_PI/float(nang);
13539 float dx=cos(2.0*M_PI*angi/float(nang)+ofs);
13540 float dy=sin(2.0*M_PI*angi/float(nang)+ofs);
13541 line->to_zero();
13542
13543 // new invariant approach Steve 7/26/18
13544// for (int dr=0; dr<rfp; dr++) {
13545// for (int r=minr; r<rsize+minr; r++) {
13546// float jx=dx*r;
13547// float jy=dy*r;
13548// float kx=dx*(r+dr);
13549// float ky=dy*(r+dr);
13550//
13551// double pwr=double(r+dr)/double(r);
13552//
13553// complex<double> v1 = (complex<double>)cimage->get_complex_at_interp(jx,jy);
13554// complex<double> v2 = (complex<double>)cimage->get_complex_at_interp(kx,ky);
13555// line->set_complex_at(r,0,0,complex<float>(pow(v1,pwr)*std::conj(v2)));
13556// }
13557
13558
13559 // original bispectrum approach
13560 for (int dr=0; dr<rfp; dr++) {
13561 double lsq=0;
13562 for (int r=minr; r<rsize+minr; r++) {
13563 float jx=dx*r;
13564 float jy=dy*r;
13565 float kx=dx*(r+dr);
13566 float ky=dy*(r+dr);
13567
13568 // original bispectrum
13569 complex<double> v1 = (complex<double>)cimage->get_complex_at_interp(jx,jy);
13570 complex<double> v2 = (complex<double>)cimage->get_complex_at_interp(kx,ky);
13571 complex<double> v3 = (complex<double>)cimage->get_complex_at_interp(jx+kx,jy+ky);
13572 complex<double> bv = v1*v2*std::conj(v3);
13573 line->set_complex_at(r,0,0,complex<float>(bv));
13574 lsq+=std::norm(bv);
13575 }
13576 float rsig = 1.0/sqrt(lsq/double(rsize));
13577
13578 // Tried a bunch of different ways of representing the bispectral invariants, but the
13579 // pseudo real-space inverse seems to perform the best in testing on various targets
13580 // (decided this wasn't true in later testing)
13581
13582 // calling mult with 1D complex objects requires a lot of overhead for the RI/AP check, so we
13583 // combine it with output generation and compute rsig on the fly. Not exactly equivalent, but good enough.
13584// line->mult(1.0f/float(line->get_attr("sigma"))); // adjust intensities, but don't shift 0
13585
13586 // pseudo real-space
13587// EMData *lreal=line->do_ift();
13588// for (int i=0; i<rsize*2; i++) ret2->set_value_at(angi,i+(r2-minr)*rsize*2,lreal->get_value_at(i,0));
13589// for (int i=0; i<rsize*2; i++) ret2->set_value_at(angi,i+dr*rsize*2,lreal->get_value_at(i,0));
13590// delete lreal;
13591
13592 // stay in Fourier space
13593 // real/imaginary
13594// for (int i=0; i<rsize*2; i++) ret2->set_value_at(angi,i+(r2-minr)*rsize*2,line->get_value_at(i+minr*2,0));
13595 for (int i=0; i<rsize*2; i++) ret2->set_value_at(angi,i+dr*rsize*2,line->get_value_at(i+minr*2,0)*rsig);
13596
13597 // Amp/phase separation
13598// for (int i=0; i<rsize*2; i+=2) {
13599// complex<float> v(line->get_value_at(i,0),line->get_value_at(i+1,0));
13600// ret2->set_value_at(angi,i+ (r2-minr)*rsize*2,std::abs(v));
13601// ret2->set_value_at(angi,i+1+(r2-minr)*rsize*2,std::arg(v));
13602// }
13603
13604// // R/I with cube root
13605// for (int i=0; i<rsize*2; i+=2) {
13606// complex<float> v(line->get_value_at(i,0),line->get_value_at(i+1,0));
13607// v=pow(v,0.3333333f);
13608// ret2->set_value_at(angi,i+ (r2-minr)*rsize*2,std::real(v));
13609// ret2->set_value_at(angi,i+1+(r2-minr)*rsize*2,std::imag(v));
13610// }
13611
13612
13613
13614// printf("%d %d %d %d\n",rsize,angi,r2-minr,line->get_xsize());
13615 }
13616 }
13617 delete ret;
13618 delete line;
13619 delete cimage;
13620 ret2->set_attr("is_bispec_rfp",(int)rfp);
13621 return ret2;
13622 }
13623 // angular integrate mode, produces the simplest rotational invariant, ignoring rotational correlations
13624 else if (params.has_key("k")) {
13625 int k=(int)params.set_default("k",1);
13626// int jkx=k;
13627// int jky=0;
13628 int kx=k;
13629 int ky=0;
13630
13631 for (float ang=0; ang<360.0; ang+=360.0/(nky*M_PI) ) {
13632// for (float ang=0; ang<360.0; ang+=2 ) {// PRB changed this; change back
13633 EMData *cimage2=cimage->process("xform",Dict("alpha",ang));
13634
13635 for (int jy=-nky; jy<nky; jy++) {
13636 for (int jx=0; jx<nkx; jx++) {
13637// int kx=jkx-jx;
13638// int ky=jky-jy;
13639 int jkx=jx+kx;
13640 int jky=jy+ky;
13641
13642// if (abs(kx)>nkx || abs(ky)>nky) continue;
13643 complex<double> v1 = (complex<double>)cimage2->get_complex_at(jx,jy);
13644 complex<double> v2 = (complex<double>)cimage2->get_complex_at(kx,ky);
13645 complex<double> v3 = (complex<double>)cimage2->get_complex_at(jkx,jky);
13646 ret->add_complex_at(jx,jy,0,(complex<float>)(v1*v2*std::conj(v3)));
13647 }
13648 }
13649 delete cimage2;
13650 }
13651 }
13652 else if (params.has_key("prbk")) {
13653
13654 if (image->is_complex()) cimage = image->copy();
13655 else cimage = image->do_fft();
13656 cimage->process_inplace("xform.phaseorigin.tocorner");
13657
13658 // Decide how large the bispectrum will be
13659 //int nky=params.set_default("size",0)/2;
13660 int nky=params.set_default("size",0);
13661
13662 printf("nky = %d , size= %d \n",nky,image->get_xsize());
13663
13664 //int nkx=nky+1;
13665 int nkx=nky;
13666
13667 //cimage=new EMData((nkx*2+fp)*2-2,(nky*2+fp)*2,1);
13668 //cimage->set_complex(1);
13669 //cimage->set_ri(1);
13670 //cimage->set_fftpad(1);
13671
13672 //if (nky<4 || nky>=cimage->get_ysize()/2) nky=cimage->get_ysize()/8;
13673 //if (nkx<5 || nky>=cimage->get_xsize()/2) nkx=cimage->get_xsize()/8+1;
13674 //if (image->get_xsize()<nky*2) throw ImageDimensionException("Image size smaller than requested footprint size, this is invalid.");
13675
13676// EMData* ret=new EMData(nkx*2,nky*2,1);
13677 EMData* ret=new EMData(2*nkx,2*nky,1);
13678 ret->set_complex(0);
13679 //ret->set_fftpad(1);
13680 ret->to_zero();
13681
13682 int k=(int)params.set_default("prbk",1);
13683// int jkx=k;
13684// int jky=0;
13685 int kx=k;
13686 int ky=0;
13687
13688// for (float ang=0; ang<360.0; ang+=360.0/(nky*M_PI) ) { // Original
13689 for (float ang=0; ang<360.0; ang+=2 ) {
13690 EMData *cimage2=cimage->process("xform",Dict("alpha",ang));
13691
13692 for (int qy=-nky; qy<nky; qy++) {
13693 for (int qx=-nkx; qx<nkx; qx++) {
13694// int kx=jkx-jx;
13695// int ky=jky-jy;
13696 int kqx=qx+kx;
13697 int kqy=qy+ky;
13698 if (abs(kqx)>nkx || abs(kqy)>nky) continue;
13699
13700// if (abs(kx)>nkx || abs(ky)>nky) continue;
13701 complex<double> v1 = (complex<double>)cimage2->get_complex_at(kx,ky);
13702 complex<double> v2 = (complex<double>)cimage2->get_complex_at(qx,qy);
13703 complex<double> v3 = (complex<double>)cimage2->get_complex_at(kqx,kqy);
13704 complex<double> vTotal = (complex<double>)(v1*v2*std::conj(v3));
13705 double RealV = (real)(vTotal);
13706 int jxInd = (qx+2*nkx)%(2*nkx);
13707 int jyInd = (qy+2*nky)%(2*nky);
13708 //printf("RealV %g vTotal %g\n",RealV,vTotal);
13709 double OldVal = ret->get_value_at(jxInd,jyInd,0);
13710 ret->set_value_at(jxInd,jyInd,0,OldVal+RealV);
13711 //ret->set_value_at(jxInd,jyInd,0,1);
13712 }
13713 }
13714 delete cimage2;
13715 }
13716 return(ret);
13717 }
13718 else if (params.has_key("prbkv2")) {
13719
13720 if (image->is_complex()) cimage = image->copy();
13721 else cimage = image->do_fft();
13722 cimage->process_inplace("xform.phaseorigin.tocorner");
13723
13724 int k=(int)params.set_default("prbkv2",1);
13725
13726 // Decide how large the bispectrum will be
13727 int nky= 2*k+1;
13728 int nkx= 2*k+1;
13729
13730
13731 printf("nkx = %d, nky = %d , size= %d \n",nkx,nky,image->get_xsize());
13732
13733
13734 EMData* ret=new EMData(nkx,nky,1);
13735 ret->set_complex(0);
13736 ret->to_zero();
13737 int kx=k;
13738 int ky=0;
13739 int Nyquist = k;
13740// for (float ang=0; ang<360.0; ang+=360.0/(nky*M_PI) ) { // Original
13741 for (float ang=0; ang<360.0; ang+=2 ) {
13742 EMData *cimage2=cimage->process("xform",Dict("alpha",ang));
13743
13744 for (int qy=-k; qy<k+1; qy++) {
13745 if (qy*qy> (0.75)*k*k) continue;
13746 for (int qx=-k; qx<1; qx++) {
13747 if ((qx+k)*(qx+k) > (k*k - qy*qy)) continue;
13748 int kqx=qx+kx;
13749 int kqy=qy+ky;
13750 complex<double> v1 = (complex<double>)cimage2->get_complex_at(kx,ky);
13751 complex<double> v2 = (complex<double>)cimage2->get_complex_at(qx,qy);
13752 complex<double> v3 = (complex<double>)cimage2->get_complex_at(kqx,kqy);
13753 complex<double> vTotal = (complex<double>)(v1*v2*std::conj(v3));
13754 double RealV = (real)(vTotal);
13755 int qxInd = (qx+nkx)%(nkx);
13756 int qyInd = (qy+nky)%(nky);
13757 int NegQx = k/2 +qx ;
13758 int QyInd = qy+Nyquist;
13759 //printf("qy %d qyInd %d QyInd %d qx %d qxInd %d NegQx %d k %d\n",qy, qyInd, QyInd,qx,qxInd,NegQx, k);
13760 //printf("qx %d qy %d NegQx %d QyInd %d RealV %g vTotal %g\n",qx,qy, NegQx,QyInd, RealV,vTotal);
13761 //double OldVal = ret->get_value_at(qxInd,qyInd,0);
13762 double OldVal = ret->get_value_at(NegQx,QyInd,0);
13763 //ret->set_value_at(qxInd,qyInd,0,OldVal+RealV);
13764 ret->set_value_at(NegQx,QyInd,0,OldVal+RealV);
13765 //ret->set_value_at(qxInd,qyInd,0,1);
13766 }
13767 }
13768 delete cimage2;
13769 }
13770 return(ret);
13771 }
13772
13773 else if (params.has_key("prb3D")) {
13774
13775 int hp=(int)params.set_default("hp",0);
13776 int Nyquist=(int)params.set_default("prb3D",30);
13777
13778 if (image->is_complex()) cimage = image->copy();
13779 else cimage = image->do_fft();
13780
13781 cimage->process_inplace("xform.phaseorigin.tocorner");
13782
13783 //int k=(int)params.set_default("PRBkv3",1);
13784
13785 // Decide how large the bispectrum will be
13786
13787
13788 int csizex = cimage->get_xsize();
13789 int csizey = cimage->get_ysize();
13790
13791 printf("csizex = %d, csizey = %d \n", csizex , csizey );
13792
13793 Nyquist = (csizey+1)/2;
13794
13795 printf("csizex = %d, csizey = %d, Nyquist= %d \n", csizex , csizey, Nyquist);
13796
13797 int nkx= Nyquist/2+1;
13798 int nky= 2*Nyquist+2;
13799 int nkz= Nyquist+1;
13800
13801
13802 printf("nkx = %d, nky = %d , size= %d \n",nkx,nky,image->get_xsize());
13803
13804
13805
13806 EMData* ret=new EMData(nkx,nky,nkz);
13807 ret->set_complex(0);
13808 ret->to_zero();
13809
13810 //int Nyquist = 1* k;
13811// for (float ang=0; ang<360.0; ang+=360.0/(nky*M_PI) ) { // Original
13812 for (float ang=0; ang<360.0; ang+=2 ) {
13813 EMData *cimage2=cimage->process("xform",Dict("alpha",ang));
13814
13815 for (int k=0; k < Nyquist+1;k++){
13816 //printf(" k %d\n",k);
13817 int k2=k*k;
13818 int qyMax = sqrt(3*k2/4);
13819
13820 for (int qy=-qyMax; qy<qyMax+1; qy++) {
13821 //if (qy*qy> (0.75)*k*k) continue;
13822 int qxMin =k/2; qxMin *= -1;
13823 int qxMax = k - sqrt(k2-qy*qy)+0.999999; qxMax *= -1;
13824 for (int qx=qxMin; qx<qxMax+1; qx++) {
13825 //if ((qx+k)*(qx+k) > (k*k - qy*qy)) continue;
13826 //if (qx<(-k/2)) continue;
13827 int kqx=qx+k;
13828 int kqy=qy;
13829 complex<double> v1 = (complex<double>)cimage2->get_complex_at(k,0);
13830 complex<double> v2 = (complex<double>)cimage2->get_complex_at(qx,qy);
13831 complex<double> v3 = (complex<double>)cimage2->get_complex_at(kqx,kqy);
13832 complex<double> vTotal = (complex<double>)(v1*v2*std::conj(v3));
13833 double RealV = (real)(vTotal);
13834 int qxInd = (qx+nkx)%(nkx);
13835 int qyInd = (qy+nky)%(nky);
13836 int NegQx = k/2 +qx ;
13837 int QyInd = qy+Nyquist;
13838 //printf("qy %d qyInd %d QyInd %d qx %d qxInd %d NegQx %d k %d\n",qy, qyInd, QyInd,qx,qxInd,NegQx, k);
13839 //double OldVal = ret->get_value_at(qxInd,qyInd,0);
13840 double OldVal = ret->get_value_at(NegQx,QyInd,k);
13841 //ret->set_value_at(qxInd,qyInd,0,OldVal+RealV);
13842 ret->set_value_at(NegQx,QyInd,k,OldVal+RealV);
13843 //ret->set_value_at(qxInd,qyInd,0,1);
13844 }
13845 }
13846 }
13847 delete cimage2;
13848 }
13849 return(ret);
13850 }
13851 else if (params.has_key("jkx") && params.has_key("jky")) {
13852 int jkx=(int)params.set_default("jkx",0);
13853 int jky=(int)params.set_default("jky",0);
13854
13855 for (int jy=-nky; jy<nky; jy++) {
13856 for (int jx=0; jx<nkx; jx++) {
13857 int kx=jkx-jx;
13858 int ky=jky-jy;
13859
13860// if (abs(kx)>nkx || abs(ky)>nky) continue;
13861 complex<double> v1 = (complex<double>)cimage->get_complex_at(jx,jy);
13862 complex<double> v2 = (complex<double>)cimage->get_complex_at(kx,ky);
13863 complex<double> v3 = (complex<double>)cimage->get_complex_at(jkx,jky);
13864 ret->set_complex_at(jx,jy,(complex<float>)(v1*v2*std::conj(v3)));
13865// ret->set_complex_at(jx,jy,(complex<float>)(v1));
13866 }
13867 }
13868 }
13869 // normal slice mode
13870 else {
13871 int kx=(int)params.set_default("kx",0);
13872 int ky=(int)params.set_default("ky",0);
13873
13874// printf("KXY %d %d %d %d\n",kx,ky,nkx,nky);
13875
13876 for (int jy=-nky; jy<nky; jy++) {
13877 for (int jx=0; jx<nkx; jx++) {
13878// if (jx+kx>nkx || abs(jy+ky)>nky || jx+kx<0) continue;
13879 complex<double> v1 = (complex<double>)cimage->get_complex_at(jx,jy);
13880 complex<double> v2 = (complex<double>)cimage->get_complex_at(kx,ky);
13881 complex<double> v3 = (complex<double>)cimage->get_complex_at(jx+kx,jy+ky);
13882 ret->set_complex_at(jx,jy,(complex<float>)(v1*v2*std::conj(v3)));
13883// ret->set_complex_at(jx,jy,(complex<float>)(v1));
13884 }
13885 }
13886 }
13887
13888 for (int jy=-nky; jy<nky; jy++) {
13889 ret->set_complex_at(0,jy,ret->get_complex_at(0,jy)/sqrt(2.0f));
13890 ret->set_complex_at(nkx-1,jy,ret->get_complex_at(nkx-1,jy)/sqrt(2.0f));
13891 }
13892
13893 delete cimage;
13894
13895 return(ret);
13896}
13897
13899 if (image->get_zsize()!=1 || image->is_complex()) throw ImageDimensionException("Only 2-D real images supported");
13900
13901 EMData *cimage = NULL;
13902// if (image->is_complex()) cimage = image->copy();
13903// else cimage = image->do_fft();
13904 int s1=image->get_ysize();
13905 EMData *im2=image->get_clip(Region(-s1*3/2,-s1*3/2,s1*4,s1*4));
13906 cimage=im2->do_fft();
13907 delete im2;
13908 cimage->process_inplace("xform.phaseorigin.tocorner");
13909
13910 // Decide how large the harmonic invariant will be
13911// int nx=cimage->get_xsize();
13912 int ny=cimage->get_ysize()/8;
13913 int naz=Util::calc_best_fft_size((int)params.set_default("size",ny));
13914
13915 // Compute a translational invariant for a single harmonic
13916 EMData* trns=new EMData(naz*2,ny/2,1);
13917 trns->to_zero();
13918 trns->set_complex(1);
13919 trns->set_ri(1);
13920 trns->set_fftpad(1); // this is kind of meaningless in this context
13921 size_t xyz=trns->get_size();
13922// printf("apix %f\tnx %d\n",(float)image->get_attr("apix_x"),(int)image->get_xsize());
13923
13924 // Compute a translational invariant for a single harmonic
13925 if (params.has_key("hn")) {
13926 int hn=(int)params.get("hn");
13927
13928 // FFT Debugging code with hn<0
13929 if (hn<0) {
13930 complex<float> *tmp = (complex<float>*)EMfft::fftmalloc(naz*2);
13931 for (int jy=0; jy<ny/4; jy+=2) {
13932 for (int x=0; x<naz; x++) trns->set_complex_at_idx(x,jy,0,(complex<float>)std::polar((float)sin(1.0f+jy/2.0f*x*M_PI*2.0f/naz),-hn/100.0f));
13933 memcpy((void*)tmp,(void*)(trns->get_data()+jy*naz*2),naz*2*sizeof(float));
13934 EMfft::complex_to_complex_1d_inplace(tmp,naz*2);
13935 memcpy((void*)(trns->get_data()+(jy+1)*naz*2),(void*)tmp,naz*2*sizeof(float));
13936 }
13937 EMfft::fftfree((float *)tmp);
13938
13939 delete cimage;
13940 EMData *ret=trns->get_clip(Region(0,0,naz*2,ny/4));
13941 delete trns;
13942// ret->set_complex(0);
13943 return(ret);
13944 }
13945
13946 // Here is the actual hn code
13947 if (hn<1) throw InvalidParameterException("Invalid parameter, hn<1");
13948 int rn = 0;
13949 // rotational/translational single. If rn==0, special case where polar coordinate version of translational invariant is generated
13950 if (params.has_key("rn")) {
13951 rn=params.get("rn");
13952
13953 // Start with the translational invariant in Fourier space in a radial coordinate system
13954 for (int ja=0; ja<naz; ja++) {
13955 float si=sin(float(2.0*M_PI*(ja+0.5)/naz));
13956 float co=cos(float(2.0*M_PI*(ja+0.5)/naz));
13957 for (int jr=3; jr<ny/2 && jr*hn<ny*2; jr++) { // This is cryoEM specific, we have bad values near the origin
13958 float jx=co*jr;
13959 float jy=si*jr;
13960 complex<double> v2 = (complex<double>)cimage->get_complex_at_interp(jx,jy);
13961 complex<double> v1 = (complex<double>)cimage->get_complex_at_interp(jx*hn,jy*hn);
13962// int jx=co*jr;
13963// int jy=si*jr;
13964// complex<double> v2 = (complex<double>)cimage->get_complex_at(jx,jy);
13965// complex<double> v1 = (complex<double>)cimage->get_complex_at(jx*hn,jy*hn);
13966 trns->set_complex_at_idx(ja,jr,0,(complex<float>)(v1*std::pow(std::conj(v2),(float)hn)));
13967 }
13968 }
13969 // rescale components to have linear amplitude WRT the original FFT, without changing phase
13970 trns->ri2ap();
13971
13972 for (size_t i=0; i<xyz; i+=2) {
13973 trns->set_value_at_index(i,pow(trns->get_value_at_index(i),float(1.0/(hn+1))));
13974 }
13975 trns->ap2ri();
13976
13977 // Only if rn is defined
13978 if (rn==0) {
13979 complex<float> *tmp = (complex<float>*)EMfft::fftmalloc(naz*2);
13980 for (int jy=3; jy<ny/2; jy++) {
13981 memcpy((void*)tmp,(void*)(trns->get_data()+jy*naz*2),naz*2*sizeof(float));
13982 EMfft::complex_to_complex_1d_inplace(tmp,naz*2);
13983 memcpy((void*)(trns->get_data()+jy*naz*2),(void*)tmp,naz*2*sizeof(float));
13984 }
13985 EMfft::fftfree((float *)tmp);
13986 }
13987 else if (rn>=0) {
13988 // Now we do the 1-D FFTs on the lines of the translational invariant
13989 complex<float> *tmp = (complex<float>*)EMfft::fftmalloc(naz*2);
13990 for (int jy=3; jy<ny/2; jy++) {
13991 // While it might seem a good idea to do inplace 1D transforms for each row, the potential memory
13992 // alignment change for each row could cause bad things to happen
13993 memcpy((void*)tmp,(void*)(trns->get_data()+jy*naz*2),naz*2*sizeof(float));
13994 EMfft::complex_to_complex_1d_inplace(tmp,naz*2);
13995 for (int jx=0; jx<naz; jx++) {
13996// float l=jx/float(rn);
13997// float frc=l-floor(l);
13998// int li=(int)l;
13999// complex<float> v2 = Util::linear_interpolate_cmplx(tmp[li],tmp[li+1],frc);
14000 if (jx*rn>naz) {
14001 trns->set_complex_at_idx(jx,jy,0,0.0f);
14002 continue;
14003 }
14004 complex<float> v2 = tmp[jx];
14005 complex<float> v1 = tmp[jx*rn];
14006 trns->set_complex_at_idx(jx,jy,0,v1*std::pow(std::conj(v2),(float)rn));
14007 }
14008 // memcpy((void*)(trns->get_data()+jy*naz*2),(void*)tmp,naz*2*sizeof(float));
14009 }
14010 EMfft::fftfree((float *)tmp);
14011
14012 // rescale components to have linear amplitude WRT the original FFT, without changing phase
14013 trns->ri2ap();
14014 for (size_t i=0; i<xyz; i+=2) {
14015 trns->set_value_at_index(i,pow(trns->get_value_at_index(i),float(1.0/(rn+1))));
14016 }
14017 trns->ap2ri();
14018 }
14019 trns->set_attr("is_harmonic_rn",(int)rn);
14020 }
14021 // With no rotational component
14022 else {
14023 trns->set_size(ny,ny,1);
14024 xyz=trns->get_size();
14025 // translational only single
14026 for (int jx=0; jx<ny/2 && jx*hn<ny*2; jx++) {
14027 for (int jy=max(-ny/2,-ny*2/hn); jy<ny/2 && jy*hn<ny*2; jy++) {
14028 if (Util::hypot_fast(jx,jy)<2.5f) {
14029 trns->set_complex_at(jx,jy,0,(complex<float>)0);
14030 continue;
14031 }
14032 complex<double> v2 = (complex<double>)cimage->get_complex_at(jx,jy);
14033 complex<double> v1 = (complex<double>)cimage->get_complex_at(jx*hn,jy*hn);
14034 trns->set_complex_at(jx,jy,0,(complex<float>)(v1*std::pow(std::conj(v2),(float)hn)));
14035 }
14036 }
14037 // rescale components to have linear amplitude WRT the original FFT, without changing phase
14038 trns->ri2ap();
14039 for (size_t i=0; i<xyz; i+=2) {
14040 trns->set_value_at_index(i,pow(trns->get_value_at_index(i),float(1.0/(hn+1))));
14041 }
14042 trns->ap2ri();
14043 // EMData *ret = trns->do_ift();
14044 }
14045 delete cimage;
14046 trns->set_attr("is_harmonic_hn",(int)hn);
14047
14048 return(trns);
14049 }
14050 if (params.has_key("rfp")) {
14051 int rfp=(int)params.get("rfp");
14052 for (int ja=0; ja<naz; ja++) {
14053 float si=sin(float(2.0*M_PI*(ja+0.5)/naz));
14054 float co=cos(float(2.0*M_PI*(ja+0.5)/naz));
14055 int y=0; // This is where the results go
14056 // Start at r=5 due to bad CryoEM values near the origin.
14057 // Go to 1/2 Nyquist because high resolution values are less invariant due to interpolaton
14058 for (int jr=5; jr<ny/4; jr++) {
14059 // Innermost loop is hn (radial harmonic coefficient) to group similar values together
14060 for (int hn=2; hn<=rfp; hn++) {
14061 float jx=co*jr;
14062 float jy=si*jr;
14063 complex<double> v2 = (complex<double>)cimage->get_complex_at_interp(jx,jy);
14064 complex<double> v1 = (complex<double>)cimage->get_complex_at_interp(jx*hn,jy*hn);
14065 v1*=std::pow(std::conj(v2),(double)hn);
14066 v1=std::polar(std::pow(std::abs(v1),1.0/(hn+1.0))/ny,std::arg(v1));
14067 trns->set_complex_at_idx(ja,y,0,(complex<float>)v1);
14068 y++;
14069 if (y>=ny/2) break;
14070 }
14071 if (y>=ny/2) break;
14072 }
14073 // rescale components to have linear amplitude WRT the original FFT, without changing phase
14074 }
14075 delete cimage;
14076 trns->set_attr("is_harmonic_rfp",(int)rfp);
14077// trns->set_complex(0);
14078 return(trns);
14079 }
14080
14081 // Rotational & Translational invariant, fp specifies the maximum harmonic (R&T) to include
14082 if (params.has_key("fp")) {
14083 int fp=(int)params.set_default("fp",4);
14084 if (fp<2) fp=2;
14085 // Start with the translational invariant in Fourier space in a radial coordinate system
14086 for (int ja=0; ja<naz; ja++) {
14087 float si=sin(float(2.0*M_PI*(ja+0.5)/naz));
14088 float co=cos(float(2.0*M_PI*(ja+0.5)/naz));
14089 int y=0; // This is where the results go
14090 // Start at r=3 due to bad CryoEM values near the origin.
14091 // Go to 1/2 Nyquist because high resolution values are less invariant due to interpolaton
14092 for (int jr=3; jr<ny/4; jr++) {
14093 // Innermost loop is hn (radial harmonic coefficient) to group similar values together, skip the phaseless hn=1
14094 for (int hn=2; hn<=fp; hn++) {
14095 float jx=co*jr;
14096 float jy=si*jr;
14097 complex<double> v2 = (complex<double>)cimage->get_complex_at_interp(jx,jy);
14098 complex<double> v1 = (complex<double>)cimage->get_complex_at_interp(jx*hn,jy*hn);
14099 v1*=std::pow(std::conj(v2),(double)hn);
14100 v1=std::polar(std::pow(std::abs(v1),1.0/(hn+1.0))/ny,std::arg(v1));
14101 trns->set_complex_at_idx(ja,y,0,(complex<float>)v1);
14102 y++;
14103 if (y>=ny/2) break;
14104 }
14105 if (y>=ny/2) break;
14106 }
14107 // rescale components to have linear amplitude WRT the original FFT, without changing phase
14108 }
14109
14110 // This holds a copy for doing the 1D FFTs efficiently
14111 complex<float> *tmp = (complex<float>*)EMfft::fftmalloc(naz*2);
14112 // One horizontal line at a time
14113 for (int jy=0; jy<ny/2; jy++) {
14114 // Now we do the 1-D FFTs on the lines of the translational invariant
14115 memcpy((void*)tmp,(void*)(trns->get_data()+jy*naz*2),naz*2*sizeof(float));
14116 EMfft::complex_to_complex_1d_inplace(tmp,naz*2);
14117 int x=0; // output x coordinate
14118 // outer loop over base rotational frequency, skip phaseless jx=0
14119 for (int jx=1; jx<naz/2; jx++) {
14120 // inner loop over rotational harmonic coefficients, skip the phaseless rn=1
14121 complex<double> v2 = tmp[jx];
14122 for (int rn=2; rn<=fp; rn++) {
14123 if (jx*rn>=naz) break;
14124 complex<double> v1 = tmp[jx*rn];
14125 v1*=std::pow(std::conj(v2),(double)rn);
14126 v1=std::polar(std::pow(std::abs(v1),1.0/(rn+1.0))/naz,std::arg(v1));
14127 trns->set_complex_at_idx(x,jy,0,(complex<float>)v1);
14128 x++;
14129 if (x>=naz/2) break;
14130 }
14131 if (x>=naz/2) break;
14132 }
14133 }
14134 EMfft::fftfree((float *)tmp);
14135
14136
14137 delete cimage;
14138 // the /4 in the next line is arbitrary to remove regions which empirically
14139 // aren't useful
14140 EMData *ret=trns->get_clip(Region(0,0,min(naz,fp*naz/4)/2,min(ny/2,fp*(ny/4-3))));
14141 delete trns;
14142 ret->set_attr("is_harmonic_fp",(int)fp);
14143 ret->set_complex(0);
14144 return(ret);
14145 }
14146
14147}
14148
14149
14151{
14152 if (image->get_zsize()!=1) throw ImageDimensionException("Only 2-D images supported");
14153 int nx = image->get_xsize();
14154 int ny = image->get_ysize();
14155
14156 EMData* conv = new EMData(image->get_xsize(),image->get_ysize(),1);
14157
14158 int ks;
14159 vector<float> kernel;
14160 kernel = params["kernel"];
14161 ks = int(sqrt(float(kernel.size())));
14162 if (ks*ks != kernel.size()) throw InvalidParameterException("Convolution kernel must be square!!");
14163
14164 float* data = image->get_data();
14165 float* cdata = conv->get_data(); // Yes I could use set_value_at_fast, but is still slower than this....
14166
14167 //I could do the edges by wrapping around, but this is not necessary(such functionality can be iplemented later)
14168 int n = (ks - 1)/2;
14169 for (int i = n; i < (nx - n); i++) {
14170 for (int j = n; j < (ny - n); j++) {
14171 //now do the convolution
14172 float cpixel = 0;
14173 int idx = 0;
14174 // Perahps I could use some form of Caching to speed things up?
14175 for (int cx = -n; cx <= n; cx++) {
14176 for (int cy = -n; cy <= n; cy++, idx++) {
14177 cpixel += data[(i+cx)+(j+cy)*nx]*kernel[idx];
14178 }
14179 }
14180 cdata[i + j * nx] = cpixel;
14181 }
14182 }
14183
14184 return conv;
14185}
14186
14188{
14189 throw UnexpectedBehaviorException("Not implemented yet");
14190
14191 return;
14192}
14193
14194
14196{
14197
14198 EMData* imageCp = image -> copy(); // This is the rotated image
14199 process_inplace(imageCp);
14200
14201 return imageCp;
14202}
14203
14204
14205void RotateInFSProcessor::process_inplace(EMData * image) // right now for 2d images
14206{
14207// float angle = params["angle"];
14208
14209
14210// Transform *rotNow = params.set_default("transform",&Transform());
14211 Transform *rotNow = params["transform"];
14212 float interpCutoff = params.set_default("interpCutoff",0.8f); // JFF, can you move this to input parameter?
14213// float interpCutoff = params["interpCutoff"]; // JFF, can you move this to input parameter?
14214// float interpCutoff =.8; // JFF, can you move this to input parameter?
14215
14216
14217 int debug=0;
14218
14219// error: conversion from 'EMAN::EMObject' to non-scalar type 'EMAN::Transform' requested
14220
14221
14222 // if 2N is size of image, then sizes of FFT are (2N+2,2N,2N) or (2N+2,2N,1)
14223 // if 2N+1 is size of image, then sizes of FFT are (2N+2,2N+1,2N+1) or (2N+2,2N+1,1)
14224
14225 int x_size = image->get_xsize(); //16
14226 int y_size = image->get_ysize(); int y_odd= (y_size%2);
14227 int z_size = image->get_zsize();
14228
14229// float size_check = abs(y_size-z_size)+abs(x_size-y_size-2+y_odd);
14230// if (size_check!=0) throw ImageDimensionException("Only cubic images");
14231 int size_check = abs(x_size-y_size-2+y_odd)+ abs(z_size-1)*abs(z_size-y_size);
14232 int N = x_size/2-1;
14233 int Mid = N+1;
14234 if (size_check!=0) throw ImageDimensionException("Only square or cubic images for now");
14235 if (image->is_real()) throw ImageDimensionException("Only for Fourier images");
14236// if (y_odd==0) throw ImageDimensionException("Only use odd images for now");
14237
14238 if (debug) printf("Mid=%d, x_size=%d, y_size=%d, N=%d, z_size=%d \n", Mid,x_size,y_size, N, z_size );
14239
14240 EMData* RotIm = image -> copy(); // This is the rotated image
14241 EMData* WeightIm = image -> copy(); WeightIm ->to_zero();// This is the Weight image for rotated image
14242 EMData* PhaseOrigIm = new EMData(N+1,2*N+1,z_size) ; PhaseOrigIm ->to_zero();// This is the Weight image for rotated image
14243 EMData* PhaseFinalIm = PhaseOrigIm -> copy(); PhaseFinalIm ->to_zero();// This is the Weight image for rotated image
14244 EMData* MagFinalIm = PhaseOrigIm -> copy(); MagFinalIm ->to_zero();// This is the Weight image for rotated image
14245
14246// float* data = image -> get_data();
14247// float* Rotdata = RotIm -> get_data(); // This is the data of the rotated image
14248// float* WeightData = WeightIm -> get_data(); //
14249
14250 float WeightNowX, WeightNowY, WeightNowZ ;
14251 int kxMin,kxMax, kyMin, kyMax, kzMin, kzMax, kxBefore, kyBefore, kzBefore ;
14252 float kxRT, kyRT, kzRT ;
14253
14254 Vec3f PosAfter;
14255 Vec3f PosBefore;
14256 Transform invRotNow;
14257 // Fill out real and imaginary full images
14258
14259 //int kz=0;
14260
14261 if (debug) {image -> write_image("OrigImageFFT.hdf");
14262 printf("Just wrote OrigImageFFT.hdf \n"); }
14263
14264
14265 for (kxBefore = 0; kxBefore <= N ; ++kxBefore) { // These are the kx, ky coordinates of the original image
14266 for (kyBefore = 0; kyBefore < y_size ; ++kyBefore) { // We need to rephase
14267 for (kzBefore = 0; kzBefore < z_size ; ++kzBefore) { // We need to rephase
14268
14269 // Now we need a
14270 float CurrentReal = RotIm -> get_value_at(2*kxBefore ,kyBefore, kzBefore);
14271 float CurrentImag = RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
14272
14273// fftOfxPRB3(1+mod(ik-Mid,N))=Grand*exp(-2*pi*1i*Mid*(ik-Mid)/x_size); % Phase to apply to centered version
14274
14275// float Phase = -2*pi*(kxBefore+kyBefore + kzBefore)*(Mid)/y_size;
14276 float Phase = -pi*(kxBefore+kyBefore + kzBefore)*x_size/y_size;
14277 // Phase = 0;
14278 float CosPhase = cos( Phase);
14279 float SinPhase = sin( Phase);
14280
14281 float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
14282 float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
14283
14284 RotIm ->set_value_at(2*kxBefore ,kyBefore, kzBefore, NewRealValue);
14285 RotIm ->set_value_at(2*kxBefore+1,kyBefore, kzBefore, NewImagValue);
14286 }}}
14287
14288 if (debug) {RotIm -> write_image("OrigImageFFTAfterPhaseCorrection.hdf");
14289 printf(" Just wrote OrigImageFFTAfterPhaseCorrection.hdf \n");}
14290
14291 // RotIm ->set_value_at(2*Mid-1,0, 0, 0);
14292 if (debug) printf(" Just about to start second loop \n");
14293
14294 image ->to_zero();
14295 invRotNow = rotNow ->inverse(); // no match for 'operator=' in 'PosBefore = EMAN::operator*(const EMAN::Transform&, const EMAN::Transform&)((
14296
14297
14298 for (int kxAfter = 0; kxAfter <= N ; ++kxAfter) { // These are the kx, ky, kz coordinates of the rotated image
14299 for (int kyAfter = -N; kyAfter < y_size-N ; ++kyAfter) { // referring to a properly centered version
14300 for (int kzAfter = -z_size/2; kzAfter <= z_size/2 ; ++kzAfter) {
14301
14302 // Now we need a
14303
14304 PosAfter = Vec3f(kxAfter, kyAfter, kzAfter);
14305 PosBefore = invRotNow*PosAfter;
14306 kxRT = PosBefore[0]; // This will be the off-lattice site, where the point was rotated from
14307 kyRT = PosBefore[1]; //
14308 kzRT = PosBefore[2]; //
14309
14310
14311 kxMin = ceil( kxRT-interpCutoff); kxMax = floor(kxRT+interpCutoff);
14312 kyMin = ceil( kyRT-interpCutoff); kyMax = floor(kyRT+interpCutoff);
14313 kzMin = ceil( kzRT-interpCutoff); kzMax = floor(kzRT+interpCutoff);
14314
14315
14316// printf("Block 0,kx=%d, ky=%d,kxMin=%d, kyMin=%d, kxMax=%d, kyMax=%d, kyAfter=%d \n",kxAfter,kyAfter,kxMin,kyMin, kxMax, kyMax, kyAfter);
14317 //continue;
14318 for (int kxI= kxMin; kxI <= kxMax; ++kxI){ // go through this
14319 for (int kyI= kyMin; kyI <= kyMax; ++kyI){ // and get values to interp
14320 for (int kzI= kzMin; kzI <= kzMax; ++kzI){ //
14321
14322//
14323 if (abs(kxI) >N) continue; // don't go off the lattice
14324 if (abs(kyI) >N) continue;
14325 if (abs(kzI) >z_size/2) continue;
14326
14327 float distx= abs(kxI-kxRT);
14328 float disty= abs(kyI-kyRT);
14329 float distz= abs(kzI-kzRT);
14330
14331 // fold kxI, kyI back into lattice if possible
14332 int IsComplexConj= 1;
14333
14334 if (kxI<0) IsComplexConj=-1;
14335 kxBefore= IsComplexConj*kxI; // The Proper coordinates will be
14336 kyBefore= IsComplexConj*kyI; // where the original data is stored
14337 kzBefore= IsComplexConj*kzI; // At this point kxBefore >=0, but not necessarily kyBefore
14338
14339 if ( kyBefore<0 ) kyBefore += y_size; // makes sure kyBefore is also >0
14340 if ( kzBefore<0 ) kzBefore += y_size; // makes sure kzBefore is also >0
14341
14342 WeightNowX = (distx ==0)? 1: (sin(pi*distx) /(pi*distx)) ;
14343 WeightNowY = (disty ==0)? 1: (sin(pi*disty) /(pi*disty)) ;
14344 WeightNowZ = (distz ==0)? 1: (sin(pi*distz) /(pi*distz)) ;
14345
14346
14347 float CurrentValue;
14348 float ToAdd;
14349 int kyAfterInd = (kyAfter+y_size)%(y_size);
14350 int kzAfterInd = (kzAfter+z_size)%(z_size);
14351
14352 // if (kxAfter==0) IsComplexConj*=-1;
14353
14354// if ((kxI+kyI)%1 ==0)
14355// printf("Block5,kx=%d, ky=%d,kxI=%d, kyI=%d, kxBefore=%d, kyBefore=%d \n",kxAfter,kyAfter,kxI,kyI, kxBefore,kyBefore);
14356// printf(" %d, %d, %d, %d, %d, %d, %d, %d \n",IsComplexConj,kxAfter,kyAfter, kyAfterInd,kxI,kyI, kxBefore,kyBefore);
14357
14358 CurrentValue = image -> get_value_at(2*kxAfter,kyAfterInd, kzAfterInd); // Update real part of Image
14359 ToAdd = WeightNowX*WeightNowY*WeightNowZ*(RotIm -> get_value_at(2*kxBefore,kyBefore, kzBefore));
14360 image -> set_value_at(2*kxAfter ,kyAfterInd , kzAfterInd, ToAdd + CurrentValue );
14361
14362
14363 CurrentValue = WeightIm -> get_value_at(kxAfter,kyAfterInd, kzAfterInd); // Update real part of Weight image
14364 ToAdd = WeightNowX*WeightNowY;
14365 WeightIm -> set_value_at(kxAfter , kyAfterInd , kzAfterInd, abs(ToAdd) + CurrentValue );
14366
14367 CurrentValue = image -> get_value_at(2*kxAfter+1,kyAfterInd); // Update imaginary part of image
14368 ToAdd = IsComplexConj*WeightNowX*WeightNowY*RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore );
14369 image -> set_value_at(2*kxAfter+1 , kyAfterInd , kzAfterInd, ToAdd + CurrentValue );
14370
14371
14372 }}}
14373
14374
14375 }}}
14376
14377// Set the image values to the rotated image, because we do it in place
14378
14379
14380 if (debug) { image -> write_image("RotImageBeforeFinalPhaseCorrection.hdf");
14381 printf(" Just wrote RotImageBeforeFinalPhaseCorrection.hdf \n"); }
14382
14383
14384 for (kxBefore = 0; kxBefore <= N ; ++kxBefore) { // This is the normalization step
14385 for (kyBefore = 0; kyBefore < y_size ; ++kyBefore) { // These are the kx, ky, kz coordinates of the original image
14386 for (kzBefore = 0; kzBefore < z_size ; ++kzBefore) {
14387
14388 float CurrentReal = image -> get_value_at(2*kxBefore , kyBefore, kzBefore);
14389 float CurrentImag = image -> get_value_at(2*kxBefore+1 , kyBefore, kzBefore);
14390
14391 PhaseFinalIm -> set_value_at(kxBefore,kyBefore, kzBefore, atan2(CurrentImag,CurrentReal));
14392 MagFinalIm -> set_value_at(kxBefore,kyBefore, kzBefore, sqrt(CurrentImag*CurrentImag+CurrentReal*CurrentReal) );
14393 float WeightNow = WeightIm -> get_value_at(kxBefore,kyBefore, kzBefore);
14394 if (WeightNow>0) {
14395 float val = (image->get_value_at(2*kxBefore , kyBefore, kzBefore))/WeightNow;
14396 image -> set_value_at(2*kxBefore , kyBefore, kzBefore, val);
14397 val = (image->get_value_at(2*kxBefore +1 , kyBefore, kzBefore))/WeightNow;
14398 image -> set_value_at(2*kxBefore +1 , kyBefore, kzBefore, val);
14399 }
14400
14401 }}}
14402
14403 if (debug) { printf(" Just did normalization step \n");}
14404
14405
14406 for ( kxBefore = 0; kxBefore < Mid ; ++kxBefore) { // This is the rephase step
14407 for ( kyBefore = 0; kyBefore < y_size ; ++kyBefore) {
14408 for ( kzBefore = 0; kzBefore < z_size ; ++kzBefore) {
14409
14410 float CurrentReal = image -> get_value_at(2*kxBefore ,kyBefore, kzBefore);
14411 float CurrentImag = image -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
14412
14413// float Phase = +2*pi*(kxBefore+kyBefore+kzBefore)*(Mid)/y_size;
14414 float Phase = pi*(kxBefore + kyBefore + kzBefore)*x_size/y_size;
14415 // Phase = 0; // Offset should be Mid-1
14416 float CosPhase = cos( Phase);
14417 float SinPhase = sin( Phase);
14418
14419 float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
14420 float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
14421
14422 image ->set_value_at(2*kxBefore, kyBefore, kzBefore, NewRealValue);
14423 image ->set_value_at(2*kxBefore+1,kyBefore, kzBefore, NewImagValue);
14424 }}}
14425
14426 if (debug) {
14427 image -> write_image("RotatedImageFFT.hdf");
14428 PhaseFinalIm -> write_image("PhaseImInFS.hdf"); // These are the phases,mags of the image when properly centered
14429 MagFinalIm -> write_image("MagFinalImInFS.hdf");
14430 WeightIm -> write_image("WeightIm.hdf");
14431 printf(" Just wrote RotatedImageFFT.hdf \n");
14432 }
14433
14434 image -> update();
14435
14436}
14437
14438EMData* CircularAverageBinarizeProcessor::process(const EMData* const image) // now do it layer by layer in 3d
14439{
14440 int thr=params.set_default("thresh",5);
14441
14442 EMData* bwmap= image -> copy();
14443 int x_size = image->get_xsize();
14444 int y_size = image->get_ysize();
14445 int z_size = image->get_zsize();
14446
14447 int ix,iy,iz,it,count,ic;
14448 int *dx=new int[thr*8],*dy=new int[thr*8];
14449 for (it=1; it<=thr; it++){
14450 // calculate the indexes
14451 count=0;
14452 for (ix=-thr-1; ix<=thr+1; ix++){
14453 for (iy=-thr-1; iy<=thr+1; iy++){
14454 int d2=ix*ix+iy*iy;
14455 if (d2>=it*it && d2<(it+1)*(it+1)){
14456 dx[count]=ix;
14457 dy[count]=iy;
14458 count++;
14459 }
14460 }
14461 }
14462 // for each pixel
14463 for (iz=0; iz<z_size; iz++){
14464 for (ix=0; ix<x_size; ix++){
14465 for (iy=0; iy<y_size; iy++){
14466 // circular average on each ring
14467 float mn=0;
14468 if (bwmap->get_value_at(ix,iy,iz)==0)
14469 continue;
14470 for (ic=0; ic<count; ic++){
14471 mn+=image->sget_value_at(ix+dx[ic],iy+dy[ic],iz);
14472 }
14473 mn/=count;
14474 if (mn>bwmap->get_value_at(ix,iy,iz))
14475 mn=0;
14476 bwmap->set_value_at(ix,iy,iz,mn);
14477 }
14478 }
14479 }
14480 }
14481 // binarize image
14482 for (iz=0; iz<z_size; iz++){
14483 for (ix=0; ix<x_size; ix++){
14484 for (iy=0; iy<y_size; iy++){
14485 if (bwmap->get_value_at(ix,iy,iz)>0)
14486 bwmap->set_value_at(ix,iy,iz,1);
14487 else
14488 bwmap->set_value_at(ix,iy,iz,0);
14489 }
14490 }
14491 }
14492 delete[] dx;
14493 delete[] dy;
14494 return bwmap;
14495
14496
14497}
14499{
14500 EMData *tmp=process(image);
14501 memcpy(image->get_data(),tmp->get_data(),(size_t)image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
14502 delete tmp;
14503 image->update();
14504 return;
14505
14506}
14507
14509{
14510
14511 EMData* imageCp= image -> copy();
14512 process_inplace(imageCp);
14513
14514 return imageCp;
14515}
14516
14518{
14519 int nx = image->get_xsize();
14520 int ny = image->get_ysize();
14521 int nz = image->get_zsize();
14522
14523 float threshold=params.set_default("thresh",0);
14524
14525 // label each object first
14526 EMData *label=image->process("threshold.belowtozero",Dict("minval",threshold));
14527 label->process_inplace("threshold.notzero");
14528 label->process_inplace("morph.object.label");
14529 int nobj=int(label->get_attr("maximum"))+1;
14530 vector<float> sden(nobj); // sum density of each object
14531 for (int i=0; i<nobj; i++) sden[i]=0;
14532
14533 for (int x=0; x<nx; x++){
14534 for (int y=0; y<ny; y++){
14535 for (int z=0; z<nz; z++){
14536 float v=image->get_value_at(x,y,z);
14537 if (v<threshold)
14538 continue;
14539
14540 int li=label->get_value_at(x,y,z);
14541 sden[li]+=v;
14542 }
14543 }
14544 }
14545 for (int x=0; x<nx; x++){
14546 for (int y=0; y<ny; y++){
14547 for (int z=0; z<nz; z++){
14548 int li=label->get_value_at(x,y,z);
14549 if (li==0)
14550 continue;
14551 image->set_value_at_fast(x,y,z,sden[li]);
14552 }
14553 }
14554 }
14555 delete label;
14556}
14558{
14559
14560 EMData* imageCp= image -> copy();
14561 process_inplace(imageCp);
14562
14563 return imageCp;
14564}
14565
14567{
14568 // Now treats 3d volume as 2d slices
14569 bool writecenter=params.set_default("write_centers",false);
14570 int nx = image->get_xsize();
14571 int ny = image->get_ysize();
14572 int nz = image->get_zsize();
14573
14574 int y1;
14575 bool spanLeft, spanRight;
14576 vector<Vec3i> pvec;
14577 float cx,cy;
14578 int npx;
14579 int count=0;
14580 vector<float> centers(2);
14581 for (int zz = 0; zz < nz; zz++) {
14582
14583 for (int yy = 0; yy < ny; yy++) {
14584 for (int xx = 0; xx < nx; xx++) {
14585 if (image->get_value_at(xx,yy,zz)>0){
14586 pvec.push_back(Vec3i(xx,yy,zz));
14587 if (writecenter && count<0){
14588 cx/=npx;cy/=npx;
14589 centers.push_back(cx);
14590 centers.push_back(cy);
14591 cx=cy=0;npx=0;
14592 }
14593 count--;
14594 }
14595 while(!pvec.empty())
14596 {
14597 Vec3i v=pvec.back();
14598 int x=v[0],y=v[1],z=v[2];
14599// printf("%d\t%d\t%d\n",x,y,z);
14600 pvec.pop_back();
14601 y1 = y;
14602 while(y1 > 0 && image->get_value_at(x,y1,zz)>0) y1--;
14603// y1++;
14604 spanLeft = spanRight = 0;
14605 bool nowstop=0;
14606 while(1)
14607 {
14608 if(image->get_value_at(x,y1,zz)>0){
14609 image->set_value_at(x,y1,zz,count);
14610 if (writecenter){
14611 cx+=x;cy+=y1;npx++;
14612 }
14613 }
14614
14615// printf("\t %d\t%d\t%d\n",x,y1,z);
14616 if(!spanLeft && x > 0 && image->get_value_at(x-1,y1,zz)>0)
14617 {
14618 pvec.push_back(Vec3i(x-1,y1,zz));
14619 spanLeft = 1;
14620 }
14621 else if(spanLeft && x > 0 && image->get_value_at(x-1,y1,zz)<=0)
14622 {
14623 spanLeft = 0;
14624 }
14625 if(!spanRight && x < nx - 1 && image->get_value_at(x+1,y1,zz)>0)
14626 {
14627 pvec.push_back(Vec3i(x+1,y1,zz));
14628 spanRight = 1;
14629 }
14630 else if(spanRight && x < nx - 1 && image->get_value_at(x+1,y1,zz)<=0)
14631 {
14632 spanRight = 0;
14633 }
14634 y1++;
14635 if (nowstop)
14636 break;
14637 if (y1 >= ny-1 || image->get_value_at(x,y1,zz)<=0)
14638 nowstop=1;
14639 }
14640 }
14641
14642
14643 }
14644 }
14645 }
14646 printf("%d objects.\n",-count);
14647 image->mult(-1);
14648 if (writecenter) image->set_attr("obj_centers",centers);
14649}
14650
14652{
14653
14654 EMData* imageCp= image -> copy();
14655 process_inplace(imageCp);
14656
14657 return imageCp;
14658}
14659
14661
14662 int nx = image->get_xsize();
14663 int ny = image->get_ysize();
14664 int nz = image->get_zsize();
14665
14666 float threshold=params.set_default("thresh",0);
14667 int ntimes=params.set_default("ntimes",-1);
14668 int verbose=params.set_default("verbose",0);
14669 int preserve=params.set_default("preserve_value",false);
14670 float array[9];
14671 int n=1;
14672 EMData* imageCp;
14673 if (preserve)
14674 imageCp= image -> copy();
14675 float *data = image->get_data();
14676 size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
14677 int nxy = nx * ny;
14678 // binarize image and deal with boundary points first
14679 float *data2 = new float[total_size];
14680 for (int k=0; k<nz; k++){
14681 if (verbose>0)
14682 printf("layer %d \n",k);
14683 size_t knxy = (size_t)k * nxy;
14684 for (int j=0; j<ny; j++){
14685 int jnx = j * nx;
14686 for (int i=0; i<nx; i++){
14687 if(i==0 || i==nx-1 || j==0 || j==ny-1)
14688 data[i+jnx+knxy]=0;
14689 else{
14690 if (data[i+jnx+knxy]>threshold)
14691 data[i+jnx+knxy]=1;
14692 else
14693 data[i+jnx+knxy]=0;
14694 }
14695 }
14696 }
14697
14698 int allt=ntimes;
14699 if (ntimes<0){ // thin to skeleton
14700 allt=65535;
14701 }
14702 // thinning
14703 int cg;
14704 for (int nt=0; nt<allt; nt++){
14705 cg=0;
14706 for (int st = 0; st<2; st++){
14707 memcpy(data2, data, total_size * sizeof(float));
14708 for (int j = n; j < ny - n; j++) {
14709 int jnx = j * nx;
14710 for (int i = n; i < nx - n; i++) {
14711 size_t s = 0;
14712 for (int i2 = i - n; i2 <= i + n; i2++) {
14713 for (int j2 = j - n; j2 <= j + n; j2++) {
14714 array[s] = data2[i2 + j2 * nx+knxy];
14715 ++s;
14716 }
14717 }
14718
14719 cg+=process_pixel(&data[i + jnx+knxy ], array, st);
14720 }
14721 }
14722 }
14723 if (verbose>1)
14724 printf("\t Iter %d, \t %d pixels changed\n",nt,cg);
14725 if(cg==0)
14726 break;
14727 }
14728
14729 // remove corner pixels when doing skeletonization
14730 if (ntimes<0){
14731 cg=0;
14732 memcpy(data2, data, total_size * sizeof(float));
14733 for (int j = n; j < ny - n; j++) {
14734 int jnx = j * nx;
14735 for (int i = n; i < nx - n; i++) {
14736 size_t s = 0;
14737 for (int i2 = i - n; i2 <= i + n; i2++) {
14738 for (int j2 = j - n; j2 <= j + n; j2++) {
14739 array[s] = data2[i2 + j2 * nx+knxy];
14740 ++s;
14741 }
14742 }
14743
14744 cg+=process_pixel(&data[i + jnx+knxy ], array, 2);
14745 }
14746 }
14747 }
14748 if (verbose>1)
14749 printf("\t %d corner pixels\n",cg);
14750 }
14751 image->update();
14752
14753 if( data2 )
14754 {
14755 delete[]data2;
14756 data2 = 0;
14757 }
14758
14759 if (preserve){
14760 image->mult(*imageCp);
14761 delete imageCp;
14762 }
14763
14764}
14765
14766
14767int BwThinningProcessor::process_pixel(float* data, float* array, int step){
14768
14769 if (*data==0){
14770 return 0;
14771 }
14772 int bp=-1; // number of 1 neighbors, not counting itself
14773 for (int i=0; i<9; i++){
14774 if (array[i]>0)
14775 bp++;
14776 }
14777 if (bp<2 || bp>6){
14778 return 0;
14779 }
14780 int ap=0; // number of transitions from 0 to 1
14781 int order[9]={0,1,2,5,8,7,6,3,0};
14782 for (int i=0; i<8; i++){
14783 if (array[order[i]]==0 && array[order[i+1]]>0){
14784 ap++;
14785 }
14786 }
14787 if (ap!=1 && step<2)
14788 return 0;
14789
14790 if (step==0){
14791 if(array[order[1]]*array[order[3]]*array[order[5]]>0)
14792 return 0;
14793 if(array[order[3]]*array[order[5]]*array[order[7]]>0)
14794 return 0;
14795 }
14796
14797 if (step==1){
14798 if(array[order[1]]*array[order[3]]*array[order[7]]>0)
14799 return 0;
14800 if(array[order[1]]*array[order[5]]*array[order[7]]>0)
14801 return 0;
14802 }
14803
14804 if (step==2){
14805 if (bp==2){
14806 if(array[order[1]]*array[order[3]]>0
14807 || array[order[3]]*array[order[5]]>0
14808 || array[order[5]]*array[order[7]]>0
14809 || array[order[7]]*array[order[1]]>0
14810 ){
14811 *data=0;
14812 return 1;
14813 }
14814 else{
14815 return 0;
14816 }
14817 }
14818 if (ap==2 ){
14819 if(array[order[1]]*array[order[3]]>0
14820 || array[order[3]]*array[order[5]]>0
14821 ){
14822 *data=0;
14823 return 1;
14824 }
14825 else{
14826 return 0;
14827 }
14828 }
14829 return 0;
14830 }
14831
14832 *data=0;
14833 return 1;
14834
14835}
14836
14838{
14839 EMData* imageCp= image -> copy();
14840 process_inplace(imageCp);
14841 return imageCp;
14842}
14843
14845 // This function is far from optimized, but it works...
14846
14847 int nx = image->get_xsize();
14848 int ny = image->get_ysize();
14849 int nz = image->get_zsize();
14850
14851 float threshold=params.set_default("thresh",0);
14852 int verbose=params.set_default("verbose",0);
14853 int maxdist=params.set_default("maxdist",3);
14854 bool returnlength=params.set_default("returnlength",false);
14855/*
14856 if (nz > 1) {
14857 ImageDimensionException("Only 2-D images supported");
14858 }*/
14859
14860 float *data = image->get_data();
14861 size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
14862
14863 float *data2 = new float[total_size];
14864 memcpy(data2, data, total_size * sizeof(float));
14865 int nxy = nx * ny;
14866 // binarize image and deal with boundary points first
14867 for (int k=0; k<nz; k++){
14868 if (verbose>0)
14869 printf("layer %d \n",k);
14870 size_t knxy = (size_t)k * nxy;
14871 // binarize image first
14872 for (int j=0; j<ny; j++){
14873 int jnx = j * nx;
14874 for (int i=0; i<nx; i++){
14875
14876 if (data[knxy+i+jnx]>threshold)
14877 data[knxy+i+jnx]=1;
14878 else
14879 data[knxy+i+jnx]=0;
14880 }
14881 }
14882
14883 float array[9];
14884 image->to_zero();
14885
14886 // find branch points
14887 int nbranch=0;
14888 for (int j=1; j < ny-1; j++) {
14889 int jnx = j * nx;
14890 for (int i=1; i<nx-1; i++) {
14891
14892 if (data2[knxy+i+jnx]<=threshold)
14893 continue;
14894 int s=0;
14895 for (int i2 = i-1; i2 <= i + 1; i2++) {
14896 for (int j2 = j - 1; j2 <= j + 1; j2++) {
14897 array[s++] = data2[knxy+i2 + j2 * nx];
14898 }
14899 }
14900 int ap=0; // number of transitions from 0 to 1
14901 int order[9]={0,1,2,5,8,7,6,3,0};
14902 for (int oi=0; oi<8; oi++){
14903 if (array[order[oi]]<=threshold && array[order[oi+1]]>threshold){
14904 ap++;
14905 }
14906 }
14907 if (ap>2){
14908 data[knxy+i+jnx]=1;
14909 nbranch++;
14910 }
14911 }
14912 }
14913 if (verbose>0)
14914 printf("\t %d branch pixels\n",nbranch);
14915
14916 // now, data->branch points, data2->binarized image
14917
14918 // distance to branch point
14919 for (int j=1; j<ny; j++){
14920 int jnx=j*nx;
14921 for (int i=0; i<nx; i++){
14922 data[knxy+i+jnx]=(1-data[knxy+i+jnx])*(maxdist+1);
14923 }
14924
14925 }
14926 for (int dt=0; dt<maxdist; dt++){
14927 for (int j=1; j < ny-1; j++) {
14928 int jnx=j*nx;
14929 for (int i=1; i<nx-1; i++) {
14930
14931 if (data2[knxy+i+jnx]<=threshold)
14932 continue;
14933 if (data[knxy+i+jnx]<=maxdist)
14934 continue;
14935 int db=maxdist; // distance from nearest branch point.
14936 for (int i2=i-1; i2<=i+1; i2++) {
14937 for (int j2=j-1; j2<=j+1; j2++) {
14938 db=(data[knxy+i2+j2*nx]==dt ? dt : db);
14939 }
14940 }
14941 data[knxy+i+jnx]=db+1;
14942 }
14943 }
14944 }
14945 // now, data->distance to the nearest branch point
14946
14947 if (returnlength==false){
14948 // mark endpoints for deletion
14949 int nend=0;
14950 for (int j=1; j < ny-1; j++) {
14951 int jnx=j*nx;
14952 for (int i=1; i<nx-1; i++) {
14953
14954 if (data2[knxy+i+jnx]<=threshold)
14955 continue;
14956 if (data[knxy+i+jnx]>maxdist)
14957 continue;
14958 int nb=-1; // number of neighbors
14959 for (int i2=i-1; i2<=i+1; i2++) {
14960 for (int j2=j-1; j2<=j+1; j2++) {
14961 nb+=(data2[knxy+i2+j2*nx]>threshold ? 1 : 0);
14962 }
14963 }
14964 if (nb==1){ // endpoint found
14965 data[knxy+i+jnx]=-data[knxy+i+jnx]; //mark for deletion
14966 data2[knxy+i+jnx]=threshold;
14967 nend++;
14968 }
14969 }
14970 }
14971
14972 // remove marked branches
14973 for (int dt=-maxdist; dt<-1; dt++){
14974 for (int j=1; j < ny-1; j++) {
14975 int jnx=j*nx;
14976 for (int i=1; i<nx-1; i++) {
14977
14978 if (data2[knxy+i+jnx]<=threshold)
14979 continue;
14980 if (data[knxy+i+jnx]<=0)
14981 continue;
14982 int rm=0; // delete this pixel
14983 for (int i2=i-1; i2<=i+1; i2++) {
14984 for (int j2=j-1; j2<=j+1; j2++) {
14985 rm=( data[knxy+i2+j2*nx]==dt ? 1 : rm );
14986 }
14987 }
14988 if (rm>0){
14989 data2[knxy+i+jnx]=threshold;
14990 data[knxy+i+jnx]=dt+1;
14991 }
14992 }
14993 }
14994 }
14995 if (verbose>0)
14996 printf("\t %d branches removed\n",nend);
14997 }
14998 }
14999 if (returnlength==false){
15000 memcpy(data, data2, total_size * sizeof(float));
15001 }
15002
15003
15004 image->update();
15005 if( data2 )
15006 {
15007 delete[]data2;
15008 data2 = 0;
15009 }
15010
15011}
15012
15014{
15015 EMData* imageCp= image -> copy();
15016 process_inplace(imageCp);
15017 return imageCp;
15018}
15019
15021 // This function is far from optimized, but it works...
15022
15023 int nx = image->get_xsize();
15024 int ny = image->get_ysize();
15025 int nz = image->get_zsize();
15026
15027 int verbose=params.set_default("verbose",0);
15028 int rad=params.set_default("radius",3);
15029
15030
15031 float *data = image->get_data();
15032 // the index of the boundary points of the box
15033 int *xlist=new int[2*rad*4];
15034 int *ylist=new int[2*rad*4];
15035 int count=0;
15036 for (int i=-rad; i<rad; i++){ xlist[count]=-rad; ylist[count]=i; count++;}
15037 for (int i=-rad; i<rad; i++){ xlist[count]=i; ylist[count]=rad; count++;}
15038 for (int i=-rad; i<rad; i++){ xlist[count]=rad; ylist[count]=-i; count++;}
15039 for (int i=-rad; i<rad; i++){ xlist[count]=-i; ylist[count]=-rad; count++;}
15040 size_t nxy = nx * ny;
15041 for (int k=0; k<nz; k++){
15042 if (verbose>0)
15043 printf("Processing layer %d \n",k);
15044
15045 size_t knxy = (size_t)k * nxy;
15046 // only grow on the endpoints
15047 for (int j=rad; j < ny-rad; j++) {
15048 int jnx=j*nx;
15049 for (int i=rad; i<nx-rad; i++) {
15050
15051 if (data[knxy+i+jnx]==0)
15052 continue;
15053 int nb=-1; // number of neighbors
15054 for (int i2=i-1; i2<=i+1; i2++) {
15055 for (int j2=j-1; j2<=j+1; j2++) {
15056 nb+=(data[knxy+i2+j2*nx]>0 ? 1 : 0);
15057 }
15058 }
15059 if (nb==1){ // endpoint found
15060 int nv=0,cp=0;
15061 for (int ic=0; ic<count; ic++){
15062 int ix=i+xlist[ic], jy=j+ylist[ic];
15063 float v=data[knxy+ix+jy*nx];
15064 if (v>0){
15065 nv++;
15066 cp=ic;
15067 }
15068 }
15069 if (nv != 1)
15070 // more than one possible directions
15071 continue;
15072
15073 // grow towards the oppisite direction
15074 for (int ig=1; ig<=rad; ig++){
15075 int ix=i-(float)xlist[cp]/rad*ig;
15076 int jy=j-(float)ylist[cp]/rad*ig;
15077 data[knxy+ix+jy*nx]=-1;
15078 }
15079 }
15080 }
15081 }
15082
15083 for (int j=rad; j < ny-rad; j++) {
15084 int jnx=j*nx;
15085 for (int i=rad; i<nx-rad; i++) {
15086 if (data[knxy+i+jnx]==-1)
15087 data[knxy+i+jnx]=1;
15088 }
15089 }
15090 }
15091 image->update();
15092
15093 delete[] xlist;
15094 delete[] ylist;
15095
15096}
15097
15099{
15100 EMData* proc = image->copy();
15101 proc->process_inplace("math.distance.manhattan");
15102 return proc;
15103}
15104
15106{
15107 if (!image) {
15108 LOGWARN("NULL Image");
15109 return;
15110 }
15111
15112 int nx = image->get_xsize();
15113 int ny = image->get_ysize();
15114 int nz = image->get_zsize();
15115 int size = nx*ny*nz;
15116
15117 // traverse from top left to bottom right
15118 for (int i=0; i<nx; i++) {
15119 for (int j=0; j<ny; j++) {
15120 for (int k=0; k<nz; k++) {
15121 if (image->get_value_at(i,j,k) == 1) {
15122 image->set_value_at_fast(i,j,k,0); // first pass and pixel was on, it gets a zero
15123 } else {
15124 image->set_value_at_fast(i,j,k,size+nx); // pixel was off. It is at most the sum of the lengths of the array away from a pixel that is on...
15125 float north = Util::get_min(image->get_value_at(i,j,k),image->get_value_at(i-1,j,k)+1);
15126 float west = Util::get_min(image->get_value_at(i,j,k),image->get_value_at(i,j-1,k)+1);
15127 float above = Util::get_min(image->get_value_at(i,j,k),image->get_value_at(i,j,k-1)+1);
15128 if (i>0) image->set_value_at_fast(i,j,k,north); // or one more than the pixel to the north
15129 if (j>0) image->set_value_at_fast(i,j,k,west); // or one more than the pixel to the west
15130 if (k>0) image->set_value_at_fast(i,j,k,above); // or one more than the pixel above
15131 }
15132 }
15133 }
15134 }
15135
15136 // traverse from bottom right to top left. Pixels will either be what we had on the first pass...
15137 for (int i=nx-2; i>=0; i--) {
15138 for (int j=ny-2; j>=0; j--) {
15139 for (int k=nz-2; k>=0; k--) {
15140 if (image->get_value_at(i,j,k) == 1) {
15141 image->set_value_at_fast(i,j,k,0); // first pass and pixel was on, it gets a zero
15142 } else {
15143 float south = Util::get_min(image->get_value_at(i,j,k),image->get_value_at(i+1,j,k)+1);
15144 float east = Util::get_min(image->get_value_at(i,j,k),image->get_value_at(i,j+1,k)+1);
15145 float below = Util::get_min(image->get_value_at(i,j,k),image->get_value_at(i,j,k+1)+1);
15146 if (i+1<nx) image->set_value_at_fast(i,j,k,south); // or one more than the pixel to the south
15147 if (j+1<ny) image->set_value_at_fast(i,j,k,east); // or one more than the pixel to the east
15148 if (k+1<nz) image->set_value_at_fast(i,j,k,below); // or one more than the pixel below
15149 }
15150 }
15151 }
15152 }
15153}
15154
15156{
15157 EMData* proc = image->copy();
15158 proc->process_inplace("morph.dilate.binary",params);
15159 return proc;
15160}
15161
15163{
15164 int iters = params.set_default("iters",1);
15165 int radius = params.set_default("radius",1);
15166 float thresh = params.set_default("threshold",0.01);
15167
15168 if (!image) {
15169 LOGWARN("NULL Image");
15170 return;
15171 }
15172
15173 int nx = image->get_xsize();
15174 int ny = image->get_ysize();
15175 int nz = image->get_zsize();
15176 int imsize = nx*ny*nz;
15177
15178 EMData *binarized = image->process("threshold.binary",Dict("value",thresh));
15179 memcpy(image->get_data(),binarized->get_data(),imsize*sizeof(float));
15180 delete binarized;
15181 image->update();
15182
15183 if ( radius == 0 || iters == 0) {
15184 return;
15185 }
15186
15187 image->mult(-1);
15188 image->add(1);
15189 for (int iter = 0; iter < iters; iter++) {
15190 image->process_inplace("math.distance.manhattan");
15191 for (int i=0; i < nx; i++){
15192 for (int j=0; j < ny; j++){
15193 for ( int k=0; k < nz; k++) {
15194 image->set_value_at_fast(i,j,k,(image->get_value_at(i,j,k)<=radius)?1:0);
15195 }
15196 }
15197 }
15198 }
15199 image->sub(1);
15200 image->mult(-1);
15201}
15202
15204{
15205 EMData* proc = image->copy();
15206 proc->process_inplace("morph.erode.binary",params);
15207 return proc;
15208}
15209
15211{
15212 int iters = params.set_default("iters",1);
15213 int radius = params.set_default("radius",1);
15214 float thresh = params.set_default("thresh",0.01);
15215
15216 if (!image) {
15217 LOGWARN("NULL Image");
15218 return;
15219 }
15220
15221 int nx = image->get_xsize();
15222 int ny = image->get_ysize();
15223 int nz = image->get_zsize();
15224 int imsize = nx*ny*nz;
15225
15226 EMData *binarized = image->process("threshold.binary",Dict("value",thresh));
15227 memcpy(image->get_data(),binarized->get_data(),imsize*sizeof(float));
15228 delete binarized;
15229 image->update();
15230
15231 if ( radius == 0 || iters == 0) {
15232 return;
15233 }
15234
15235 for (int iter = 0; iter < iters; iter++) {
15236 image->process_inplace("math.distance.manhattan");
15237 for (int i=0; i < nx; i++){
15238 for (int j=0; j < ny; j++){
15239 for (int k=0; k < nz; k++) {
15240 image->set_value_at_fast(i,j,k,(image->get_value_at(i,j,k)<=radius)?1:0);
15241 }
15242 }
15243 }
15244 }
15245}
15246
15248{
15249 EMData* proc = image->copy();
15250 proc->process_inplace("morph.open.binary",params);
15251 return proc;
15252}
15253
15255{
15256 int iters=params.set_default("iters",1);
15257 float thresh = params.set_default("thresh",0.5);
15258 image->process_inplace("threshold.binary",Dict("value",thresh));
15259
15260 for (int i = 0; i < iters; i++) image->process_inplace("morph.erode.binary",params);
15261 for (int i = 0; i < iters; i++) image->process_inplace("morph.dilate.binary",params);
15262}
15263
15265{
15266 EMData* proc = image->copy();
15267 proc->process_inplace("morph.close.binary",params);
15268 return proc;
15269}
15270
15272{
15273 int iters=params.set_default("iters",1);
15274 float thresh = params.set_default("thresh",0.5);
15275 image->process_inplace("threshold.binary",Dict("value",thresh));
15276
15277 for (int i = 0; i < iters; i++) image->process_inplace("morph.dilate.binary",params);
15278 for (int i = 0; i < iters; i++) image->process_inplace("morph.erode.binary",params);
15279}
15280
15282{
15283 EMData* proc = image->copy();
15284 proc->process_inplace("morph.gradient.internal",params);
15285 return proc;
15286}
15287
15289{
15290 int iters=params.set_default("iters",1);
15291 float thresh = params.set_default("thresh",0.5);
15292 image->process_inplace("threshold.binary",Dict("value",thresh));
15293
15294 for (int i = 0; i < iters; i++){
15295 EMData *cpy = image->copy();
15296 cpy->process_inplace("morph.erode.binary",params);
15297 image->sub(*cpy);
15298 delete cpy;
15299 }
15300}
15301
15303{
15304 EMData* proc = image->copy();
15305 proc->process_inplace("morph.gradient.external",params);
15306 return proc;
15307}
15308
15310{
15311 int iters = params.set_default("iters",1);
15312 float thresh = params.set_default("thresh",0.5);
15313 image->process_inplace("threshold.binary",Dict("value",thresh));
15314
15315 for (int i = 0; i < iters; i++){
15316 EMData *cpy = image->copy();
15317 image->process_inplace("morph.dilate.binary",params);
15318 image->sub(*cpy);
15319 delete cpy;
15320 }
15321}
15322
15324{
15325 EMData* proc = image->copy();
15326 proc->process_inplace("morph.gradient",params);
15327 return proc;
15328}
15329
15331{
15332 int iters = params.set_default("iters",1);
15333 float thresh = params.set_default("thresh",0.5);
15334 image->process_inplace("threshold.binary",Dict("value",thresh));
15335
15336 for (int i = 0; i < iters; i++){
15337 EMData *eroded = image->process("morph.erode.binary",params);
15338 image->process_inplace("morph.dilate.binary",params);
15339 image->sub(*eroded);
15340 delete eroded;
15341 }
15342}
15343
15345{
15346 EMData* proc = image->copy();
15347 proc->process_inplace("morph.tophat.binary",params);
15348 return proc;
15349}
15350
15352{
15353 int iters=params.set_default("iters",1);
15354 float thresh = params.set_default("thresh",0.5);
15355 image->process_inplace("threshold.binary",Dict("value",thresh));
15356
15357 for (int i = 0; i < iters; i++){
15358 EMData* open = image->process("morph.open.binary",params);
15359 image->sub(*open);
15360 delete open;
15361 }
15362}
15363
15365{
15366 EMData* proc = image->copy();
15367 proc->process_inplace("morph.blackhat.binary",params);
15368 return proc;
15369}
15370
15372{
15373 int iters=params.set_default("iters",1);
15374 float thresh = params.set_default("thresh",0.5);
15375 image->process_inplace("threshold.binary",Dict("value",thresh));
15376
15377 for (int i = 0; i < iters; i++){
15378 EMData* close = image->process("morph.close.binary",params);
15379 image->sub(*close);
15380 delete close;
15381 }
15382}
15383
15385{
15386 EMData* proc = image->copy();
15387 proc->process_inplace("misc.zthick",params);
15388 return proc;
15389}
15390
15392{
15393 float thresh=params.set_default("thresh",0);
15394 int nx = image->get_xsize();
15395 int ny = image->get_ysize();
15396 int nz = image->get_zsize();
15397
15398 for (int i=0; i<nx; i++) {
15399 for (int j=0; j<ny; j++) {
15400 // depth
15401 int dep=0, starti=0;
15402 bool counting=false;
15403 for (int k=0; k<nz; k++) {
15404 if (image->get_value_at(i,j,k)>thresh){
15405 if (!counting){
15406 // start counting
15407 starti=k;
15408 dep=0;
15409 counting=true;
15410 }
15411 dep++;
15412 }
15413 else{
15414 if (counting){
15415 counting=false;
15416 // go back and set the voxels to the depth value
15417 for (int u=starti; u<k; u++){
15418 image->set_value_at_fast(i,j,u,dep);
15419// printf("%d,%d,%d,%d\n", i,j,u,dep);
15420
15421 }
15422 }
15423 }
15424 }
15425 }
15426 }
15427
15428
15429}
15430
15431
15433{
15434 EMData* proc = image->copy();
15435 proc->process_inplace("math.multamplitude",params);
15436 return proc;
15437}
15438
15440{
15441 EMData *amp=params["amp"];
15442 float* data = image->get_data();
15443 float* mult = amp->get_data();
15444
15445 int nx = image->get_xsize();
15446 int ny = image->get_ysize();
15447 int nz = image->get_zsize();
15448
15449
15450
15451 int anx = amp->get_xsize();
15452 int any = amp->get_ysize();
15453 int anz = amp->get_zsize();
15454
15455 int div=2;
15456
15457 if (nx==anx){ // in case the amplitude volume has the same size...
15458 div=1;
15459 anx=nx/2;
15460 }
15461
15462
15463
15464 if (( (nx==anx*2) && (ny==any) && (nz==anz) )==false)
15465 throw InvalidParameterException("AmpMultProcessor: amplitude image size mismatch...");
15466
15467 int sz=nx*ny*nz;
15468
15469 for (int i=0; i<sz; i++){
15470 data[i]*=mult[i/div];
15471 }
15472
15473 image->update();
15474
15475}
15476#ifdef SPARX_USING_CUDA
15477
15478/* CLASS MPICUDA_kmeans processor
15479 *
15480 */
15481#include "sparx/cuda/cuda_mpi_kmeans.h"
15482MPICUDA_kmeans::MPICUDA_kmeans() {
15483 h_IM = NULL;
15484 h_AVE = NULL;
15485 h_ASG = NULL;
15486 h_dist = NULL;
15487 h_AVE2 = NULL;
15488 h_im2 = NULL;
15489 h_NC = NULL;
15490 params = NULL;
15491 d_im = NULL;
15492 d_AVE = NULL;
15493 d_dist = NULL;
15494}
15495
15496MPICUDA_kmeans::~MPICUDA_kmeans() {
15497 if (h_IM) delete h_IM;
15498 if (h_ASG) delete h_ASG;
15499 if (h_AVE) delete h_AVE;
15500 if (h_dist) delete h_dist;
15501 if (h_AVE2) delete h_AVE2;
15502 if (h_im2) delete h_im2;
15503 if (h_NC) delete h_NC;
15504 if (params) delete params;
15505}
15506
15507#include "sparx/cuda/cuda_mpi_kmeans.h"
15508int MPICUDA_kmeans::setup(int extm, int extN, int extn, int extK, int extn_start) {
15509 m = extm; // number of pixels per image
15510 N = extN; // Total number of images
15511 n = extn; // Number of images used locally
15512 K = extK; // number of classes
15513 n_start = extn_start; // Starting point to local images
15514 size_IM = m * N; // nb elements in IM
15515 size_im = m * n; // nb elements in im
15516 size_AVE = m * K; // nb elements in ave
15517 size_dist = n * K; // nb elements in dist
15518 ite = 0; // init nb of iterations
15519 BLOCK_SIZE = 512;
15520 NB = size_dist / BLOCK_SIZE;
15521 ins_BLOCK = NB * BLOCK_SIZE;
15522 // Host memory allocation for images
15523 h_IM = (float*)malloc(size_IM * sizeof(float));
15524 if (h_IM == 0) return 1;
15525 h_im = &h_IM[n_start * m]; // for local images
15526 // Host memory allocation for the averages
15527 h_AVE = (float*)malloc(size_AVE * sizeof(float));
15528 if (h_AVE == 0) return 1;
15529 // Host memory allocation for all assignment
15530 h_ASG = (unsigned short int*)malloc(N * sizeof(unsigned short int));
15531 if (h_ASG == 0) return 1;
15532 h_asg = &h_ASG[n_start]; // for local assignment
15533 // allocate the memory for the sum squared of averages
15534 h_AVE2 = (float*)malloc(K * sizeof(float));
15535 if (h_AVE2 == 0) return 1;
15536 // allocate the memory for the sum squared of images
15537 h_im2 = (float*)malloc(n * sizeof(float));
15538 if (h_im2 == 0) return 1;
15539 // allocate the memory for the distances
15540 h_dist = (float*)malloc(size_dist * sizeof(float));
15541 if (h_dist == 0) return 1;
15542 // allocate the memory for the number of images per class
15543 h_NC = (unsigned int*)malloc(K * sizeof(unsigned int));
15544 if (h_NC == 0) return 1;
15545 // allocate the memory to parameters
15546 params = (int*)malloc(8 * sizeof(int));
15547 if (params == 0) return 1;
15548 params[0] = n;
15549 params[1] = m;
15550 params[2] = K;
15551 params[3] = 0; // Reserve for flag_stop_iteration
15552 params[4] = 0; // Reserve for ct_im_mv (debug)
15553 params[5] = BLOCK_SIZE; // Size of threads block (512)
15554 params[6] = NB; // Number of blocks which fit with BLOCK_SIZE
15555 params[7] = ins_BLOCK; // Number of blocks remaining
15556
15557
15558 return 0;
15559}
15560
15561// add image pre-process by Util.compress_image_mask
15562void MPICUDA_kmeans::append_flat_image(EMData* im, int pos) {
15563
15564 for (int i = 0; i < m ; ++i) h_IM[pos * m + i] = (*im)(i);
15565
15566}
15567
15568// cuda init mem device, cublas (get device ptr)
15569int MPICUDA_kmeans::init_mem(int numdev) {
15570 int stat = 1;
15571 float** hd_AVE = NULL;
15572 float** hd_im = NULL;
15573 float** hd_dist = NULL;
15574 hd_AVE = &d_AVE;
15575 hd_im = &d_im;
15576 hd_dist = &d_dist;
15577 stat = cuda_mpi_init(h_im, hd_im, hd_AVE, hd_dist, size_im, size_AVE, size_dist, numdev);
15578 //printf("C++ get this pointer for d_AVE: %p\n", d_AVE);
15579 //printf("C++ get this pointer for d_im: %p\n", d_im);
15580 //printf("C++ get this pointer for d_dist: %p\n", d_dist);
15581 return stat;
15582}
15583
15584// precalculate im2
15585void MPICUDA_kmeans::compute_im2() {
15586 for (int i = 0; i < n; i++) {
15587 h_im2[i] = 0.0f;
15588 for (int j = 0; j < m; j++) h_im2[i] += (h_im[i * m + j] * h_im[i * m + j]);
15589 }
15590}
15591
15592// init randomly the first assignment
15593int MPICUDA_kmeans::random_ASG(long int rnd) {
15594 srand(rnd);
15595 int ret = 20;
15596 int flag = 0;
15597 int i, k;
15598 std::cout<<"111111111 number of image==="<<N<<"number cluster=="<<K<<"img size"<<m<<std::endl;
15599 for (k = 0; k < K; k++) h_NC[k] = 0;
15600 while (ret > 0) {
15601 ret--;
15602 for (i = 0; i < N; i++) {
15603 h_ASG[i] = rand() % K;
15604 h_NC[h_ASG[i]]++;
15605 }
15606 flag = 1;
15607 k = K;
15608 while (k > 0 && flag) {
15609 k--;
15610 if (h_NC[k] <= 1) {
15611 flag = 0;
15612 if (ret == 0) {
15613 //printf("Erreur randomize assignment\n");
15614 return -1;
15615 }
15616 for (k = 0; k < K; k++) h_NC[k] = 0;
15617 }
15618 if (flag == 1) ret = 0;
15619 }
15620 }
15621
15622 return 0;
15623}
15624
15625// get back the assignment
15626vector <int> MPICUDA_kmeans::get_ASG() {
15627 vector <int> ASG(h_ASG, &h_ASG[N]);
15628 return ASG;
15629}
15630
15631// get back the global assignment
15632vector <int> MPICUDA_kmeans::get_asg() {
15633 vector <int> asg(h_asg, &h_asg[n]);
15634 return asg;
15635}
15636
15637// compute NC from ASG
15638void MPICUDA_kmeans::compute_NC() {
15639 for (int i = 0; i < K; ++i) h_NC[i] = 0;
15640 for (int i = 0; i < N; ++i) h_NC[h_ASG[i]]++;
15641}
15642
15643// get NC
15644vector <int> MPICUDA_kmeans::get_NC() {
15645 vector <int> NC(h_NC, &h_NC[K]);
15646 return NC;
15647}
15648
15649// set a new global assignment
15650void MPICUDA_kmeans::set_ASG(const vector <int>& ASG) {
15651 for (int i = 0; i < N ; ++i) h_ASG[i] = ASG[i];
15652}
15653
15654// set number of objects per group
15655void MPICUDA_kmeans::set_NC(const vector <int>& NC) {
15656 for (int i = 0; i < K; ++i) h_NC[i] = NC[i];
15657}
15658
15659// get back some information (ite and T0)
15660int MPICUDA_kmeans::get_ct_im_mv() {
15661 return params[4]; // ct_im_mov
15662}
15663
15664// set the value of T
15665void MPICUDA_kmeans::set_T(float extT) {
15666 T = extT;
15667}
15668
15669// get the T value
15670float MPICUDA_kmeans::get_T() {
15671 return T;
15672}
15673
15674// compute ave and ave2
15675void MPICUDA_kmeans::compute_AVE() {
15676 float buf = 0.0f;
15677 int i, j, c, d, ind;
15678 // compute the averages according ASG
15679 for (i = 0; i < size_AVE; ++i) h_AVE[i] = 0.0f; // set averages to zero
15680 for (i = 0; i < N; ++i) {
15681 c = h_ASG[i] * m;
15682 d = i * m;
15683 for (j = 0; j < m; ++j) h_AVE[c + j] += h_IM[d + j]; // accumulate images
15684 }
15685 for (i = 0; i < K; i++) {
15686 buf = 0.0f;
15687 for (j = 0 ; j < m; j++) {
15688 ind = i * m + j;
15689 h_AVE[ind] /= (float)h_NC[i]; // compute average
15690 buf += (h_AVE[ind] * h_AVE[ind]); // do sum squared AVE
15691 }
15692 h_AVE2[i] = buf;
15693 }
15694
15695 /*for (i = 0; i < K; i++) {
15696 std::cout<<"average image"<<std::endl;
15697 std::cout<<h_AVE[i*m+0]<<" "<<h_AVE[i*m+1]<<" "<<h_AVE[i*m+2]<<" "<<h_AVE[i*m+3]<<" "<<h_AVE[i*m+4]<<std::endl;
15698 }*/
15699
15700}
15701
15702// set averages
15703void MPICUDA_kmeans::set_AVE(EMData* im, int pos) {
15704 for (int i = 0; i < m ; ++i) h_AVE[pos * m + i] = (*im)(i);
15705}
15706
15707// get back the averages
15708vector<EMData*> MPICUDA_kmeans::get_AVE() {
15709 vector<EMData*> ave(K);
15710 for (int k = 0; k < K; ++k) {
15711 EMData* im = new EMData();
15712 im->set_size(m, 1, 1);
15713 float *ptr = im->get_data();
15714 for (int i = 0; i < m; ++i) {ptr[i] = h_AVE[k * m + i];}
15715 ave[k] = im->copy();
15716 delete im;
15717 }
15718 return ave;
15719}
15720
15721// k-means one iteration
15722int MPICUDA_kmeans::one_iter() {
15723 int status = cuda_mpi_kmeans(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params);
15724 ite++;
15725 return status;
15726}
15727// k-means SSE one iteration help function
15728/*int MPICUDA_kmeans::init_dist() {
15729
15730 int status = cuda_mpi_kmeans_dist_SSE(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params);
15731
15732 return status;
15733}*/
15734
15735/*int MPICUDA_kmeans::AVE_to_host() {
15736
15737 int status = cuda_mpi_kmeans_copy_ave_from_device(h_AVE, d_AVE, params);
15738
15739 return status;
15740}*/
15741
15742
15743int one_iter_SA();
15744// k-means SSE one iteration
15745/*int MPICUDA_kmeans::one_iter_SSE() {
15746 //if ( ite == 0)
15747
15748 if( ite ==0) {
15749 int status_init=init_dist();
15750 ttt = compute_tt();//int status = 0;
15751 printf("intial energy ===%f\n",ttt);
15752 }
15753 //std::cout<<bb<<BB<<std::endl;
15754 int status = cuda_mpi_kmeans_SSE(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params, ite, ttt);
15755
15756 //float t = compute_tt();//int status = 0;
15757 //std::cout<<"engery at iteration"<<ite<<"==="<<t<<std::endl;
15758
15759 ite++;
15760 return status;
15761}*/
15762// k-means SA one iteration
15763int MPICUDA_kmeans::one_iter_SA() {
15764 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);
15765 ite++;
15766 return status;
15767}
15768
15769// compute ji
15770vector <float> MPICUDA_kmeans::compute_ji() {
15771 int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
15772 vector <float> ji(K);
15773 int i;
15774 if (status != 0) {
15775 for (i = 0; i < K; ++i) ji[i] = -1.0;
15776 return ji;
15777 }
15778 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]]);
15779 return ji;
15780}
15781
15782
15783float MPICUDA_kmeans::compute_tt() {
15784 /*int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
15785 vector <float> ji(K);
15786 int i;
15787 if (status != 0) {
15788 for (i = 0; i < K; ++i) ji[i] = -1.0;
15789 return -11111111;
15790 }
15791 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]]);
15792 float t =0.0;
15793 for (i =0; i<K;i++)
15794 t +=ji[i];
15795 return t;*/
15796
15797
15798 vector <float> ji(K);
15799 int i,j;
15800 float dist, temp;
15801 for (i = 0; i < n; ++i)
15802 {
15803 dist =0;
15804 for ( j=0; j<m; j++) {
15805 temp = (h_im[i*m+j] -h_AVE[ h_asg[i]*m+j]);
15806 dist = dist + temp*temp;
15807 }
15808 ji[h_asg[i]] = ji[h_asg[i]]+ dist;
15809 }
15810
15811 float t =0.0;
15812 for (i =0; i<K;i++)
15813 t +=ji[i];
15814 return t;
15815}
15816
15817
15818//
15819vector <float> MPICUDA_kmeans::compute_criterion(const vector <float>& Ji) {
15820 float buf = 0.0f;
15821 float Je = 0.0f;
15822 float Tr_AVE = 0.0f;
15823 float v_max = 0.0f;
15824 float* S_AVE2 = (float*)calloc(m, sizeof(float));
15825 float* S_AVE = (float*)calloc(m, sizeof(float));
15826 vector <float> crit(4);
15827 int i, j, k;
15828 // Je
15829 for (i = 0; i < K; ++i) Je += (Ji[i] / float(m));
15830 crit[0] = Je;
15831 // trace ave
15832 for (i = 0; i < K; ++i) {
15833 for (j = 0; j < m; ++j) {
15834 S_AVE[j] += h_AVE[i * m + j];
15835 S_AVE2[j] += (h_AVE[i * m + j] * h_AVE[i * m +j]);
15836 }
15837 }
15838 buf = 1 / (float)K;
15839 for (i = 0; i < m; ++i) Tr_AVE += (buf * (S_AVE2[i] - buf * S_AVE[i] * S_AVE[i]));
15840 // Coleman
15841 crit[1] = Tr_AVE * Je;
15842 // Harabasz
15843 crit[2] = (Tr_AVE * (float)(N - K)) / (Je * (float)(K - 1));
15844 // Davies-Bouldin
15845 for (i = 0; i < K; ++i) {
15846 v_max = 0.0f;
15847 for (j = 0; j < K; ++j) {
15848 if (j != i) {
15849 buf = 0.0f;
15850 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]));
15851 buf = (Ji[i] / (float)h_NC[i] + Ji[j] / (float)h_NC[j]) * ((float)m / buf);
15852 }
15853 if (buf > v_max) v_max = buf;
15854 }
15855 crit[3] += v_max;
15856 }
15857 crit[3] /= (float)K;
15858 free(S_AVE);
15859 free(S_AVE2);
15860 return crit;
15861}
15862
15863// shutdown cublas and release device mem
15864int MPICUDA_kmeans::shutdown() {
15865 return cuda_mpi_shutdown(d_im, d_AVE, d_dist);
15866}
15868
15869#endif //SPARX_USING_CUDA
15870
15871
#define V(i, j)
Definition: analyzer.cpp:697
#define rdata(i)
Definition: analyzer.cpp:592
#define v0(i)
Definition: analyzer.cpp:698
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7535
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7165
virtual float get_sigma(EMData *)
Definition: processor.h:6523
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:5853
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7010
float get_sigma(EMData *image)
Definition: processor.cpp:5876
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1380
void process_inplace(EMData *in)
To process an image in-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1730
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:1692
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2482
virtual void create_kernel() const =0
virtual void process_pixel(float *pixel, float, float, float, float *area_matrix) const
Definition: processor.h:4384
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:6757
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8621
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8486
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:6702
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8542
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4452
Averager class defines a way to do averaging on a set of images.
Definition: averager.h:93
virtual EMData * finish()=0
Finish up the averaging and return the result.
virtual void add_image(EMData *image)
To add an image to the Averager.
Definition: averager.cpp:81
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1250
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:872
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7820
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4227
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:5334
virtual void process_inplace(EMData *image)
Definition: processor.cpp:5314
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
Operates on two images, returning an image containing the maximum/minimum/multiplied pixel (etc,...
Definition: processor.h:7780
virtual EMData * process(EMData *image)
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image, Dict &params)
Boolean shrink an image inplace.
Definition: processor.cpp:3465
EMData * process(const EMData *const image, Dict &params)
Boolean shrink an image, returning the processed image.
Definition: processor.cpp:3344
BoxStatProcessor files are a kind of neighborhood processors.
Definition: processor.h:4480
virtual EMData * process(EMData *image)
Definition: processor.cpp:2658
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2649
virtual void process_pixel(float *pixel, const float *array, int n) const =0
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
int process_pixel(float *data, float *array, int step)
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1203
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7710
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9089
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void calc_locals(EMData *image)
Definition: processor.cpp:2382
void process_inplace(EMData *image)
To process an image in-place.
The base class for fourier space processor working on individual pixels.
Definition: processor.h:4312
virtual void process_pixel(float *x) const =0
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2453
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
CoordinateProcessor applies processing based on a pixel's value and it coordinates.
Definition: processor.h:3629
virtual void calc_locals(EMData *)
Definition: processor.h:3643
virtual bool is_valid() const
Definition: processor.h:3646
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2268
virtual void process_pixel(float *pixel, int xi, int yi, int zi) const =0
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:6879
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:6871
Ctf is the base class for all CTF model.
Definition: ctf.h:60
virtual void compute_2d_complex(EMData *img, CtfType t, XYData *struct_factor=0)=0
float cs
Definition: ctf.h:87
float bfactor
Definition: ctf.h:85
float voltage
Definition: ctf.h:86
float apix
Definition: ctf.h:88
virtual vector< float > compute_1d(int size, float ds, CtfType t, XYData *struct_factor=0)=0
float defocus
Definition: ctf.h:84
@ CTF_WIENER_FILTER
Definition: ctf.h:70
@ CTF_AMP
Definition: ctf.h:65
@ CTF_INTEN
Definition: ctf.h:74
@ CTF_SNR
Definition: ctf.h:68
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2761
string get_name() const
Get the processor's name.
Definition: processor.h:4814
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4485
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
size_t size() const
Ask the Dictionary for its size.
Definition: emobject.h:519
void put(const string &key, EMObject val)
Put the value/key pair into the dictionary probably better to just use operator[].
Definition: emobject.h:545
type set_default(const string &key, type val)
Default setting behavior This can be achieved using a template - d.woolford Jan 2008 (before there wa...
Definition: emobject.h:569
bool has_key(const string &key) const
Ask the Dictionary if it as a particular key.
Definition: emobject.h:511
EMObject get(const string &key) const
Get the EMObject corresponding to the particular key Probably better to just use operator[].
Definition: emobject.h:527
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2710
string get_name() const
Get the processor's name.
Definition: processor.h:4780
virtual EMData * process(const EMData *const image)
Definition: processor.cpp:8811
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1588
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:1595
void create_radial_func(vector< float > &radial_mask) const
Definition: processor.cpp:2189
EMAN2Ctf is the default CTF model used in EMAN2.
Definition: ctf.h:237
float dfdiff
Definition: ctf.h:240
vector< float > compute_1d(int size, float ds, CtfType type, XYData *struct_factor=0)
Definition: ctf.cpp:731
void copy_from(const Ctf *new_ctf)
Definition: ctf.cpp:653
float ampcont
Definition: ctf.h:243
float dsbg
Definition: ctf.h:247
static const double pi
Definition: emobject.h:79
EMData stores an image's data and defines core image processing routines.
Definition: emdata.h:82
void translate(float dx, float dy, float dz)
Translate this image.
Definition: emdata.cpp:904
EMData * get_clip(const Region &area, const float fill=0) const
Get an inclusive clip.
Definition: emdata.cpp:592
void apply_radial_func(float x0, float dx, vector< float >array, bool interp=true)
multiplies by a radial function in fourier space.
Definition: emdata.cpp:2677
vector< float > calc_radial_dist(int n, float x0, float dx, int inten)
calculates radial distribution.
Definition: emdata.cpp:2781
vector< float > calc_hist(int hist_size=128, float hist_min=0, float hist_max=0, const float &brt=0.0f, const float &cont=1.0f)
Calculates the histogram of 'this' image.
Definition: emdata.cpp:2365
void transform(const Transform &t)
Rotate then translate the image.
Definition: emdata.h:295
EMData * convolute(EMData *with)
Convolutes 2 data sets.
Definition: emdata.cpp:3567
void clip_inplace(const Region &area, const float &fill_value=0)
Clip the image inplace - clipping region must be smaller than the current region internally memory is...
Definition: emdata.cpp:350
EMObject is a wrapper class for types including int, float, double, etc as defined in ObjectType.
Definition: emobject.h:123
@ EM_COMPRESSED
Definition: emutil.h:105
static bool is_same_size(const EMData *image1, const EMData *image2)
Check whether two EMData images are of the same size.
Definition: emutil.cpp:1224
static void * em_calloc(const size_t nmemb, const size_t size)
Definition: emutil.h:370
@ IMAGE_UNKNOWN
Definition: emutil.h:113
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:997
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:906
void process_inplace(EMData *image)
To process an image in-place.
void fft_resample(EMData *to, const EMData *const from, const float &sample_rate)
An internal function that encapsulates a routine common to both process and process inplace.
Definition: processor.cpp:3074
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:2989
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:3033
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1036
virtual EMData * process(EMData const *image)
To proccess an image out-of-place.
Definition: processor.cpp:7573
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7564
Factory is used to store objects to create new instances.
Definition: emobject.h:725
static T * get(const string &instance_name)
Definition: emobject.h:781
static vector< string > get_list()
Definition: emobject.h:837
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7773
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:3622
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:5755
FloatPoint defines a float-coordinate point in a 1D/2D/3D space.
Definition: geometry.h:278
virtual void preprocess(EMData *)
Definition: processor.h:413
virtual void create_radial_func(vector< float > &radial_mask, EMData *image) const =0
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:734
static const float kernel[12][12][12]
static const float kernel[9][9][9]
base class for Fourier filters
Definition: processor.h:333
virtual void preprocess(EMData *image)
Definition: processor.h:354
virtual void create_radial_func(vector< float > &radial_mask) const =0
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:688
virtual void process_inplace(EMData *image)
Fourier origin shift the image in the forward direction.
Definition: processor.cpp:6013
virtual void process_inplace(EMData *image)
Fourier origin shift the image in the backwards direction Should only be called after the application...
Definition: processor.cpp:5885
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1441
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:1448
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1300
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
string get_name() const
Get the processor's name.
Definition: processor.h:5208
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:3809
string get_name() const
Get the processor's name.
Definition: processor.h:5178
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:3582
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:818
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void create_radial_func(vector< float > &radial_mask, EMData *image) const
Definition: processor.cpp:2148
virtual void preprocess(EMData *image)
Definition: processor.cpp:2127
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:645
virtual EMData * create_processor_image() const =0
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8118
IntPoint defines an integer-coordinate point in a 1D/2D/3D space.
Definition: geometry.h:192
void assert_valid_aspect(const vector< int > &translation, const EMData *const image) const
Check that the particular aspect is valid.
virtual EMData * process(const EMData *const image)
virtual void process_inplace(EMData *image)
Region get_clip_region(vector< int > &translation, const EMData *const image) const
Get the clip region that will achieve the desired translation.
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8745
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7096
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1920
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:1739
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
void create_kernel() const
Definition: processor.cpp:2577
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2565
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1927
virtual void create_radial_func(vector< float > &radial_mask) const
Definition: processor.cpp:2051
void create_radial_func(vector< float > &radial_mask) const
Definition: processor.cpp:2165
void create_radial_func(vector< float > &radial_mask) const
Definition: processor.cpp:2176
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7952
void set_level(int level)
Definition: log.cpp:165
void error(const char *format,...)
log an error message.
Definition: log.cpp:156
static Log * logger()
Definition: log.cpp:80
@ ERROR_LOG
Definition: log.h:73
void create_radial_func(vector< float > &radial_mask, EMData *image) const
Definition: processor.cpp:1143
void create_radial_func(vector< float > &radial_mask) const
Definition: processor.cpp:2059
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2061
void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2336
void calc_locals(EMData *image)
Definition: processor.cpp:2399
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:785
void create_radial_func(vector< float > &radial_mask, EMData *image) const
Definition: processor.cpp:8226
void accrue_mean_one_p_five(EMData *to, const EMData *const from)
Accrue the local mean in the image 'from' to the image 'to' using the the special case shrink factor ...
Definition: processor.cpp:3289
virtual void process_inplace(EMData *image)
Mean shrink inplace.
Definition: processor.cpp:3174
virtual EMData * process(const EMData *const image)
The meanshrink processor has its own process function to minise memory usage - if this function was n...
Definition: processor.cpp:3124
void accrue_mean(EMData *to, const EMData *const from, const int shrinkfactor)
Accrue the local mean in the image 'from' to the image 'to' using the given shrinkfactor An internal ...
Definition: processor.cpp:3229
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4359
virtual void process_inplace(EMData *image)
Median shrink the image.
Definition: processor.cpp:2842
void accrue_median(EMData *to, const EMData *const from, const int shrink_factor)
Accrue the local median in the image 'from' to the image 'to' using the given shrinkfactor An interna...
Definition: processor.cpp:2911
virtual EMData * process(const EMData *const image)
The medianshrink processor has its own process function to minise memory usage - if this function was...
Definition: processor.cpp:2878
void process_inplace(EMData *in)
To process an image in-place.
float radprofile(float r, int type)
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:3724
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4756
float calc_mean(EMData *image) const
Definition: processor.cpp:4832
float calc_mean(EMData *image) const
Definition: processor.cpp:4823
float calc_mean(EMData *image) const
Definition: processor.cpp:5018
float calc_mean(EMData *image) const
Definition: processor.cpp:4904
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4685
float calc_mean(EMData *image) const
Definition: processor.cpp:4893
float calc_sigma(EMData *image) const
Definition: processor.cpp:4882
Base class for normalization processors.
Definition: processor.h:5827
virtual float calc_sigma(EMData *image) const
Definition: processor.cpp:4630
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4635
virtual float calc_mean(EMData *image) const =0
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4733
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4926
float calc_mean(EMData *image) const
Definition: processor.cpp:5009
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:5203
float calc_sigma(EMData *image) const
Definition: processor.cpp:4665
float calc_sigma(EMData *image) const
Definition: processor.cpp:4675
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4166
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2304
void fourier_phaseshift180(EMData *image)
fourier_phaseshift180 - fourier phase shift by 180 this function is called internally if the argument...
Definition: processor.cpp:6159
void swap_corners_180(EMData *image)
swap_corners_180 - works on 2D and 3D images
Definition: processor.cpp:6184
void swap_central_slices_180(EMData *image)
swap_central_slices_180 - works on 2D and 3D images
Definition: processor.cpp:6281
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:6550
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:6402
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7498
Pixel describes a 3D pixel's coordinates and its intensity value.
Definition: geometry.h:452
Typical usage of Processors are as follows:
Definition: processor.h:90
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:637
virtual void process_inplace(EMData *image)=0
To process an image in-place.
virtual string get_name() const =0
Get the processor's name.
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
string get_name() const
Get the processor's name.
Definition: processor.h:5315
void process_inplace(EMData *image)
To process an image in-place.
The wrapper class for gsl's random number generater.
Definition: randnum.h:86
void set_seed(unsigned long long seed)
Set the seed for the random number generator.
Definition: randnum.cpp:142
static Randnum * Instance()
Definition: randnum.cpp:104
float get_gauss_rand(float mean, float sigma) const
Return a Gaussian random number.
Definition: randnum.cpp:168
float get_frand(double lo=0.0, double hi=1.0) const
This function returns a random float from lo inclusive to hi.
Definition: randnum.cpp:158
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2202
The base class for real space processor working on individual pixels.
Definition: processor.h:2179
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2243
virtual void calc_locals(EMData *)
Definition: processor.h:2202
virtual void process_pixel(float *x) const =0
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:3987
string get_name() const
Get the processor's name.
Definition: processor.h:5367
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
FloatSize size
Definition: geometry.h:655
FloatPoint origin
Definition: geometry.h:654
virtual void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:5595
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:5688
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1218
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7627
virtual EMData * process(const EMData *const image)
virtual void process_inplace(EMData *image)
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7238
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2599
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8311
void create_radial_func(vector< float > &radial_mask, EMData *image) const
Definition: processor.cpp:8376
string get_name() const
Get the processor's name.
Definition: processor.h:5525
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4045
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8431
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7899
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:5188
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:5059
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8000
Symmetry3D - A base class for 3D Symmetry objects.
Definition: symmetry.h:57
static vector< Transform > get_symmetries(const string &symmetry)
Definition: symmetry.cpp:1240
virtual int point_in_which_asym_unit(const Vec3f &v) const
A function that will determine in which asymmetric unit a given vector resides The asymmetric unit 'n...
Definition: symmetry.cpp:1072
virtual vector< Transform > get_syms() const
Definition: symmetry.cpp:1224
virtual void process_inplace(EMData *image)
Make an image where the axes (where x,y and z=0) are some nono zero value.
Definition: processor.cpp:9401
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9811
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9964
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8935
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:8994
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9180
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9303
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9357
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9881
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9288
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
void preprocess(EMData *image)
Definition: processor.cpp:8923
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9509
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9483
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9688
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9601
virtual string get_name() const
Get the processor's name.
Definition: processor.h:8528
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9552
virtual string get_name() const
Get the processor's name.
Definition: processor.h:8485
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:9741
virtual void process_inplace(EMData *image)
Make a useful tomographic phantom image.
void insert_rectangle(EMData *image, const Region &region, const float &value, const Transform &t3d=Transform())
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7331
virtual void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:7423
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2429
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
float * transform(const EMData *const image, const Transform &t) const
virtual void process_inplace(EMData *image)
void assert_valid_aspect(const EMData *const image) const
virtual EMData * process(const EMData *const image)
A Transform object is a somewhat specialized object designed specifically for EMAN2/Sparx storage of ...
Definition: transform.h:75
Dict get_params(const string &euler_type) const
Get the parameters of the entire transform, using a specific euler convention.
Definition: transform.cpp:479
bool get_mirror() const
Query whether x_mirroring is occurring.
Definition: transform.cpp:1250
Vec2f transform(const float &x, const float &y) const
Transform 2D coordinates using the internal transformation matrix.
Definition: transform.h:417
void copy_matrix_into_array(float *const) const
Definition: transform.cpp:158
void set_rotation(const Dict &rotation)
Set a rotation using a specific Euler type and the dictionary interface Works for all Euler types.
Definition: transform.cpp:519
Dict get_rotation(const string &euler_type="eman") const
Get a rotation in any Euler format.
Definition: transform.cpp:829
Vec3f get_trans() const
Get the post trans as a vec3f.
Definition: transform.cpp:1046
float get_scale() const
Get the scale that was applied.
Definition: transform.cpp:1145
Transform inverse() const
Get the inverse of this transformation matrix.
Definition: transform.cpp:1327
void set_scale(const float &scale)
Set the scale.
Definition: transform.cpp:1123
bool is_identity() const
Returns whethers or this matrix is the identity.
Definition: transform.cpp:222
void set_trans(const float &x, const float &y, const float &z=0)
Set the post translation component.
Definition: transform.cpp:1036
virtual EMData * process(const EMData *const image)
See Processor comments for more details.
Definition: processor.cpp:5722
virtual void process_inplace(EMData *image)
See Processor comments for more details.
Definition: processor.cpp:5738
static void calc_least_square_fit(size_t nitems, const float *data_x, const float *data_y, float *p_slope, float *p_intercept, bool ignore_zero, float absmax=0)
calculate the least square fit value.
Definition: util.cpp:538
static int hypot3sq(int x, int y, int z)
Euclidean distance function squared in 3D: f(x,y,z) = (x*x + y*y + z*z);.
Definition: util.h:805
static float angle_norm_pi(float in)
Normalize an angle in radians so it is in the -pi to pi range.
Definition: util.h:1051
static std::complex< float > trilinear_interpolate_complex(std::complex< float > p1, std::complex< float > p2, std::complex< float > p3, std::complex< float > p4, std::complex< float > p5, std::complex< float > p6, std::complex< float > p7, std::complex< float > p8, float t, float u, float v)
Calculate trilinear interpolation.
Definition: util.h:645
static short hypot_fast_int(int x, int y)
Euclidean distance in 2D for integers computed fast using a cached lookup table.
Definition: util.cpp:764
static float angle_sub_2pi(float x, float y)
Calculate the difference of 2 angles and makes the equivalent result to be less than Pi.
Definition: util.h:1066
static int square(int n)
Calculate a number's square.
Definition: util.h:736
static int fast_floor(float x)
A fast way to calculate a floor, which is largest integral value not greater than argument.
Definition: util.h:874
static int goodf(const float *p_f)
Check whether a number is a good float.
Definition: util.h:1112
static float get_frand(int low, int high)
Get a float random number between low and high, [low, high)
Definition: util.cpp:725
static float hypot3(int x, int y, int z)
Euclidean distance function in 3D: f(x,y,z) = sqrt(x*x + y*y + z*z);.
Definition: util.h:827
static int round(float x)
Get ceiling round of a float number x.
Definition: util.h:465
static int calc_best_fft_size(int low)
Search the best FFT size with good primes.
Definition: util.cpp:1021
static void save_data(const vector< float > &x_array, const vector< float > &y_array, const string &filename)
Save (x y) data array into a file.
Definition: util.cpp:604
static float trilinear_interpolate(float p1, float p2, float p3, float p4, float p5, float p6, float p7, float p8, float t, float u, float v)
Calculate trilinear interpolation.
Definition: util.h:619
static int get_min(int f1, int f2)
Get the minimum of 2 numbers.
Definition: util.h:922
static float bilinear_interpolate(float p1, float p2, float p3, float p4, float t, float u)
Calculate bilinear interpolation.
Definition: util.h:543
static float square_sum(float x, float y)
Calcuate (x*x + y*y).
Definition: util.h:764
static float hypot_fast(int x, int y)
Euclidean distance in 2D for integers computed fast using a cached lookup table.
Definition: util.cpp:742
static float hypot2(float x, float y)
Euclidean distance function in 2D: f(x,y) = sqrt(x*x + y*y);.
Definition: util.h:774
static bool IsPower2(int x)
Return true if an integer is positive and is power of 2.
Definition: util.h:1304
The Vec2 is precisely the same as Vec3 except it works exclusively in 2D Note there are convenient ty...
Definition: vec3.h:710
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:3956
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
virtual void process_inplace(EMData *)
To process an image in-place.
virtual string get_name() const
Get the processor's name.
Definition: processor.h:8963
virtual void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1077
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:1955
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:1982
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:2043
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
Definition: processor.cpp:1991
void process_inplace(EMData *image)
To process an image in-place.
XYData defines a 1D (x,y) data set.
Definition: xydata.h:47
void make_gauss(int n, float xmax, float width)
Definition: xydata.cpp:162
void update()
Definition: xydata.cpp:53
void set_x(size_t i, float x)
Definition: xydata.h:89
size_t get_size() const
Definition: xydata.h:127
float get_y(size_t i) const
Definition: xydata.h:95
float get_yatx(float x, bool outzero=true)
Definition: xydata.cpp:172
void set_y(size_t i, float y)
Definition: xydata.h:101
float get_x(size_t i) const
Definition: xydata.h:84
vector< float > get_state() const
Definition: xydata.cpp:285
int read_file(const string &filename)
Definition: xydata.cpp:77
void set_state(vector< float >)
Definition: xydata.cpp:297
void process_inplace(EMData *image)
To process an image in-place.
void process_inplace(EMData *image)
To process an image in-place.
virtual void process_inplace(EMData *image)
To process an image in-place.
virtual EMData * process(const EMData *const image)
To proccess an image out-of-place.
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4576
void process_inplace(EMData *image)
To process an image in-place.
Definition: processor.cpp:4537
VolumeData * getVolumeData()
Definition: volume.cpp:69
void emdata_phaseorigin_to_corner(float *data, const int nx, const int ny, const int nz)
void emdata_phaseorigin_to_center(float *data, const int nx, const int ny, const int nz)
float * emdata_transform_cuda(const float *const m, const int nx, const int ny, const int nz)
void emdata_rotate_180(float *data, const int nx, const int ny)
Rotates by 180 degrees using memory swapping, uses shared memory for efficiency Works on 2D images - ...
#define Assert(s)
Define Assert() function that is effective only when -DDEBUG is used.
Definition: emassert.h:42
EMData * copy() const
This file is a part of "emdata.h", to use functions in this file, you should "#include "emdata....
EMData * log() const
return natural logarithm image for a image
void mult(int n)
multiply an integer number to each pixel value of the image.
Definition: emdata_core.h:97
void set_value_at(Vec3i loc, float val)
set_value_at with Vec3i
Definition: emdata_core.h:552
EMData * sqrt() const
return square root of current image
float get_value_at(int x, int y, int z) const
Get the pixel density value at coordinates (x,y,z).
Definition: emdata_core.h:221
EMData * log10() const
return base 10 logarithm image for a image
EMData * real() const
return real part of a complex image as a real image format, if this image is a real image,...
EMData * phase() const
return phase part of a complex image as a real image format
void div(float f)
make each pixel value divided by a float number.
void write_image(const string &filename, int img_index=0, EMUtil::ImageType imgtype=EMUtil::IMAGE_UNKNOWN, bool header_only=false, const Region *region=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)
write the header and data out to an image.
bool is_real() const
Is this a real image?
int get_ysize() const
Get the image y-dimensional size.
bool is_complex() const
Is this a complex image?
void update()
Mark EMData as changed, statistics, etc will be updated at need.
float * get_data() const
Get the image pixel density data in a 1D float array.
void process_inplace(const string &processorname, const Dict &params=Dict())
This file is a part of "emdata.h", to use functions in this file, you should "#include "emdata....
#define InvalidParameterException(desc)
Definition: exception.h:361
#define InvalidValueException(val, desc)
Definition: exception.h:285
#define ImageFormatException(desc)
Definition: exception.h:147
#define InvalidStringException(str, desc)
Definition: exception.h:306
#define ImageDimensionException(desc)
Definition: exception.h:166
#define UnexpectedBehaviorException(desc)
Definition: exception.h:400
#define InvalidCallException(desc)
Definition: exception.h:348
#define NullPointerException(desc)
Definition: exception.h:241
#define LOGWARN
Definition: log.h:53
#define LOGERR
Definition: log.h:51
#define ENTERFUNC
Definition: log.h:48
#define EXITFUNC
Definition: log.h:49
E2Exception class.
Definition: aligner.h:40
Vec3< float > Vec3f
Definition: vec3.h:693
Vec3< int > Vec3i
Definition: vec3.h:694
map< string, vector< string > > group_processors()
int multi_processors(EMData *image, vector< string > processornames)
double length(const Vector3 &v)
Definition: vecmath.h:313
void dump_processors()
map< string, vector< string > > dump_processors_list()
int MIRE(int x, int nx)
Definition: processor.cpp:2656
#define FFTRADIALOVERSAMPLE
Definition: processor.cpp:687
#define y(i, j)
Definition: projector.cpp:1516
#define x(i)
Definition: projector.cpp:1517
#define dm(i)
Definition: projector.cpp:1606
friend bool operator<(const WSsortlist &l, const WSsortlist &r)