Exemple #1
0
// Inforce Hermitian symmetry ---------------------------------------------
void FourierTransformer::enforceHermitianSymmetry()
{
	int ndim = 3;
	if (ZSIZE(*fReal) == 1)
	{
		ndim = 2;
		if (YSIZE(*fReal) == 1)
		{
			ndim = 1;
		}
	}
	long int yHalf = YSIZE(*fReal) / 2;
	if (YSIZE(*fReal) % 2 == 0)
	{
		yHalf--;
	}
	long int zHalf = ZSIZE(*fReal) / 2;
	if (ZSIZE(*fReal) % 2 == 0)
	{
		zHalf--;
	}
	switch (ndim)
	{
	case 2:
		for (long int i = 1; i <= yHalf; i++)
		{
			long int isym = intWRAP(-i, 0, YSIZE(*fReal) - 1);
			Complex mean = 0.5 * (
			                   DIRECT_A2D_ELEM(fFourier, i, 0) +
			                   conj(DIRECT_A2D_ELEM(fFourier, isym, 0)));
			DIRECT_A2D_ELEM(fFourier, i, 0) = mean;
			DIRECT_A2D_ELEM(fFourier, isym, 0) = conj(mean);
		}
		break;
	case 3:
		for (long int k = 0; k < ZSIZE(*fReal); k++)
		{
			long int ksym = intWRAP(-k, 0, ZSIZE(*fReal) - 1);
			for (long int i = 1; i <= yHalf; i++)
			{
				long int isym = intWRAP(-i, 0, YSIZE(*fReal) - 1);
				Complex mean = 0.5 * (
				                   DIRECT_A3D_ELEM(fFourier, k, i, 0) +
				                   conj(DIRECT_A3D_ELEM(fFourier, ksym, isym, 0)));
				DIRECT_A3D_ELEM(fFourier, k, i, 0) = mean;
				DIRECT_A3D_ELEM(fFourier, ksym, isym, 0) = conj(mean);
			}
		}
		for (long int k = 1; k <= zHalf; k++)
		{
			long int ksym = intWRAP(-k, 0, ZSIZE(*fReal) - 1);
			Complex mean = 0.5 * (
			                   DIRECT_A3D_ELEM(fFourier, k, 0, 0) +
			                   conj(DIRECT_A3D_ELEM(fFourier, ksym, 0, 0)));
			DIRECT_A3D_ELEM(fFourier, k, 0, 0) = mean;
			DIRECT_A3D_ELEM(fFourier, ksym, 0, 0) = conj(mean);
		}
		break;
	}
}
void FourierProjector::produceSideInfo()
{
    // Zero padding
    MultidimArray<double> Vpadded;
    int paddedDim=(int)(paddingFactor*volumeSize);
    // JMRT: TODO: I think it is a very poor design to modify the volume passed
    // in the construct, it will be padded anyway, so new memory should be allocated
    volume->window(Vpadded,FIRST_XMIPP_INDEX(paddedDim),FIRST_XMIPP_INDEX(paddedDim),FIRST_XMIPP_INDEX(paddedDim),
                   LAST_XMIPP_INDEX(paddedDim),LAST_XMIPP_INDEX(paddedDim),LAST_XMIPP_INDEX(paddedDim));
    volume->clear();
    // Make Fourier transform, shift the volume origin to the volume center and center it
    MultidimArray< std::complex<double> > Vfourier;
    transformer3D.completeFourierTransform(Vpadded,Vfourier);
    ShiftFFT(Vfourier, FIRST_XMIPP_INDEX(XSIZE(Vpadded)), FIRST_XMIPP_INDEX(YSIZE(Vpadded)), FIRST_XMIPP_INDEX(ZSIZE(Vpadded)));
    CenterFFT(Vfourier,true);
    Vfourier.setXmippOrigin();

    // Compensate for the Fourier normalization factor
    double K=(double)(XSIZE(Vpadded)*XSIZE(Vpadded)*XSIZE(Vpadded))/(double)(volumeSize*volumeSize);
    FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(Vfourier)
    DIRECT_MULTIDIM_ELEM(Vfourier,n)*=K;
    Vpadded.clear();
    // Compute Bspline coefficients
    if (BSplineDeg==3)
    {
        MultidimArray< double > VfourierRealAux, VfourierImagAux;
        Complex2RealImag(Vfourier, VfourierRealAux, VfourierImagAux);
        Vfourier.clear();
        produceSplineCoefficients(BSPLINE3,VfourierRealCoefs,VfourierRealAux);
        produceSplineCoefficients(BSPLINE3,VfourierImagCoefs,VfourierImagAux);
        //VfourierRealAux.clear();
        //VfourierImagAux.clear();
    }
    else
        Complex2RealImag(Vfourier, VfourierRealCoefs, VfourierImagCoefs);

    // Allocate memory for the 2D Fourier transform
    projection().initZeros(volumeSize,volumeSize);
    projection().setXmippOrigin();
    transformer2D.FourierTransform(projection(),projectionFourier,false);

    // Calculate phase shift terms
    phaseShiftImgA.initZeros(projectionFourier);
    phaseShiftImgB.initZeros(projectionFourier);
    double shift=-FIRST_XMIPP_INDEX(volumeSize);
    double xxshift = -2 * PI * shift / volumeSize;
    for (size_t i=0; i<YSIZE(projectionFourier); ++i)
    {
        double phasey=(double)(i) * xxshift;
        for (size_t j=0; j<XSIZE(projectionFourier); ++j)
        {
            // Phase shift to move the origin of the image to the corner
            double dotp = (double)(j) * xxshift + phasey;
            sincos(dotp,&DIRECT_A2D_ELEM(phaseShiftImgB,i,j),&DIRECT_A2D_ELEM(phaseShiftImgA,i,j));
        }
    }
}
Exemple #3
0
TEST_F( FftwTest, directFourierTransformComplex)
{

    MultidimArray< std::complex< double > > FFT1, complxDouble;
    FourierTransformer transformer1;
    typeCast(mulDouble, complxDouble);
    transformer1.FourierTransform(complxDouble, FFT1, false);
    transformer1.inverseFourierTransform();

    transformer1.inverseFourierTransform();
    MultidimArray<std::complex<double> > auxFFT;
    auxFFT.resize(3,3);
    DIRECT_A2D_ELEM(auxFFT,0,0) = std::complex<double>(2.77778,0);
    DIRECT_A2D_ELEM(auxFFT,0,1) = std::complex<double>(-0.0555556,0.096225);
    DIRECT_A2D_ELEM(auxFFT,0,2) = std::complex<double>(-0.0555556,-0.096225);

    DIRECT_A2D_ELEM(auxFFT,1,0) = std::complex<double>(-0.388889,0.673575) ;
    DIRECT_A2D_ELEM(auxFFT,1,1) = std::complex<double>(-0.388889,-0.096225);
    DIRECT_A2D_ELEM(auxFFT,1,2) = std::complex<double>(-0.0555556,-0.288675);

    DIRECT_A2D_ELEM(auxFFT,2,0) = std::complex<double>(-0.388889,-0.673575) ;
    DIRECT_A2D_ELEM(auxFFT,2,1) = std::complex<double>(-0.0555556,0.288675) ;
    DIRECT_A2D_ELEM(auxFFT,2,2) = std::complex<double>(-0.388889,0.096225) ;
    EXPECT_EQ(FFT1,auxFFT);
    transformer1.cleanup();
}
Exemple #4
0
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();
}
Exemple #5
0
    //init metadatas
    virtual void SetUp()
    {
        mulDouble.resize(3,3);
        DIRECT_A2D_ELEM(mulDouble,0,0) = 1;
        DIRECT_A2D_ELEM(mulDouble,0,1) = 2;
        DIRECT_A2D_ELEM(mulDouble,0,2) = 3;

        DIRECT_A2D_ELEM(mulDouble,1,0) = 3;
        DIRECT_A2D_ELEM(mulDouble,1,1) = 2;
        DIRECT_A2D_ELEM(mulDouble,1,2) = 1;

        DIRECT_A2D_ELEM(mulDouble,2,0) = 4;
        DIRECT_A2D_ELEM(mulDouble,2,1) = 4;
        DIRECT_A2D_ELEM(mulDouble,2,2) = 5;
    }
