Xmipp  v3.23.11-Nereus
Classes | Macros | Functions | Variables
Parameters Projection for Tomography
Collaboration diagram for Parameters Projection for Tomography:

Classes

class  ParametersProjectionTomography
 
struct  project_thread_params
 

Macros

#define x0   STARTINGX(IMGMATRIX(*proj))
 
#define xF   FINISHINGX(IMGMATRIX(*proj))
 
#define y0   STARTINGY(IMGMATRIX(*proj))
 
#define yF   FINISHINGY(IMGMATRIX(*proj))
 
#define xDim   XSIZE(IMGMATRIX(*proj))
 
#define yDim   YSIZE(IMGMATRIX(*proj))
 

Functions

template<class T >
void project_SimpleGrid (Image< T > *vol, const SimpleGrid *grid, const Basis *basis, Projection *proj, Projection *norm_proj, int FORW, int eq_mode, const Image< int > *VNeq, Matrix2D< double > *M, const MultidimArray< int > *mask=nullptr, double ray_length=-1.0, int thread_id=-1, int num_threads=1)
 
void projectVolume (MultidimArray< double > &V, Projection &P, int Ydim, int Xdim, double rot, double tilt, double psi, const Matrix1D< double > *roffset=nullptr)
 
void projectVolumeOffCentered (MultidimArray< double > &V, Projection &P, int Ydim, int Xdim)
 
void singleWBP (MultidimArray< double > &V, Projection &P)
 
void count_eqs_in_projection (GridVolumeT< int > &GVNeq, const Basis &basis, Projection &read_proj)
 
void project_Crystal_Volume (GridVolume &vol, const Basis &basis, Projection &proj, Projection &norm_proj, int Ydim, int Xdim, double rot, double tilt, double psi, const Matrix1D< double > &shift, const Matrix1D< double > &aint, const Matrix1D< double > &bint, const Matrix2D< double > &D, const Matrix2D< double > &Dinv, const MultidimArray< int > &mask, int FORW, int eq_mode=ARTK)
 
template<class T >
void * project_SimpleGridThread (void *params)
 
template<class T >
void project_GridVolume (GridVolumeT< T > &vol, const Basis &basis, Projection &proj, Projection &norm_proj, int Ydim, int Xdim, double rot, double tilt, double psi, int FORW, int eq_mode, GridVolumeT< int > *GVNeq, Matrix2D< double > *M, const MultidimArray< int > *mask, double ray_length, int threads)
 

Variables

barrier_t project_barrier
 
pthread_mutex_t project_mutex
 
project_thread_paramsproject_threads
 
constexpr int FORWARD = 1
 
constexpr int BACKWARD = 0
 
constexpr int ARTK = 1
 
constexpr int CAVK = 2
 
constexpr int COUNT_EQ = 3
 
constexpr int CAV = 4
 
constexpr int CAVARTK = 5
 
const int ART_PIXEL_SUBSAMPLING = 2
 

Detailed Description

Macro Definition Documentation

◆ x0

#define x0   STARTINGX(IMGMATRIX(*proj))

Definition at line 255 of file projection.h.

◆ xDim

#define xDim   XSIZE(IMGMATRIX(*proj))

Definition at line 259 of file projection.h.

◆ xF

#define xF   FINISHINGX(IMGMATRIX(*proj))

Definition at line 256 of file projection.h.

◆ y0

#define y0   STARTINGY(IMGMATRIX(*proj))

Definition at line 257 of file projection.h.

◆ yDim

#define yDim   YSIZE(IMGMATRIX(*proj))

Definition at line 260 of file projection.h.

◆ yF

#define yF   FINISHINGY(IMGMATRIX(*proj))

Definition at line 258 of file projection.h.

Function Documentation

◆ count_eqs_in_projection()

void count_eqs_in_projection ( GridVolumeT< int > &  GVNeq,
const Basis basis,
Projection read_proj 
)

Count equations in volume. For Component AVeraing (CAV), the number of equations in which each basis is involved is needed.

Definition at line 1206 of file projection.cpp.

1208 {
1209  for (size_t i = 0; i < GVNeq.VolumesNo(); i++)
1210  project_SimpleGrid(&(GVNeq(i)), &(GVNeq.grid(i)), &basis,
1211  &read_proj, &read_proj, FORWARD, COUNT_EQ, NULL, NULL);
1212 }
constexpr int COUNT_EQ
Definition: projection.h:179
#define i
size_t VolumesNo() const
Definition: grids.h:1003
void project_SimpleGrid(Image< T > *vol, const SimpleGrid *grid, const Basis *basis, Projection *proj, Projection *norm_proj, int FORW, int eq_mode, const Image< int > *VNeq, Matrix2D< double > *M, const MultidimArray< int > *mask, double ray_length, int thread_id, int numthreads)
#define FORWARD
Definition: blobs.cpp:1091
const SimpleGrid & grid(size_t n) const
Definition: grids.h:978

◆ project_Crystal_Volume()

void project_Crystal_Volume ( GridVolume vol,
const Basis basis,
Projection proj,
Projection norm_proj,
int  Ydim,
int  Xdim,
double  rot,
double  tilt,
double  psi,
const Matrix1D< double > &  shift,
const Matrix1D< double > &  aint,
const Matrix1D< double > &  bint,
const Matrix2D< double > &  D,
const Matrix2D< double > &  Dinv,
const MultidimArray< int > &  mask,
int  FORW,
int  eq_mode = ARTK 
)

Project a crystal basis volume. This function projects a crystal deformed basis volume, ie, in the documentation volume g. However the angles given must be those for volume f, the undeformed one. You must supply the deformed lattice vectors, and the matrix to pass from the deformed to the undeformed vectors (D and Dinv). a=D*ai;

Valid eq_modes are ARTK, CAVARTK and CAV.

Definition at line 1157 of file projection.cpp.

1176 {
1177  // If projecting forward initialise projections
1178  if (FORW)
1179  {
1180  proj.reset(Ydim, Xdim);
1181  proj.setAngles(rot, tilt, psi);
1182  norm_proj().resize(proj());
1183  }
1184 
1185  // Project each subvolume
1186  for (size_t i = 0; i < vol.VolumesNo(); i++)
1187  {
1188  project_Crystal_SimpleGrid(vol(i), vol.grid(i), basis,
1189  proj, norm_proj, shift, aint, bint, D, Dinv, mask, FORW, eq_mode);
1190 
1191 #ifdef DEBUG
1192 
1193  Image<double> save;
1194  save = norm_proj;
1195  if (FORW)
1196  save.write((std::string)"PPPnorm_FORW" + (char)(48 + i));
1197  else
1198  save.write((std::string)"PPPnorm_BACK" + (char)(48 + i));
1199 #endif
1200 
1201  }
1202 }
void reset(int Ydim, int Xdim)
void project_Crystal_SimpleGrid(Image< double > &vol, const SimpleGrid &grid, const Basis &basis, Projection &proj, Projection &norm_proj, const Matrix1D< double > &shift, const Matrix1D< double > &aint, const Matrix1D< double > &bint, const Matrix2D< double > &D, const Matrix2D< double > &Dinv, const MultidimArray< int > &mask, int FORW, int eq_mode)
Definition: projection.cpp:773
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
#define i
size_t VolumesNo() const
Definition: grids.h:1003
const SimpleGrid & grid(size_t n) const
Definition: grids.h:978
double psi(const double x)
void setAngles(double _rot, double _tilt, double _psi)

◆ project_GridVolume()

template<class T >
void project_GridVolume ( GridVolumeT< T > &  vol,
const Basis basis,
Projection proj,
Projection norm_proj,
int  Ydim,
int  Xdim,
double  rot,
double  tilt,
double  psi,
int  FORW,
int  eq_mode,
GridVolumeT< int > *  GVNeq,
Matrix2D< double > *  M,
const MultidimArray< int > *  mask,
double  ray_length,
int  threads 
)

Projection of a Grid Volume.

Project a grid volume with a basis. The Grid volume is projected onto a projection plane defined by (rot, tilt, psi) (1st, 2nd and 3rd Euler angles). The projection is previously is resized to Ydim x Xdim and initialized to 0. The projection itself, from now on, will keep the Euler angles.

