예제 #1
0
// neighs is a matrix with ntakens rows. The n-th row has the neighbours of the 
// n-th Takens' vector. n is also present as neighbour. The n-th position of the 
// nneighs vector has the number of neighs of the n-th takens' vector.
// verticalHistogram: vector with ntakens elements
void getVerticalHistogram(int* neighs, int* nneighs, int* ntakens, int *vmin, 
int* verticalHistogram){
  int i, j, count, lne;
  for (i = 0; i < (*ntakens); i++){
    verticalHistogram[i] = 0;
  }
  // find vertical lines in every column/row
  for (i = 0; i < (*ntakens); i++){
      // count number of neighbours + itself
      lne = nneighs[i];
      j=1;
      while (j < lne){
        count=1;
        // while there is a vertical line, update the length (count)
        while( (j < lne) && (MAT_ELEM(neighs,i,j,*ntakens) == (MAT_ELEM(neighs,i,(j-1),*ntakens)+1) ) ){
          j++;
          count++;
        }
        // update the histogram if the current length > vmin
        if (count >= (*vmin)){
          verticalHistogram[count-1]++;
        }
        j++;
      }
  } 
}  
예제 #2
0
// compute the diagonal histogram and the recurrenceHistogram
void getDiagonalHistogramRecurrenceHistogram(int* neighs, int* nneighs, int* ntakens, int *lmin,
      int* diagonalHistogram,int* recurrenceHistogram){
  int i,j, currentNeigh, lastPosition;
  for (i=0;i <  (*ntakens) ;i++){
    diagonalHistogram[i]=0;
    recurrenceHistogram[i]=0;
  }
  // Treat the first row separately: It will be easier if we find diagonals that
  // "originate" at the first row separately
  for (j=0;j < nneighs[0]; j++){
    currentNeigh = MAT_ELEM(neighs,0,j,*ntakens);
    // update recurrenceHistogram: the recurrence histogram takes into accoutn
    // the distance between neigbours. In this case:currentNeigh-0, and we store
    //it in tre previous position (position 0 stores distance 1)
    recurrenceHistogram[currentNeigh-1]++;
    // update diagonal histogram
    updateLengthHistogram(0,currentNeigh,neighs,nneighs, *ntakens,diagonalHistogram,*lmin);
  }
  // find diagonals that "originate" at other rows
  lastPosition = *ntakens-*lmin;
  for (i=1;i < lastPosition; i++){
    for (j=0;j < nneighs[i]; j++){
       currentNeigh = MAT_ELEM(neighs,i,j,*ntakens);
      //check if we have already took into acount the pair i,j
      if (currentNeigh <= i) continue;
      // update recurrenceHistogram
      recurrenceHistogram[currentNeigh-i-1]++;
      //check if this diagonal has its origin in any row before
      if (isContainedInNeighbourhood(currentNeigh-1,i-1,neighs,*ntakens,nneighs[i-1]) == 1){
        continue;
      } else{
        //update the diagonalHistogram and the recurrenceHistogram
        updateLengthHistogram(i,currentNeigh,neighs,nneighs, *ntakens,diagonalHistogram,*lmin);  
      }      
    }
  }
  //complete the recurrence vector if needed
  if (lastPosition < (*ntakens)){
    for (i=lastPosition;i < (*ntakens); i++){
      for (j=0;j < nneighs[i]; j++){
        currentNeigh = MAT_ELEM(neighs,i,j,*ntakens);
         if (currentNeigh <= i) continue;
        // update recurrenceHistogram
        recurrenceHistogram[currentNeigh-i-1]++;
      }
    }
  }  
  
  for (i=0;i <  (*ntakens) ;i++){
    diagonalHistogram[i]=2*diagonalHistogram[i];
    recurrenceHistogram[i]=2*recurrenceHistogram[i];
  }
  diagonalHistogram[*ntakens-1] = 1;
}
예제 #3
0
파일: hessianLLE.cpp 프로젝트: I2PC/scipion
void HessianLLE::completeYt(const Matrix2D<double> &V,
		const Matrix2D<double> &Yi, Matrix2D<double> &Yt_complete)
{
    size_t Xdim = 1+MAT_XSIZE(V)+MAT_XSIZE(Yi);
    size_t Ydim = MAT_YSIZE(Yi);
    Yt_complete.resizeNoCopy(Ydim, Xdim);

    for (size_t i=0; i<Ydim; ++i)
    {
    	MAT_ELEM(Yt_complete,i,0)=1.;
    	memcpy(&MAT_ELEM(Yt_complete,i,1),             &MAT_ELEM(V,i,0), MAT_XSIZE(V)*sizeof(double));
    	memcpy(&MAT_ELEM(Yt_complete,i,MAT_XSIZE(V)+1),&MAT_ELEM(Yi,i,0),MAT_XSIZE(Yi)*sizeof(double));
    }
}
예제 #4
0
/* Compute alphas ---------------------------------------------------------- */
double matrix_fitness(double *p, void *prm)
{
    TiltPairAligner *aligner = (TiltPairAligner *) prm;
    Euler_angles2matrix(-p[1], p[3], p[2], aligner->pair_E);
    double retval = 0;
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
        {
            double error = fabs(
                               MAT_ELEM(aligner->pair_E,i, j)
                               - MAT_ELEM(aligner->Put, i, j));
            retval += error * error;
        }
    return retval;
}
예제 #5
0
void LaplacianEigenmap::reduceDimensionality()
{
	Matrix2D<double> G,L,D;
	Matrix1D<double> mappedX;
	//Construct neighborhood graph
	computeDistanceToNeighbours(*X,numberOfNeighbours,G,distance,false);
	//Compute Gaussian kernel(heat kernel based weights)
	computeSimilarityMatrix(G,sigma,true,true);
	//Compute Laplacian
	computeGraphLaplacian(G,L);
	//Construct diagonal weight matrix
	D.initZeros(MAT_YSIZE(G),MAT_YSIZE(G));
	FOR_ALL_ELEMENTS_IN_MATRIX2D(G)
		MAT_ELEM(D,i,i)+=MAT_ELEM(G,i,j);
	//Construct eigenmaps
	generalizedEigs(L,D,mappedX,Y);
	keepColumns(Y,1,(int)outputDim);
}
예제 #6
0
/* ------------------------------------------------------------------------- */
NaiveBayes::NaiveBayes(
    const std::vector< MultidimArray<double> > &features,
    const Matrix1D<double> &priorProbs,
    int discreteLevels)
{
    K = features.size();
    Nfeatures=XSIZE(features[0]);
    __priorProbsLog10.initZeros(K);
    FOR_ALL_ELEMENTS_IN_MATRIX1D(__priorProbsLog10)
    VEC_ELEM(__priorProbsLog10,i)=log10(VEC_ELEM(priorProbs,i));

    // Create a dummy leaf for features that cannot classify
    std::vector < MultidimArray<double> > aux(K);
    dummyLeaf=new LeafNode(aux,0);

    // Build a leafnode for each feature and assign a weight
    __weights.initZeros(Nfeatures);
    for (int f=0; f<Nfeatures; f++)
    {
        for (int k=0; k<K; k++)
            features[k].getCol(f, aux[k]);
        LeafNode *leaf=new LeafNode(aux,discreteLevels);
        if (leaf->__discreteLevels>0)
        {
            __leafs.push_back(leaf);
            DIRECT_A1D_ELEM(__weights,f)=__leafs[f]->computeWeight();
        }
        else
        {
            __leafs.push_back(dummyLeaf);
            DIRECT_A1D_ELEM(__weights,f)=0;
            delete leaf;
        }
#ifdef DEBUG_WEIGHTS

        if(debugging == true)
        {
            std::cout << "Node " << f << std::endl;
            std::cout << *(__leafs[f]) << std::endl;
            //char c;
            //std::cin >> c;
        }
#endif

    }
    double norm=__weights.computeMax();
    if (norm>0)
    	__weights *= 1.0/norm;

    // Set default cost matrix
    __cost.resizeNoCopy(K,K);
    __cost.initConstant(1);
    for (int i=0; i<K; i++)
        MAT_ELEM(__cost,i,i)=0;
}
예제 #7
0
파일: hessianLLE.cpp 프로젝트: I2PC/scipion
void HessianLLE::buildYiHessianEstimator(const Matrix2D<double> &V,
		Matrix2D<double> &Yi, size_t no_dim, size_t dp)
{
    size_t ct = 0;
    Yi.resizeNoCopy(MAT_YSIZE(V),dp);

    for(size_t mm=0; mm<no_dim; mm++)
    {
        size_t length = no_dim-mm;
        size_t indle=mm;
        for(size_t nn=0; nn<length; nn++)
        {
            size_t column = ct+nn;
            for(size_t element = 0; element<MAT_YSIZE(V); element++)
                MAT_ELEM(Yi, element, column) = MAT_ELEM(V, element, mm)*MAT_ELEM(V, element, indle);
            ++indle;
        }
        ct += length;
    }
}
예제 #8
0
int isContainedInNeighbourhood(int possibleNeigh, int i,int* neighs,int ntakens,int nneighs){
  int iter;
  int found = 0;
  for (iter = 0; iter < nneighs; iter++ ){
    if (possibleNeigh == MAT_ELEM(neighs,i,iter,ntakens)){
      found = 1;
      break;
    }
  }
  return found;
  
}
예제 #9
0
파일: kernelPCA.cpp 프로젝트: I2PC/scipion
void KernelPCA::reduceDimensionality() {
	// Compute Gram matrix
	Matrix2D<double> D2;
	computeDistance(*X, D2, distance, false);
	computeSimilarityMatrix(D2,sigma);

	// Normalize it
	Matrix1D<double> mean_i;
	D2.rowSum(mean_i);
	mean_i/=MAT_XSIZE(D2);
	double mean=mean_i.computeMean();
	FOR_ALL_ELEMENTS_IN_MATRIX2D(D2)
		MAT_ELEM(D2,i,j)+=mean-VEC_ELEM(mean_i,i)-VEC_ELEM(mean_i,j);

	// Compute the largest eigenvalues
	Matrix1D<double> lambda;
	firstEigs(D2,outputDim,lambda,Y);

	// Readjust variances
	FOR_ALL_ELEMENTS_IN_MATRIX1D(lambda)
		VEC_ELEM(lambda,i)=sqrt(VEC_ELEM(lambda,i));
	FOR_ALL_ELEMENTS_IN_MATRIX2D(Y)
		MAT_ELEM(Y,i,j)*=VEC_ELEM(lambda,j);
}
예제 #10
0
	void mapOntoTilt()
	{
		p_map.resize(p_unt.size());
		for (int u = 0; u < p_map.size()/2; u++)
		{
			double xu = (double)p_unt[2*u];
			double yu = (double)p_unt[2*u+1];

			p_map[2*u] = ROUND(MAT_ELEM(Pass, 0, 0) * xu + MAT_ELEM(Pass, 0, 1) * yu + MAT_ELEM(Pass, 0, 2));
			p_map[2*u+1] = ROUND(MAT_ELEM(Pass, 1, 0) * xu + MAT_ELEM(Pass, 1, 1) * yu + MAT_ELEM(Pass, 1, 2));

		}
	}