Exemple #6
0
/* Generate a complete CTF Image ------------------------------------------------------ */
void CTF::getFftwImage(MultidimArray<DOUBLE> &result, int orixdim, int oriydim, DOUBLE angpix,
		    		bool do_abs, bool do_only_flip_phases, bool do_intact_until_first_peak, bool do_damping)
{

	DOUBLE xs = (DOUBLE)orixdim * angpix;
	DOUBLE ys = (DOUBLE)oriydim * angpix;
	FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM2D(result)
	{
		DOUBLE x = (DOUBLE)jp / xs;
		DOUBLE y = (DOUBLE)ip / ys;
		DIRECT_A2D_ELEM(result, i, j) = getCTF(x, y, do_abs, do_only_flip_phases, do_intact_until_first_peak, do_damping);
	}
}
Exemple #7
0
EnsembleNaiveBayes::EnsembleNaiveBayes(
    const std::vector < MultidimArray<double> >  &features,
    const Matrix1D<double> &priorProbs,
    int discreteLevels, int numberOfClassifiers,
    double samplingFeatures, double samplingIndividuals,
    const std::string &newJudgeCombination)
{
    int NFeatures=XSIZE(features[0]);
    int NsubFeatures=CEIL(NFeatures*samplingFeatures);
    K=features.size();
    judgeCombination=newJudgeCombination;

#ifdef WEIGHTED_SAMPLING
    // Measure the classification power of each variable
    NaiveBayes *nb_weights=new NaiveBayes(features, priorProbs, discreteLevels);
    MultidimArray<double> weights=nb_weights->__weights;
    delete nb_weights;
    double sumWeights=weights.sum();
#endif

    for (int n=0; n<numberOfClassifiers; n++)
    {
        // Produce the set of features for this subclassifier
        MultidimArray<int> subFeatures(NsubFeatures);
        FOR_ALL_ELEMENTS_IN_ARRAY1D(subFeatures)
        {
#ifdef WEIGHTED_SAMPLING
            double random_sum_weight=rnd_unif(0,sumWeights);
            int j=0;
            do
            {
                double wj=DIRECT_A1D_ELEM(weights,j);
                if (wj<random_sum_weight)
                {
                    random_sum_weight-=wj;
                    j++;
                    if (j==NFeatures)
                    {
                        j=NFeatures-1;
                        break;
                    }
                }
                else
                    break;
            }
            while (true);
            DIRECT_A1D_ELEM(subFeatures,i)=j;
#else

            DIRECT_A1D_ELEM(subFeatures,i)=round(rnd_unif(0,NFeatures-1));
#endif

        }

        // Container for the new training sample
        std::vector< MultidimArray<double> >  newFeatures;

        // Produce the data set for each class
        for (int k=0; k<K; k++)
        {
            int NIndividuals=YSIZE(features[k]);
            int NsubIndividuals=CEIL(NIndividuals*samplingIndividuals);
            MultidimArray<int> subIndividuals(NsubIndividuals);
            FOR_ALL_ELEMENTS_IN_ARRAY1D(subIndividuals)
            subIndividuals(i)=ROUND(rnd_unif(0,NsubIndividuals-1));

            MultidimArray<double> newFeaturesK;
            newFeaturesK.initZeros(NsubIndividuals,NsubFeatures);
            const MultidimArray<double>& features_k=features[k];
            FOR_ALL_ELEMENTS_IN_ARRAY2D(newFeaturesK)
            DIRECT_A2D_ELEM(newFeaturesK,i,j)=DIRECT_A2D_ELEM(features_k,
                                              DIRECT_A1D_ELEM(subIndividuals,i),
                                              DIRECT_A1D_ELEM(subFeatures,j));

            newFeatures.push_back(newFeaturesK);
        }

        // Create a Naive Bayes classifier with this data
        NaiveBayes *nb=new NaiveBayes(newFeatures, priorProbs, discreteLevels);
        ensemble.push_back(nb);
        ensembleFeatures.push_back(subFeatures);
    }
}
Exemple #8
0
// Split several histograms within the indexes l0 and lF so that
// the entropy after division is maximized
int splitHistogramsUsingEntropy(const std::vector<Histogram1D> &hist,
                                size_t l0, size_t lF)
{
    // Number of classes
    int K = hist.size();

    // Set everything outside l0 and lF to zero, and make it a PDF
    std::vector<Histogram1D> histNorm;
    for (int k = 0; k < K; k++)
    {
        Histogram1D histaux = hist[k];
        for (size_t l = 0; l < XSIZE(histaux); l++)
            if (l < l0 || l > lF)
                DIRECT_A1D_ELEM(histaux,l) = 0;
        histaux *= 1.0/histaux.sum();
        histNorm.push_back(histaux);
    }

    // Compute for each class the probability of being l<=l0 and l>l0
    MultidimArray<double> p(K, 2);
    for (int k = 0; k < K; k++)
    {
        const Histogram1D& histogram=histNorm[k];
        DIRECT_A2D_ELEM(p,k, 0) = DIRECT_A1D_ELEM(histogram,l0);
        DIRECT_A2D_ELEM(p,k, 1) = 0;
        for (size_t l = l0 + 1; l <= lF; l++)
            DIRECT_A2D_ELEM(p,k, 1) += DIRECT_A1D_ELEM(histogram,l);
    }

    // Compute the splitting l giving maximum entropy
    double maxEntropy = 0;
    int lmaxEntropy = -1;
    size_t l = l0;
    while (l < lF)
    {
        // Compute the entropy of the classes if we split by l
        double entropy = 0;
        FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(p)
        {
            double aux=DIRECT_MULTIDIM_ELEM(p,n);
            if (aux != 0)
                entropy -= aux * log10(aux);
        }

#ifdef DEBUG_SPLITTING_USING_ENTROPY
        std::cout << "Splitting at "  << l << " entropy=" << entropy
        << std::endl;
#endif

        // Check if this is the maximum
        if (entropy > maxEntropy)
        {
            maxEntropy = entropy;
            lmaxEntropy = l;
        }

        // Move to next split point
        ++l;

        // Update probabilities of being l<=l0 and l>l0
        for (int k = 0; k < K; k++)
        {
            const Histogram1D& histogram=histNorm[k];
            double aux=DIRECT_A1D_ELEM(histogram,l);
            DIRECT_A2D_ELEM(p,k, 0) += aux;
            DIRECT_A2D_ELEM(p,k, 1) -= aux;
        }
    }

#ifdef DEBUG_SPLITTING_USING_ENTROPY
    std::cout << "Finally in l=[" << l0 << "," << lF
    << " Max Entropy:" << maxEntropy
    << " lmax=" << lmaxEntropy << std::endl;
#endif

    // If the point giving the maximum entropy is too much on the extreme,
    // substitute it by the middle point
    if (lmaxEntropy<=2 || lmaxEntropy>=(int)lF-2)
        lmaxEntropy = (int)ceil((lF + l0)/2.0);

    return lmaxEntropy;
}
void FourierProjector::project(double rot, double tilt, double psi)
{
    double freqy, freqx;
    std::complex< double > f;
    Euler_angles2matrix(rot,tilt,psi,E);

    projectionFourier.initZeros();
    double shift=-FIRST_XMIPP_INDEX(volumeSize);
    double xxshift = -2 * PI * shift / volumeSize;
    double maxFreq2=maxFrequency*maxFrequency;
    double volumePaddedSize=XSIZE(VfourierRealCoefs);
    for (size_t i=0; i<YSIZE(projectionFourier); ++i)
    {
        FFT_IDX2DIGFREQ(i,volumeSize,freqy);
        double freqy2=freqy*freqy;
        double phasey=(double)(i) * xxshift;

        double freqYvol_X=MAT_ELEM(E,1,0)*freqy;
        double freqYvol_Y=MAT_ELEM(E,1,1)*freqy;
        double freqYvol_Z=MAT_ELEM(E,1,2)*freqy;
        for (size_t j=0; j<XSIZE(projectionFourier); ++j)
        {
            // The frequency of pairs (i,j) in 2D
            FFT_IDX2DIGFREQ(j,volumeSize,freqx);

            // Do not consider pixels with high frequency
            if ((freqy2+freqx*freqx)>maxFreq2)
                continue;

            // Compute corresponding frequency in the volume
            double freqvol_X=freqYvol_X+MAT_ELEM(E,0,0)*freqx;
            double freqvol_Y=freqYvol_Y+MAT_ELEM(E,0,1)*freqx;
            double freqvol_Z=freqYvol_Z+MAT_ELEM(E,0,2)*freqx;

            double c,d;
            if (BSplineDeg==0)
            {
                // 0 order interpolation
                // Compute corresponding index in the volume
                int kVolume=(int)round(freqvol_Z*volumePaddedSize);
                int iVolume=(int)round(freqvol_Y*volumePaddedSize);
                int jVolume=(int)round(freqvol_X*volumePaddedSize);
                c = A3D_ELEM(VfourierRealCoefs,kVolume,iVolume,jVolume);
                d = A3D_ELEM(VfourierImagCoefs,kVolume,iVolume,jVolume);
            }
            else if (BSplineDeg==1)
            {
                // B-spline linear interpolation
                double kVolume=freqvol_Z*volumePaddedSize;
                double iVolume=freqvol_Y*volumePaddedSize;
                double jVolume=freqvol_X*volumePaddedSize;
                c=VfourierRealCoefs.interpolatedElement3D(jVolume,iVolume,kVolume);
                d=VfourierImagCoefs.interpolatedElement3D(jVolume,iVolume,kVolume);
            }
            else
            {
                // B-spline cubic interpolation
                double kVolume=freqvol_Z*volumePaddedSize;
                double iVolume=freqvol_Y*volumePaddedSize;
                double jVolume=freqvol_X*volumePaddedSize;
                c=VfourierRealCoefs.interpolatedElementBSpline3D(jVolume,iVolume,kVolume);
                d=VfourierImagCoefs.interpolatedElementBSpline3D(jVolume,iVolume,kVolume);
            }

            // Phase shift to move the origin of the image to the corner
            double dotp = (double)(j) * xxshift + phasey;
            double a,b;
            sincos(dotp,&b,&a);

            // Multiply Fourier coefficient in volume times phase shift
            double ac = a * c;
            double bd = b * d;
            double ab_cd = (a + b) * (c + d);

            // And store the multiplication
            double *ptrI_ij=(double *)&DIRECT_A2D_ELEM(projectionFourier,i,j);
            *ptrI_ij = ac - bd;
            *(ptrI_ij+1) = ab_cd - ac - bd;
        }
    }
    //VfourierRealCoefs.clear();
    //VfourierImagCoefs.clear();
    transformer2D.inverseFourierTransform();
}
// Fit the beam-induced translations for all average micrographs
void ParticlePolisherMpi::fitMovementsAllMicrographs()
{

	int total_nr_micrographs = exp_model.average_micrographs.size();

	// Each node does part of the work
	long int my_first_micrograph, my_last_micrograph, my_nr_micrographs;
	divide_equally(total_nr_micrographs, node->size, node->rank, my_first_micrograph, my_last_micrograph);
	my_nr_micrographs = my_last_micrograph - my_first_micrograph + 1;

	// Loop over all average micrographs
	int barstep;
	if (verb > 0)
	{
		std::cout << " + Fitting straight paths for beam-induced movements in all micrographs ... " << std::endl;
		init_progress_bar(my_nr_micrographs);
		barstep = XMIPP_MAX(1, my_nr_micrographs/ 60);
	}

	for (long int i = my_first_micrograph; i <= my_last_micrograph; i++)
	{
    	if (verb > 0 && i % barstep == 0)
			progress_bar(i);

		fitMovementsOneMicrograph(i);
	}

	// Wait until all micrographs have been done
	MPI_Barrier(MPI_COMM_WORLD);

	if (verb > 0)
	{
		progress_bar(my_nr_micrographs);
	}

	// Combine results from all nodes
	MultidimArray<DOUBLE> allnodes_fitted_movements;
	allnodes_fitted_movements.resize(fitted_movements);
	MPI_Allreduce(MULTIDIM_ARRAY(fitted_movements), MULTIDIM_ARRAY(allnodes_fitted_movements), MULTIDIM_SIZE(fitted_movements), MY_MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
	fitted_movements = allnodes_fitted_movements;

    // Set the fitted movements in the xoff and yoff columns of the exp_model.MDimg
    for (long int ipart = 0; ipart < exp_model.numberOfParticles(); ipart++)
	{
		long int part_id = exp_model.particles[ipart].id;
		DOUBLE xoff = DIRECT_A2D_ELEM(fitted_movements, part_id, 0);
		DOUBLE yoff = DIRECT_A2D_ELEM(fitted_movements, part_id, 1);
		exp_model.MDimg.setValue(EMDL_ORIENT_ORIGIN_X, xoff, part_id);
		exp_model.MDimg.setValue(EMDL_ORIENT_ORIGIN_Y, yoff, part_id);
	}

    if (node->isMaster())
    {
		// Write out the STAR file with all the fitted movements
		FileName fn_tmp = fn_in.withoutExtension() + "_" + fn_out + ".star";
		exp_model.MDimg.write(fn_tmp);
		std::cout << " + Written out all fitted movements in STAR file: " << fn_tmp << std::endl;
    }


}
Exemple #11
0
// Shift an image through phase-shifts in its Fourier Transform (without pretabulated sine and cosine)
void shiftImageInFourierTransform(MultidimArray<Complex >& in,
                                  MultidimArray<Complex >& out,
                                  double oridim, Matrix1D<double> shift)
{
	out.resize(in);
	shift /= -oridim;
	double dotp, a, b, c, d, ac, bd, ab_cd, x, y, z, xshift, yshift, zshift;
	switch (in.getDim())
	{
	case 1:
		xshift = XX(shift);
		if (ABS(xshift) < XMIPP_EQUAL_ACCURACY)
		{
			out = in;
			return;
		}
		for (long int j = 0; j < XSIZE(in); j++)
		{
			x = j;
			dotp = 2 * PI * (x * xshift);
			a = cos(dotp);
			b = sin(dotp);
			c = DIRECT_A1D_ELEM(in, j).real;
			d = DIRECT_A1D_ELEM(in, j).imag;
			ac = a * c;
			bd = b * d;
			ab_cd = (a + b) * (c + d); // (ab_cd-ac-bd = ad+bc : but needs 4 multiplications)
			DIRECT_A1D_ELEM(out, j) = Complex(ac - bd, ab_cd - ac - bd);
		}
		break;
	case 2:
		xshift = XX(shift);
		yshift = YY(shift);
		if (ABS(xshift) < XMIPP_EQUAL_ACCURACY && ABS(yshift) < XMIPP_EQUAL_ACCURACY)
		{
			out = in;
			return;
		}
		for (long int i = 0; i < XSIZE(in); i++)
			for (long int j = 0; j < XSIZE(in); j++)
			{
				x = j;
				y = i;
				dotp = 2 * PI * (x * xshift + y * yshift);
				a = cos(dotp);
				b = sin(dotp);
				c = DIRECT_A2D_ELEM(in, i, j).real;
				d = DIRECT_A2D_ELEM(in, i, j).imag;
				ac = a * c;
				bd = b * d;
				ab_cd = (a + b) * (c + d);
				DIRECT_A2D_ELEM(out, i, j) =  Complex(ac - bd, ab_cd - ac - bd);
			}
		for (long int i = YSIZE(in) - 1; i >= XSIZE(in); i--)
		{
			y = i - YSIZE(in);
			for (long int j = 0; j < XSIZE(in); j++)
			{
				x = j;
				dotp = 2 * PI * (x * xshift + y * yshift);
				a = cos(dotp);
				b = sin(dotp);
				c = DIRECT_A2D_ELEM(in, i, j).real;
				d = DIRECT_A2D_ELEM(in, i, j).imag;
				ac = a * c;
				bd = b * d;
				ab_cd = (a + b) * (c + d);
				DIRECT_A2D_ELEM(out, i, j) = Complex(ac - bd, ab_cd - ac - bd);
			}
		}
		break;
	case 3:
		xshift = XX(shift);
		yshift = YY(shift);
		zshift = ZZ(shift);
		if (ABS(xshift) < XMIPP_EQUAL_ACCURACY && ABS(yshift) < XMIPP_EQUAL_ACCURACY && ABS(zshift) < XMIPP_EQUAL_ACCURACY)
		{
			out = in;
			return;
		}
		for (long int k = 0; k < ZSIZE(in); k++)
		{
			z = (k < XSIZE(in)) ? k : k - ZSIZE(in);
			for (long int i = 0; i < YSIZE(in); i++)
			{
				y = (i < XSIZE(in)) ? i : i - YSIZE(in);
				for (long int j = 0; j < XSIZE(in); j++)
				{
					x = j;
					dotp = 2 * PI * (x * xshift + y * yshift + z * zshift);
					a = cos(dotp);
					b = sin(dotp);
					c = DIRECT_A3D_ELEM(in, k, i, j).real;
					d = DIRECT_A3D_ELEM(in, k, i, j).imag;
					ac = a * c;
					bd = b * d;
					ab_cd = (a + b) * (c + d);
					DIRECT_A3D_ELEM(out, k, i, j) = Complex(ac - bd, ab_cd - ac - bd);
				}
			}
		}
		break;
	default:
		REPORT_ERROR("shiftImageInFourierTransform ERROR: dimension should be 1, 2 or 3!");
	}
}
Exemple #12
0
void Projector::rotate2D(MultidimArray<Complex > &f2d, Matrix2D<DOUBLE> &A, bool inv)
{
	DOUBLE fx, fy, xp, yp;
	int x0, x1, y0, y1, y, y2, r2;
	bool is_neg_x;
	Complex d00, d01, d10, d11, dx0, dx1;
	Matrix2D<DOUBLE> Ainv;

    // f2d should already be in the right size (ori_size,orihalfdim)
    // AND the points outside max_r should already be zero...
    // f2d.initZeros();
	// Use the inverse matrix
    if (inv)
    	Ainv = A;
    else
    	Ainv = A.transpose();

    // The f2d image may be smaller than r_max, in that case also make sure not to fill the corners!
    int my_r_max = XMIPP_MIN(r_max, XSIZE(f2d) - 1);

    // Go from the 2D slice coordinates to the map coordinates
    Ainv *= (DOUBLE)padding_factor;  // take scaling into account directly
    int max_r2 = my_r_max * my_r_max;
    int min_r2_nn = r_min_nn * r_min_nn;
#ifdef DEBUG
    std::cerr << " XSIZE(f2d)= "<< XSIZE(f2d) << std::endl;
    std::cerr << " YSIZE(f2d)= "<< YSIZE(f2d) << std::endl;
    std::cerr << " XSIZE(data)= "<< XSIZE(data) << std::endl;
    std::cerr << " YSIZE(data)= "<< YSIZE(data) << std::endl;
    std::cerr << " STARTINGX(data)= "<< STARTINGX(data) << std::endl;
    std::cerr << " STARTINGY(data)= "<< STARTINGY(data) << std::endl;
    std::cerr << " STARTINGZ(data)= "<< STARTINGZ(data) << std::endl;
    std::cerr << " max_r= "<< r_max << std::endl;
    std::cerr << " Ainv= " << Ainv << std::endl;
#endif
	for (int i=0; i < YSIZE(f2d); i++)
	{
		// Don't search beyond square with side max_r
		if (i <= my_r_max)
		{
			y = i;
		}
		else if (i >= YSIZE(f2d) - my_r_max)
		{
			y = i - YSIZE(f2d);
		}
		else
			continue;
		y2 = y * y;
		for (int x=0; x <= my_r_max; x++)
		{
	    	// Only include points with radius < max_r (exclude points outside circle in square)
			r2 = x * x + y2;
			if (r2 > max_r2)
				continue;

			// Get logical coordinates in the 3D map
			xp = Ainv(0,0) * x + Ainv(0,1) * y;
			yp = Ainv(1,0) * x + Ainv(1,1) * y;
			if (interpolator == TRILINEAR || r2 < min_r2_nn)
			{
				// Only asymmetric half is stored
				if (xp < 0)
				{
					// Get complex conjugated hermitian symmetry pair
					xp = -xp;
					yp = -yp;
					is_neg_x = true;
				}
				else
				{
					is_neg_x = false;
				}

				// Trilinear interpolation (with physical coords)
				// Subtract STARTINGY to accelerate access to data (STARTINGX=0)
				// In that way use DIRECT_A3D_ELEM, rather than A3D_ELEM
    			x0 = FLOOR(xp);
				fx = xp - x0;
				x1 = x0 + 1;

				y0 = FLOOR(yp);
				fy = yp - y0;
				y0 -=  STARTINGY(data);
				y1 = y0 + 1;

				// Matrix access can be accelerated through pre-calculation of z0*xydim etc.
				d00 = DIRECT_A2D_ELEM(data, y0, x0);
				d01 = DIRECT_A2D_ELEM(data, y0, x1);
				d10 = DIRECT_A2D_ELEM(data, y1, x0);
				d11 = DIRECT_A2D_ELEM(data, y1, x1);

				// Set the interpolated value in the 2D output array
#ifndef FLOAT_PRECISION
                __m256d __interpx = LIN_INTERP_AVX(_mm256_setr_pd(d00.real, d00.imag, d10.real, d10.imag),
                                                   _mm256_setr_pd(d01.real, d01.imag, d11.real, d11.imag),
                                                   _mm256_set1_pd(fx));
#else
                __m128 __interpx = LIN_INTERP_AVX(_mm_setr_ps(d00.real, d00.imag, d10.real, d10.imag),
                                                  _mm_setr_ps(d01.real, d01.imag, d11.real, d11.imag),
                                                  _mm_set1_ps(fx));
#endif

                Complex* interpx = (Complex*)&__interpx;
				DIRECT_A2D_ELEM(f2d, i, x) = LIN_INTERP(fy, interpx[0], interpx[1]);
				// Take complex conjugated for half with negative x
				if (is_neg_x)
					DIRECT_A2D_ELEM(f2d, i, x) = conj(DIRECT_A2D_ELEM(f2d, i, x));
			} // endif TRILINEAR
			else if (interpolator == NEAREST_NEIGHBOUR )
			{
				x0 = ROUND(xp);
				y0 = ROUND(yp);
				if (x0 < 0)
					DIRECT_A2D_ELEM(f2d, i, x) = conj(A2D_ELEM(data, -y0, -x0));
				else
					DIRECT_A2D_ELEM(f2d, i, x) = A2D_ELEM(data, y0, x0);
			} // endif NEAREST_NEIGHBOUR
			else
				REPORT_ERROR("Unrecognized interpolator in Projector::project");
		} // endif x-loop
	} // endif y-loop
}
Exemple #13
0
void FourierProjector::project(double rot, double tilt, double psi, const MultidimArray<double> *ctf)
{
    double freqy, freqx;
    std::complex< double > f;
    Euler_angles2matrix(rot,tilt,psi,E);

    projectionFourier.initZeros();
    double maxFreq2=maxFrequency*maxFrequency;
    int Xdim=(int)XSIZE(VfourierRealCoefs);
    int Ydim=(int)YSIZE(VfourierRealCoefs);
    int Zdim=(int)ZSIZE(VfourierRealCoefs);

    for (size_t i=0; i<YSIZE(projectionFourier); ++i)
    {
        FFT_IDX2DIGFREQ(i,volumeSize,freqy);
        double freqy2=freqy*freqy;

        double freqYvol_X=MAT_ELEM(E,1,0)*freqy;
        double freqYvol_Y=MAT_ELEM(E,1,1)*freqy;
        double freqYvol_Z=MAT_ELEM(E,1,2)*freqy;
        for (size_t j=0; j<XSIZE(projectionFourier); ++j)
        {
            // The frequency of pairs (i,j) in 2D
            FFT_IDX2DIGFREQ(j,volumeSize,freqx);

            // Do not consider pixels with high frequency
            if ((freqy2+freqx*freqx)>maxFreq2)
                continue;

            // Compute corresponding frequency in the volume
            double freqvol_X=freqYvol_X+MAT_ELEM(E,0,0)*freqx;
            double freqvol_Y=freqYvol_Y+MAT_ELEM(E,0,1)*freqx;
            double freqvol_Z=freqYvol_Z+MAT_ELEM(E,0,2)*freqx;

            double c,d;
            if (BSplineDeg==0)
            {
                // 0 order interpolation
                // Compute corresponding index in the volume
                int kVolume=(int)round(freqvol_Z*volumePaddedSize);
                int iVolume=(int)round(freqvol_Y*volumePaddedSize);
                int jVolume=(int)round(freqvol_X*volumePaddedSize);
                c = A3D_ELEM(VfourierRealCoefs,kVolume,iVolume,jVolume);
                d = A3D_ELEM(VfourierImagCoefs,kVolume,iVolume,jVolume);
            }
            else if (BSplineDeg==1)
            {
                // B-spline linear interpolation
                double kVolume=freqvol_Z*volumePaddedSize;
                double iVolume=freqvol_Y*volumePaddedSize;
                double jVolume=freqvol_X*volumePaddedSize;
                c=VfourierRealCoefs.interpolatedElement3D(jVolume,iVolume,kVolume);
                d=VfourierImagCoefs.interpolatedElement3D(jVolume,iVolume,kVolume);
            }
            else
            {
                // B-spline cubic interpolation
                double kVolume=freqvol_Z*volumePaddedSize;
                double iVolume=freqvol_Y*volumePaddedSize;
                double jVolume=freqvol_X*volumePaddedSize;

                // Commented for speed-up, the corresponding code is below
                // c=VfourierRealCoefs.interpolatedElementBSpline3D(jVolume,iVolume,kVolume);
                // d=VfourierImagCoefs.interpolatedElementBSpline3D(jVolume,iVolume,kVolume);

                // The code below is a replicate for speed reasons of interpolatedElementBSpline3D
                double z=kVolume;
                double y=iVolume;
                double x=jVolume;

                // Logical to physical
                z -= STARTINGZ(VfourierRealCoefs);
                y -= STARTINGY(VfourierRealCoefs);
                x -= STARTINGX(VfourierRealCoefs);

                int l1 = (int)ceil(x - 2);
                int l2 = l1 + 3;

                int m1 = (int)ceil(y - 2);
                int m2 = m1 + 3;

                int n1 = (int)ceil(z - 2);
                int n2 = n1 + 3;

                c = d = 0.0;
                double aux;
                for (int nn = n1; nn <= n2; nn++)
                {
                    int equivalent_nn=nn;
                    if      (nn<0)
                        equivalent_nn=-nn-1;
                    else if (nn>=Zdim)
                        equivalent_nn=2*Zdim-nn-1;
                    double yxsumRe = 0.0, yxsumIm = 0.0;
                    for (int m = m1; m <= m2; m++)
                    {
                        int equivalent_m=m;
                        if      (m<0)
                            equivalent_m=-m-1;
                        else if (m>=Ydim)
                            equivalent_m=2*Ydim-m-1;
                        double xsumRe = 0.0, xsumIm = 0.0;
                        for (int l = l1; l <= l2; l++)
                        {
                            double xminusl = x - (double) l;
                            int equivalent_l=l;
                            if      (l<0)
                                equivalent_l=-l-1;
                            else if (l>=Xdim)
                                equivalent_l=2*Xdim-l-1;
                            double CoeffRe = (double) DIRECT_A3D_ELEM(VfourierRealCoefs,equivalent_nn,equivalent_m,equivalent_l);
                            double CoeffIm = (double) DIRECT_A3D_ELEM(VfourierImagCoefs,equivalent_nn,equivalent_m,equivalent_l);
                            BSPLINE03(aux,xminusl);
                            xsumRe += CoeffRe * aux;
                            xsumIm += CoeffIm * aux;
                        }

                        double yminusm = y - (double) m;
                        BSPLINE03(aux,yminusm);
						yxsumRe += xsumRe * aux;
						yxsumIm += xsumIm * aux;
                    }

                    double zminusn = z - (double) nn;
                    BSPLINE03(aux,zminusn);
					c += yxsumRe * aux;
					d += yxsumIm * aux;
                }
            }

            // Phase shift to move the origin of the image to the corner
            double a=DIRECT_A2D_ELEM(phaseShiftImgA,i,j);
            double b=DIRECT_A2D_ELEM(phaseShiftImgB,i,j);
            if (ctf!=NULL)
            {
            	double ctfij=DIRECT_A2D_ELEM(*ctf,i,j);
            	a*=ctfij;
            	b*=ctfij;
            }

            // Multiply Fourier coefficient in volume times phase shift
            double ac = a * c;
            double bd = b * d;
            double ab_cd = (a + b) * (c + d);

            // And store the multiplication
            double *ptrI_ij=(double *)&DIRECT_A2D_ELEM(projectionFourier,i,j);
            *ptrI_ij = ac - bd;
            *(ptrI_ij+1) = ab_cd - ac - bd;
        }
    }
    transformer2D.inverseFourierTransform();
}