示例#1
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();
}
示例#2
0
文件: fftw.cpp 项目: shy3u/GeRelion
// 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));
        }
    }
}
示例#4
0
void FourierTransformer::setReal(MultidimArray<std::complex<double> > &input)
{
    bool recomputePlan=false;
    if (fComplex==NULL)
        recomputePlan=true;
    else if (complexDataPtr!=MULTIDIM_ARRAY(input))
        recomputePlan=true;
    else
        recomputePlan=!(fComplex->sameShape(input));
    fFourier.resizeNoCopy(input);
    fComplex=&input;

    if (recomputePlan)
    {
        int ndim=3;
        if (ZSIZE(input)==1)
        {
            ndim=2;
            if (YSIZE(input)==1)
                ndim=1;
        }
        int *N = new int[ndim];
        switch (ndim)
        {
        case 1:
            N[0]=XSIZE(input);
            break;
        case 2:
            N[0]=YSIZE(input);
            N[1]=XSIZE(input);
            break;
        case 3:
            N[0]=ZSIZE(input);
            N[1]=YSIZE(input);
            N[2]=XSIZE(input);
            break;
        }

        pthread_mutex_lock(&fftw_plan_mutex);
        if (fPlanForward!=NULL)
            fftw_destroy_plan(fPlanForward);
        fPlanForward=NULL;
        fPlanForward = fftw_plan_dft(ndim, N, (fftw_complex*) MULTIDIM_ARRAY(*fComplex),
                                     (fftw_complex*) MULTIDIM_ARRAY(fFourier), FFTW_FORWARD, FFTW_ESTIMATE);
        if (fPlanBackward!=NULL)
            fftw_destroy_plan(fPlanBackward);
        fPlanBackward=NULL;
        fPlanBackward = fftw_plan_dft(ndim, N, (fftw_complex*) MULTIDIM_ARRAY(fFourier),
                                      (fftw_complex*) MULTIDIM_ARRAY(*fComplex), FFTW_BACKWARD, FFTW_ESTIMATE);
        if (fPlanForward == NULL || fPlanBackward == NULL)
            REPORT_ERROR(ERR_PLANS_NOCREATE, "FFTW plans cannot be created");
        delete [] N;
        complexDataPtr=MULTIDIM_ARRAY(*fComplex);
        pthread_mutex_unlock(&fftw_plan_mutex);
    }
}
示例#5
0
void FourierTransformer::setReal(MultidimArray<double> &input)
{
    bool recomputePlan=false;
    if (fReal==NULL)
        recomputePlan=true;
    else if (dataPtr!=MULTIDIM_ARRAY(input))
        recomputePlan=true;
    else
        recomputePlan=!(fReal->sameShape(input));
    fFourier.resizeNoCopy(ZSIZE(input),YSIZE(input),XSIZE(input)/2+1);
    fReal=&input;

    if (recomputePlan)
    {
        int ndim=3;
        if (ZSIZE(input)==1)
        {
            ndim=2;
            if (YSIZE(input)==1)
                ndim=1;
        }
        int N[3];
        switch (ndim)
        {
        case 1:
            N[0]=XSIZE(input);
            break;
        case 2:
            N[0]=YSIZE(input);
            N[1]=XSIZE(input);
            break;
        case 3:
            N[0]=ZSIZE(input);
            N[1]=YSIZE(input);
            N[2]=XSIZE(input);
            break;
        }

        pthread_mutex_lock(&fftw_plan_mutex);
        if (fPlanForward!=NULL)
            fftw_destroy_plan(fPlanForward);
        fPlanForward=NULL;
        fPlanForward = fftw_plan_dft_r2c(ndim, N, MULTIDIM_ARRAY(*fReal),
                                         (fftw_complex*) MULTIDIM_ARRAY(fFourier), FFTW_ESTIMATE);
        if (fPlanBackward!=NULL)
            fftw_destroy_plan(fPlanBackward);
        fPlanBackward=NULL;
        fPlanBackward = fftw_plan_dft_c2r(ndim, N,
                                          (fftw_complex*) MULTIDIM_ARRAY(fFourier), MULTIDIM_ARRAY(*fReal),
                                          FFTW_ESTIMATE);
        if (fPlanForward == NULL || fPlanBackward == NULL)
            REPORT_ERROR(ERR_PLANS_NOCREATE, "FFTW plans cannot be created");
        dataPtr=MULTIDIM_ARRAY(*fReal);
        pthread_mutex_unlock(&fftw_plan_mutex);
    }
}
示例#6
0
文件: fftw.cpp 项目: shy3u/GeRelion
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();

}
示例#7
0
/*
	FUNCTION: InitNewFont(LOGFONT, COLORREF)

	PURPOSE: Prepares a new font for use in the terminal screen

	PARAMETERS:
		LogFont		- New logical font for the screen
		rgbColour	- New colour for screen painting

*/
void InitNewFont(LOGFONT LogFont, COLORREF rgbColour) {
	TEXTMETRIC	tm;
	HDC			hDC;

	// If an old font exits, delete it
	if (HSCREENFONT(TermInfo)) {
		DeleteObject(HSCREENFONT(TermInfo));
	}

	LFSCREENFONT(TermInfo) = LogFont;
	HSCREENFONT(TermInfo) = CreateFontIndirect(&(LFSCREENFONT(TermInfo)));
	FGCOLOUR(TermInfo) = rgbColour;

	hDC = GetDC(ghWndMain);
	SelectObject(hDC, HSCREENFONT(TermInfo));
	GetTextMetrics(hDC, &tm);
	ReleaseDC(ghWndMain, hDC);

	// Character width and height
	XCHAR(TermInfo) = tm.tmAveCharWidth;
	YCHAR(TermInfo) = tm.tmHeight + tm.tmExternalLeading;

	// Set the terminal height and width based on the current font
	XSIZE(TermInfo) = tm.tmAveCharWidth * MAXCOLS;
	YSIZE(TermInfo) = (tm.tmHeight + tm.tmExternalLeading) * MAXROWS;

}
示例#8
0
static void game_compute_size(const game_params *params, int tilesize,
                              int *x, int *y)
{
    struct bbox bb = find_bbox(params);

    *x = XSIZE(tilesize, bb, solids[params->solid]);
    *y = YSIZE(tilesize, bb, solids[params->solid]);
}
示例#9
0
// Really import ==========================================================
void ProgXrayImport::readAndCrop(const FileName &fn, Image<double> &I, int xCropSize, int yCropSize) const
{
    I.read(fn);
    I().selfWindow(yCropSize,xCropSize,
                   (int)(YSIZE(I())-yCropSize-1),(int)(XSIZE(I())-xCropSize-1));

    I().resetOrigin();
}
示例#10
0
/* Filter generation ------------------------------------------------------- */
void Steerable::generate1DFilters(double sigma,
    const MultidimArray<double> &Vtomograph,
    std::vector< MultidimArray<double> > &hx1,
    std::vector< MultidimArray<double> > &hy1,
    std::vector< MultidimArray<double> > &hz1){

    // Initialization 
    MultidimArray<double> aux;
    aux.initZeros(XSIZE(Vtomograph));
    aux.setXmippOrigin();
    for (int i=0; i<6; i++) hx1.push_back(aux);
    
    aux.initZeros(YSIZE(Vtomograph));
    aux.setXmippOrigin();
    for (int i=0; i<6; i++) hy1.push_back(aux);

    aux.initZeros(ZSIZE(Vtomograph));
    aux.setXmippOrigin();
    for (int i=0; i<6; i++) hz1.push_back(aux);

    double sigma2=sigma*sigma;       
    double k1 =  1.0/pow((2.0*PI*sigma),(3.0/2.0));
    double k2 = -1.0/(sigma2);
    
    FOR_ALL_ELEMENTS_IN_ARRAY1D(hx1[0])
    {        
        double i2=i*i;
        double g = -exp(-i2/(2.0*sigma2));
	hx1[0](i) = k1*k2*g*(1.0-(i2/sigma2));
	hx1[1](i) = k1*k2*g;
	hx1[2](i) = k1*k2*g;
	hx1[3](i) = k1*k2*k2*g*i;
	hx1[4](i) = k1*k2*k2*g*i;
	hx1[5](i) = k1*k2*k2*g;
    }    
    FOR_ALL_ELEMENTS_IN_ARRAY1D(hy1[0])
    {
        double i2=i*i;
        double g = -exp(-i2/(2.0*sigma2));
        hy1[0](i) = g;
        hy1[1](i) = g*(1.0-(i2/sigma2));
        hy1[2](i) = g;
        hy1[3](i) = g*i;
        hy1[4](i) = g;
        hy1[5](i) = g*i;
    }
    FOR_ALL_ELEMENTS_IN_ARRAY1D(hz1[0])
    {
        double i2=i*i;
        double g = -exp(-i2/(2.0*sigma2));
	hz1[0](i) = g;
	hz1[1](i) = g;
	hz1[2](i) = g*(1.0-(i2/sigma2));
	hz1[3](i) = g;
	hz1[4](i) = g*i;
	hz1[5](i) = g*i;
    }
}
示例#11
0
文件: ctf.cpp 项目: dtegunov/vlion
void CTF::getCenteredImage(MultidimArray<DOUBLE> &result, DOUBLE Tm,
		    		bool do_abs, bool do_only_flip_phases, bool do_intact_until_first_peak, bool do_damping)
{
	result.setXmippOrigin();
	DOUBLE xs = (DOUBLE)XSIZE(result) * Tm;
	DOUBLE ys = (DOUBLE)YSIZE(result) * Tm;

	FOR_ALL_ELEMENTS_IN_ARRAY2D(result)
	{
		DOUBLE x = (DOUBLE)j / xs;
		DOUBLE y = (DOUBLE)i / ys;
		A2D_ELEM(result, i, j) = getCTF(x, y, do_abs, do_only_flip_phases, do_intact_until_first_peak, do_damping);
	}

}
示例#12
0
void FourierProjector::produceSideInfo()
{
    // Zero padding
    MultidimArray<double> Vpadded;
    int paddedDim=(int)(paddingFactor*volumeSize);
    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);
}
示例#13
0
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();
}
示例#14
0
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);
}
示例#15
0
	void run()
	{
		MD.read(fn_star);

		// Check for rlnImageName label
		if (!MD.containsLabel(EMDL_IMAGE_NAME))
			REPORT_ERROR("ERROR: Input STAR file does not contain the rlnImageName label");

		if (do_split_per_micrograph && !MD.containsLabel(EMDL_MICROGRAPH_NAME))
			REPORT_ERROR("ERROR: Input STAR file does not contain the rlnMicrographName label");

		Image<DOUBLE> in;
		FileName fn_img, fn_mic;
		std::vector<FileName> fn_mics;
		std::vector<int> mics_ndims;

		// First get number of images and their size
		int ndim=0;
		bool is_first=true;
		int xdim, ydim, zdim;
		FOR_ALL_OBJECTS_IN_METADATA_TABLE(MD)
		{
			if (is_first)
			{
				MD.getValue(EMDL_IMAGE_NAME, fn_img);
				in.read(fn_img);
				xdim=XSIZE(in());
				ydim=YSIZE(in());
				zdim=ZSIZE(in());
				is_first=false;
			}

			if (do_split_per_micrograph)
			{
				MD.getValue(EMDL_MICROGRAPH_NAME, fn_mic);
				bool have_found = false;
				for (int m = 0; m < fn_mics.size(); m++)
				{
					if (fn_mic == fn_mics[m])
					{
						have_found = true;
						mics_ndims[m]++;
						break;
					}
				}
				if (!have_found)
				{
					fn_mics.push_back(fn_mic);
					mics_ndims.push_back(1);
				}
			}
			ndim++;
		}


		// If not splitting, just fill fn_mics and mics_ndim with one entry (to re-use loop below)
		if (!do_split_per_micrograph)
		{
			fn_mics.push_back("");
			mics_ndims.push_back(ndim);
		}


		// Loop over all micrographs
		for (int m = 0; m < fn_mics.size(); m++)
		{
			ndim = mics_ndims[m];
			fn_mic = fn_mics[m];

			// Resize the output image
			std::cout << "Resizing the output stack to "<< ndim<<" images of size: "<<xdim<<"x"<<ydim<<"x"<<zdim << std::endl;
			DOUBLE Gb = ndim*zdim*ydim*xdim*8./1024./1024./1024.;
			std::cout << "This will require " << Gb << "Gb of memory...."<< std::endl;
			Image<DOUBLE> out(xdim, ydim, zdim, ndim);

			int n = 0;
			init_progress_bar(ndim);
			FOR_ALL_OBJECTS_IN_METADATA_TABLE(MD)
			{
				FileName fn_mymic;
				if (do_split_per_micrograph)
					MD.getValue(EMDL_MICROGRAPH_NAME, fn_mymic);
				else
					fn_mymic="";

				if (fn_mymic == fn_mic)
				{

					MD.getValue(EMDL_IMAGE_NAME, fn_img);
					in.read(fn_img);

					if (do_apply_trans)
					{
						DOUBLE xoff = 0.;
						DOUBLE yoff = 0.;
						DOUBLE psi = 0.;
						MD.getValue(EMDL_ORIENT_ORIGIN_X, xoff);
						MD.getValue(EMDL_ORIENT_ORIGIN_Y, yoff);
						MD.getValue(EMDL_ORIENT_PSI, psi);
						// Apply the actual transformation
						Matrix2D<DOUBLE> A;
						rotation2DMatrix(psi, A);
					    MAT_ELEM(A,0, 2) = xoff;
					    MAT_ELEM(A,1, 2) = yoff;
					    selfApplyGeometry(in(), A, IS_NOT_INV, DONT_WRAP);
					}

					out().setImage(n, in());
					n++;
					if (n%100==0) progress_bar(n);

				}
			}
			progress_bar(ndim);


			FileName fn_out;
			if (do_split_per_micrograph)
			{
				// Remove any extensions from micrograph names....
				fn_out = fn_root + "_" + fn_mic.withoutExtension() + fn_ext;
			}
			else
				fn_out = fn_root + fn_ext;
			out.write(fn_out);
			std::cout << "Written out: " << fn_out << std::endl;
		}
		std::cout << "Done!" <<std::endl;
	}