예제 #11
0
파일: euler.cpp 프로젝트: dtegunov/liblion
	/* Euler angles --> matrix ------------------------------------------------- */
	void Euler_angles2matrix(DOUBLE alpha, DOUBLE beta, DOUBLE gamma,
		Matrix2D<DOUBLE> &A, bool homogeneous)
	{
		DOUBLE ca, sa, cb, sb, cg, sg;
		DOUBLE cc, cs, sc, ss;

		if (homogeneous)
		{
			A.initZeros(4, 4);
			MAT_ELEM(A, 3, 3) = 1;
		}
		else
			if (MAT_XSIZE(A) != 3 || MAT_YSIZE(A) != 3)
				A.resize(3, 3);

		alpha = DEG2RAD(alpha);
		beta = DEG2RAD(beta);
		gamma = DEG2RAD(gamma);

		ca = cos(alpha);
		cb = cos(beta);
		cg = cos(gamma);
		sa = sin(alpha);
		sb = sin(beta);
		sg = sin(gamma);
		cc = cb * ca;
		cs = cb * sa;
		sc = sb * ca;
		ss = sb * sa;

		A(0, 0) = cg * cc - sg * sa;
		A(0, 1) = cg * cs + sg * ca;
		A(0, 2) = -cg * sb;
		A(1, 0) = -sg * cc - cg * sa;
		A(1, 1) = -sg * cs + cg * ca;
		A(1, 2) = sg * sb;
		A(2, 0) = sc;
		A(2, 1) = ss;
		A(2, 2) = cb;
	}
