/* Footprint of a blob ----------------------------------------------------- */ void footprint_blob( ImageOver &blobprint, // blob foot_print table const struct blobtype &blob, // blob description int istep, // number of foot-print samples per one sample // on projection plane in u,v directions int normalise) // set to 1 if you want normalise. Usually // you may omit it and no normalisation is performed { // Resize output image and redefine the origin of it int footmax = CEIL(blob.radius); blobprint.init(-footmax, footmax, istep, -footmax, footmax, istep); // Run for Imge class indexes for (int i = STARTINGY(blobprint()); i <= FINISHINGY(blobprint()); i++) for (int j = STARTINGX(blobprint()); j <= FINISHINGX(blobprint()); j++) { // Compute oversampled index and blob value double vi, ui; IMG2OVER(blobprint, i, j, vi, ui); double r = sqrt(vi * vi + ui * ui); IMGPIXEL(blobprint, i, j) = blob_proj(r, blob); } // Adjust the footprint structure if (normalise) blobprint() /= blobprint().sum(); }
// 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; }
//#define DEBUG void spatial_Bspline032voxels(const GridVolume &vol_splines, MultidimArray<double> *vol_voxels, int Zdim, int Ydim, int Xdim) { // Resize and set starting corner ....................................... if (Zdim == 0 || Ydim == 0 || Xdim == 0) { Matrix1D<double> size = vol_splines.grid(0).highest - vol_splines.grid(0).lowest; Matrix1D<double> corner = vol_splines.grid(0).lowest; (*vol_voxels).initZeros(CEIL(ZZ(size)), CEIL(YY(size)), CEIL(XX(size))); STARTINGX(*vol_voxels) = FLOOR(XX(corner)); STARTINGY(*vol_voxels) = FLOOR(YY(corner)); STARTINGZ(*vol_voxels) = FLOOR(ZZ(corner)); } else { (*vol_voxels).initZeros(Zdim, Ydim, Xdim); (*vol_voxels).setXmippOrigin(); } // Convert each subvolume ............................................... for (size_t i = 0; i < vol_splines.VolumesNo(); i++) { spatial_Bspline032voxels_SimpleGrid(vol_splines(i)(), vol_splines.grid(i), vol_voxels); #ifdef DEBUG std::cout << "Spline grid no " << i << " stats: "; vol_splines(i)().printStats(); std::cout << std::endl; std::cout << "So far vol stats: "; (*vol_voxels).printStats(); std::cout << std::endl; VolumeXmipp save; save() = *vol_voxels; save.write((std::string)"PPPvoxels" + integerToString(i)); #endif } // Now normalise the resulting volume .................................. double inorm = 1.0 / sum_spatial_Bspline03_Grid(vol_splines.grid()); FOR_ALL_ELEMENTS_IN_ARRAY3D(*vol_voxels) A3D_ELEM(*vol_voxels, k, i, j) *= inorm; // Set voxels outside interest region to minimum value ................. double R = vol_splines.grid(0).get_interest_radius(); if (R != -1) { double R2 = (R - 6) * (R - 6); // Compute minimum value within sphere double min_val = A3D_ELEM(*vol_voxels, 0, 0, 0); FOR_ALL_ELEMENTS_IN_ARRAY3D(*vol_voxels) if (j*j + i*i + k*k <= R2 - 4) min_val = XMIPP_MIN(min_val, A3D_ELEM(*vol_voxels, k, i, j)); // Substitute minimum value R2 = (R - 2) * (R - 2); FOR_ALL_ELEMENTS_IN_ARRAY3D(*vol_voxels) if (j*j + i*i + k*k >= R2) A3D_ELEM(*vol_voxels, k, i, j) = min_val; }
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; }
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)); } } }
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"); } }
// 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); }