示例#16
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);
    }
}
示例#17
0
文件: fftw.cpp 项目: shy3u/GeRelion
// 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!");
	}
}
示例#18
0
void ProgSSNR::estimateSSNR(int dim, Matrix2D<double> &output)
{
    // These vectors are for 1D
    Matrix1D<double> S_S21D((int)(XSIZE(S()) / 2 - ring_width)),
    S_N21D((int)(XSIZE(S()) / 2 - ring_width)),
    K1D((int)(XSIZE(S()) / 2 - ring_width)),
    S_SSNR1D;
    Matrix1D<double> N_S21D((int)(XSIZE(S()) / 2 - ring_width)),
    N_N21D((int)(XSIZE(S()) / 2 - ring_width)),
    N_SSNR1D;

    // Selfile of the 2D images
    MetaData SF_individual;

    std::cerr << "Computing the SSNR ...\n";
    init_progress_bar(SF_S.size());
    int imgno = 1;
    Image<double> Is, In;
    Projection Iths, Ithn;
    MultidimArray< std::complex<double> > FFT_Is, FFT_Iths,  FFT_In, FFT_Ithn;
    MultidimArray<double> S2s, N2s, S2n, N2n;
    FileName fn_img;
    FourierTransformer FT(FFTW_BACKWARD);
    FourierProjector *Sprojector=NULL;
    FourierProjector *Nprojector=NULL;
    if (fourierProjections)
    {
    	Sprojector=new FourierProjector(S(),2,0.5,LINEAR);
    	Nprojector=new FourierProjector(N(),2,0.5,LINEAR);
    }
    FOR_ALL_OBJECTS_IN_METADATA2(SF_S, SF_N)
    {
    	double rot, tilt, psi;
    	SF_S.getValue(MDL_ANGLE_ROT,rot, __iter.objId);
    	SF_S.getValue(MDL_ANGLE_TILT,tilt,__iter.objId);
    	SF_S.getValue(MDL_ANGLE_PSI,psi,__iter.objId);
    	SF_S.getValue(MDL_IMAGE,fn_img,__iter.objId);
        Is.read(fn_img);
        Is().setXmippOrigin();
    	SF_N.getValue(MDL_IMAGE,fn_img,__iter2.objId);
        In.read(fn_img);
        In().setXmippOrigin();

        if (fourierProjections)
        {
        	projectVolume(*Sprojector, Iths, YSIZE(Is()), XSIZE(Is()), rot, tilt, psi);
        	projectVolume(*Nprojector, Ithn, YSIZE(Is()), XSIZE(Is()), rot, tilt, psi);
        }
        else
        {
			projectVolume(S(), Iths, YSIZE(Is()), XSIZE(Is()), rot, tilt, psi);
			projectVolume(N(), Ithn, YSIZE(Is()), XSIZE(Is()), rot, tilt, psi);
        }

#ifdef DEBUG

        Image<double> save;
        save() = Is();
        save.write("PPPread_signal.xmp");
        save() = In();
        save.write("PPPread_noise.xmp");
        save() = Iths();
        save.write("PPPtheo_signal.xmp");
        save() = Ithn();
        save.write("PPPtheo_noise.xmp");
#endif

        Is() -= Iths();
        In() -= Ithn(); // According to the article: should we not subtract here (simply remove this line)
                        // "...except that there is no subtraction in the denominator because the
        				// underlying signal is zero by definition."

        if (dim == 2)
        {
            FT.completeFourierTransform(Is(), FFT_Is);
            FT.completeFourierTransform(Iths(), FFT_Iths);
            FT.completeFourierTransform(In(), FFT_In);
            FT.completeFourierTransform(Ithn(), FFT_Ithn);
        }
        else
        {
            FT.FourierTransform(Is(), FFT_Is);
            FT.FourierTransform(Iths(), FFT_Iths);
            FT.FourierTransform(In(), FFT_In);
            FT.FourierTransform(Ithn(), FFT_Ithn);
        }

#ifdef DEBUG

        Image< std::complex<double> > savec;
        savec() = FFT_Is;
        savec.write("PPPFFTread_signal.xmp");
        savec() = FFT_In;
        savec.write("PPPFFTread_noise.xmp");
        savec() = FFT_Iths;
        savec.write("PPPFFTtheo_signal.xmp");
        savec() = FFT_Ithn;
        savec.write("PPPFFTtheo_noise.xmp");
#endif

        // Compute the amplitudes
        S2s.resizeNoCopy(FFT_Iths);
        N2s.resizeNoCopy(FFT_Iths);
        S2n.resizeNoCopy(FFT_Iths);
        N2n.resizeNoCopy(FFT_Iths);
        FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(FFT_Iths)
        {
            DIRECT_MULTIDIM_ELEM(S2s, n) = abs(DIRECT_MULTIDIM_ELEM(FFT_Iths, n));
            DIRECT_MULTIDIM_ELEM(S2s, n) *= DIRECT_MULTIDIM_ELEM(S2s, n);
            DIRECT_MULTIDIM_ELEM(N2s, n) = abs(DIRECT_MULTIDIM_ELEM(FFT_Is, n));
            DIRECT_MULTIDIM_ELEM(N2s, n) *= DIRECT_MULTIDIM_ELEM(N2s, n);
            DIRECT_MULTIDIM_ELEM(S2n, n) = abs(DIRECT_MULTIDIM_ELEM(FFT_Ithn, n));
            DIRECT_MULTIDIM_ELEM(S2n, n) *= DIRECT_MULTIDIM_ELEM(S2n, n);
            DIRECT_MULTIDIM_ELEM(N2n, n) = abs(DIRECT_MULTIDIM_ELEM(FFT_In, n));
            DIRECT_MULTIDIM_ELEM(N2n, n) *= DIRECT_MULTIDIM_ELEM(N2n, n);
        }

#ifdef DEBUG

        save() = S2s();
        save.write("PPPS2s.xmp");
        save() = N2s();
        save.write("PPPN2s.xmp");
        save() = S2n();
        save.write("PPPS2n.xmp");
        save() = N2n();
        save.write("PPPN2n.xmp");
#endif

        if (dim == 2)
        {
            // Compute the SSNR image
            Image<double> SSNR2D;
            SSNR2D().initZeros(S2s);
            const MultidimArray<double> & SSNR2Dmatrix=SSNR2D();
            FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(S2s)
            {
                double ISSNR = 0, alpha = 0, SSNR = 0;
                double aux = DIRECT_MULTIDIM_ELEM(N2s,n);
                if (aux > min_power)
                    ISSNR = DIRECT_MULTIDIM_ELEM(S2s,n) / aux;
                aux = DIRECT_MULTIDIM_ELEM(N2n,n);
                if (aux > min_power)
                    alpha = DIRECT_MULTIDIM_ELEM(S2n,n) / aux;
                if (alpha > min_power)
                {
                    aux = ISSNR / alpha - 1.0;
                    SSNR = XMIPP_MAX(aux, 0.0);
                }
                if (SSNR    > min_power)
                    DIRECT_MULTIDIM_ELEM(SSNR2Dmatrix,n) = 10.0 * log10(SSNR + 1.0);
            }
            CenterFFT(SSNR2D(), true);
#ifdef DEBUG

            save() = SSNR2Dmatrix;
            save.write("PPPSSNR2D.xmp");
#endif

            // Save image
            FileName fn_img_out;
            fn_img_out.compose(imgno, fn_out_images, "stk");
            SSNR2D.write(fn_img_out);
            size_t objId = SF_individual.addObject();
            SF_individual.setValue(MDL_IMAGE,fn_img_out,objId);
            SF_individual.setValue(MDL_ANGLE_ROT,rot,objId);
            SF_individual.setValue(MDL_ANGLE_TILT,tilt,objId);
            SF_individual.setValue(MDL_ANGLE_PSI,psi,objId);
        }
示例#19
0
static void game_redraw(drawing *dr, game_drawstate *ds,
                        const game_state *oldstate, const game_state *state,
                        int dir, const game_ui *ui,
                        float animtime, float flashtime)
{
    int i, j;
    struct bbox bb = find_bbox(&state->params);
    struct solid *poly;
    const int *pkey, *gkey;
    float t[3];
    float angle;
    int square;

    draw_rect(dr, 0, 0, XSIZE(GRID_SCALE, bb, state->solid),
	      YSIZE(GRID_SCALE, bb, state->solid), COL_BACKGROUND);

    if (dir < 0) {
        const game_state *t;

        /*
         * This is an Undo. So reverse the order of the states, and
         * run the roll timer backwards.
         */
	assert(oldstate);

        t = oldstate;
        oldstate = state;
        state = t;

        animtime = ROLLTIME - animtime;
    }

    if (!oldstate) {
        oldstate = state;
        angle = 0.0;
        square = state->current;
        pkey = state->dpkey;
        gkey = state->dgkey;
    } else {
        angle = state->angle * animtime / ROLLTIME;
        square = state->previous;
        pkey = state->spkey;
        gkey = state->sgkey;
    }
    state = oldstate;

    for (i = 0; i < state->grid->nsquares; i++) {
        int coords[8];

        for (j = 0; j < state->grid->squares[i].npoints; j++) {
            coords[2*j] = ((int)(state->grid->squares[i].points[2*j] * GRID_SCALE)
			   + ds->ox);
            coords[2*j+1] = ((int)(state->grid->squares[i].points[2*j+1]*GRID_SCALE)
			     + ds->oy);
        }

        draw_polygon(dr, coords, state->grid->squares[i].npoints,
                     GET_SQUARE(state, i) ? COL_BLUE : COL_BACKGROUND,
		     COL_BORDER);
    }

    /*
     * Now compute and draw the polyhedron.
     */
    poly = transform_poly(state->solid, state->grid->squares[square].flip,
                          pkey[0], pkey[1], angle);

    /*
     * Compute the translation required to align the two key points
     * on the polyhedron with the same key points on the current
     * face.
     */
    for (i = 0; i < 3; i++) {
        float tc = 0.0;

        for (j = 0; j < 2; j++) {
            float grid_coord;

            if (i < 2) {
                grid_coord =
                    state->grid->squares[square].points[gkey[j]*2+i];
            } else {
                grid_coord = 0.0;
            }

            tc += (grid_coord - poly->vertices[pkey[j]*3+i]);
        }

        t[i] = tc / 2;
    }
    for (i = 0; i < poly->nvertices; i++)
        for (j = 0; j < 3; j++)
            poly->vertices[i*3+j] += t[j];

    /*
     * Now actually draw each face.
     */
    for (i = 0; i < poly->nfaces; i++) {
        float points[8];
        int coords[8];

        for (j = 0; j < poly->order; j++) {
            int f = poly->faces[i*poly->order + j];
            points[j*2] = (poly->vertices[f*3+0] -
                           poly->vertices[f*3+2] * poly->shear);
            points[j*2+1] = (poly->vertices[f*3+1] -
                             poly->vertices[f*3+2] * poly->shear);
        }

        for (j = 0; j < poly->order; j++) {
            coords[j*2] = (int)floor(points[j*2] * GRID_SCALE) + ds->ox;
            coords[j*2+1] = (int)floor(points[j*2+1] * GRID_SCALE) + ds->oy;
        }

        /*
         * Find out whether these points are in a clockwise or
         * anticlockwise arrangement. If the latter, discard the
         * face because it's facing away from the viewer.
         *
         * This would involve fiddly winding-number stuff for a
         * general polygon, but for the simple parallelograms we'll
         * be seeing here, all we have to do is check whether the
         * corners turn right or left. So we'll take the vector
         * from point 0 to point 1, turn it right 90 degrees,
         * and check the sign of the dot product with that and the
         * next vector (point 1 to point 2).
         */
        {
            float v1x = points[2]-points[0];
            float v1y = points[3]-points[1];
            float v2x = points[4]-points[2];
            float v2y = points[5]-points[3];
            float dp = v1x * v2y - v1y * v2x;

            if (dp <= 0)
                continue;
        }

        draw_polygon(dr, coords, poly->order,
                     state->facecolours[i] ? COL_BLUE : COL_BACKGROUND,
		     COL_BORDER);
    }
    sfree(poly);

    draw_update(dr, 0, 0, XSIZE(GRID_SCALE, bb, state->solid),
		YSIZE(GRID_SCALE, bb, state->solid));

    /*
     * Update the status bar.
     */
    {
	char statusbuf[256];

	if (state->completed) {
		strcpy(statusbuf, _("COMPLETED!"));
		strcpy(statusbuf+strlen(statusbuf), " ");
	} else statusbuf[0] = '\0';
	sprintf(statusbuf+strlen(statusbuf), _("Moves: %d"),
		(state->completed ? state->completed : state->movecount));

	status_bar(dr, statusbuf);
    }
}
示例#20
0
void PolyZernikes::fit(const Matrix1D<int> & coef, MultidimArray<double> & im, MultidimArray<double> &weight,
                       MultidimArray<bool> & ROI, int verbose)
{
    this->create(coef);

    size_t xdim = XSIZE(im);
    size_t ydim = YSIZE(im);
    //int numZer = (size_t)coef.sum();
    int numZer = (size_t)coef.sum();

    //Actually polOrder corresponds to the polynomial order +1
    int polOrder=(int)ZERNIKE_ORDER(coef.size());

    im.setXmippOrigin();

    Matrix2D<double> polValue(polOrder,polOrder);

    //First argument means number of images
    //Second argument means number of pixels
    WeightedLeastSquaresHelper weightedLeastSquaresHelper;
    Matrix2D<double>& zerMat=weightedLeastSquaresHelper.A;

    zerMat.resizeNoCopy((size_t)ROI.sum(), numZer);
    double iMaxDim2 = 2./std::max(xdim,ydim);

    size_t pixel_idx=0;

    weightedLeastSquaresHelper.b.resizeNoCopy((size_t)ROI.sum());
    weightedLeastSquaresHelper.w.resizeNoCopy(weightedLeastSquaresHelper.b);

    FOR_ALL_ELEMENTS_IN_ARRAY2D(im)
    {
        if ( (A2D_ELEM(ROI,i,j)))
        {
            //For one i we swap the different j
            double y=i*iMaxDim2;
            double x=j*iMaxDim2;

            //polValue = [ 0    y   y2    y3   ...
            //             x   xy  xy2    xy3  ...
            //             x2  x2y x2y2   x2y3 ]
            //dMij(polValue,py,px) py es fila, px es columna

            for (int py = 0; py < polOrder; ++py)
            {
                double ypy=std::pow(y,py);
                for (int px = 0; px < polOrder; ++px)
                    dMij(polValue,px,py) = ypy*std::pow(x,px);
            }

            Matrix2D<int> *fMat;

            //We generate the representation of the Zernike polynomials
            for (int k=0; k < numZer; ++k)
            {
                fMat = &fMatV[k];

                if (fMat == NULL)
                    continue;

                double temp = 0;
                for (size_t px = 0; px < (*fMat).Xdim(); ++px)
                    for (size_t py = 0; py < (*fMat).Ydim(); ++py)
                        temp += dMij(*fMat,py,px)*dMij(polValue,py,px);

                dMij(zerMat,pixel_idx,k) = temp;
            }

            VEC_ELEM(weightedLeastSquaresHelper.b,pixel_idx)=A2D_ELEM(im,i,j);
            VEC_ELEM(weightedLeastSquaresHelper.w,pixel_idx)=std::abs(A2D_ELEM(weight,i,j));
            ++pixel_idx;
        }
    }

    Matrix1D<double> zernikeCoefficients;
    weightedLeastSquares(weightedLeastSquaresHelper, zernikeCoefficients);
    fittedCoeffs = zernikeCoefficients;

    // Pointer to the image to be fitted
    MultidimArray<double> reconstructed;

    reconstructed.resizeNoCopy(im);
    pixel_idx=0;

    FOR_ALL_ELEMENTS_IN_ARRAY2D(im)
    if (A2D_ELEM(ROI,i,j))
    {
        double temp=0;
        for (int k=0; k < numZer; ++k)
            temp+=dMij(zerMat,pixel_idx,k)*VEC_ELEM(fittedCoeffs,k);

        A2D_ELEM(reconstructed,i,j)=temp;

        if ( fabs(A2D_ELEM(reconstructed,i,j)-A2D_ELEM(im,i,j)) > PI)
            A2D_ELEM(ROI,i,j) = false;

        ++pixel_idx;
    }

    pixel_idx=0;

    if (verbose > 0)
    {
        Image<double> save;
        save()=reconstructed;
        save.write("reconstructedZernikes.xmp");
        ROI.write("ROI.txt");
    }
}
示例#21
0
void Projector::rotate3D(MultidimArray<Complex > &f3d, Matrix2D<DOUBLE> &A, bool inv)
{
	DOUBLE fx, fy, fz, xp, yp, zp;
	int x0, x1, y0, y1, z0, z1, y, z, y2, z2, r2;
	bool is_neg_x;
	Complex d000, d010, d100, d110, d001, d011, d101, d111, dx00, dx10, dxy0, dx01, dx11, dxy1;
	Matrix2D<DOUBLE> Ainv;

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

    // The f3d 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(f3d) - 1);

    // Go from the 3D rotated coordinates to the original 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(f3d)= "<< XSIZE(f3d) << std::endl;
    std::cerr << " YSIZE(f3d)= "<< YSIZE(f3d) << 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 k=0; k < ZSIZE(f3d); k++)
	{
		// Don't search beyond square with side max_r
		if (k <= my_r_max)
		{
			z = k;
		}
		else if (k >= ZSIZE(f3d) - my_r_max)
		{
			z = k - ZSIZE(f3d);
		}
		else
			continue;
		z2 = z * z;

		for (int i=0; i < YSIZE(f3d); i++)
		{
			// Don't search beyond square with side max_r
			if (i <= my_r_max)
			{
				y = i;
			}
			else if (i >= YSIZE(f3d) - my_r_max)
			{
				y = i - YSIZE(f3d);
			}
			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 + z2;
				if (r2 > max_r2)
					continue;

				// Get logical coordinates in the 3D map
				xp = Ainv(0,0) * x + Ainv(0,1) * y + Ainv(0,2) * z;
				yp = Ainv(1,0) * x + Ainv(1,1) * y + Ainv(1,2) * z;
				zp = Ainv(2,0) * x + Ainv(2,1) * y + Ainv(2,2) * z;

				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;
						zp = -zp;
						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;

					z0 = FLOOR(zp);
					fz = zp - z0;
					z0 -=  STARTINGZ(data);
					z1 = z0 + 1;

					// Matrix access can be accelerated through pre-calculation of z0*xydim etc.
					d000 = DIRECT_A3D_ELEM(data, z0, y0, x0);
					d001 = DIRECT_A3D_ELEM(data, z0, y0, x1);
					d010 = DIRECT_A3D_ELEM(data, z0, y1, x0);
					d011 = DIRECT_A3D_ELEM(data, z0, y1, x1);
					d100 = DIRECT_A3D_ELEM(data, z1, y0, x0);
					d101 = DIRECT_A3D_ELEM(data, z1, y0, x1);
					d110 = DIRECT_A3D_ELEM(data, z1, y1, x0);
					d111 = DIRECT_A3D_ELEM(data, z1, y1, x1);

					// Set the interpolated value in the 2D output array
					// interpolate in x
#ifndef FLOAT_PRECISION
                    __m256d __fx = _mm256_set1_pd(fx);
                    __m256d __interpx1 = LIN_INTERP_AVX(_mm256_setr_pd(d000.real, d000.imag, d100.real, d100.imag),
                                                        _mm256_setr_pd(d001.real, d001.imag, d101.real, d101.imag),
                                                        __fx);
                    __m256d __interpx2 = LIN_INTERP_AVX(_mm256_setr_pd(d010.real, d010.imag, d110.real, d110.imag),
                                                        _mm256_setr_pd(d011.real, d011.imag, d111.real, d111.imag),
                                                        __fx);

                    // interpolate in y
                    __m256d __fy = _mm256_set1_pd(fy);
                    __m256d __interpy = LIN_INTERP_AVX(__interpx1, __interpx2, __fy);
#else
                    __m128 __fx = _mm_set1_ps(fx);
                    __m128 __interpx1 = LIN_INTERP_AVX(_mm_setr_ps(d000.real, d000.imag, d100.real, d100.imag),
                                                       _mm_setr_ps(d001.real, d001.imag, d101.real, d101.imag),
                                                       __fx);
                    __m128 __interpx2 = LIN_INTERP_AVX(_mm_setr_ps(d010.real, d010.imag, d110.real, d110.imag),
                                                       _mm_setr_ps(d011.real, d011.imag, d111.real, d111.imag),
                                                       __fx);

                    // interpolate in y
                    __m128 __fy = _mm_set1_ps(fy);
                    __m128 __interpy = LIN_INTERP_AVX(__interpx1, __interpx2, __fy);
#endif

                    Complex* interpy = (Complex*)&__interpy;

					//interpolate in z
					DIRECT_A3D_ELEM(f3d, k, i, x) = LIN_INTERP(fz, interpy[0], interpy[1]);

					// Take complex conjugated for half with negative x
					if (is_neg_x)
						DIRECT_A3D_ELEM(f3d, k, i, x) = conj(DIRECT_A3D_ELEM(f3d, k, i, x));

				} // endif TRILINEAR
				else if (interpolator == NEAREST_NEIGHBOUR )
				{
					x0 = ROUND(xp);
					y0 = ROUND(yp);
					z0 = ROUND(zp);

					if (x0 < 0)
						DIRECT_A3D_ELEM(f3d, k, i, x) = conj(A3D_ELEM(data, -z0, -y0, -x0));
					else
						DIRECT_A3D_ELEM(f3d, k, i, x) = A3D_ELEM(data, z0, y0, x0);

				} // endif NEAREST_NEIGHBOUR
				else
					REPORT_ERROR("Unrecognized interpolator in Projector::project");
			} // endif x-loop
		} // endif y-loop
	} // endif z-loop
}
示例#22
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();
}
示例#23
0
void runThread(ThreadArgument &thArg)
{
    int thread_id = thArg.thread_id;
    ProgXrayImport * ptrProg= (ProgXrayImport *)thArg.workClass;

    MetaData localMD;
    Image<double> Iaux;
    FileName fnImgIn, fnImgOut;
    size_t first = 0, last = 0;
    MultidimArray<char> mask;

    while (ptrProg->td->getTasks(first, last))
    {
        for (size_t i=first; i<=last; i++)
        {
            ptrProg->inMD.getValue(MDL_IMAGE, fnImgIn, ptrProg->objIds[i]);


            MDRow rowGeo;
            ptrProg->readGeoInfo(fnImgIn, rowGeo);
//            ptrProg->readAndCrop(fnImgIn, Iaux, ptrProg->cropSizeX, ptrProg->cropSizeY);

            Iaux.read(fnImgIn);
            Iaux().selfWindow(ptrProg->cropSizeYi,ptrProg->cropSizeXi,
            		(int)(YSIZE(Iaux())-ptrProg->cropSizeYe-1),(int)(XSIZE(Iaux())-ptrProg->cropSizeXe-1));

            Iaux().resetOrigin();




            if (XSIZE(ptrProg->IavgDark())!=0)
            {
                Iaux()-=ptrProg->IavgDark();
                forcePositive(Iaux());
            }


            double currentBeam = 1;
            double expTime = 1;
            double slitWidth = 1;

            if ( ptrProg->dSource == ptrProg->MISTRAL )
            {
                size_t idx = fnImgIn.getPrefixNumber();
                currentBeam = dMi(ptrProg->cBeamArray, idx-1);
                expTime = dMi(ptrProg->expTimeArray, idx-1);
                slitWidth = dMi(ptrProg->slitWidthArray, idx-1);
            }
            else
                ptrProg->readCorrectionInfo(fnImgIn, currentBeam, expTime, slitWidth);

            Iaux() *= 1.0/(currentBeam*expTime*slitWidth);
            if (XSIZE(ptrProg->IavgFlat())!=0)
                Iaux()/=ptrProg->IavgFlat();

            // Assign median filter to zero valued pixels to avoid -inf when applying log10
            Iaux().equal(0,mask);
            mask.resizeNoCopy(Iaux());

            if (XSIZE(ptrProg->bpMask()) != 0)
                mask += ptrProg->bpMask();

            boundMedianFilter(Iaux(), mask);

            if (ptrProg->logFix)
            {
                Iaux().selfLog();
                if (ptrProg->selfAttFix)
                    Iaux() *= -1.;
            }

            fnImgOut.compose(i+1, ptrProg->fnOut);


            size_t objId = localMD.addObject();
            localMD.setValue(MDL_IMAGE,fnImgOut,objId);
            localMD.setRow(rowGeo, objId); //
            //            localMD.setValue(MDL_ANGLE_TILT,Iaux.tilt(),objId);
            Iaux.write(fnImgOut);
            if (thread_id==0)
                progress_bar(i);
        }
    }
    //Lock for update the total counter
    ptrProg->mutex.lock();
    ptrProg->outMD.unionAll(localMD);
    ptrProg->mutex.unlock();
}
示例#24
0
void PolyZernikes::zernikePols(const Matrix1D<int> coef, MultidimArray<double> & im, MultidimArray<bool> & ROI, int verbose)
{

    this->create(coef);

    int polOrder=(int)ZERNIKE_ORDER(coef.size());
    int numZer = coef.size();

    int xdim = XSIZE(im);
    int ydim = YSIZE(im);

    im.setXmippOrigin();

    Matrix2D<double> polValue(polOrder,polOrder);
    double iMaxDim2 = 2./std::max(xdim,ydim);

    double temp = 0;
    FOR_ALL_ELEMENTS_IN_ARRAY2D(im)
    {
        if (A2D_ELEM(ROI,i,j))
        {
            //For one i we swap the different j
            double y=i*iMaxDim2;
            double x=j*iMaxDim2;

            //polValue = [ 0    y   y2    y3   ...
            //             x   xy  xy2    xy3  ...
            //             x2  x2y x2y2   x2y3 ]
            //dMij(polValue,py,px) py es fila, px es columna
            for (int py = 0; py < polOrder; ++py)
            {
                double ypy=std::pow(y,py);
                for (int px = 0; px < polOrder; ++px)
                    dMij(polValue,px,py) = ypy*std::pow(x,px);
            }

            Matrix2D<int> *fMat;
            //We generate the representation of the Zernike polynomials

            for (int k=0; k < numZer; ++k)
            {
                fMat = &fMatV[k];

                if ( (dMij(*fMat,0,0) == 0) && MAT_SIZE(*fMat) == 1 )
                    continue;

                for (size_t px = 0; px < (*fMat).Xdim(); ++px)
                    for (size_t py = 0; py < (*fMat).Ydim(); ++py)
                        temp += dMij(*fMat,py,px)*dMij(polValue,py,px)*VEC_ELEM(coef,k);
            }

            A2D_ELEM(im,i,j) = temp;
            temp = 0;
        }
    }

    STARTINGX(im)=STARTINGY(im)=0;

    if (verbose == 1)
    {
        Image<double> save;
        save()=im;
        save.write("PPP1.xmp");
    }
}
示例#25
0
void ProgXrayImport::run()
{
    // Delete output stack if it exists
    fnOut = fnRoot + ".mrc";
    fnOut.deleteFile();

    /* Turn off error handling */
    H5Eset_auto(H5E_DEFAULT, NULL, NULL);

    if (dSource == MISTRAL)
        H5File.openFile(fnInput, H5F_ACC_RDONLY);


    // Reading bad pixels mask
    if ( !fnBPMask.empty() )
    {
        std::cerr << "Reading bad pixels mask from "+fnBPMask << "." << std::endl;
        bpMask.read(fnBPMask);
        if ( (cropSizeX + cropSizeY ) > 0 )
            bpMask().selfWindow(cropSizeY,cropSizeX,
                                (int)(YSIZE(bpMask())-cropSizeY-1),(int)(XSIZE(bpMask())-cropSizeX-1));
        STARTINGX(bpMask()) = STARTINGY(bpMask()) = 0;
    }


    // Setting the image projections list
    switch (dSource)
    {
    case MISTRAL:
        {
            inMD.read(fnInput);
            H5File.getDataset("NXtomo/data/rotation_angle", anglesArray, false);
            H5File.getDataset("NXtomo/instrument/sample/ExpTimes", expTimeArray, false);
            H5File.getDataset("NXtomo/instrument/sample/current", cBeamArray);

            /* In case there is no angles information we set them to to an increasing sequence
             * just to be able to continue importing data */
            if ( anglesArray.size() != inMD.size() )
            {
                reportWarning("Input file does not contains angle information. Default sequence used.");
                anglesArray.resizeNoCopy(inMD.size());
                anglesArray.enumerate();
            }

            // If expTime is empty or only one single value in nexus file then we fill with 1
            if (expTimeArray.size() < 2)
            {
                reportWarning("Input file does not contains tomogram exposition time information.");
                expTimeArray.initConstant(anglesArray.size(), 1.);
            }
            // If current is empty or only one single value in nexus file then we fill with 1
            if (cBeamArray.size() < 2)
            {
                reportWarning("Input file does not contains tomogram current beam information.");
                cBeamArray.initConstant(anglesArray.size(), 1.);
            }
            // Since Alba does not provide slit width, we set to ones
            slitWidthArray.initConstant(anglesArray.size(), 1.);
        }
        break;
    case BESSY:
        {
            size_t objId;

            for (size_t i = tIni; i <= tEnd; ++i)
            {
                objId = inMD.addObject();
                inMD.setValue(MDL_IMAGE, fnInput + formatString("/img%d.spe", i), objId);
            }
            break;
        }
    case GENERIC:
        {
            // Get Darkfield
            std::cerr << "Getting darkfield from "+fnInput << " ..." << std::endl;
            getDarkfield(fnInput, IavgDark);
            if (XSIZE(IavgDark())!=0)
                IavgDark.write(fnRoot+"_darkfield.xmp");


            std::vector<FileName> listDir;
            fnInput.getFiles(listDir);
            size_t objId;

            for (size_t i = 0; i < listDir.size(); ++i)
            {
                if (!listDir[i].hasImageExtension())
                    continue;
                objId = inMD.addObject();
                inMD.setValue(MDL_IMAGE, fnInput+"/"+listDir[i], objId);
            }
        }
        break;
    }

    inMD.findObjects(objIds);
    size_t nIm = inMD.size();

    // Create empty output stack file

    getImageInfo(inMD, imgInfo);


    /* Get the flatfield:: We get the FF after the image list because we need the image size to adapt the FF
     * in case they were already cropped.
     */
    if (!fnFlat.empty())
    {
        std::cout << "Getting flatfield from "+fnFlat << " ..." << std::endl;
        getFlatfield(fnFlat,IavgFlat);
        if ( XSIZE(IavgFlat()) != 0 )
        {
            FileName ffName = fnRoot+"_flatfield_avg.xmp";
            IavgFlat.write(ffName);
            fMD.setValue(MDL_IMAGE, ffName, fMD.addObject());
        }
    }

    createEmptyFile(fnOut, imgInfo.adim.xdim-cropSizeXi-cropSizeXe, imgInfo.adim.ydim-cropSizeYi-cropSizeYe, 1, nIm);

    // Process images
    td = new ThreadTaskDistributor(nIm, XMIPP_MAX(1, nIm/30));
    tm = new ThreadManager(thrNum, this);
    std::cerr << "Getting data from " << fnInput << " ...\n";
    init_progress_bar(nIm);
    tm->run(runThread);
    progress_bar(nIm);

    // Write Metadata and angles
    MetaData MDSorted;
    MDSorted.sort(outMD,MDL_ANGLE_TILT);
    MDSorted.write("tomo@"+fnRoot + ".xmd");
    if ( fMD.size() > 0 )
        fMD.write("flatfield@"+fnRoot + ".xmd", MD_APPEND);

    // We also reference initial and final images at 0 degrees for Mistral tomograms
    if ( dSource == MISTRAL )
    {
        fMD.clear();
        FileName degree0Fn = "NXtomo/instrument/sample/0_degrees_initial_image";
        if ( H5File.checkDataset(degree0Fn.c_str()))
            fMD.setValue(MDL_IMAGE, degree0Fn + "@" + fnInput, fMD.addObject());
        degree0Fn = "NXtomo/instrument/sample/0_degrees_final_image";
        if ( H5File.checkDataset(degree0Fn.c_str()))
            fMD.setValue(MDL_IMAGE, degree0Fn + "@" + fnInput, fMD.addObject());
        if ( fMD.size() > 0 )
            fMD.write("degree0@"+fnRoot + ".xmd", MD_APPEND);
    }

    // Write tlt file for IMOD
    std::ofstream fhTlt;
    fhTlt.open((fnRoot+".tlt").c_str());
    if (!fhTlt)
        REPORT_ERROR(ERR_IO_NOWRITE,fnRoot+".tlt");
    FOR_ALL_OBJECTS_IN_METADATA(MDSorted)
    {
        double tilt;
        MDSorted.getValue(MDL_ANGLE_TILT,tilt,__iter.objId);
        fhTlt << tilt << std::endl;
    }
    fhTlt.close();
    delete td;
    delete tm;
}
示例#26
0
// Evaluate plane ----------------------------------------------------------
double evaluatePlane(double rot, double tilt,
                     const MultidimArray<double> *V, const MultidimArray<double> *Vmag,
                     double maxFreq, double planeWidth, int direction,
                     MultidimArray<double> *Vdraw=NULL,
                     bool setPos=false, double rotPos=0, double tiltPos=0)
{
    if (rot<0 || rot>360 || tilt<-90 || tilt>90)
        return 0;

    Matrix2D<double> E, Einv;
    Euler_angles2matrix(rot,tilt,0,E);
    Einv=E.transpose();

    if (setPos)
    {
        Matrix2D<double> Epos;
        Euler_angles2matrix(rotPos,tiltPos,0,Epos);
        double angle=acos(E(2,0)*Epos(2,0)+E(2,1)*Epos(2,1)+E(2,2)*Epos(2,2));
        angle=RAD2DEG(angle);
        if (fabs(angle)<20 || fabs(180-angle)<20)
            return 0;
    }

    size_t N=XMIPP_MAX(XSIZE(*Vmag),YSIZE(*Vmag)/2);
    N=XMIPP_MAX(N,ZSIZE(*Vmag)/2);
    double df=0.5/N;
    Matrix1D<double> freq(3), freqp(3);
    Matrix1D<int> idx(3);
    double sumNeg=0, sumPos=0;
    int Nneg=0, Npos=0;
    double maxFreq2=maxFreq*maxFreq;
    int iPlaneWidth=(int)ceil(planeWidth);
    for (double ix=0; ix<=N; ix++)
    {
        XX(freq)=ix*df;
        double fx2=XX(freq)*XX(freq);
        if (fx2>maxFreq2)
            continue;
        for (double iy=-(int)N; iy<=N; iy++)
        {
            YY(freq)=iy*df;
            double fx2fy2=fx2+YY(freq)*YY(freq);
            if (fx2fy2>maxFreq2)
                continue;
            for (int iz=-iPlaneWidth; iz<=iPlaneWidth; iz++)
            {
                if (iz==0 || ix==0 || iy==0)
                    continue;

                // Frequency in the coordinate system of the plane
                ZZ(freq)=iz*df;

                // Frequency in the coordinate system of the volume
                SPEED_UP_temps012;
                M3x3_BY_V3x1(freqp,Einv,freq);
                bool inverted=false;
                if (XX(freqp)<0)
                {
                    XX(freqp)=-XX(freqp);
                    YY(freqp)=-YY(freqp);
                    ZZ(freqp)=-ZZ(freqp);
                    inverted=true;
                }

                // Get the corresponding index
                DIGFREQ2FFT_IDX(ZZ(freqp), ZSIZE(*V), ZZ(idx));
                DIGFREQ2FFT_IDX(YY(freqp), YSIZE(*V), YY(idx));
                DIGFREQ2FFT_IDX(XX(freqp), XSIZE(*V), XX(idx));
                if (XX(idx) < STARTINGX(*Vmag) || XX(idx) > FINISHINGX(*Vmag) ||
                    YY(idx) < STARTINGY(*Vmag) || YY(idx) > FINISHINGY(*Vmag) ||
                    ZZ(idx) < STARTINGZ(*Vmag) || ZZ(idx) > FINISHINGZ(*Vmag))
                    continue;

                // Make the corresponding sums
                bool negativeSum;
                if (direction==1)
                    negativeSum=iz<0;
                else
                    negativeSum=iz>0;
                double val=A3D_ELEM(*Vmag,ZZ(idx),YY(idx),XX(idx));
                if ((negativeSum && !inverted) || (!negativeSum && inverted)) // XOR
                {
                    sumNeg+=val;
                    Nneg++;
                    if (Vdraw!=NULL)
                        (*Vdraw)(idx)=2*direction*val;
                }
                else
                {
                    sumPos+=val;
                    Npos++;
                    if (Vdraw!=NULL)
                        (*Vdraw)(idx)=1.0/2.0*direction*val;
                }
            }
        }
    }
    if (fabs(Nneg-Npos)/(0.5*(Nneg+Npos))>0.5)
        // If there is a difference of more than 50%
        return 1e38;
    if (Nneg!=0)
        sumNeg/=Nneg;
    else
        return 1e38;
    if (Npos!=0)
        sumPos/=Npos;
    else
        return 1e38;

    return -(sumPos-sumNeg);
}
示例#27
0
文件: fftw.cpp 项目: shy3u/GeRelion
void FourierTransformer::setReal(MultidimArray<double>& input)
{
	bool recomputePlan = false;
	if (fReal == NULL)
	{
		recomputePlan = true;
	}
	else if (dataPtr != MULTIDIM_ARRAY(input))
	{
		recomputePlan = true;
	}
	else
	{
		recomputePlan = !(fReal->sameShape(input));
	}
	fFourier.resize(ZSIZE(input), YSIZE(input), XSIZE(input) / 2 + 1);
	fReal = &input;

	if (recomputePlan)
	{
		int ndim = 3;
		if (ZSIZE(input) == 1)
		{
			ndim = 2;
			if (YSIZE(input) == 1)
			{
				ndim = 1;
			}
		}
		int* N = new int[ndim];
		switch (ndim)
		{
		case 1:
			N[0] = XSIZE(input);
			break;
		case 2:
			N[0] = YSIZE(input);
			N[1] = XSIZE(input);
			break;
		case 3:
			N[0] = ZSIZE(input);
			N[1] = YSIZE(input);
			N[2] = XSIZE(input);
			break;
		}

		// Destroy both forward and backward plans if they already exist
		destroyPlans();
		// Make new plans
		pthread_mutex_lock(&fftw_plan_mutex);
		fPlanForward = fftw_plan_dft_r2c(ndim, N, MULTIDIM_ARRAY(*fReal),
		                                 (fftw_complex*) MULTIDIM_ARRAY(fFourier), FFTW_ESTIMATE);
		fPlanBackward = fftw_plan_dft_c2r(ndim, N,
		                                  (fftw_complex*) MULTIDIM_ARRAY(fFourier), MULTIDIM_ARRAY(*fReal),
		                                  FFTW_ESTIMATE);
		pthread_mutex_unlock(&fftw_plan_mutex);

		if (fPlanForward == NULL || fPlanBackward == NULL)
		{
			REPORT_ERROR("FFTW plans cannot be created");
		}

#ifdef DEBUG_PLANS
		std::cerr << " SETREAL fPlanForward= " << fPlanForward << " fPlanBackward= " << fPlanBackward  << " this= " << this << std::endl;
#endif

		delete [] N;
		dataPtr = MULTIDIM_ARRAY(*fReal);
	}
}
示例#28
0
//#define DEBUG
void ProgResolutionIBW::run()
{
    V.read(fnVol);

    //Mask generation
    Image<double> aux;
    double bg_mean;
    MultidimArray<double> Vmask;
    detectBackground(V(),aux(),0.1,bg_mean);
#ifdef DEBUG

    aux.write("PPPmask_no_ero_03.vol");
#endif

    //Mask volume erosion to expand the mask boundaries
    Vmask.initZeros(V());
    erode3D(aux(),Vmask, 18,0,2);

    //Correction of some flaws produced in the edges of the mask volume
    FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(Vmask)
    if (k<=4 || i<=4 || j<=4 ||
        k>=ZSIZE(Vmask)-4 || i>=YSIZE(Vmask)-4 || j>=XSIZE(Vmask)-4)
        DIRECT_A3D_ELEM(Vmask,k,i,j)=1;

    aux()=Vmask;
#ifdef DEBUG

    aux.write("PPPmask_ero_03.vol");
#endif

    //Sobel edge detection applied to original volume
    Image<double> Vedge;
    computeEdges(V(),Vedge());
#ifdef DEBUG

    Vedge.write("PPPvolume_sobel_unmask_03.vol");
#endif

    //Masked volume generation
    const MultidimArray<double> &mVedge=Vedge();
    FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(mVedge)
    if (DIRECT_MULTIDIM_ELEM(Vmask,n)==1)
        DIRECT_MULTIDIM_ELEM(mVedge,n)=0;
#ifdef DEBUG

    Vedge.write("volume_sobel_mask_03.vol");
#endif

    double minval, maxval, avg, stddev;

    //Invert the mask to meet computeStats_within_binary_mask requirements
    FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(Vmask)
    if (DIRECT_MULTIDIM_ELEM(Vmask,n)==1)
        DIRECT_MULTIDIM_ELEM(Vmask,n)=0;
    else
        DIRECT_MULTIDIM_ELEM(Vmask,n)=1;

    //Threshold is 3 times the standard deviation of unmasked pixel values
    double thresh;
    computeStats_within_binary_mask(Vmask,mVedge,minval, maxval, avg, stddev);
    thresh=3*stddev;

    //Final edge volume generated by setting to 1 positions with values > threshold
    Image<double> Vaux;
    Vaux().initZeros(mVedge);
    FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(mVedge)
    if (DIRECT_MULTIDIM_ELEM(mVedge,n)>=thresh)
        DIRECT_MULTIDIM_ELEM(Vaux(),n)=1;

#ifdef DEBUG

    Vaux.write("volumen_bordes_definitivo_03.vol");
#endif

    const MultidimArray<double> &mVaux=Vaux();

    //Spline coefficient volume from original volume, to allow <1 step sizes
    MultidimArray<double> Volcoeffs;
    Volcoeffs.initZeros(V());

    produceSplineCoefficients(3,Volcoeffs,V());

    //Width parameter volume initialization
    Image<double> widths;
    widths().resizeNoCopy(V());
    widths().initConstant(1e5);
    double step=0.25;

    Matrix1D<double> direction(3);

    //Calculation of edge width for 10 different directions, if a smaller value is found for a different
    //direction on a given position the former value is overwritten

    //Direction (1,0,0)
    VECTOR_R3(direction,1,0,0);
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (0,1,0)
    VECTOR_R3(direction,0,1,0);
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (0,0,1)
    VECTOR_R3(direction,0,0,1);
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (1,1,0)
    VECTOR_R3(direction,(1/sqrt(2)),(1/sqrt(2)),0);
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (1,0,1)
    VECTOR_R3(direction,(1/sqrt(2)),0,(1/sqrt(2)));
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (0,1,1)
    VECTOR_R3(direction,0,(1/sqrt(2)),(1/sqrt(2)));
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (1,1,1)
    VECTOR_R3(direction,(1/sqrt(3)),(1/sqrt(3)),(1/sqrt(3)));
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (-1,1,1)
    VECTOR_R3(direction,-(1/sqrt(3)),(1/sqrt(3)),(1/sqrt(3)));
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (1,1,-1)
    VECTOR_R3(direction,(1/sqrt(3)),(1/sqrt(3)),-(1/sqrt(3)));
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

    //Direction (1,-1,1)
    VECTOR_R3(direction,(1/sqrt(3)),-(1/sqrt(3)),(1/sqrt(3)));
    edgeWidth(Volcoeffs, mVaux, widths(), direction, step);

#ifdef DEBUG

    std::cout << "width stats: ";
    widths().printStats();
    std::cout << std::endl;
    widths.write("PPPwidths.vol");
#endif

    double ibw=calculateIBW(widths());
    std::cout << "Resolution ibw= " << ibw << std::endl;
    if (fnOut!="")
    	widths.write(fnOut);
}
/* Run --------------------------------------------------------------------- */
void ProgAngularProjectLibrary::run()
{
    /////////////////////////////
    // PreRun for all nodes but not for all works
    /////////////////////////////
    //only rank 0
	mysampling.verbose=verbose;
    show();
    //all ranks
    mysampling.setSampling(sampling);
    srand ( time(NULL) );
    //process the symmetry file
    //only checks symmetry and set pg_order and pg_group, no memory allocation
    if (!mysampling.SL.isSymmetryGroup(fn_sym, symmetry, sym_order))
        REPORT_ERROR(ERR_VALUE_INCORRECT,
                     (std::string)"Invalid symmetry" +  fn_sym);
    if(perturb_projection_vector!=0)
    {
        int my_seed;
        my_seed=rand();
        // set noise deviation and seed
        mysampling.setNoise(perturb_projection_vector,my_seed);
    }
    if(angular_distance_bool!=0)
        mysampling.setNeighborhoodRadius(angular_distance);//irrelevant
    //true -> half_sphere
    mysampling.computeSamplingPoints(false,max_tilt_angle,min_tilt_angle);
    //only rank 0
    //mysampling.createSymFile(fn_sym,symmetry, sym_order);
    //all nodes
    mysampling.SL.readSymmetryFile(fn_sym);
    //store symmetry matrices, this is faster than computing them each time
    mysampling.fillLRRepository();
    //mpi_barrier here
    //all working nodes must read symmetry file
    //and experimental docfile if apropiate
    //symmetry_file = symmetry + ".sym";
    //SL.readSymmetryFile(symmetry_file)
    // We first sample The  whole sphere
    // Then we remove point redundant due to sampling symmetry
    // use old symmetry, this is geometric does not use L_R
    mysampling.removeRedundantPoints(symmetry, sym_order);

    //=========================
    //======================
    //recompute symmetry with neigh symmetry
    // If uncomment neighbour are not OK. BE CAREFULL
#define BREAKSIMMETRY
#ifdef BREAKSIMMETRY
    if (!mysampling.SL.isSymmetryGroup(fn_sym_neigh, symmetry, sym_order))
            REPORT_ERROR(ERR_VALUE_INCORRECT,
                         (std::string)"Invalid neig symmetry" +  fn_sym_neigh);
        mysampling.SL.readSymmetryFile(fn_sym_neigh);
        mysampling.fillLRRepository();
#endif
#undef BREAKSIMMETRY
        //precompute product between symmetry matrices and experimental data
    if (FnexperimentalImages.size() > 0)
        mysampling.fillExpDataProjectionDirectionByLR(FnexperimentalImages);

    //remove points not close to experimental points, only for no symmetric cases
    if (FnexperimentalImages.size() > 0 &&
        remove_points_far_away_from_experimental_data_bool)
    {
        // here we remove points no close to experimental data, neight symmetry must be use
        mysampling.removePointsFarAwayFromExperimentalData();
    }
    if(compute_closer_sampling_point_bool)
    {
        //find sampling point closer to experimental point (only 0) and bool
        //and save docfile with this information
        // use neight symmetry
        mysampling.findClosestSamplingPoint(FnexperimentalImages,output_file_root);
    }
    //only rank 0
    //write docfile with vectors and angles
    mysampling.createAsymUnitFile(output_file_root);
    //all nodes
    //If there is no reference available exit
    try
    {
        inputVol.read(input_volume);
    }
    catch (XmippError XE)
    {
        std::cout << XE;
        exit(0);
    }
    inputVol().setXmippOrigin();
    Xdim = XSIZE(inputVol());
    Ydim = YSIZE(inputVol());

    if (compute_neighbors_bool)
    {
        // new symmetry
        mysampling.computeNeighbors(only_winner);
        mysampling.saveSamplingFile(output_file_root,false);
    }
    //release some memory
    mysampling.exp_data_projection_direction_by_L_R.clear();

    unlink(output_file.c_str());

    //mpi master should divide doc in chuncks
    //in this serial program there is a unique chunck
    //angle information is in
    //mysampling.no_redundant_sampling_points_vector[i]
    //Run for all works
    project_angle_vector(0,
                         mysampling.no_redundant_sampling_points_angles.size()-1,verbose);

    //only rank 0 create sel file
    MetaData  mySFin, mySFout;
    FileName fn_temp;
    mySFin.read(output_file_root+"_angles.doc");
    size_t myCounter=0;
    size_t id;
    int ref;
    for (double mypsi=0;mypsi<360;mypsi += psi_sampling)
    {
        FOR_ALL_OBJECTS_IN_METADATA(mySFin)
        {
            double x,y,z, rot, tilt, psi;
            mySFin.getValue(MDL_ANGLE_ROT,rot,__iter.objId);
            mySFin.getValue(MDL_ANGLE_TILT,tilt,__iter.objId);
            mySFin.getValue(MDL_ANGLE_PSI,psi,__iter.objId);
            mySFin.getValue(MDL_X,x,__iter.objId);
            mySFin.getValue(MDL_Y,y,__iter.objId);
            mySFin.getValue(MDL_Z,z,__iter.objId);
            mySFin.getValue(MDL_REF,ref,__iter.objId);
            fn_temp.compose( ++myCounter,output_file);
            id = mySFout.addObject();
            mySFout.setValue(MDL_IMAGE,fn_temp,id);
            mySFout.setValue(MDL_ENABLED,1,id);
            mySFout.setValue(MDL_ANGLE_ROT,rot,id);
            mySFout.setValue(MDL_ANGLE_TILT,tilt,id);
            mySFout.setValue(MDL_ANGLE_PSI,psi+mypsi,id);
            mySFout.setValue(MDL_X,x,id);
            mySFout.setValue(MDL_Y,y,id);
            mySFout.setValue(MDL_Z,z,id);
            mySFout.setValue(MDL_SCALE,1.0,id);
            mySFout.setValue(MDL_REF,ref,id);
        }
    }
    mySFout.setComment("x,y,z refer to the coordinates of the unitary vector at direction given by the euler angles");
    mySFout.write(output_file_root+".doc");
    unlink((output_file_root+"_angles.doc").c_str());

    if (fn_groups!="")
        createGroupSamplingFiles();
}
示例#30
0
void ProgVolumePCA::run()
{
    show();
    produce_side_info();

    const MultidimArray<int> &imask=mask.imask;
    size_t Nvoxels=imask.sum();
    MultidimArray<float> v;
    v.initZeros(Nvoxels);

    // Add all volumes to the analyzer
    FileName fnVol;
    FOR_ALL_OBJECTS_IN_METADATA(mdVols)
    {
        mdVols.getValue(MDL_IMAGE,fnVol,__iter.objId);
        V.read(fnVol);

        // Construct vector
        const MultidimArray<double> &mV=V();
        size_t idx=0;
        FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(mV)
        {
            if (DIRECT_MULTIDIM_ELEM(imask,n))
                DIRECT_MULTIDIM_ELEM(v,idx++)=DIRECT_MULTIDIM_ELEM(mV,n);
        }

        analyzer.addVector(v);
    }

    // Construct PCA basis
    analyzer.subtractAvg();
    analyzer.learnPCABasis(NPCA,100);

    // Project onto the PCA basis
    Matrix2D<double> proj;
    analyzer.projectOnPCABasis(proj);
    std::vector<double> dimredProj;
    dimredProj.resize(NPCA);
    int i=0;
    FOR_ALL_OBJECTS_IN_METADATA(mdVols)
    {
        memcpy(&dimredProj[0],&MAT_ELEM(proj,i,0),NPCA*sizeof(double));
        mdVols.setValue(MDL_DIMRED,dimredProj,__iter.objId);
        i++;
    }
    if (fnVolsOut!="")
        mdVols.write(fnVolsOut);
    else
        mdVols.write(fnVols);

    // Save the basis
    const MultidimArray<double> &mV=V();
    for (int i=NPCA-1; i>=0; --i)
    {
        V().initZeros();
        size_t idx=0;
        const MultidimArray<double> &mPCA=analyzer.PCAbasis[i];
        FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(mV)
        {
            if (DIRECT_MULTIDIM_ELEM(imask,n))
                DIRECT_MULTIDIM_ELEM(mV,n)=DIRECT_MULTIDIM_ELEM(mPCA,idx++);
        }
        if (fnBasis!="")
            V.write(fnBasis,i+1,true,WRITE_OVERWRITE);
    }

    // Generate the PCA volumes
    if (listOfPercentiles.size()>0 && fnOutStack!="" && fnAvgVol!="")
    {
        Image<double> Vavg;
        if (fnAvgVol!="")
            Vavg.read(fnAvgVol);
        else
            Vavg().initZeros(V());

        Matrix1D<double> p;
        proj.toVector(p);
        Matrix1D<double> psorted=p.sort();

        Image<double> Vpca;
        Vpca()=Vavg();
        createEmptyFile(fnOutStack,(int)XSIZE(Vavg()),(int)YSIZE(Vavg()),(int)ZSIZE(Vavg()),listOfPercentiles.size());
        std::cout << "listOfPercentiles.size()=" << listOfPercentiles.size() << std::endl;
        for (size_t i=0; i<listOfPercentiles.size(); i++)
        {
            int idx=(int)round(textToFloat(listOfPercentiles[i].c_str())/100.0*VEC_XSIZE(p));
            std::cout << "Percentile " << listOfPercentiles[i] << " -> idx=" << idx << " p(idx)=" << psorted(idx) << std::endl;
            Vpca()+=psorted(idx)*V();
            Vpca.write(fnOutStack,i+1,true,WRITE_REPLACE);
        }
    }
}