FORWARD process: Each volume of the grid is projected on to the projection plane. The output is the projection itself and a normalising image, the normalising image is the projection of the same grid supposing that all basis are of value 1. This normalising image is used by the ART process

BACKWARD process: During the backward process the normalising projection contains the correction image to apply to the volume (in the ART sense). The output is the volume itself, the projection image is useless in this case, and the normalising projection is not modified at all.

As for the mode, valid modes are ARTK, CAVK, COUNT_EQ, CAVARTK.

M is the matrix corresponding to the projection process.

Definition at line 1863 of file projection.cpp.

1881 {
1882 
1883  // If projecting forward initialize projections
1884  if (FORW)
1885  {
1886  proj.reset(Ydim, Xdim);
1887  proj.setAngles(rot, tilt, psi);
1888  norm_proj().initZeros(proj());
1889  }
1890 
1891  if( threads > 1 )
1892  {
1893  for( int c = 0 ; c < threads ; c++ )
1894  {
1895  project_threads[c].global_proj = &proj;
1896  project_threads[c].global_norm_proj = &norm_proj;
1897  project_threads[c].FORW = FORW;
1898  project_threads[c].eq_mode = eq_mode;
1899  project_threads[c].basis = &basis;
1900  project_threads[c].M = M;
1901  project_threads[c].rot = rot;
1902  project_threads[c].tilt = tilt;
1903  project_threads[c].psi = psi;
1904  project_threads[c].ray_length = ray_length;
1905  }
1906  }
1907 
1908 
1909 #ifdef DEBUG_LITTLE
1910  if (FORW)
1911  {
1912  std::cout << "Number of volumes: " << vol.VolumesNo() << std::endl
1913  << "YdimxXdim: " << Ydim << "x" << Xdim << std::endl;
1914  for (int i = 0; i < vol.VolumesNo(); i++)
1915  std::cout << "Volume " << i << std::endl << vol.grid(i) << std::endl;
1916  }
1917 
1918 #endif
1919 
1920  // Project each subvolume
1921  for (size_t i = 0; i < vol.VolumesNo(); i++)
1922  {
1923  Image<int> *VNeq;
1924  if (GVNeq != NULL)
1925  VNeq = &((*GVNeq)(i));
1926  else
1927  VNeq = NULL;
1928 
1929  if( threads > 1 )
1930  {
1931  for( int c = 0 ; c < threads ; c++ )
1932  {
1933  project_threads[c].vol = &(vol(i));
1934  project_threads[c].grid = &(vol.grid(i));
1935  project_threads[c].VNeq = VNeq;
1936  project_threads[c].mask = mask;
1937  }
1938 
1940 
1941  // Here is being processed the volume by the threads
1942 
1944  }
1945  else
1946  {
1947  // create no thread to do the job
1948  project_SimpleGrid(&(vol(i)), &(vol.grid(i)), &basis,
1949  &proj, &norm_proj, FORW, eq_mode,
1950  VNeq, M, mask, ray_length);
1951  }
1952 
1953 #ifdef DEBUG
1954  Image<double> save;
1955  save = norm_proj;
1956  if (FORW)
1957  save.write((std::string)"PPPnorm_FORW" + (char)(48 + i));
1958  else
1959  save.write((std::string)"PPPnorm_BACK" + (char)(48 + i));
1960 #endif
1961 
1962  }
1963 }
const MultidimArray< int > * mask
Definition: projection.h:150
void reset(int Ydim, int Xdim)
doublereal * c
Projection * global_norm_proj
Definition: projection.h:145
const SimpleGrid * grid
Definition: projection.h:142
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
#define i
const Image< int > * VNeq
Definition: projection.h:148
size_t VolumesNo() const
Definition: grids.h:1003
void project_SimpleGrid(Image< T > *vol, const SimpleGrid *grid, const Basis *basis, Projection *proj, Projection *norm_proj, int FORW, int eq_mode, const Image< int > *VNeq, Matrix2D< double > *M, const MultidimArray< int > *mask, double ray_length, int thread_id, int numthreads)
barrier_t project_barrier
Definition: projection.cpp:46
Image< double > * vol
Definition: projection.h:141
Matrix2D< double > * M
Definition: projection.h:149
const SimpleGrid & grid(size_t n) const
Definition: grids.h:978
double psi(const double x)
project_thread_params * project_threads
Definition: projection.cpp:48
Projection * global_proj
Definition: projection.h:144
void setAngles(double _rot, double _tilt, double _psi)
int barrier_wait(barrier_t *barrier)
const Basis * basis
Definition: projection.h:143

◆ project_SimpleGrid()

template<class T >
void project_SimpleGrid ( Image< T > *  vol,
const SimpleGrid grid,
const Basis basis,
Projection proj,
Projection norm_proj,
int  FORW,
int  eq_mode,
const Image< int > *  VNeq,
Matrix2D< double > *  M,
const MultidimArray< int > *  mask,
double  ray_length,
int  thread_id,
int  numthreads 
)

Projection of a Simple Grid. Valid eq_modes are ARTK, CAVARTK and CAV.

Definition at line 1314 of file projection.cpp.

