void Projector::initialiseData(int current_size) { // By default r_max is half ori_size if (current_size < 0) r_max = ori_size / 2; else r_max = current_size / 2; // Never allow r_max beyond Nyquist... r_max = XMIPP_MIN(r_max, ori_size / 2); // Set pad_size pad_size = 2 * (padding_factor * r_max + 1) + 1; // Short side of data array switch (ref_dim) { case 2: data.resize(pad_size, pad_size / 2 + 1); break; case 3: data.resize(pad_size, pad_size, pad_size / 2 + 1); break; default: REPORT_ERROR("Projector::resizeData%%ERROR: Dimension of the data array should be 2 or 3"); } // Set origin in the y.z-center, but on the left side for x. data.setXmippOrigin(); data.xinit=0; }
void read(int argc, char **argv) { parser.setCommandLine(argc, argv); int general_section = parser.addSection("General Options"); fn_unt = parser.getOption("--u", "STAR file with the untilted xy-coordinates"); fn_til = parser.getOption("--t", "STAR file with the untilted xy-coordinates"); size = textToInteger(parser.getOption("--size", "Largest dimension of the micrograph (in pixels), e.g. 4096")); dim = textToInteger(parser.getOption("--dim", "Dimension of boxed particles (for EMAN .box files in pixels)", "200")); acc = textToFloat(parser.getOption("--acc", "Allowed accuracy (in pixels), e.g. half the particle diameter")); tilt = textToFloat(parser.getOption("--tilt", "Fix tilt angle (in degrees)", "99999.")); rot = textToFloat(parser.getOption("--rot", "Fix direction of the tilt axis (in degrees), 0 = along y, 90 = along x", "99999.")); do_opt = !parser.checkOption("--dont_opt", "Skip optimization of the transformation matrix"); mind2 = ROUND(acc * acc); int angle_section = parser.addSection("Specified tilt axis and translational search ranges"); tilt0 = textToFloat(parser.getOption("--tilt0", "Minimum tilt angle (in degrees)","0.")); tiltF = textToFloat(parser.getOption("--tiltF", "Maximum tilt angle (in degrees)","99999.")); if (tiltF == 99999.) tiltF = tilt0; tiltStep = textToFloat(parser.getOption("--tiltStep", "Tilt angle step size (in degrees)","1.")); rot0 = textToFloat(parser.getOption("--rot0", "Minimum rot angle (in degrees)","0.")); rotF = textToFloat(parser.getOption("--rotF", "Maximum rot angle (in degrees)","99999.")); if (rotF == 99999.) rotF = rot0; rotStep = textToFloat(parser.getOption("--rotStep", "Rot angle step size (in degrees)","1.")); x0 = textToInteger(parser.getOption("--x0", "Minimum X offset (pixels)","-99999")); xF = textToInteger(parser.getOption("--xF", "Maximum X offset (pixels)","99999")); xStep = textToInteger(parser.getOption("--xStep", "X offset step size (pixels)","-1")); y0 = textToInteger(parser.getOption("--y0", "Minimum Y offset (pixels)","-99999")); yF = textToInteger(parser.getOption("--yF", "Maximum Y offset (pixels)","99999")); yStep = textToInteger(parser.getOption("--yStep", "Y offset step size (pixels)","-1")); // Check for errors in the command-line option if (parser.checkForErrors()) REPORT_ERROR("Errors encountered on the command line, exiting..."); // If tilt and rot were given: do not search those if (tilt != 99999.) { tilt0 = tiltF = tilt; tiltStep = 1.; } if (rot != 99999.) { rot0 = rotF = rot; rotStep = 1.; } // By default search the entire micrograph x0 = XMIPP_MAX(x0, -size); xF = XMIPP_MIN(xF, size); // By default use a xStep of one third the accuracy if (xStep < 0) xStep = acc / 3; // By default treat y search in the same way as the x-search if (y0 == -99999) y0 = x0; if (yF == 99999) yF = xF; if (yStep < 0) yStep = xStep; // Done reading, now fill p_unt and p_til MDunt.read(fn_unt); MDtil.read(fn_til); // Check for the correct labels if (!MDunt.containsLabel(EMDL_IMAGE_COORD_X) || !MDunt.containsLabel(EMDL_IMAGE_COORD_Y)) REPORT_ERROR("ERROR: Untilted STAR file does not contain the rlnCoordinateX or Y labels"); if (!MDtil.containsLabel(EMDL_IMAGE_COORD_X) || !MDtil.containsLabel(EMDL_IMAGE_COORD_Y)) REPORT_ERROR("ERROR: Tilted STAR file does not contain the rlnCoordinateX or Y labels"); double x, y; p_unt.clear(); FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDunt) { MDunt.getValue(EMDL_IMAGE_COORD_X, x); MDunt.getValue(EMDL_IMAGE_COORD_Y, y); p_unt.push_back((int)x); p_unt.push_back((int)y); } p_til.clear(); FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDtil) { MDtil.getValue(EMDL_IMAGE_COORD_X, x); MDtil.getValue(EMDL_IMAGE_COORD_Y, y); p_til.push_back((int)x); p_til.push_back((int)y); } // Initialize best transformation params best_x = best_y = 9999; best_rot = best_tilt = 9999.; }
//#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; }
//#define DEBUG double spatial_Bspline03_proj( const Matrix1D<double> &r, const Matrix1D<double> &u) { // Avoids divisions by zero and allows orthogonal rays computation static Matrix1D<double> ur(3); if (XX(u) == 0) XX(ur) = XMIPP_EQUAL_ACCURACY; else XX(ur) = XX(u); if (YY(u) == 0) YY(ur) = XMIPP_EQUAL_ACCURACY; else YY(ur) = YY(u); if (ZZ(u) == 0) ZZ(ur) = XMIPP_EQUAL_ACCURACY; else ZZ(ur) = ZZ(u); // Some precalculated variables double x_sign = SGN(XX(ur)); double y_sign = SGN(YY(ur)); double z_sign = SGN(ZZ(ur)); // Compute the minimum and maximum alpha for the ray double alpha_xmin = (-2 - XX(r)) / XX(ur); double alpha_xmax = (2 - XX(r)) / XX(ur); double alpha_ymin = (-2 - YY(r)) / YY(ur); double alpha_ymax = (2 - YY(r)) / YY(ur); double alpha_zmin = (-2 - ZZ(r)) / ZZ(ur); double alpha_zmax = (2 - ZZ(r)) / ZZ(ur); double alpha_min = XMIPP_MAX(XMIPP_MIN(alpha_xmin, alpha_xmax), XMIPP_MIN(alpha_ymin, alpha_ymax)); alpha_min = XMIPP_MAX(alpha_min, XMIPP_MIN(alpha_zmin, alpha_zmax)); double alpha_max = XMIPP_MIN(XMIPP_MAX(alpha_xmin, alpha_xmax), XMIPP_MAX(alpha_ymin, alpha_ymax)); alpha_max = XMIPP_MIN(alpha_max, XMIPP_MAX(alpha_zmin, alpha_zmax)); if (alpha_max - alpha_min < XMIPP_EQUAL_ACCURACY) return 0.0; #ifdef DEBUG std::cout << "Pixel: " << r.transpose() << std::endl << "Dir: " << ur.transpose() << std::endl << "Alpha x:" << alpha_xmin << " " << alpha_xmax << std::endl << " " << (r + alpha_xmin*ur).transpose() << std::endl << " " << (r + alpha_xmax*ur).transpose() << std::endl << "Alpha y:" << alpha_ymin << " " << alpha_ymax << std::endl << " " << (r + alpha_ymin*ur).transpose() << std::endl << " " << (r + alpha_ymax*ur).transpose() << std::endl << "Alpha z:" << alpha_zmin << " " << alpha_zmax << std::endl << " " << (r + alpha_zmin*ur).transpose() << std::endl << " " << (r + alpha_zmax*ur).transpose() << std::endl << "alpha :" << alpha_min << " " << alpha_max << std::endl << std::endl; #endif // Compute the first point in the volume intersecting the ray static Matrix1D<double> v(3); V3_BY_CT(v, ur, alpha_min); V3_PLUS_V3(v, r, v); #ifdef DEBUG std::cout << "First entry point: " << v.transpose() << std::endl; std::cout << " Alpha_min: " << alpha_min << std::endl; #endif // Follow the ray double alpha = alpha_min; double ray_sum = 0; do { double alpha_x = (XX(v) + x_sign - XX(r)) / XX(ur); double alpha_y = (YY(v) + y_sign - YY(r)) / YY(ur); double alpha_z = (ZZ(v) + z_sign - ZZ(r)) / ZZ(ur); // Which dimension will ray move next step into?, it isn't neccesary to be only // one. double diffx = ABS(alpha - alpha_x); double diffy = ABS(alpha - alpha_y); double diffz = ABS(alpha - alpha_z); double diff_alpha = XMIPP_MIN(XMIPP_MIN(diffx, diffy), diffz); ray_sum += spatial_Bspline03_integral(r, ur, alpha, alpha + diff_alpha); // Update alpha and the next entry point if (ABS(diff_alpha - diffx) <= XMIPP_EQUAL_ACCURACY) alpha = alpha_x; if (ABS(diff_alpha - diffy) <= XMIPP_EQUAL_ACCURACY) alpha = alpha_y; if (ABS(diff_alpha - diffz) <= XMIPP_EQUAL_ACCURACY) alpha = alpha_z; XX(v) += diff_alpha * XX(ur); YY(v) += diff_alpha * YY(ur); ZZ(v) += diff_alpha * ZZ(ur); #ifdef DEBUG std::cout << "Alpha x,y,z: " << alpha_x << " " << alpha_y << " " << alpha_z << " ---> " << alpha << std::endl; std::cout << " Next entry point: " << v.transpose() << std::endl << " diff_alpha: " << diff_alpha << std::endl << " ray_sum: " << ray_sum << std::endl << " Alfa tot: " << alpha << "alpha_max: " << alpha_max << std::endl; #endif } while ((alpha_max - alpha) > XMIPP_EQUAL_ACCURACY); return ray_sum; }
//#define DEBUG void normalize_tomography(MultidimArray<double> &I, double tilt, double &mui, double &sigmai, bool tiltMask, bool tomography0, double mu0, double sigma0) { // Tilt series are always 2D I.checkDimension(2); const int L=2; // Build a mask using the tilt angle I.setXmippOrigin(); MultidimArray<int> mask; mask.initZeros(I); int Xdimtilt=(int)XMIPP_MIN(FLOOR(0.5*(XSIZE(I)*cos(DEG2RAD(tilt)))), 0.5*(XSIZE(I)-(2*L+1))); int N=0; for (int i=STARTINGY(I); i<=FINISHINGY(I); i++) for (int j=-Xdimtilt; j<=Xdimtilt;j++) { A2D_ELEM(mask,i,j)=1; N++; } // Estimate the local variance MultidimArray<double> localVariance; localVariance.initZeros(I); double meanVariance=0; FOR_ALL_ELEMENTS_IN_ARRAY2D(I) { // Center a mask of size 5x5 and estimate the variance within the mask double meanPiece=0, variancePiece=0; double Npiece=0; for (int ii=i-L; ii<=i+L; ii++) { if (INSIDEY(I,ii)) for (int jj=j-L; jj<=j+L; jj++) { if (INSIDEX(I,jj)) { double pixval=A2D_ELEM(I,ii,jj); meanPiece+=pixval; variancePiece+=pixval*pixval; ++Npiece; } } } meanPiece/=Npiece; variancePiece=variancePiece/(Npiece-1)- Npiece/(Npiece-1)*meanPiece*meanPiece; A2D_ELEM(localVariance,i,j)=variancePiece; meanVariance+=variancePiece; } meanVariance*=1.0/N; // Test the hypothesis that the variance in this piece is // the same as the variance in the whole image double iFu=1/icdf_FSnedecor(4*L*L+4*L,N-1,0.975); double iFl=1/icdf_FSnedecor(4*L*L+4*L,N-1,0.025); double iMeanVariance=1.0/meanVariance; FOR_ALL_ELEMENTS_IN_ARRAY2D(localVariance) { if (A2D_ELEM(localVariance,i,j)==0) A2D_ELEM(mask,i,j)=-2; if (A2D_ELEM(mask,i,j)==1) { double ratio=A2D_ELEM(localVariance,i,j)*iMeanVariance; double thl=ratio*iFu; double thu=ratio*iFl; if (thl>1 || thu<1) A2D_ELEM(mask,i,j)=-1; } } #ifdef DEBUG Image<double> save; save()=I; save.write("PPP.xmp"); save()=localVariance; save.write("PPPLocalVariance.xmp"); Image<int> savemask; savemask()=mask; savemask.write("PPPmask.xmp"); #endif // Compute the statistics again in the reduced mask double avg, stddev, min, max; computeStats_within_binary_mask(mask, I, min, max, avg, stddev); double cosTilt=cos(DEG2RAD(tilt)); double iCosTilt=1.0/cosTilt; if (tomography0) { double iadjustedStddev=1.0/(sigma0*cosTilt); FOR_ALL_ELEMENTS_IN_ARRAY2D(I) switch (A2D_ELEM(mask,i,j)) { case -2: A2D_ELEM(I,i,j)=0; break; case 0: if (tiltMask) A2D_ELEM(I,i,j)=0; else A2D_ELEM(I,i,j)=(A2D_ELEM(I,i,j)*iCosTilt-mu0)*iadjustedStddev; break; case -1: case 1: A2D_ELEM(I,i,j)=(A2D_ELEM(I,i,j)*iCosTilt-mu0)*iadjustedStddev; break; } } else {
void busca() { static float f[22][22]; float pi = 3.141592653; short in1, mu5, i, mu3, ind, ind1, indice, iflag, j, ix=0, iy=0, k; float h, th, costh, sinth, fi, anc, xk0, yk0, hpi, x, y, z, xx, yy; float b, g, d1, e1, ext; int count = 0; suaviza(); in = XMIPP_MIN(in, 10); mu1 = mu - 1; m = 2 * mu; mu4 = mu * ncic; mt = 2 * m; ntot = mt * ncic; ntot4 = ntot + mu4 + ncic; zzz0 = ntot; ncic2 = 2 * ncic; in1 = in + 1; h = 2. * pi / ntot; idz = 2 - ntot; th = ncic * h; costh = cos(th); sinth = sin(th); b = 2. / (th * th) * (1. + costh * costh - sin(2. * th) / th); g = 4. / (th * th) * (sinth / th - costh); d1 = 2. * th / 45.; e1 = d1 * sinth * 2.; d1 *= sin(2. * th); mu5 = mu4 - 1; for (i = 1; i <= mu5; i++) { fi = i * h; coseno[i] = sin(fi); } coseno[mu4] = 1.; mu3 = 2 * mu4; for (i = 1; i <= mu5; i++) { coseno[mu3-i] = coseno[i]; coseno[mu3+i] = -coseno[i]; coseno[ntot-i] = -coseno[i]; coseno[ntot+i] = coseno[i]; } coseno[mu3] = 0.; coseno[mu3+mu4] = -1.; coseno[ntot] = 0.; coseno[ntot+mu4] = 1.; ind = 2 * in + 1; ind1 = ind - 1; indice = 0; iflag = 0; e9: if (indice >= ni) goto e10; if (iflag == 2) goto e22; anc = (int)(3. + in * del); xk0 = xc0; yk0 = yc0; rh = XMIPP_MIN(rh, r2); rh = XMIPP_MIN(rh, xk0 - anc - 1.); rh = XMIPP_MIN(rh, yk0 - anc - 1.); rh = XMIPP_MIN(rh, largo - xk0 - anc); rh = XMIPP_MIN(rh, lancho - yk0 - anc); ir = (int)((rh - r1) / r3 + 1); hpi = h / 2. / pi / ir; cxp1 = 2. * b * e1 * hpi; cxp2 = -2. * g * d1 * hpi; cxp3 = 2. * (g * e1 - b * d1) * hpi; cxm1 = (b * b + e1 * e1) * hpi; cxm2 = (g * g + d1 * d1) * hpi; cxm3 = 2. * (b * g - d1 * e1) * hpi; /* if(iflag == 1) goto 21 */ if (iflag == 2) goto e22; x = xc0 - in * del; for (i = 1; i <= ind; i++) /* do 5 */ { y = yc0 - in * del; for (j = 1; j <= ind; j++) /*do 4 */ { ergrot(x, y, &z); /* printf ("%10.3f%10.3f%10.5f%10.3f%10.3f AA\n", x,y,z,del,rh);*/ printf("."); fflush(stdout); z = 100. + indmul * z; f[i][j] = z; y += del; } x += del; } // Introduced by Sjors dd 28.9.2004 to avoid infinite loops count++; if (count > 1000) goto s1; e23: ext = -1000000.; for (i = 1; i <= ind; i++) /* do 7 */ for (j = 1; j <= ind; j++) /* do 7 */ { if (f[i][j] > ext) { ix = i; iy = j; ext = f[i][j]; } } xc0 = xc0 + (ix - in - 1) * del; yc0 = yc0 + (iy - in - 1) * del; if (ix == 1 || ix == ind || iy == 1 || iy == ind) goto e8; del /= in; iflag = 2; indice++; goto e9; e8: iflag = 1; goto e9; e22: f[1][1] = f[ix-1][iy-1]; f[ind][1] = f[ix+1][iy-1]; f[1][ind] = f[ix-1][iy+1]; f[ind][ind] = f[ix+1][iy+1]; f[1][in1] = f[ix-1][iy]; f[in1][1] = f[ix][iy-1]; f[ind][in1] = f[ix+1][iy]; f[in1][ind] = f[ix][iy+1]; f[in1][in1] = f[ix][iy]; x = xc0 - (in - 1) * del; for (i = 2; i < ind1; i++) /* do 11 */ { y = yc0 - (in - 1) * del; for (j = 2;j <= ind1; j++) /* do 12 */ { if (i == in1 && j == in1) goto e13; ergrot(x, y, &z); /* printf ("%10.3f%10.3f%10.5f%10.3f BB \n", x,y,z,del);*/ printf("."); fflush(stdout); z = 100. + indmul * z; f[i][j] = z; e13: y += del; } x += del; } x = xc0 - (in - 1) * del; y = yc0 - (in - 1) * del; for (k = 2; k <= ind1; k++) /* do 16 */ { if (k == in1) goto e17; xx = xc0 - in * del; ergrot(xx, y, &z); /* printf ("%10.3f%10.3f%10.5f%10.3f CC \n", xx,y,z,del);*/ printf("."); fflush(stdout); z = 100. + indmul * z; f[1][k] = z; yy = yc0 - in * del; ergrot(x, yy, &z); /* printf ("%10.3f%10.3f%10.5f%10.3f DD \n", xx,y,z,del);*/ printf("."); fflush(stdout); z = 100. + indmul * z; f[k][1] = z; xx = xc0 + in * del; ergrot(xx, y, &z); /* printf ("%10.3f%10.3f%10.5f%10.3f EE \n", xx,y,z,del);*/ printf("."); fflush(stdout); z = 100. + indmul * z; f[ind][k] = z; yy = yc0 + in * del; ergrot(x, yy, &z); /* printf ("%10.3f%10.3f%10.5f%10.3f FF\n", x,yy,z,del);*/ printf("."); fflush(stdout); z = 100. + indmul * z; f[k][ind] = z; e17: x += del; y += del; } goto e23; e10: std::cout << "\nOptimal center coordinates: x= " << yc0-1 << " ,y= " << xc0-1 << " " << std::endl; return; s1: yc0=xc0=-1; printf("\nNot-converged\n"); return; }
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 }