// check the reslicing is right TEST( MultidimTest, reslice) { XMIPP_TRY MultidimArray<float> imgSliced, imgRef; imgRef.resize(3,3,3); FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(imgRef) dAi(imgRef, n) = n; imgRef.reslice(imgSliced, VIEW_Y_NEG); // imgSliced.reslice(ImageGeneric::Y_NEG); FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(imgRef) { EXPECT_EQ(DIRECT_ZYX_ELEM(imgRef,k,i,j), DIRECT_ZYX_ELEM(imgSliced,ZSIZE(imgSliced)-1-i,k,j)); } imgRef.reslice(imgSliced, VIEW_X_NEG); FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(imgRef) { EXPECT_EQ(DIRECT_ZYX_ELEM(imgRef,k,i,j), DIRECT_ZYX_ELEM(imgSliced,ZSIZE(imgSliced)-1-j,i,k)); } XMIPP_CATCH }
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); } }
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); } }
// Show a complex array --------------------------------------------------- std::ostream& operator<<(std::ostream& ostrm, const MultidimArray< Complex >& v) { if (v.xdim == 0) ostrm << "NULL MultidimArray\n"; else ostrm << std::endl; for (int l = 0; l < NSIZE(v); l++) { if (NSIZE(v)>1) ostrm << "Image No. " << l << std::endl; for (int k = STARTINGZ(v); k <= FINISHINGZ(v); k++) { if (ZSIZE(v) > 1) ostrm << "Slice No. " << k << std::endl; for (int i = STARTINGY(v); i <= FINISHINGY(v); i++) { for (int j = STARTINGX(v); j <= FINISHINGX(v); j++) ostrm << "(" << A3D_ELEM(v, k, i, j).real << "," << A3D_ELEM(v, k, i, j).imag << ")" << ' '; ostrm << std::endl; } } } return ostrm; }
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(); }
/* 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; } }
// 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 run() { FileName fn_out; FileName fn_ext = fn_in.getExtension(); Image<double> I, label; I.read(fn_in); int object_no; if (ZSIZE(I())==1) object_no=labelImage2D(I(), label()); else object_no=labelImage3D(I(), label()); for (int o = 0; o <= object_no; o++) { I() = label(); MultidimArray<double> &Im=MULTIDIM_ARRAY(I); FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(Im) { DIRECT_MULTIDIM_ELEM(Im,n) = (DIRECT_MULTIDIM_ELEM(Im,n) == o); if (invert) DIRECT_MULTIDIM_ELEM(Im,n) = 1 - DIRECT_MULTIDIM_ELEM(Im,n); } double number_elements = I().sum(); if (number_elements > min_size) { fn_out.compose(fn_root, o+1, fn_ext); I.write(fn_out); } if (ZSIZE(I())==1) std::cout << "Image number " << o+1 << " contains " << number_elements << " pixels set to 1\n"; else std::cout << "Volume number " << o+1 << " contains " << number_elements << " voxels set to 1\n"; } }
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); } } }
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); }
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); }
// 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); }
// 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!"); } }
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); } }
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; }
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 }
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(); }
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; FourierTransformer transformer3D; 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); // Release memory as soon as you can VfourierRealAux.clear(); // Remove all those coefficients we are sure we will not use during the projections volumePaddedSize=XSIZE(VfourierRealCoefs); int idxMax=maxFrequency*XSIZE(VfourierRealCoefs)+10; // +10 is a safety guard idxMax=std::min(FINISHINGX(VfourierRealCoefs),idxMax); int idxMin=std::max(-idxMax,STARTINGX(VfourierRealCoefs)); VfourierRealCoefs.selfWindow(idxMin,idxMin,idxMin,idxMax,idxMax,idxMax); produceSplineCoefficients(BSPLINE3,VfourierImagCoefs,VfourierImagAux); VfourierImagAux.clear(); VfourierImagCoefs.selfWindow(idxMin,idxMin,idxMin,idxMax,idxMax,idxMax); } 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)); } } }
//#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); }