1321 {
1322  Matrix1D<double> zero(3); // Origin (0,0,0)
1323  Matrix1D<double> prjPix(3); // Position of the pixel within the projection
1324  Matrix1D<double> prjX(3); // Coordinate: Projection of the
1325  Matrix1D<double> prjY(3); // 3 grid vectors
1326  Matrix1D<double> prjZ(3);
1327  Matrix1D<double> prjOrigin(3); // Coordinate: Where in the 2D
1328  // projection plane the origin of
1329  // the grid projects
1330  Matrix1D<double> prjDir(3); // Projection direction
1331 
1332  Matrix1D<double> actprj(3); // Coord: Actual position inside
1333  // the projection plane
1334  Matrix1D<double> beginZ(3); // Coord: Plane coordinates of the
1335  // projection of the 3D point
1336  // (z0,YY(lowest),XX(lowest))
1337  Matrix1D<double> univ_beginY(3); // Coord: coordinates of the
1338  // grid point
1339  // (z0,y0,XX(lowest))
1340  Matrix1D<double> univ_beginZ(3); // Coord: coordinates of the
1341  // grid point
1342  // (z0,YY(lowest),XX(lowest))
1343  Matrix1D<double> beginY(3); // Coord: Plane coordinates of the
1344  // projection of the 3D point
1345  // (z0,y0,XX(lowest))
1346  double XX_footprint_size=0.; // The footprint is supposed
1347  double YY_footprint_size=0.; // to be defined between
1348  double ZZ_footprint_size=0.;
1349  // (-vmax,+vmax) in the Y axis,
1350  // and (-umax,+umax) in the X axis
1351  // This footprint size is the
1352  // R2 vector (umax,vmax).
1353 
1354  int XX_corner2;
1355  int XX_corner1; // Coord: Corners of the
1356  int YY_corner2;
1357  int YY_corner1; // footprint when it is projected
1358  // onto the projection plane
1359  int foot_V1=0;
1360  int foot_U1=0; // Img Coord: coordinate (in
1361  // an image fashion, not in an
1362  // oversampled image fashion)
1363  // inside the blobprint of the
1364  // corner1
1365  int foot_V;
1366  int foot_U; // Img Coord: coordinate
1367  int foot_W = 0;
1368  // corresponding to the blobprint
1369  // point which matches with this
1370  // pixel position
1371  int Vsampling=0;
1372  int Usampling=0; // Sampling rate in Y and X
1373  // directions respectively
1374  // inside the blobprint
1375  double vol_corr=0.; // Correction for a volume element
1376  int N_eq; // Number of equations in which
1377  // a blob is involved
1378  int i;
1379  int j;
1380  int k; // volume element indexes
1381  bool isVolPSF = false; // Blob footprint is VolumePSF
1382 
1383  // Prepare system matrix for printing ...................................
1384  if (M != NULL)
1385  M->initZeros(YSIZE((*proj)())*XSIZE((*proj)()), grid->get_number_of_samples());
1386 
1387  // Project grid axis ....................................................
1388  // These vectors ((1,0,0),(0,1,0),...) are referred to the grid
1389  // coord. system and the result is a 2D vector in the image plane
1390  // The unit size within the image plane is 1, ie, the same as for
1391  // the universal grid.
1392  // actprj is reused with a different purpose
1393  VECTOR_R3(actprj, 1, 0, 0);
1394  grid->Gdir_project_to_plane(actprj, proj->euler, prjX);
1395  VECTOR_R3(actprj, 0, 1, 0);
1396  grid->Gdir_project_to_plane(actprj, proj->euler, prjY);
1397  VECTOR_R3(actprj, 0, 0, 1);
1398  grid->Gdir_project_to_plane(actprj, proj->euler, prjZ);
1399 
1400  // This time the origin of the grid is in the universal coord system
1401  Uproject_to_plane(grid->origin, proj->euler, prjOrigin);
1402 
1403  // Get the projection direction .........................................
1404  proj->euler.getRow(2, prjDir);
1405 
1406  // Footprint size .......................................................
1407  // The following vectors are integer valued vectors, but they are
1408  // stored as real ones to make easier operations with other vectors
1409  if (basis->type == Basis::blobs)
1410  {
1411  XX_footprint_size = basis->blobprint.umax();
1412  YY_footprint_size = basis->blobprint.vmax();
1413  Usampling = basis->blobprint.Ustep();
1414  Vsampling = basis->blobprint.Vstep();
1415 
1416  // Set the limit for grid points out of PSF
1417  if (basis->VolPSF != NULL)
1418  {
1419  isVolPSF = true;
1420  ZZ_footprint_size = basis->blobprint.wmax();
1421  }
1422  }
1423  else if (basis->type == Basis::voxels || basis->type == Basis::splines)
1424  {
1425  YY_footprint_size = XX_footprint_size = CEIL(basis->maxLength());
1426  Usampling = Vsampling = 0;
1427  }
1428  XX_footprint_size += XMIPP_EQUAL_ACCURACY;
1429  YY_footprint_size += XMIPP_EQUAL_ACCURACY;
1430 
1431  // Project the whole grid ...............................................
1432  // Corner of the plane defined by Z. These coordinates try to be within
1433  // the valid indexes of the projection (defined between STARTING and
1434  // FINISHING values, but it could be that they may lie outside.
1435  // These coordinates need not to be integer, in general, they are
1436  // real vectors.
1437  // The vectors returned by the projection routines are R3 but we
1438  // are only interested in their first 2 components, ie, in the
1439  // in-plane components
1440 
1441  // This type conversion gives more speed
1442 
1443  auto ZZ_lowest = (int) ZZ(grid->lowest);
1444 
1445  if( thread_id != -1 )
1446  ZZ_lowest += thread_id;
1447 
1448  auto YY_lowest = (int) YY(grid->lowest);
1449  auto XX_lowest = (int) XX(grid->lowest);
1450  auto ZZ_highest = (int) ZZ(grid->highest);
1451  auto YY_highest = (int) YY(grid->highest);
1452  auto XX_highest = (int) XX(grid->highest);
1453 
1454  beginZ = (double)XX_lowest * prjX + (double)YY_lowest * prjY + (double)ZZ_lowest * prjZ + prjOrigin;
1455 
1456  // Check if in VSSNR
1457  bool VSSNR_mode = (ray_length == basis->maxLength());
1458 
1459 #ifdef DEBUG_LITTLE
1460 
1461  int condition;
1462  condition = thread_id==1;
1463  if (condition || numthreads==1)
1464  {
1465  std::cout << "Equation mode " << eq_mode << std::endl;
1466  std::cout << "Footprint size " << YY_footprint_size << "x"
1467  << XX_footprint_size << std::endl;
1468  std::cout << "rot=" << proj->rot() << " tilt=" << proj->tilt()
1469  << " psi=" << proj->psi() << std::endl;
1470  std::cout << "Euler matrix " << proj->euler;
1471  std::cout << "Projection direction " << prjDir << std::endl;
1472  std::cout << *grid;
1473  std::cout << "image limits (" << x0 << "," << y0 << ") (" << xF << ","
1474  << yF << ")\n";
1475  std::cout << "prjX " << prjX.transpose() << std::endl;
1476  std::cout << "prjY " << prjY.transpose() << std::endl;
1477  std::cout << "prjZ " << prjZ.transpose() << std::endl;
1478  std::cout << "prjOrigin " << prjOrigin.transpose() << std::endl;
1479  std::cout << "beginZ(coord) " << beginZ.transpose() << std::endl;
1480  std::cout << "lowest " << XX_lowest << " " << YY_lowest
1481  << " " << XX_lowest << std::endl;
1482  std::cout << "highest " << XX_highest << " " << YY_highest
1483  << " " << XX_highest << std::endl;
1484  std::cout << "Stats of input basis volume ";
1485  (*vol)().printStats();
1486  std::cout << std::endl;
1487  std::cout.flush();
1488  }
1489 #endif
1490 
1491  // Compute the grid lattice vectors in space ............................
1492  Matrix2D<double> grid_basis(3, 3);
1493  grid_basis = grid->basis * grid->relative_size;
1494  Matrix1D<double> gridX(3); // Direction of the grid lattice vectors
1495  Matrix1D<double> gridY(3); // in universal coordinates
1496  Matrix1D<double> gridZ(3);
1497  Matrix1D<double> univ_position(3);
1498 
1499  grid_basis.getCol(0, gridX);
1500  grid_basis.getCol(1, gridY);
1501  grid_basis.getCol(2, gridZ);
1502 
1503  univ_beginZ = (double)XX_lowest * gridX + (double)YY_lowest * gridY + (double)ZZ_lowest * gridZ + grid->origin;
1504 
1505  int number_of_basis = 0;
1506 
1507  for (k = ZZ_lowest; k <= ZZ_highest; k += numthreads)
1508  {
1509  // Corner of the row defined by Y
1510  beginY = beginZ;
1511  univ_beginY = univ_beginZ;
1512  for (i = YY_lowest; i <= YY_highest; i++)
1513  {
1514  // First point in the row
1515  actprj = beginY;
1516  univ_position = univ_beginY;
1517  for (j = XX_lowest; j <= XX_highest; j++)
1518  {
1519  // Ray length interesting
1520  bool ray_length_interesting = true;
1521  double zCenterDist;
1522  double z = 0; // z = 0 standard value for non 3D blobprints
1523 
1524  if (ray_length != -1 || isVolPSF)
1525  {
1526  zCenterDist = point_plane_distance_3D(univ_position, zero,
1527  proj->direction);
1528  if (ray_length != -1)
1529  ray_length_interesting = (ABS(zCenterDist) <= ray_length);
1530 
1531  // Points out of 3DPSF
1532  if (isVolPSF && ray_length_interesting)
1533  {
1534  ray_length_interesting = (ABS(zCenterDist) <= ZZ_footprint_size);
1535  // There is still missing the shift of the volume from focal plane
1536  z = zCenterDist; // + shiftZ
1537  }
1538  }
1539 
1540  if (grid->is_interesting(univ_position) &&
1541  ray_length_interesting)
1542  {
1543  // Be careful that you cannot skip any basis, although its
1544  // value be 0, because it is useful for norm_proj
1545 #ifdef DEBUG
1546  condition = thread_id == 1;
1547  if (condition)
1548  {
1549  printf("\nProjecting grid coord (%d,%d,%d) ", j, i, k);
1550  std::cout << "Vol there = " << VOLVOXEL(*vol, k, i, j) << std::endl;
1551  printf(" 3D universal position (%f,%f,%f) \n",
1552  XX(univ_position), YY(univ_position), ZZ(univ_position));
1553  std::cout << " Center of the basis proj (2D) " << XX(actprj) << "," << YY(actprj) << std::endl;
1554  Matrix1D<double> aux;
1555  Uproject_to_plane(univ_position, proj->euler, aux);
1556  std::cout << " Center of the basis proj (more accurate) " << aux.transpose() << std::endl;
1557  }
1558 #endif
1559 
1560  // Search for integer corners for this basis
1561  XX_corner1 = CEIL(XMIPP_MAX(STARTINGX(IMGMATRIX(*proj)), XX(actprj) - XX_footprint_size));
1562  YY_corner1 = CEIL(XMIPP_MAX(STARTINGY(IMGMATRIX(*proj)), YY(actprj) - YY_footprint_size));
1563  XX_corner2 = FLOOR(XMIPP_MIN(FINISHINGX(IMGMATRIX(*proj)), XX(actprj) + XX_footprint_size));
1564  YY_corner2 = FLOOR(XMIPP_MIN(FINISHINGY(IMGMATRIX(*proj)), YY(actprj) + YY_footprint_size));
1565 
1566 #ifdef DEBUG
1567 
1568  if (condition)
1569  {
1570  std::cout << "Clipped and rounded Corner 1 " << XX_corner1
1571  << " " << YY_corner1 << " " << std::endl;
1572  std::cout << "Clipped and rounded Corner 2 " << XX_corner2
1573  << " " << YY_corner2 << " " << std::endl;
1574  }
1575 #endif
1576 
1577  // Check if the basis falls outside the projection plane
1578  // COSS: I have changed here
1579  if (XX_corner1 <= XX_corner2 && YY_corner1 <= YY_corner2)
1580  {
1581  // Compute the index of the basis for corner1
1582  if (basis->type == Basis::blobs)
1583  {
1584  OVER2IMG(basis->blobprint, (double)YY_corner1 - YY(actprj),
1585  (double)XX_corner1 - XX(actprj), foot_V1, foot_U1);
1586  if (isVolPSF != false)
1587  OVER2IMG_Z(basis->blobprint, z, foot_W);
1588  }
1589 
1590  if (!FORW)
1591  vol_corr = 0;
1592 
1593  // Effectively project this basis
1594  // N_eq=(YY_corner2-YY_corner1+1)*(XX_corner2-XX_corner1+1);
1595  N_eq = 0;
1596  foot_V = foot_V1;
1597  for (int y = YY_corner1; y <= YY_corner2; y++)
1598  {
1599  foot_U = foot_U1;
1600  for (int x = XX_corner1; x <= XX_corner2; x++)
1601  {
1602  if (!((mask != NULL) && A2D_ELEM(*mask,y,x)<0.5))
1603  {
1604 #ifdef DEBUG
1605  if (condition)
1606  {
1607  std::cout << "Position in projection (" << x << ","
1608  << y << ") ";
1609  double y, x;
1610  if (basis->type == Basis::blobs)
1611  {
1612  std::cout << "in footprint ("
1613  << foot_U << "," << foot_V << ")";
1614  IMG2OVER(basis->blobprint, foot_V, foot_U, y, x);
1615  std::cout << " (d= " << sqrt(y*y + x*x) << ") ";
1616  fflush(stdout);
1617  }
1618  }
1619 #endif
1620  double a;
1621  double a2;
1622  // Check if volumetric interpolation (i.e., SSNR)
1623  if (VSSNR_mode)
1624  {
1625  // This is the VSSNR case
1626  // Get the pixel position in the universal coordinate
1627  // system
1629  VECTOR_R3(prjPix, x, y, z);
1630  M3x3_BY_V3x1(prjPix, proj->eulert, prjPix);
1631  V3_MINUS_V3(prjPix, prjPix, univ_position);
1632  a = basis->valueAt(prjPix);
1633  a2 = a * a;
1634  }
1635  else
1636  {
1637  // This is normal reconstruction from projections
1638  if (basis->type == Basis::blobs)
1639  {
1640  // Projection of a blob
1641  a = VOLVOXEL(basis->blobprint, foot_W, foot_V, foot_U);
1642  a2 = VOLVOXEL(basis->blobprint2, foot_W, foot_V, foot_U);
1643 
1644  }
1645  else
1646  {
1647  // Projection of other bases
1648  // If the basis is big enough, then
1649  // it is not necessary to integrate at several
1650  // places. Big enough is being greater than
1651  // 1.41 which is the maximum separation
1652  // between two pixels
1653  if (XX_footprint_size > 1.41)
1654  {
1655  // Get the pixel in universal coordinates
1657  VECTOR_R3(prjPix, x, y, 0);
1658  // Express the point in a local coordinate system
1659  M3x3_BY_V3x1(prjPix, proj->eulert, prjPix);
1660 #ifdef DEBUG
1661 
1662  if (condition)
1663  std::cout << " in volume coord ("
1664  << prjPix.transpose() << ")";
1665 #endif
1666 
1667  V3_MINUS_V3(prjPix, prjPix, univ_position);
1668 #ifdef DEBUG
1669 
1670  if (condition)
1671  std::cout << " in voxel coord ("
1672  << prjPix.transpose() << ")";
1673 #endif
1674 
1675  a = basis->projectionAt(prjDir, prjPix);
1676  a2 = a * a;
1677  }
1678  else
1679  {
1680  // If the basis is too small (of the
1681  // range of the voxel), then it is
1682  // necessary to sample in a few places
1683  const double p0 = 1.0 / (2 * ART_PIXEL_SUBSAMPLING) - 0.5;
1684  const double pStep = 1.0 / ART_PIXEL_SUBSAMPLING;
1685  const double pAvg = 1.0 / (ART_PIXEL_SUBSAMPLING * ART_PIXEL_SUBSAMPLING);
1686  int ii;
1687  int jj;
1688  double px;
1689  double py;
1690  a = 0;
1691 #ifdef DEBUG
1692 
1693  if (condition)
1694  std::cout << std::endl;
1695 #endif
1696 
1697  for (ii = 0, px = p0; ii < ART_PIXEL_SUBSAMPLING; ii++, px += pStep)
1698  for (jj = 0, py = p0; jj < ART_PIXEL_SUBSAMPLING; jj++, py += pStep)
1699  {
1700 #ifdef DEBUG
1701  if (condition)
1702  std::cout << " subsampling (" << ii << ","
1703  << jj << ") ";
1704 #endif
1705 
1707  // Get the pixel in universal coordinates
1708  VECTOR_R3(prjPix, x + px, y + py, 0);
1709  // Express the point in a local coordinate system
1710  M3x3_BY_V3x1(prjPix, proj->eulert, prjPix);
1711 #ifdef DEBUG
1712 
1713  if (condition)
1714  std::cout << " in volume coord ("
1715  << prjPix.transpose() << ")";
1716 #endif
1717 
1718  V3_MINUS_V3(prjPix, prjPix, univ_position);
1719 #ifdef DEBUG
1720 
1721  if (condition)
1722  std::cout << " in voxel coord ("
1723  << prjPix.transpose() << ")";
1724 #endif
1725 
1726  a += basis->projectionAt(prjDir, prjPix);
1727 #ifdef DEBUG
1728 
1729  if (condition)
1730  std::cout << " partial a="
1731  << basis->projectionAt(prjDir, prjPix)
1732  << std::endl;
1733 #endif
1734 
1735  }
1736  a *= pAvg;
1737  a2 = a * a;
1738 #ifdef DEBUG
1739 
1740  if (condition)
1741  std::cout << " Finally ";
1742 #endif
1743 
1744  }
1745  }
1746  }
1747 #ifdef DEBUG
1748  if (condition)
1749  std::cout << "=" << a << " , " << a2;
1750 #endif
1751 
1752  if (FORW)
1753  {
1754  switch (eq_mode)
1755  {
1756  case CAVARTK:
1757  case ARTK:
1758  IMGPIXEL(*proj, y, x) += VOLVOXEL(*vol, k, i, j) * a;
1759  IMGPIXEL(*norm_proj, y, x) += a2;
1760  if (M != NULL)
1761  {
1762  int py;
1763  int px;
1764  (*proj)().toPhysical(y, x, py, px);
1765  int number_of_pixel = py * XSIZE((*proj)()) + px;
1766  dMij(*M, number_of_pixel, number_of_basis) = a;
1767  }
1768  break;
1769  case CAVK:
1770  IMGPIXEL(*proj, y, x) += VOLVOXEL(*vol, k, i, j) * a;
1771  IMGPIXEL(*norm_proj, y, x) += a2 * N_eq;
1772  break;
1773  case COUNT_EQ:
1774  VOLVOXEL(*vol, k, i, j)++;
1775  break;
1776  case CAV:
1777  IMGPIXEL(*proj, y, x) += VOLVOXEL(*vol, k, i, j) * a;
1778  IMGPIXEL(*norm_proj, y, x) += a2 *
1779  VOLVOXEL(*VNeq, k, i, j);
1780  break;
1781  }
1782 
1783 #ifdef DEBUG
1784  if (condition)
1785  {
1786  std::cout << " proj= " << IMGPIXEL(*proj, y, x)
1787  << " norm_proj=" << IMGPIXEL(*norm_proj, y, x) << std::endl;
1788  std::cout.flush();
1789  }
1790 #endif
1791 
1792  }
1793  else
1794  {
1795  vol_corr += IMGPIXEL(*norm_proj, y, x) * a;
1796  if (a != 0)
1797  N_eq++;
1798 #ifdef DEBUG
1799 
1800  if (condition)
1801  {
1802  std::cout << " corr_img= " << IMGPIXEL(*norm_proj, y, x)
1803  << " correction=" << vol_corr << std::endl;
1804  std::cout.flush();
1805  }
1806 #endif
1807 
1808  }
1809  }
1810  // Prepare for next operation
1811  foot_U += Usampling;
1812  }
1813  foot_V += Vsampling;
1814  } // Project this basis
1815 
1816  if (!FORW)
1817  {
1818  T correction = 0;
1819  switch (eq_mode)
1820  {
1821  case ARTK:
1822  correction = (T) vol_corr;
1823  break;
1824  case CAVARTK:
1825  if (N_eq != 0)
1826  correction = (T)(vol_corr / N_eq);
1827  break;
1828  case CAVK:
1829  case CAV:
1830  correction = (T) vol_corr;
1831  break;
1832  }
1833  VOLVOXEL(*vol, k, i, j) += correction;
1834 
1835 #ifdef DEBUG
1836 
1837  if (condition)
1838  {
1839  printf("\nFinal value at (%d,%d,%d) ", j, i, k);
1840  std::cout << " = " << VOLVOXEL(*vol, k, i, j) << std::endl;
1841  std::cout.flush();
1842  }
1843 #endif
1844 
1845  }
1846  } // If not collapsed
1847  number_of_basis++;
1848  } // If interesting
1849 
1850  // Prepare for next iteration
1851  V2_PLUS_V2(actprj, actprj, prjX);
1852  V3_PLUS_V3(univ_position, univ_position, gridX);
1853  }
1854  V2_PLUS_V2(beginY, beginY, prjY);
1855  V3_PLUS_V3(univ_beginY, univ_beginY, gridY);
1856  }
1857  V2_PLUS_V2(beginZ, beginZ, prjZ * numthreads );
1858  V3_PLUS_V3(univ_beginZ, univ_beginZ, gridZ * numthreads);
1859  }
1860 }
Matrix2D< double > eulert
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
#define VOLVOXEL(V, k, i, j)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
Matrix1D< double > highest
Definition: grids.h:161
#define FINISHINGX(v)
constexpr int COUNT_EQ
Definition: projection.h:179
double psi(const size_t n=0) const
double projectionAt(const Matrix1D< double > &u, const Matrix1D< double > &r) const
Definition: basis.cpp:367
void sqrt(Image< double > &op)
Matrix2D< double > euler
#define V3_MINUS_V3(a, b, c)
Definition: matrix1d.h:202
int umax() const
constexpr int ARTK
Definition: projection.h:177
tBasisFunction type
Basis function to use.
Definition: basis.h:52
#define x
double rot(const size_t n=0) const
ImageOver blobprint2
Square of the footprint.
Definition: basis.h:74
double maxLength() const
Definition: basis.cpp:242
#define IMGMATRIX(I)
Matrix1D< double > lowest
Definition: grids.h:158
int Vstep() const
#define xF
Definition: projection.cpp:38
int Ustep() const
#define V2_PLUS_V2(a, b, c)
Definition: matrix1d.h:134
#define STARTINGX(v)
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
double tilt(const size_t n=0) const
#define STARTINGY(v)
const int ART_PIXEL_SUBSAMPLING
Definition: projection.h:296
int vmax() const
#define FLOOR(x)
Definition: xmipp_macros.h:240
#define XX(v)
Definition: matrix1d.h:85
MultidimArray< double > * VolPSF
Footprint is convolved with a volume PSF // At this moment only used with blobs.
Definition: basis.h:55
double point_plane_distance_3D(const Matrix1D< double > &p, const Matrix1D< double > &a, const Matrix1D< double > &v)
Definition: geometry.h:171
#define CEIL(x)
Definition: xmipp_macros.h:225
#define dMij(m, i, j)
Definition: matrix2d.h:139
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
#define IMG2OVER(IO, iv, iu, v, u)
#define XSIZE(v)
#define ABS(x)
Definition: xmipp_macros.h:142
#define yF
Definition: projection.cpp:40
double z
for(j=1;j<=i__1;++j)
Matrix1D< double > direction
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
double valueAt(const Matrix1D< double > &r) const
Definition: basis.cpp:332
#define j
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
#define YY(v)
Definition: matrix1d.h:93
#define x0
Definition: projection.cpp:37
constexpr int CAV
Definition: projection.h:180
#define FINISHINGY(v)
constexpr int CAVARTK
Definition: projection.h:181
#define y
Matrix1D< double > origin
Origin of the grid in the Universal coordinate system.
Definition: grids.h:165
constexpr int CAVK
Definition: projection.h:178
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
int get_number_of_samples() const
Definition: grids.cpp:69
#define OVER2IMG(IO, v, u, iv, iu)
void initZeros()
Definition: matrix2d.h:626
void Gdir_project_to_plane(const Matrix1D< double > &gr, double rot, double tilt, double psi, Matrix1D< double > &result) const
Definition: grids.h:432
void getRow(size_t i, Matrix1D< T > &v) const
Definition: matrix2d.cpp:871
void Uproject_to_plane(const Matrix1D< double > &point, const Matrix1D< double > &direction, double distance, Matrix1D< double > &result)
Definition: geometry.cpp:39
#define ZZ(v)
Definition: matrix1d.h:101
doublereal * a
ql0001_ & zero(ctemp+1),(cvec+1),(a+1),(b+1),(bl+1),(bu+1),(x+1),(w+1), &iout, ifail, &zero,(w+3), &lwar2,(iw+1), &leniw, &glob_grd.epsmac
#define y0
Definition: projection.cpp:39
#define V3_PLUS_V3(a, b, c)
Definition: matrix1d.h:190
#define IMGPIXEL(I, i, j)
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403
ImageOver blobprint
Blob footprint.
Definition: basis.h:71
int wmax() const
#define OVER2IMG_Z(IO, w, iw)