예제 #12
0
void TiltPairAligner::addCoordinatePair(int _muX, int _muY, int _mtX,
                                        int _mtY)
{
    coordU.push_back(_muX);
    coordU.push_back(_muY);
    coordT.push_back(_mtX);
    coordT.push_back(_mtY);
    Nu++; // Number of particles

#ifdef _DEBUG

    std::cout << "Adding point U(" << U.X << "," << U.Y << ") T(" << T.X << ","
    << T.Y << ")\n";
    std::cout << "A at input" << Au << "B at input" << Bt;
#endif
    // Adjust untilted dependent matrix
    MAT_ELEM(Au,0, 0) += _muX * _muX;
    MAT_ELEM(Au,0, 1) += _muX * _muY;
    MAT_ELEM(Au,0, 2) += _muX;
    MAT_ELEM(Au,1, 0) = MAT_ELEM(Au,0, 1);
    MAT_ELEM(Au,1, 1) += _muY * _muY;
    MAT_ELEM(Au,1, 2) += _muY;
    MAT_ELEM(Au,2, 0) = MAT_ELEM(Au,0, 2);
    MAT_ELEM(Au,2, 1) = MAT_ELEM(Au,1, 2);
    MAT_ELEM(Au,2, 2) = Nu;

    // Adjust tilted dependent matrix
    MAT_ELEM(Bt,0, 0) += _mtX * _muX;
    MAT_ELEM(Bt,0, 1) += _mtY * _muX;
    MAT_ELEM(Bt,0, 2) = MAT_ELEM(Au,0, 2);
    MAT_ELEM(Bt,1, 0) += _mtX * _muY;
    MAT_ELEM(Bt,1, 1) += _mtY * _muY;
    MAT_ELEM(Bt,1, 2) = MAT_ELEM(Au,1, 2);
    MAT_ELEM(Bt,2, 0) += _mtX;
    MAT_ELEM(Bt,2, 1) += _mtY;
    MAT_ELEM(Bt,2, 2) = MAT_ELEM(Au,2, 2);

#ifdef _DEBUG

    std::cout << "A at output" << Au << "B at output" << Bt;
#endif


}
예제 #13
0
	double optimiseTransformationMatrix(bool do_optimise_nr_pairs)
	{
		std::vector<int> best_pairs_t2u, best_map;
		double score, best_score, best_dist=9999.;
		if (do_optimise_nr_pairs)
			best_score = 0.;
		else
			best_score = -999999.;

		int nn = XMIPP_MAX(1., (rotF-rot0)/rotStep);
		nn *= XMIPP_MAX(1., (tiltF-tilt0)/tiltStep);
		nn *= XMIPP_MAX(1., (xF-x0)/xStep);
		nn *= XMIPP_MAX(1., (yF-y0)/yStep);
		int n = 0;
		init_progress_bar(nn);
		for (double rot = rot0; rot <= rotF; rot+= rotStep)
		{
			for (double tilt = tilt0; tilt <= tiltF; tilt+= tiltStep)
			{
				// Assume tilt-axis lies in-plane...
				double psi = -rot;
				// Rotate all points correspondingly
				Euler_angles2matrix(rot, tilt, psi, Pass);
				//std::cerr << " Pass= " << Pass << std::endl;
				// Zero-translations for now (these are added in the x-y loops below)
				MAT_ELEM(Pass, 0, 2) = MAT_ELEM(Pass, 1, 2) = 0.;
				mapOntoTilt();
				for (int x = x0; x <= xF; x += xStep)
				{
					for (int y = y0; y <= yF; y += yStep, n++)
					{
						if (do_optimise_nr_pairs)
							score = getNumberOfPairs(x, y);
						else
							score = -getAverageDistance(x, y); // negative because smaller distance is better!

                                                bool is_best = false;
                                                if (do_optimise_nr_pairs && score==best_score)
                                                {
                                                    double dist = getAverageDistance(x, y);
                                                    if (dist < best_dist)
                                                    {
                                                        best_dist = dist;
                                                        is_best = true;
                                                    }
                                                }
						if (score > best_score || is_best)
						{
							best_score = score;
							best_pairs_t2u = pairs_t2u;
							best_rot = rot;
							best_tilt = tilt;
							best_x = x;
							best_y = y;
						}
						if (n%1000==0) progress_bar(n);
					}
				}
			}
		}
		progress_bar(nn);
		// Update pairs with the best_pairs
		if (do_optimise_nr_pairs)
			pairs_t2u = best_pairs_t2u;

		// Update the Passing matrix and the mapping
		Euler_angles2matrix(best_rot, best_tilt, -best_rot, Pass);
		// Zero-translations for now (these are added in the x-y loops below)
		MAT_ELEM(Pass, 0, 2) = MAT_ELEM(Pass, 1, 2) = 0.;
		mapOntoTilt();
		return best_score;

	}
