// Remove wedge ------------------------------------------------------------ void MissingWedge::removeWedge(MultidimArray<double> &V) const { Matrix2D<double> Epos, Eneg; Euler_angles2matrix(rotPos,tiltPos,0,Epos); Euler_angles2matrix(rotNeg,tiltNeg,0,Eneg); Matrix1D<double> freq(3), freqPos, freqNeg; Matrix1D<int> idx(3); FourierTransformer transformer; MultidimArray< std::complex<double> > Vfft; transformer.FourierTransform(V,Vfft,false); FOR_ALL_ELEMENTS_IN_ARRAY3D(Vfft) { // Frequency in the coordinate system of the volume VECTOR_R3(idx,j,i,k); FFT_idx2digfreq(V,idx,freq); // Frequency in the coordinate system of the plane freqPos=Epos*freq; freqNeg=Eneg*freq; if (ZZ(freqPos)<0 || ZZ(freqNeg)>0) Vfft(k,i,j)=0; } transformer.inverseFourierTransform(); }
void actualPhaseFlip(MultidimArray<double> &I, CTFDescription ctf) { // Perform the Fourier transform FourierTransformer transformer; MultidimArray< std::complex<double> > M_inFourier; transformer.FourierTransform(I,M_inFourier,false); Matrix1D<double> freq(2); // Frequencies for Fourier plane int yDim=YSIZE(I); int xDim=XSIZE(I); double iTm=1.0/ctf.Tm; for (size_t i=0; i<YSIZE(M_inFourier); ++i) { FFT_IDX2DIGFREQ(i, yDim, YY(freq)); YY(freq) *= iTm; for (size_t j=0; j<XSIZE(M_inFourier); ++j) { FFT_IDX2DIGFREQ(j, xDim, XX(freq)); XX(freq) *= iTm; ctf.precomputeValues(XX(freq),YY(freq)); if (ctf.getValuePureWithoutDampingAt()<0) DIRECT_A2D_ELEM(M_inFourier,i,j)*=-1; } } // Perform inverse Fourier transform and finish transformer.inverseFourierTransform(); }
void getSpectrum(MultidimArray<double>& Min, MultidimArray<double>& spectrum, int spectrum_type) { MultidimArray<Complex > Faux; int xsize = XSIZE(Min); Matrix1D<double> f(3); MultidimArray<double> count(xsize); FourierTransformer transformer; spectrum.initZeros(xsize); count.initZeros(); transformer.FourierTransform(Min, Faux, false); FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(Faux) { long int idx = ROUND(sqrt(kp * kp + ip * ip + jp * jp)); if (spectrum_type == AMPLITUDE_SPECTRUM) { spectrum(idx) += abs(dAkij(Faux, k, i, j)); } else { spectrum(idx) += norm(dAkij(Faux, k, i, j)); } count(idx) += 1.; } for (long int i = 0; i < xsize; i++) if (count(i) > 0.) { spectrum(i) /= count(i); } }
void multiplyBySpectrum(MultidimArray<double>& Min, MultidimArray<double>& spectrum, bool leave_origin_intact) { MultidimArray<Complex > Faux; Matrix1D<double> f(3); MultidimArray<double> lspectrum; FourierTransformer transformer; double dim3 = XSIZE(Min) * YSIZE(Min) * ZSIZE(Min); transformer.FourierTransform(Min, Faux, false); lspectrum = spectrum; if (leave_origin_intact) { lspectrum(0) = 1.; } FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(Faux) { long int idx = ROUND(sqrt(kp * kp + ip * ip + jp * jp)); dAkij(Faux, k, i, j) *= lspectrum(idx) * dim3; } transformer.inverseFourierTransform(); }
void correctMapForMTF(MultidimArray<double >& img, FileName& fn_mtf) { FourierTransformer transformer; MultidimArray<Complex > FT; transformer.FourierTransform(img, FT, false); correctMapForMTF(FT, XSIZE(img), fn_mtf); transformer.inverseFourierTransform(); }
void getFSC(MultidimArray< double >& m1, MultidimArray< double >& m2, MultidimArray< double >& fsc) { MultidimArray< Complex > FT1, FT2; FourierTransformer transformer; transformer.FourierTransform(m1, FT1); transformer.FourierTransform(m2, FT2); getFSC(FT1, FT2, fsc); }
// Produce side info ------------------------------------------------------- void ProgDetectMissingWedge::produceSideInfo() { V.read(fn_vol); FourierTransformer transformer; MultidimArray< std::complex<double> > Vfft; transformer.FourierTransform(MULTIDIM_ARRAY(V),Vfft,false); Vmag = new MultidimArray<double>(); Vmag->resize(Vfft); FOR_ALL_ELEMENTS_IN_ARRAY3D(*Vmag) (*Vmag)(k,i,j)=20*log10(abs(Vfft(k,i,j))); }
void resizeMap(MultidimArray<double >& img, int newsize) { FourierTransformer transformer; MultidimArray<Complex > FT, FT2; transformer.FourierTransform(img, FT, false); windowFourierTransform(FT, FT2, newsize); if (img.getDim() == 2) { img.resize(newsize, newsize); } else if (img.getDim() == 3) { img.resize(newsize, newsize, newsize); } transformer.inverseFourierTransform(FT2, img); }
void randomizePhasesBeyond(MultidimArray<double>& v, int index) { MultidimArray< Complex > FT; FourierTransformer transformer; transformer.FourierTransform(v, FT, false); int index2 = index * index; FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(FT) { if (kp * kp + ip * ip + jp * jp >= index2) { double mag = abs(DIRECT_A3D_ELEM(FT, k, i, j)); double phas = rnd_unif(0., 2.*PI); double realval = mag * cos(phas); double imagval = mag * sin(phas); DIRECT_A3D_ELEM(FT, k, i, j) = Complex(realval, imagval); } } // Inverse transform transformer.inverseFourierTransform(); }
void Steerable::singleFilter(const MultidimArray<double>& Vin, MultidimArray<double> &hx1, MultidimArray<double> &hy1, MultidimArray<double> &hz1, MultidimArray<double> &Vout){ MultidimArray< std::complex<double> > H, Aux; Vout.initZeros(Vin); // Filter in X #define MINUS_ONE_POWER(n) (((n)%2==0)? 1:-1) FourierTransformer transformer; transformer.FourierTransform(hx1,H); FOR_ALL_ELEMENTS_IN_ARRAY1D(H) H(i)*= MINUS_ONE_POWER(i); FourierTransformer transformer2; MultidimArray<double> aux(XSIZE(Vin)); transformer2.setReal(aux); for (size_t k=0; k<ZSIZE(Vin); k++) for (size_t i=0; i<YSIZE(Vin); i++) { for (size_t j=0; j<XSIZE(Vin); j++) DIRECT_A1D_ELEM(aux,j)=DIRECT_A3D_ELEM(Vin,k,i,j); transformer2.FourierTransform( ); transformer2.getFourierAlias( Aux ); Aux*=H; transformer2.inverseFourierTransform( ); for (size_t j=0; j<XSIZE(Vin); j++) DIRECT_A3D_ELEM(Vout,k,i,j)=XSIZE(aux)*DIRECT_A1D_ELEM(aux,j); } // Filter in Y transformer.FourierTransform(hy1,H); FOR_ALL_ELEMENTS_IN_ARRAY1D(H) H(i)*= MINUS_ONE_POWER(i); aux.initZeros(YSIZE(Vin)); transformer2.setReal(aux); for (size_t k=0; k<ZSIZE(Vin); k++) for (size_t j=0; j<XSIZE(Vin); j++) { for (size_t i=0; i<YSIZE(Vin); i++) DIRECT_A1D_ELEM(aux,i)=DIRECT_A3D_ELEM(Vout,k,i,j); transformer2.FourierTransform( ); transformer2.getFourierAlias( Aux ); Aux*=H; transformer2.inverseFourierTransform( ); for (size_t i=0; i<YSIZE(Vin); i++) DIRECT_A3D_ELEM(Vout,k,i,j)=XSIZE(aux)*DIRECT_A1D_ELEM(aux,i); } // Filter in Z transformer.FourierTransform(hz1,H); FOR_ALL_ELEMENTS_IN_ARRAY1D(H) H(i)*= MINUS_ONE_POWER(i); aux.initZeros(ZSIZE(Vin)); transformer2.setReal(aux); for (size_t i=0; i<YSIZE(Vin); i++) for (size_t j=0; j<XSIZE(Vin); j++) { for (size_t k=0; k<ZSIZE(Vin); k++) DIRECT_A1D_ELEM(aux,k)=DIRECT_A3D_ELEM(Vout,k,i,j); transformer2.FourierTransform( ); transformer2.getFourierAlias( Aux ); Aux*=H; transformer2.inverseFourierTransform( ); for (size_t k=0; k<ZSIZE(Vin); k++) DIRECT_A3D_ELEM(Vout,k,i,j)=XSIZE(aux)*DIRECT_A1D_ELEM(aux,k); } // If Missing wedge if (MW!=NULL) MW->removeWedge(Vout); }
// Fill data array with oversampled Fourier transform, and calculate its power spectrum void Projector::computeFourierTransformMap(MultidimArray<DOUBLE> &vol_in, MultidimArray<DOUBLE> &power_spectrum, int current_size, int nr_threads, bool do_gridding) { MultidimArray<DOUBLE> Mpad; MultidimArray<Complex > Faux; FourierTransformer transformer; // DEBUGGING: multi-threaded FFTWs are giving me a headache? // For a long while: switch them off! //transformer.setThreadsNumber(nr_threads); DOUBLE normfft; // Size of padded real-space volume int padoridim = padding_factor * ori_size; // Initialize data array of the oversampled transform ref_dim = vol_in.getDim(); // Make Mpad switch (ref_dim) { case 2: Mpad.initZeros(padoridim, padoridim); normfft = (DOUBLE)(padding_factor * padding_factor); break; case 3: Mpad.initZeros(padoridim, padoridim, padoridim); if (data_dim ==3) normfft = (DOUBLE)(padding_factor * padding_factor * padding_factor); else normfft = (DOUBLE)(padding_factor * padding_factor * padding_factor * ori_size); break; default: REPORT_ERROR("Projector::computeFourierTransformMap%%ERROR: Dimension of the data array should be 2 or 3"); } // First do a gridding pre-correction on the real-space map: // Divide by the inverse Fourier transform of the interpolator in Fourier-space // 10feb11: at least in 2D case, this seems to be the wrong thing to do!!! // TODO: check what is best for subtomo! if (do_gridding)// && data_dim != 3) griddingCorrect(vol_in); // Pad translated map with zeros vol_in.setXmippOrigin(); Mpad.setXmippOrigin(); FOR_ALL_ELEMENTS_IN_ARRAY3D(vol_in) // This will also work for 2D A3D_ELEM(Mpad, k, i, j) = A3D_ELEM(vol_in, k, i, j); // Translate padded map to put origin of FT in the center CenterFFT(Mpad, true); // Calculate the oversampled Fourier transform transformer.FourierTransform(Mpad, Faux, false); // Free memory: Mpad no longer needed Mpad.clear(); // Resize data array to the right size and initialise to zero initZeros(current_size); // Fill data only for those points with distance to origin less than max_r // (other points will be zero because of initZeros() call above // Also calculate radial power spectrum power_spectrum.initZeros(ori_size / 2 + 1); MultidimArray<DOUBLE> counter(power_spectrum); counter.initZeros(); int max_r2 = r_max * r_max * padding_factor * padding_factor; FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(Faux) // This will also work for 2D { int r2 = kp*kp + ip*ip + jp*jp; // The Fourier Transforms are all "normalised" for 2D transforms of size = ori_size x ori_size if (r2 <= max_r2) { // Set data array A3D_ELEM(data, kp, ip, jp) = DIRECT_A3D_ELEM(Faux, k, i, j) * normfft; // Calculate power spectrum int ires = ROUND( sqrt((DOUBLE)r2) / padding_factor ); // Factor two because of two-dimensionality of the complex plane DIRECT_A1D_ELEM(power_spectrum, ires) += norm(A3D_ELEM(data, kp, ip, jp)) / 2.; DIRECT_A1D_ELEM(counter, ires) += 1.; } } // Calculate radial average of power spectrum FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY1D(power_spectrum) { if (DIRECT_A1D_ELEM(counter, i) < 1.) DIRECT_A1D_ELEM(power_spectrum, i) = 0.; else DIRECT_A1D_ELEM(power_spectrum, i) /= DIRECT_A1D_ELEM(counter, i); } transformer.cleanup(); }
void Postprocessing::sharpenMap() { MultidimArray<Complex > FT; FourierTransformer transformer; transformer.FourierTransform(I1(), FT, true); makeGuinierPlot(FT, guinierin); // A. If MTF curve is given, first divide by the MTF divideByMtf(FT); makeGuinierPlot(FT, guinierinvmtf); // B. Then perform B-factor sharpening if (do_fsc_weighting) { if (verb > 0) { std::cout <<"== Applying sqrt(2*FSC/(FSC+1)) weighting (as in Rosenthal & Henderson, 2003) ..." <<std::endl; } applyFscWeighting(FT, fsc_true); } makeGuinierPlot(FT, guinierweighted); global_bfactor = 0.; if (do_auto_bfac) { if (verb > 0) { std::cout <<"== Fitting straight line through Guinier plot to find B-factor ..." <<std::endl; std::cout.width(35); std::cout << std::left <<" + fit from resolution: "; std::cout << fit_minres << std::endl; std::cout.width(35); std::cout << std::left <<" + fit until resolution: "; std::cout << fit_maxres << std::endl; } fitStraightLine(guinierweighted, global_slope, global_intercept, global_corr_coeff); global_bfactor = 4. * global_slope; if (verb > 0) { std::cout.width(35); std::cout << std::left <<" + slope of fit: "; std::cout << global_slope << std::endl; std::cout.width(35); std::cout << std::left <<" + intercept of fit: "; std::cout << global_intercept << std::endl; std::cout.width(35); std::cout << std::left <<" + correlation of fit: "; std::cout << global_corr_coeff << std::endl; } } else if (ABS(adhoc_bfac) > 0.) { if (verb > 0) { std::cout <<"== Using a user-provided (ad-hoc) B-factor ..." <<std::endl; } if (adhoc_bfac > 0.) std::cout <<" WARNING: using a positive B-factor. This will effectively dampen your map. Use negative value to sharpen it!" << std::endl; global_bfactor = adhoc_bfac; } // Now apply the B-factor if (ABS(global_bfactor) > 0.) { if (verb > 0) { std::cout.width(35); std::cout << std::left <<" + apply b-factor of: "; std::cout << global_bfactor << std::endl; } applyBFactorToMap(FT, XSIZE(I1()), global_bfactor, angpix); } makeGuinierPlot(FT, guiniersharpen); if (verb > 0) { std::cout << "== Low-pass filtering final map ... " << std::endl; } DOUBLE my_filter = (low_pass_freq > 0.) ? low_pass_freq : global_resol; if (verb > 0) { std::cout.width(35); std::cout << std::left <<" + filter frequency: "; std::cout << my_filter << std::endl; } lowPassFilterMap(FT, XSIZE(I1()), my_filter, angpix, filter_edge_width); transformer.inverseFourierTransform(FT, I1()); }