◆ project_SimpleGridThread()

template<class T >
void* project_SimpleGridThread ( void *  params)

Threaded projection for simple grids

Definition at line 1215 of file projection.cpp.

1216 {
1217  auto * thread_data = (project_thread_params *)params;
1218 
1219  Image<T> * vol;
1220  const SimpleGrid * grid;
1221 
1222  int thread_id = thread_data->thread_id;
1223  int threads_count = thread_data->threads_count;
1224 
1225  const Basis * basis;
1226 
1227  Projection * proj;
1228  Projection * norm_proj;
1229 
1230  auto * forw_proj = new Projection();
1231  auto * forw_norm_proj = new Projection();
1232 
1233  Projection * global_proj;
1234  Projection * global_norm_proj;
1235 
1236  int FORW;
1237  int eq_mode;
1238  const Image<int> *VNeq=NULL;
1239  Matrix2D<double> *M=NULL;
1240  const MultidimArray<int> *mask=NULL;
1241  double ray_length;
1242 
1243  double rot;
1244  double tilt;
1245  double psi;
1246 
1247  do
1248  {
1250 
1251  if( thread_data->destroy == true )
1252  break;
1253 
1254  vol = thread_data->vol;
1255  grid = thread_data->grid;
1256  basis = thread_data->basis;
1257  FORW = thread_data->FORW;
1258  eq_mode = thread_data->eq_mode;
1259  VNeq = thread_data->VNeq;
1260  M = thread_data->M;
1261  mask = thread_data->mask;
1262  ray_length = thread_data->ray_length;
1263  global_proj = thread_data->global_proj;
1264  global_norm_proj = thread_data->global_norm_proj;
1265 
1266  rot = thread_data->rot;
1267  tilt = thread_data->tilt;
1268  psi = thread_data->psi;
1269 
1270  if( FORW )
1271  {
1272  proj = forw_proj;
1273  norm_proj = forw_norm_proj;
1274 
1275  proj->reset(YSIZE( (*global_proj)() ), XSIZE( (*global_proj)() ));
1276  proj->setAngles(rot, tilt, psi);
1277  (*norm_proj)().initZeros((*proj)());
1278  }
1279  else
1280  {
1281  proj = global_proj;
1282  norm_proj = global_norm_proj;
1283  }
1284 
1285  project_SimpleGrid( vol, grid,
1286  basis,
1287  proj,
1288  norm_proj, FORW, eq_mode,
1289  VNeq, M, mask,
1290  ray_length,
1291  thread_id,
1292  threads_count
1293  );
1294 
1295  if( FORW )
1296  {
1297 
1298  pthread_mutex_lock( &project_mutex );
1299 
1300  (*global_proj)() = (*global_proj)() + (*proj)();
1301  (*global_norm_proj)() = (*global_norm_proj)() + (*norm_proj)();
1302 
1303  pthread_mutex_unlock( &project_mutex );
1304  }
1305 
1307  }
1308  while(1);
1309 
1310  return (void *)NULL;
1311 }
#define YSIZE(v)
void reset(int Ydim, int Xdim)
double rot(const size_t n=0) const
void project_SimpleGrid(Image< T > *vol, const SimpleGrid *grid, const Basis *basis, Projection *proj, Projection *norm_proj, int FORW, int eq_mode, const Image< int > *VNeq, Matrix2D< double > *M, const MultidimArray< int > *mask, double ray_length, int thread_id, int numthreads)
Definition: basis.h:45
pthread_mutex_t project_mutex
Definition: projection.cpp:47
#define XSIZE(v)
barrier_t project_barrier
Definition: projection.cpp:46
double psi(const double x)
void setAngles(double _rot, double _tilt, double _psi)
int barrier_wait(barrier_t *barrier)