예제 #14
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();
}
예제 #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
/** Image inplace subtraction, equivalent to -= operator */
PyObject *
Image_applyTransforMatScipion(PyObject *obj, PyObject *args, PyObject *kwargs)
{

	PyObject * list = NULL;
    PyObject * item = NULL;
    ImageObject *self = (ImageObject*) obj;
    ImageBase * img;
    PyObject *only_apply_shifts = Py_False;
    PyObject *wrap = (WRAP ? Py_True : Py_False);
    img = self->image->image;
    bool boolOnly_apply_shifts = false;
    bool boolWrap = WRAP;

    try
    {
        PyArg_ParseTuple(args, "O|OO", &list, &only_apply_shifts, &wrap);
        if (PyList_Check(list))
        {
            if (PyBool_Check(only_apply_shifts))
                boolOnly_apply_shifts = (only_apply_shifts == Py_True);
            else
                PyErr_SetString(PyExc_TypeError, "ImageGeneric::applyGeo: Expecting boolean value");
            if (PyBool_Check(wrap))
                boolWrap = (wrap == Py_True);
            else
                PyErr_SetString(PyExc_TypeError, "ImageGeneric::applyGeo: Expecting boolean value");


            size_t size = PyList_Size(list);
            Matrix2D<double> A,B;
            A.initIdentity(4);
            for (size_t i = 0; i < size; ++i)
            {
                item  = PyList_GetItem(list, i);
                MAT_ELEM(A,i/4,i%4 ) = PyFloat_AsDouble(item);
            }
            double scale, shiftX, shiftY, shiftZ, rot,tilt, psi;
            bool flip;
            transformationMatrix2Parameters3D(A, flip, scale, shiftX, shiftY, shiftZ, rot,tilt, psi);
            double _rot;
            if (tilt==0.)
                _rot=rot + psi;
            else
                _rot=psi;
            img->setEulerAngles(0,0.,_rot);
            img->setShifts(shiftX,shiftY);
            img->setScale(scale);
            img->setFlip(flip);
            img->selfApplyGeometry(LINEAR, boolWrap, boolOnly_apply_shifts);//wrap, onlyShifts
            Py_RETURN_NONE;
        }
        else
        {
            PyErr_SetString(PyExc_TypeError, "ImageGeneric::applyTransforMatScipion: Expecting a list");

        }
    }
    catch (XmippError &xe)
    {
        PyErr_SetString(PyXmippError, xe.msg.c_str());
    }
    return NULL;
}//operator +=
// Outliers ===============================================================
void ProgClassifyCL2DCore::computeStableCores()
{
    if (verbose && node->rank==0)
        std::cerr << "Computing stable cores ...\n";
    MetaData thisClass, anotherClass, commonImages, thisClassCore;
    MDRow row;
    size_t first, last;
    Matrix2D<unsigned char> coocurrence;
    Matrix1D<unsigned char> maximalCoocurrence;
    int Nblocks=blocks.size();
    taskDistributor->reset();
    std::vector<size_t> commonIdx;
    std::map<String,size_t> thisClassOrder;
    String fnImg;
    while (taskDistributor->getTasks(first, last))
        for (size_t idx=first; idx<=last; ++idx)
        {
            // Read block
            CL2DBlock &thisBlock=blocks[idx];
            if (thisBlock.level<=tolerance)
                continue;
            if (!existsBlockInMetaDataFile(thisBlock.fnLevelCore, thisBlock.block))
                continue;
            thisClass.read(thisBlock.block+"@"+thisBlock.fnLevelCore);
            thisClassCore.clear();

            // Add MDL_ORDER
            if (thisClass.size()>0)
            {
                size_t order=0;
                thisClassOrder.clear();
                FOR_ALL_OBJECTS_IN_METADATA(thisClass)
                {
                    thisClass.getValue(MDL_IMAGE,fnImg,__iter.objId);
                    thisClassOrder[fnImg]=order++;
                }

                // Calculate coocurrence within all blocks whose level is inferior to this
                size_t NthisClass=thisClass.size();
                if (NthisClass>0)
                {
                    try {
                       coocurrence.initZeros(NthisClass,NthisClass);
                    } catch (XmippError e)
                    {
                       std::cerr << e << std::endl;
                       std::cerr << "There is a memory allocation error. Most likely there are too many images in this class ("
                                 << NthisClass << " images). Consider increasing the number of initial and final classes\n";
                       REPORT_ERROR(ERR_MEM_NOTENOUGH,"While computing stable class");
                    }
                    for (int n=0; n<Nblocks; n++)
                    {
                        CL2DBlock &anotherBlock=blocks[n];
                        if (anotherBlock.level>=thisBlock.level)
                            break;
                        if (!existsBlockInMetaDataFile(anotherBlock.fnLevelCore, anotherBlock.block))
                            continue;
                        anotherClass.read(anotherBlock.block+"@"+anotherBlock.fnLevelCore);
                        anotherClass.intersection(thisClass,MDL_IMAGE);
                        commonImages.join1(anotherClass, thisClass, MDL_IMAGE,LEFT);
                        commonIdx.resize(commonImages.size());
                        size_t idx=0;
                        FOR_ALL_OBJECTS_IN_METADATA(commonImages)
                        {
                            commonImages.getValue(MDL_IMAGE,fnImg,__iter.objId);
                            commonIdx[idx++]=thisClassOrder[fnImg];
                        }
                        size_t Ncommon=commonIdx.size();
                        for (size_t i=0; i<Ncommon; i++)
                        {
                            size_t idx_i=commonIdx[i];
                            for (size_t j=i+1; j<Ncommon; j++)
                            {
                                size_t idx_j=commonIdx[j];
                                MAT_ELEM(coocurrence,idx_i,idx_j)+=1;
                            }
                        }
                    }
                }

                // Take only those elements whose coocurrence is maximal
                maximalCoocurrence.initZeros(NthisClass);
                int aimedCoocurrence=thisBlock.level-tolerance;
                FOR_ALL_ELEMENTS_IN_MATRIX2D(coocurrence)
                if (MAT_ELEM(coocurrence,i,j)==aimedCoocurrence)
                    VEC_ELEM(maximalCoocurrence,i)=VEC_ELEM(maximalCoocurrence,j)=1;

                // Now compute core
                FOR_ALL_OBJECTS_IN_METADATA(thisClass)
                {
                    thisClass.getValue(MDL_IMAGE,fnImg,__iter.objId);
                    size_t idx=thisClassOrder[fnImg];
                    if (VEC_ELEM(maximalCoocurrence,idx))
                    {
                        thisClass.getRow(row,__iter.objId);
                        thisClassCore.addRow(row);
                    }
                }
            }
            thisClassCore.write(thisBlock.fnLevel.insertBeforeExtension((String)"_stable_core_"+thisBlock.block),MD_APPEND);
        }
예제 #18
0
void ProbabilisticPCA::reduceDimensionality()
{
    size_t N=MAT_YSIZE(*X);  // N= number of rows of X
    size_t D=MAT_XSIZE(*X);  // D= number of columns of X

    bool converged=false;
    size_t iter=0;
    double sigma2=rnd_unif()*2;
    double Q=MAXDOUBLE, oldQ;

    Matrix2D<double> S, W, inW, invM, Ez, WtX, Wp1, Wp2, invWp2, WinvM, WinvMWt, WtSDIW, invCS;

    // Compute variance and row energy
    subtractColumnMeans(*X);
    matrixOperation_AtA(*X,S);
    S/=(double)N;
    Matrix1D<double> normX;
    X->rowEnergySum(normX);

    W.initRandom(D,outputDim,0,2,RND_UNIFORM);
    matrixOperation_AtA(W,inW);

    MultidimArray <double> Ezz(N,outputDim,outputDim);
    while (!converged && iter<=Niters)
    {
        ++iter;

        // Perform E-step
        // Ez=(W^t*W)^-1*W^t*X^t
        for (size_t i=0; i<outputDim; ++i)
        	MAT_ELEM(inW,i,i)+=sigma2;
        inW.inv(invM);
        matrixOperation_AtBt(W,*X,WtX);
        matrixOperation_AB(invM,WtX,Ez);

        for (size_t k=0; k<N; ++k)
        	FOR_ALL_ELEMENTS_IN_MATRIX2D(invM)
        		DIRECT_A3D_ELEM(Ezz,k,i,j)=MAT_ELEM(invM,i,j)*sigma2+MAT_ELEM(Ez,i,k)*MAT_ELEM(Ez,j,k);

        // Perform M-step (maximize mapping W)
		Wp1.initZeros(D,outputDim);
		Wp2.initZeros(outputDim,outputDim);
		for (size_t k=0; k<N; ++k)
		{
			FOR_ALL_ELEMENTS_IN_MATRIX2D(Wp1)
				MAT_ELEM(Wp1,i,j)+=MAT_ELEM(*X,k,i)*MAT_ELEM(Ez,j,k);
			FOR_ALL_ELEMENTS_IN_MATRIX2D(Wp2)
				MAT_ELEM(Wp2,i,j)+=DIRECT_A3D_ELEM(Ezz,k,i,j);
		}

		Wp2.inv(invWp2);
		matrixOperation_AB(Wp1,invWp2,W);
		matrixOperation_AtA(W,inW);

		// Update sigma2
		double sigma2_new=0;
		for (size_t k=0; k<N; ++k){
			double EzWtX=0;
			FOR_ALL_ELEMENTS_IN_MATRIX2D(W)
				EzWtX+=MAT_ELEM(*X,k,i)*MAT_ELEM(W,i,j)*MAT_ELEM(Ez,j,k);

			double t=0;
			for (size_t i = 0; i < outputDim; ++i)
			{
				double aux=0.;
				for (size_t kk = 0; kk < outputDim; ++kk)
					aux += DIRECT_A3D_ELEM(Ezz,k,i,kk) * MAT_ELEM(inW, kk, i);
				t+=aux;
			}

			sigma2_new += VEC_ELEM(normX,k) - 2 * EzWtX + t;
		}
		sigma2_new/=(double) N * (double) D;

		//Compute likelihood of new model
		oldQ = Q;

		if (iter > 1)
		{
			matrixOperation_AB(W,invM,WinvM);
			matrixOperation_ABt(WinvM,W,WinvMWt);
			matrixOperation_IminusA(WinvMWt);
			WinvMWt*=1/sigma2_new;

			matrixOperation_AtA(W,WtSDIW);
			WtSDIW*=1/sigma2_new;
			matrixOperation_IplusA(WtSDIW);

			double detC = pow(sigma2_new,D)* WtSDIW.det();

			matrixOperation_AB(WinvMWt,S,invCS);
			Q = (N*(-0.5)) * (D * log (2*PI) + log(detC) + invCS.trace());
		}

		// Stop condition to detect convergence
		// Must not apply to the first iteration, because then it will end inmediately
		if (iter>2 && abs(oldQ-Q) < 0.001)
			converged=true;

		sigma2=sigma2_new;
    }

    //mapping.M = (inW \ W')';
    matrixOperation_ABt(W,inW.inv(),A);
    matrixOperation_AB(*X,A,Y);
	if (fnMapping!="")
		A.write(fnMapping);
}
예제 #19
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();
}
예제 #20
0
// ######################################################################
//img : input image in RGB space
//K   : number of groups create by kmean
//dist: distance weight when doing the segment, higher weight will make
//      each region group by its neighbor pixel
// ######################################################################
Image<PixRGB<byte> > getKMeans(Image<PixRGB<byte> > img,int K,float dist)
{
  //convert iNVT image to cvImage
  IplImage *cvImg = img2ipl(img);

  int h = img.getHeight();
  int w = img.getWidth();
  LINFO("Image Width %d Height %d cv W %d,H %d",w,h,cvImg->width,cvImg->height);
  CvMat *sample  = cvCreateMat(w*h, 1, CV_32FC(5));   
  //CvMat *sample  = cvCreateMat(w*h, 1, CV_32FC(3));   
  CvMat *cluster = cvCreateMat(w*h, 1, CV_32SC1);   
  for(int y = 0; y < h; y++)
    { 
      for(int x = 0; x < w; x++)
        {     
          int idx= y*w+x;   
          int idxpix= y*w*3+x*3;   
          MAT_ELEM(sample,idx,0,0,x*dist);   
          MAT_ELEM(sample,idx,0,1,y*dist);   
          MAT_ELEM(sample,idx,0,2, *(cvImg->imageData + idxpix + 0));
          MAT_ELEM(sample,idx,0,3, *(cvImg->imageData + idxpix + 1));
          MAT_ELEM(sample,idx,0,4, *(cvImg->imageData + idxpix + 2));
        }   
    }   

  //Doing cvKmean
  cvKMeans2(sample, K, cluster,
            cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,
                           TT_KMEANS_ITERATIONS, TT_KMEANS_PRECISION)) ;

  IplImage 	*dst = cvCreateImage(cvGetSize(cvImg),8,3);   
  cvZero(dst);   

  std::vector<std::vector<Point2D<int> > >  groups;
  groups.resize(K);

  // Put Pixel Color to each labeled bin
  for(int y = 0; y < h; y++)
    {   
      for(int x = 0; x < w; x++)
        {   
          int idx = cluster->data.i[y*w+x];   
          groups[idx].push_back(Point2D<int>(x,y));
        }   
    }
   
  // Given a int label map, we will create a average color map
  Image<PixRGB<byte> > output(img.getDims(), ZEROS);

  //Compute avg color for each region
  for(size_t grpIdx=0; grpIdx < groups.size(); grpIdx++)
    {
      //Compute Average Color
      PixRGB<long> avgColor(0,0,0);
      for(size_t pntIdx=0; pntIdx<groups[grpIdx].size(); pntIdx++)
        avgColor +=  img.getVal(groups[grpIdx][pntIdx]);

      if(groups[grpIdx].size() != 0)
        avgColor /= groups[grpIdx].size();

      //Asign avg color to region pixels
      for(size_t pntIdx=0; pntIdx<groups[grpIdx].size(); pntIdx++)
        output.setVal(groups[grpIdx][pntIdx],avgColor);
    }

  cvReleaseMat(&sample);   
  cvReleaseMat(&cluster);         
  cvReleaseImage(&cvImg);  
  return output;	
}
예제 #21
0
파일: hessianLLE.cpp 프로젝트: I2PC/scipion
void HessianLLE::reduceDimensionality()
{
    Matrix2D<int> neighboursMatrix;
    Matrix2D<double> distanceNeighboursMatrix;

    kNearestNeighbours(*X, kNeighbours, neighboursMatrix, distanceNeighboursMatrix);

    size_t sizeY = MAT_YSIZE(*X);
    size_t dp = outputDim * (outputDim+1)/2;
    Matrix2D<double> weightMatrix, thisX, U, V, Vpr, Yi, Yi_complete, Yt, R, Pii;
    Matrix1D<double> D, vector;

    weightMatrix.initZeros(dp*sizeY,sizeY);

    for(size_t index=0; index<MAT_YSIZE(*X);++index)
    {
        extractNearestNeighbours(*X, neighboursMatrix, index, thisX);
        subtractColumnMeans(thisX);
        thisX = thisX.transpose();
        svdcmp(thisX, U, D, Vpr); // thisX = U * D * Vpr^t

        // Copy the first columns of Vpr onto V
        V.resizeNoCopy(MAT_YSIZE(Vpr),outputDim);
        for (size_t y=0; y<MAT_YSIZE(V); ++y)
        	memcpy(&MAT_ELEM(V,y,0),&MAT_ELEM(Vpr,y,0),outputDim*sizeof(double));

        //Basically, the above is applying PCA to the neighborhood of Xi.
        //The PCA mapping that is found (and that is contained in V) is an
        //approximation for the tangent space at Xi.

        //Build Hessian estimator
        buildYiHessianEstimator(V,Yi,outputDim,dp);
        completeYt(V, Yi, Yt);
        orthogonalizeColumnsGramSchmidt(Yt);

        //Get the transpose of the last columns
        size_t indexExtra = outputDim+1;
        size_t Ydim = MAT_XSIZE(Yt)-indexExtra;
        Pii.resizeNoCopy(Ydim,MAT_YSIZE(Yt));
        FOR_ALL_ELEMENTS_IN_MATRIX2D(Pii)
        	MAT_ELEM(Pii,i,j) = MAT_ELEM(Yt,j,indexExtra+i);

        //Double check weights sum to 1
        for (size_t j=0; j<dp; j++)
        {
        	Pii.getRow(j,vector);
        	double sum = vector.sum();
        	if(sum > 0.0001)
        		vector*=1.0/sum;

        	//Fill weight matrix
          	for(int k = 0; k<kNeighbours; k++){
        		size_t neighbourElem = MAT_ELEM(neighboursMatrix,index,k);
        		MAT_ELEM(weightMatrix,index*dp+j,neighbourElem) = VEC_ELEM(vector,k);
          	}
        }
    }
  	Matrix2D<double> G;
  	matrixOperation_AtA(weightMatrix,G);

  	Matrix1D<double> v;
  	eigsBetween(G,1,outputDim,v,Y);
  	Y*=sqrt(sizeY);
}
예제 #22
0
void MpiProgImageRotationalPCA::comunicateMatrix(Matrix2D<double> &W)
{
    MPI_Bcast(&MAT_ELEM(W,0,0),MAT_XSIZE(W)*MAT_YSIZE(W),MPI_DOUBLE,0,MPI_COMM_WORLD);
}
예제 #23
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);
        }
    }
}