◆ projectVolume()

void projectVolume ( MultidimArray< double > &  V,
Projection P,
int  Ydim,
int  Xdim,
double  rot,
double  tilt,
double  psi,
const Matrix1D< double > *  roffset = nullptr 
)

From voxel volumes. The voxel volume is projected onto a projection plane defined by (rot, tilt, psi) (1st, 2nd and 3rd Euler angles) . The projection is previously is resized to Ydim x Xdim and initialized to 0. The projection itself, from now on, will keep the Euler angles.

The offset is a 3D vector specifying the offset that must be applied when going from the projection space to the universal space

rproj=E*r+roffset => r=E^t (rproj-roffset)

Set it to NULL if you don't want to use it

Definition at line 337 of file projection.cpp.

340 {
342 
343  // Initialise projection
344  P.reset(Ydim, Xdim);
345  P.setAngles(rot, tilt, psi);
346 
347  // Compute the distance for this line crossing one voxel
348  int x_0 = STARTINGX(V);
349  int x_F = FINISHINGX(V);
350  int y_0 = STARTINGY(V);
351  int y_F = FINISHINGY(V);
352  int z_0 = STARTINGZ(V);
353  int z_F = FINISHINGZ(V);
354 
355  // Distances in X and Y between the center of the projection pixel begin
356  // computed and each computed ray
357  double step = 1.0 / 3.0;
358 
359  // Avoids divisions by zero and allows orthogonal rays computation
360  if (XX(P.direction) == 0)
362  if (YY(P.direction) == 0)
364  if (ZZ(P.direction) == 0)
366 
367  // Some precalculated variables
368  int x_sign = SGN(XX(P.direction));
369  int y_sign = SGN(YY(P.direction));
370  int z_sign = SGN(ZZ(P.direction));
371  double half_x_sign = 0.5 * x_sign;
372  double half_y_sign = 0.5 * y_sign;
373  double half_z_sign = 0.5 * z_sign;
374  double iXXP_direction=1.0/XX(P.direction);
375  double iYYP_direction=1.0/YY(P.direction);
376  double iZZP_direction=1.0/ZZ(P.direction);
377 
378  MultidimArray<double> &mP = P();
379  Matrix1D<double> v(3);
380  Matrix1D<double> r_p(3); // r_p are the coordinates of the
381  // pixel being projected in the
382  // coordinate system attached to the
383  // projection
384  Matrix1D<double> p1(3); // coordinates of the pixel in the
385  // universal space
386  Matrix1D<double> p1_shifted(3); // shifted half a pixel
388  {
389  double ray_sum = 0.0; // Line integral value
390 
391  // Computes 4 different rays for each pixel.
392  for (int rays_per_pixel = 0; rays_per_pixel < 4; rays_per_pixel++)
393  {
394  // universal coordinate system
395  switch (rays_per_pixel)
396  {
397  case 0:
398  VECTOR_R3(r_p, j - step, i - step, 0);
399  break;
400  case 1:
401  VECTOR_R3(r_p, j - step, i + step, 0);
402  break;
403  case 2:
404  VECTOR_R3(r_p, j + step, i - step, 0);
405  break;
406  case 3:
407  VECTOR_R3(r_p, j + step, i + step, 0);
408  break;
409  }
410 
411  // Express r_p in the universal coordinate system
412  if (roffset!=nullptr)
413  r_p-=*roffset;
414  M3x3_BY_V3x1(p1, P.eulert, r_p);
415  XX(p1_shifted)=XX(p1)-half_x_sign;
416  YY(p1_shifted)=YY(p1)-half_y_sign;
417  ZZ(p1_shifted)=ZZ(p1)-half_z_sign;
418 
419  // Compute the minimum and maximum alpha for the ray
420  // intersecting the given volume
421  double alpha_xmin = (x_0 - 0.5 - XX(p1))* iXXP_direction;
422  double alpha_xmax = (x_F + 0.5 - XX(p1))* iXXP_direction;
423  double alpha_ymin = (y_0 - 0.5 - YY(p1))* iYYP_direction;
424  double alpha_ymax = (y_F + 0.5 - YY(p1))* iYYP_direction;
425  double alpha_zmin = (z_0 - 0.5 - ZZ(p1))* iZZP_direction;
426  double alpha_zmax = (z_F + 0.5 - ZZ(p1))* iZZP_direction;
427 
428  double auxMin;
429  double auxMax;
430  if (alpha_xmin<alpha_xmax)
431  {
432  auxMin=alpha_xmin;
433  auxMax=alpha_xmax;
434  }
435  else
436  {
437  auxMin=alpha_xmax;
438  auxMax=alpha_xmin;
439  }
440  double alpha_min=auxMin;
441  double alpha_max=auxMax;
442  if (alpha_ymin<alpha_ymax)
443  {
444  auxMin=alpha_ymin;
445  auxMax=alpha_ymax;
446  }
447  else
448  {
449  auxMin=alpha_ymax;
450  auxMax=alpha_ymin;
451  }
452  alpha_min=fmax(auxMin,alpha_min);
453  alpha_max=fmin(auxMax,alpha_max);
454  if (alpha_zmin<alpha_zmax)
455  {
456  auxMin=alpha_zmin;
457  auxMax=alpha_zmax;
458  }
459  else
460  {
461  auxMin=alpha_zmax;
462  auxMax=alpha_zmin;
463  }
464  alpha_min=fmax(auxMin,alpha_min);
465  alpha_max=fmin(auxMax,alpha_max);
466  if (alpha_max - alpha_min < XMIPP_EQUAL_ACCURACY)
467  continue;
468 
469 #ifdef DEBUG
470 
471  std::cout << "Pixel: " << r_p.transpose() << std::endl
472  << "Univ: " << p1.transpose() << std::endl
473  << "Dir: " << P.direction.transpose() << std::endl
474  << "Alpha x:" << alpha_xmin << " " << alpha_xmax << std::endl
475  << " " << (p1 + alpha_xmin*P.direction).transpose() << std::endl
476  << " " << (p1 + alpha_xmax*P.direction).transpose() << std::endl
477  << "Alpha y:" << alpha_ymin << " " << alpha_ymax << std::endl
478  << " " << (p1 + alpha_ymin*P.direction).transpose() << std::endl
479  << " " << (p1 + alpha_ymax*P.direction).transpose() << std::endl
480  << "Alpha z:" << alpha_zmin << " " << alpha_zmax << std::endl
481  << " " << (p1 + alpha_zmin*P.direction).transpose() << std::endl
482  << " " << (p1 + alpha_zmax*P.direction).transpose() << std::endl
483  << "alpha :" << alpha_min << " " << alpha_max << std::endl
484  << std::endl;
485 #endif
486 
487  // Compute the first point in the volume intersecting the ray
488  double zz_idxd;
489  double yy_idxd;
490  double xx_idxd;
491  int zz_idx;
492  int yy_idx;
493  int xx_idx;
494  V3_BY_CT(v, P.direction, alpha_min);
495  V3_PLUS_V3(v, p1, v);
496 
497  // Compute the index of the first voxel
498  xx_idx = ROUND(XX(v));
499  yy_idx = ROUND(YY(v));
500  zz_idx = ROUND(ZZ(v));
501 
502  xx_idxd = xx_idx = CLIP(xx_idx, x_0, x_F);
503  yy_idxd = yy_idx = CLIP(yy_idx, y_0, y_F);
504  zz_idxd = zz_idx = CLIP(zz_idx, z_0, z_F);
505 
506 #ifdef DEBUG
507 
508  std::cout << "First voxel: " << v.transpose() << std::endl;
509  std::cout << " First index: " << idx.transpose() << std::endl;
510  std::cout << " Alpha_min: " << alpha_min << std::endl;
511 #endif
512 
513  // Follow the ray
514  double alpha = alpha_min;
515  do
516  {
517 #ifdef DEBUG
518  std::cout << " \n\nCurrent Value: " << V(zz_idx, yy_idx, xx_idx) << std::endl;
519 #endif
520 
521  double alpha_x = (xx_idxd - XX(p1_shifted))* iXXP_direction;
522  double alpha_y = (yy_idxd - YY(p1_shifted))* iYYP_direction;
523  double alpha_z = (zz_idxd - ZZ(p1_shifted))* iZZP_direction;
524 
525  // Which dimension will ray move next step into?, it isn't necessary to be only
526  // one.
527  double diffx = fabs(alpha-alpha_x);
528  double diffy = fabs(alpha-alpha_y);
529  double diffz = fabs(alpha-alpha_z);
530  int diff_source=0;
531  double diff_alpha=diffx;
532  if (diffy<diff_alpha)
533  {
534  diff_source=1;
535  diff_alpha=diffy;
536  }
537  if (diffz<diff_alpha)
538  {
539  diff_source=2;
540  diff_alpha=diffz;
541  }
542  ray_sum += diff_alpha * A3D_ELEM(V, zz_idx, yy_idx, xx_idx);
543 
544  switch (diff_source)
545  {
546  case 0:
547  alpha = alpha_x;
548  xx_idx += x_sign;
549  xx_idxd = xx_idx;
550  break;
551  case 1:
552  alpha = alpha_y;
553  yy_idx += y_sign;
554  yy_idxd = yy_idx;
555  break;
556  default:
557  alpha = alpha_z;
558  zz_idx += z_sign;
559  zz_idxd = zz_idx;
560  }
561 
562 #ifdef DEBUG
563  std::cout << "Alpha x,y,z: " << alpha_x << " " << alpha_y
564  << " " << alpha_z << " ---> " << alpha << std::endl;
565 
566  XX(v) += diff_alpha * XX(P.direction);
567  YY(v) += diff_alpha * YY(P.direction);
568  ZZ(v) += diff_alpha * ZZ(P.direction);
569 
570  std::cout << " Next entry point: " << v.transpose() << std::endl
571  << " Index: " << idx.transpose() << std::endl
572  << " diff_alpha: " << diff_alpha << std::endl
573  << " ray_sum: " << ray_sum << std::endl
574  << " Alfa tot: " << alpha << "alpha_max: " << alpha_max <<
575  std::endl;
576 #endif
577 
578  }
579  while ((alpha_max - alpha) > XMIPP_EQUAL_ACCURACY);
580  } // for
581 
582  A2D_ELEM(IMGMATRIX(P), i, j) = ray_sum * 0.25;
583 #ifdef DEBUG
584 
585  std::cout << "Assigning P(" << i << "," << j << ")=" << ray_sum << std::endl;
586 #endif
587 
588  }
589 }
Matrix2D< double > eulert
#define A2D_ELEM(v, i, j)
double alpha
Smoothness parameter.
Definition: blobs.h:121
void reset(int Ydim, int Xdim)
#define FINISHINGX(v)
#define FINISHINGZ(v)
#define IMGMATRIX(I)
#define STARTINGX(v)
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
#define STARTINGY(v)
#define CLIP(x, x0, xF)
Definition: xmipp_macros.h:260
#define A3D_ELEM(V, k, i, j)
#define V3_BY_CT(a, b, c)
Definition: matrix1d.h:238
#define XX(v)
Definition: matrix1d.h:85
void transpose(double *array, int size)
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
#define ROUND(x)
Definition: xmipp_macros.h:210
Matrix1D< double > direction
#define j
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
#define YY(v)
Definition: matrix1d.h:93
#define FINISHINGY(v)
double psi(const double x)
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
void setAngles(double _rot, double _tilt, double _psi)
double fmax
#define SGN(x)
Definition: xmipp_macros.h:155
#define STARTINGZ(v)
#define ZZ(v)
Definition: matrix1d.h:101
#define V3_PLUS_V3(a, b, c)
Definition: matrix1d.h:190
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403

◆ projectVolumeOffCentered()

void projectVolumeOffCentered ( MultidimArray< double > &  V,
Projection P,
int  Ydim,
int  Xdim 
)

From voxel volumes, off-centered tilt axis. This routine projects a volume that is rotating (angle) degrees around the axis defined by the two angles (axisRot,axisTilt) and that passes through the point raxis. The projection can be further inplane rotated and shifted through the parameters (inplaneRot) and (rinplane).

All vectors involved must be 3D.

The projection model is rproj=H Rinplane Raxis r + Rinplane (I-Raxis) raxis + rinplane

Where Raxis is the 3D rotation matrix given by the axis and the angle.

Definition at line 594 of file projection.cpp.

596 {
597  Matrix1D<double> roffset(3);
598  P.getShifts(XX(roffset), YY(roffset), ZZ(roffset));
599 
600  projectVolume(V, P, Ydim, Xdim, P.rot(), P.tilt(), P.psi(), &roffset);
601 }
double psi(const size_t n=0) const
double rot(const size_t n=0) const
double tilt(const size_t n=0) const
#define XX(v)
Definition: matrix1d.h:85
void projectVolume(MultidimArray< double > &V, Projection &P, int Ydim, int Xdim, double rot, double tilt, double psi, const Matrix1D< double > *roffset)
Definition: projection.cpp:337
#define YY(v)
Definition: matrix1d.h:93
#define ZZ(v)
Definition: matrix1d.h:101
void getShifts(double &xoff, double &yoff, double &zoff, const size_t n=0) const

◆ singleWBP()

void singleWBP ( MultidimArray< double > &  V,
Projection P 
)

Single Weighted Back Projection. Projects a single particle into a voxels volume by updating its components this way: Voxel(i,j,k) = Voxel(i,j,k) + Pixel( x,y) * Distance.

Where:

  • Voxel(i,j,k) is the voxel the ray is crossing.
  • Pixel( y,z ) is the value of the pixel where the ray departs from.
  • Distance is the distance the ray goes through the Voxel.

Definition at line 609 of file projection.cpp.

610 {
612 
613  // Compute the distance for this line crossing one voxel
614  int x_0 = STARTINGX(V);
615  int x_F = FINISHINGX(V);
616  int y_0 = STARTINGY(V);
617  int y_F = FINISHINGY(V);
618  int z_0 = STARTINGZ(V);
619  int z_F = FINISHINGZ(V);
620 
621  // Avoids divisions by zero and allows orthogonal rays computation
622  if (XX(P.direction) == 0)
624  if (YY(P.direction) == 0)
626  if (ZZ(P.direction) == 0)
628 
629  // Some precalculated variables
630  int x_sign = SGN(XX(P.direction));
631  int y_sign = SGN(YY(P.direction));
632  int z_sign = SGN(ZZ(P.direction));
633  double half_x_sign = 0.5 * x_sign;
634  double half_y_sign = 0.5 * y_sign;
635  double half_z_sign = 0.5 * z_sign;
636 
637  MultidimArray<double> &mP = P();
638  Matrix1D<double> r_p(3); // r_p are the coordinates of the
639  // pixel being projected in the
640  // coordinate system attached to the
641  // projection
642  Matrix1D<double> p1(3); // coordinates of the pixel in the
643  Matrix1D<double> v(3);
644  Matrix1D<int> idx(3);
646  {
647  // Computes 4 different rays for each pixel.
648  VECTOR_R3(r_p, j, i, 0);
649 
650  // Express r_p in the universal coordinate system
651  M3x3_BY_V3x1(p1, P.eulert, r_p);
652 
653  // Compute the minimum and maximum alpha for the ray
654  // intersecting the given volume
655  double alpha_xmin = (x_0 - 0.5 - XX(p1)) / XX(P.direction);
656  double alpha_xmax = (x_F + 0.5 - XX(p1)) / XX(P.direction);
657  double alpha_ymin = (y_0 - 0.5 - YY(p1)) / YY(P.direction);
658  double alpha_ymax = (y_F + 0.5 - YY(p1)) / YY(P.direction);
659  double alpha_zmin = (z_0 - 0.5 - ZZ(p1)) / ZZ(P.direction);
660  double alpha_zmax = (z_F + 0.5 - ZZ(p1)) / ZZ(P.direction);
661 
662  double alpha_min = fmax(fmin(alpha_xmin, alpha_xmax),
663  fmin(alpha_ymin, alpha_ymax));
664  alpha_min = fmax(alpha_min, fmin(alpha_zmin, alpha_zmax));
665  double alpha_max = fmin(fmax(alpha_xmin, alpha_xmax),
666  fmax(alpha_ymin, alpha_ymax));
667  alpha_max = fmin(alpha_max, fmax(alpha_zmin, alpha_zmax));
668  if (alpha_max - alpha_min < XMIPP_EQUAL_ACCURACY)
669  continue;
670 
671  // Compute the first point in the volume intersecting the ray
672  V3_BY_CT(v, P.direction, alpha_min);
673  V3_PLUS_V3(v, p1, v);
674 
675  // Compute the index of the first voxel
676  XX(idx) = CLIP(ROUND(XX(v)), x_0, x_F);
677  YY(idx) = CLIP(ROUND(YY(v)), y_0, y_F);
678  ZZ(idx) = CLIP(ROUND(ZZ(v)), z_0, z_F);
679 
680 
681 #ifdef DEBUG
682 
683  std::cout << "First voxel: " << v.transpose() << std::endl;
684  std::cout << " First index: " << idx.transpose() << std::endl;
685  std::cout << " Alpha_min: " << alpha_min << std::endl;
686 #endif
687 
688  // Follow the ray
689  double alpha = alpha_min;
690  do
691  {
692 #ifdef DEBUG
693  std::cout << " \n\nCurrent Value: " << V(ZZ(idx), YY(idx), XX(idx)) << std::endl;
694 #endif
695 
696  double alpha_x = (XX(idx) + half_x_sign - XX(p1)) / XX(P.direction);
697  double alpha_y = (YY(idx) + half_y_sign - YY(p1)) / YY(P.direction);
698  double alpha_z = (ZZ(idx) + half_z_sign - ZZ(p1)) / ZZ(P.direction);
699 
700  // Which dimension will ray move next step into?, it isn't necessary to be only
701  // one.
702  double diffx = ABS(alpha - alpha_x);
703  double diffy = ABS(alpha - alpha_y);
704  double diffz = ABS(alpha - alpha_z);
705 
706  double diff_alpha = fmin(fmin(diffx, diffy), diffz);
707 
708  A3D_ELEM(V, ZZ(idx), YY(idx), XX(idx)) += diff_alpha * A2D_ELEM(P(), i, j);
709 
710  if (ABS(diff_alpha - diffx) <= XMIPP_EQUAL_ACCURACY)
711  {
712  alpha = alpha_x;
713  XX(idx) += x_sign;
714  }
715  if (ABS(diff_alpha - diffy) <= XMIPP_EQUAL_ACCURACY)
716  {
717  alpha = alpha_y;
718  YY(idx) += y_sign;
719  }
720  if (ABS(diff_alpha - diffz) <= XMIPP_EQUAL_ACCURACY)
721  {
722  alpha = alpha_z;
723  ZZ(idx) += z_sign;
724  }
725 
726  }
727  while ((alpha_max - alpha) > XMIPP_EQUAL_ACCURACY);
728 #ifdef DEBUG
729 
730  std::cout << "Assigning P(" << i << "," << j << ")=" << ray_sum << std::endl;
731 #endif
732 
733  }
734 }
Matrix2D< double > eulert
#define A2D_ELEM(v, i, j)
double alpha
Smoothness parameter.
Definition: blobs.h:121
#define FINISHINGX(v)
#define FINISHINGZ(v)
#define STARTINGX(v)
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
#define STARTINGY(v)
#define CLIP(x, x0, xF)
Definition: xmipp_macros.h:260
#define A3D_ELEM(V, k, i, j)
#define V3_BY_CT(a, b, c)
Definition: matrix1d.h:238
#define XX(v)
Definition: matrix1d.h:85
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
#define ABS(x)
Definition: xmipp_macros.h:142
#define ROUND(x)
Definition: xmipp_macros.h:210
Matrix1D< double > direction
#define j
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
#define YY(v)
Definition: matrix1d.h:93
#define FINISHINGY(v)
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
double fmax
#define SGN(x)
Definition: xmipp_macros.h:155
#define STARTINGZ(v)
#define ZZ(v)
Definition: matrix1d.h:101
#define V3_PLUS_V3(a, b, c)
Definition: matrix1d.h:190
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403

Variable Documentation

◆ ART_PIXEL_SUBSAMPLING

const int ART_PIXEL_SUBSAMPLING = 2

Definition at line 296 of file projection.h.

◆ ARTK

constexpr int ARTK = 1

Definition at line 177 of file projection.h.

◆ BACKWARD

constexpr int BACKWARD = 0

Definition at line 175 of file projection.h.

◆ CAV

constexpr int CAV = 4

Definition at line 180 of file projection.h.

◆ CAVARTK

constexpr int CAVARTK = 5

Definition at line 181 of file projection.h.

◆ CAVK

constexpr int CAVK = 2

Definition at line 178 of file projection.h.

◆ COUNT_EQ

constexpr int COUNT_EQ = 3

Definition at line 179 of file projection.h.

◆ FORWARD

constexpr int FORWARD = 1

Definition at line 174 of file projection.h.

◆ project_barrier

barrier_t project_barrier

Definition at line 46 of file projection.cpp.

◆ project_mutex

pthread_mutex_t project_mutex

Definition at line 47 of file projection.cpp.

◆ project_threads

project_thread_params* project_threads

Definition at line 48 of file projection.cpp.