Xmipp  v3.23.11-Nereus
Classes | Macros | Functions | Variables
Collaboration diagram for Blobs:

Classes

struct  blobtype
 

Macros

#define blob_val(r, blob)   kaiser_value(r, blob.radius, blob.alpha, blob.order)
 
#define blob_proj(r, blob)   kaiser_proj(r, blob.radius, blob.alpha, blob.order)
 
#define blob_Fourier_val(w, blob)   kaiser_Fourier_value(w, blob.radius, blob.alpha, blob.order)
 
#define blob_mass(blob)   basvolume(blob.radius, blob.alpha, blob.order,3)
 

Functions

double kaiser_value (double r, double a, double alpha, int m)
 
double kaiser_proj (double r, double a, double alpha, int m)
 
double kaiser_Fourier_value (double w, double a, double alpha, int m)
 
double basvolume (double a, double alpha, int m, int n)
 
double in_zeroarg (int n)
 
double inph_zeroarg (int n)
 
double i_nph (int n, double x)
 
double i_n (int n, double x)
 
double blob_freq_zero (struct blobtype b)
 
double blob_att (double w, struct blobtype b)
 
double blob_ops (double w, struct blobtype b)
 
double optimal_CC_grid_relative_size (struct blobtype b)
 
double optimal_BCC_grid_relative_size (struct blobtype b)
 
double optimal_FCC_grid_relative_size (struct blobtype b)
 
blobtype best_blob (double alpha_0, double alpha_F, double inc_alpha, double a_0, double a_F, double inc_a, double w, double *target_att, int target_length=1)
 
void footprint_blob (ImageOver &blobprint, const struct blobtype &blob, int istep=50, int normalise=0)
 
double sum_blob_Grid (const struct blobtype &blob, const Grid &grid, const Matrix2D< double > *D=nullptr)
 
void voxel_volume_shape (const GridVolume &vol_blobs, const struct blobtype &blob, const Matrix2D< double > *D, Matrix1D< int > &corner1, Matrix1D< int > &size)
 
void blobs2voxels (const GridVolume &vol_blobs, const struct blobtype &blob, MultidimArray< double > *vol_voxels, const Matrix2D< double > *D=nullptr, int threads=1, int Zdim=0, int Ydim=0, int Xdim=0)
 
void blobs2space_coefficients (const GridVolume &vol_blobs, const struct blobtype &blob, MultidimArray< double > *vol_coefs)
 
void voxels2blobs (const MultidimArray< double > *vol_voxels, const struct blobtype &blob, GridVolume &vol_blobs, int grid_type, double grid_relative_size, double lambda, const MultidimArray< double > *vol_mask=nullptr, const Matrix2D< double > *D=nullptr, double final_error_change=0.01, int tell=0, double R=-1, int threads=1)
 
void ART_voxels2blobs_single_step (GridVolume &vol_in, GridVolume *vol_out, const struct blobtype &blob, const Matrix2D< double > *D, double lambda, MultidimArray< double > *theo_vol, const MultidimArray< double > *read_vol, MultidimArray< double > *corr_vol, const MultidimArray< double > *mask_vol, double &mean_error, double &max_error, int eq_mode=VARTK, int threads=1)
 

Variables

constexpr int SHOW_CONVERSION = 1
 
constexpr int VARTK = 1
 
constexpr int VMAXARTK = 2
 

Detailed Description

Macro Definition Documentation

◆ blob_Fourier_val

#define blob_Fourier_val (   w,
  blob 
)    kaiser_Fourier_value(w, blob.radius, blob.alpha, blob.order)

Fourier transform of a blob. This function returns the value of the Fourier transform of the blob at a given frequency (w). This frequency must be normalized by the sampling rate. For instance, for computing the Fourier Transform of a blob at 1/Ts (Ts in Amstrongs) you must provide the frequency Tm/Ts, where Tm is the sampling rate.

The Fourier Transform can be computed only for blobs with m=2 or m=0.

Definition at line 174 of file blobs.h.

◆ blob_mass

#define blob_mass (   blob)    basvolume(blob.radius, blob.alpha, blob.order,3)

Formula for a volume integral of a blob (n is the blob dimension)

Definition at line 181 of file blobs.h.

◆ blob_proj

#define blob_proj (   r,
  blob 
)    kaiser_proj(r, blob.radius, blob.alpha, blob.order)

Blob projection. This function returns the value of the blob line integral through a straight line which passes at a distance 'r' (in Universal System units) from the center of the blob. Remember that a blob is spherically symmetrycal so the only parameter to know this blob line integral is its distance to the center of the blob. It doesn't matter if this distance is larger than the real blob spatial extension, in this case the function returns 0. \ Ex:

struct blobtype blob; blob.radius = 2; blob.order = 2; blob.alpha = 3.6;
std::cout << "Blob line integral through (1,1,1) = " << blob_proj(v.mod(),blob)
<< std::endl;

Definition at line 161 of file blobs.h.

◆ blob_val

#define blob_val (   r,
  blob 
)    kaiser_value(r, blob.radius, blob.alpha, blob.order)

Blob value. This function returns the value of a blob at a given distance from its center (in Universal System units). The distance must be always positive. Remember that a blob is spherically symmetrycal so the only parameter to know the blob value at a point is its distance to the center of the blob. It doesn't matter if this distance is larger than the real blob spatial extension, in this case the function returns 0 as blob value. \ Ex:

struct blobtype blob; blob.radius = 2; blob.order = 2; blob.alpha = 3.6;
std::cout << "Blob value at (1,1,1) = " << blob_val(v.mod(),blob) << std::endl;

Definition at line 139 of file blobs.h.

Function Documentation

◆ ART_voxels2blobs_single_step()

void ART_voxels2blobs_single_step ( GridVolume vol_in,
GridVolume vol_out,
const struct blobtype blob,
const Matrix2D< double > *  D,
double  lambda,
MultidimArray< double > *  theo_vol,
const MultidimArray< double > *  read_vol,
MultidimArray< double > *  corr_vol,
const MultidimArray< double > *  mask_vol,
double &  mean_error,
double &  max_error,
int  eq_mode = VARTK,
int  threads = 1 
)

Voxels —> Blobs, single step. This is the basic step of the voxels to blobs conversion. It applies an ART step to the blob volume and produces its output in a different (or the same) volume. You must provide the blob structure, lambda and deformation matrix (typical for crystals). The theoretical volume and correction volume are resized inside and are output volumes meaning the conversion from blobs to voxels before this step and the correction applied to the blob volume. The read volume is the one to reproduce with blobs and the mask volume is used to select only one region to adjust.

If the mask is NULL then it is assumed that all voxels in the input voxel volume must be adjusted by the blobs. If the input voxel volume is NULL the it is assumed that it is equal to 0 and only those corresponding to the 1 positions within the mask must be adjusted. An exception is thrown if the mask and voxels volume are both NULL.

Then mean and maximum error committed for each blob are returned.

Valid eq_modes are \VARTK: ART by blocks for volumes. \VMAXARTK: update with the maximum update.

Definition at line 1094 of file blobs.cpp.

1111 {
1112 
1113  // Resize output volumes ................................................
1114  if (read_vol != nullptr)
1115  {
1116  (*theo_vol).initZeros(*read_vol);
1117  }
1118  else if (mask_vol != nullptr)
1119  {
1120  (*theo_vol).initZeros(*mask_vol);
1121  }
1122  else
1123  {
1125  "ART_voxels2blobs_single_step: Mask and voxel volumes are empty");
1126  }
1127  (*corr_vol).initZeros(*theo_vol);
1128 
1129  auto * th_ids = (pthread_t *)malloc( threads * sizeof( pthread_t));
1130  auto * threads_d = (ThreadBlobsToVoxels *) malloc ( threads * sizeof( ThreadBlobsToVoxels ) );
1131 
1132  // Translate actual blob volume to voxels ...............................
1133  for (size_t i = 0; i < vol_in.VolumesNo(); i++)
1134  {
1135  int min_distance = (int)ceil((2*(vol_in.grid(i)).relative_size ) / blob.radius ) + 1;
1136 
1137  slices_status = new int[(int)(ZZ(vol_in.grid(i).highest)-ZZ(vol_in.grid(i).lowest)+1)]();
1138  slices_processed = 0;
1139 
1140  for( int c = 0 ; c < threads ; c++ )
1141  {
1142  threads_d[c].vol_blobs = &(vol_in(i)());
1143  threads_d[c].grid = &(vol_in.grid(i));
1144  threads_d[c].blob = &blob;
1145  threads_d[c].vol_voxels = theo_vol;
1146  threads_d[c].D = D;
1147  threads_d[c].istep = 50;
1148  threads_d[c].vol_corr = corr_vol;
1149  threads_d[c].vol_mask = mask_vol;
1150  threads_d[c].FORW = true;
1151  threads_d[c].eq_mode = eq_mode;
1152  threads_d[c].thread_id = c;
1153  threads_d[c].threads_num = threads;
1154  threads_d[c].min_separation = min_distance;
1155 
1156  pthread_create( (th_ids+c), nullptr, blobs2voxels_SimpleGrid, (void *)(threads_d+c) );
1157  }
1158 
1159  // Wait for threads to finish
1160  for( int c = 0 ; c < threads ; c++ )
1161  {
1162  pthread_join(*(th_ids+c),nullptr);
1163  }
1164 
1165  delete[] slices_status;
1166  // blobs2voxels_SimpleGrid(vol_in(i)(), vol_in.grid(i), blob, theo_vol, D,
1167  // 50, corr_vol, mask_vol, FORWARD, eq_mode);
1168 #ifdef DEBUG
1169 
1170  std::cout << "Blob grid no " << i << " stats: ";
1171  vol_in(i)().printStats();
1172  std::cout << std::endl;
1173  std::cout << "So far vol stats: ";
1174  (*theo_vol)().printStats();
1175  std::cout << std::endl;
1176 #endif
1177 
1178  }
1179 
1180  // Now normalise the resulting volume ..................................
1181  double norm = sum_blob_Grid(blob, vol_in.grid(), D); // Aqui tambien hay que multiplicar ****!!!!
1182  FOR_ALL_ELEMENTS_IN_ARRAY3D(*theo_vol)
1183  A3D_ELEM(*theo_vol, k, i, j) /= norm;
1184 
1185 #ifdef DEBUG
1186 
1187  Image<double> save, save2;
1188  save() = *theo_vol;
1189  save.write("PPPtheovol.vol");
1190  std::cout << "Theo stats:";
1191  save().printStats();
1192  std::cout << std::endl;
1193  save() = *corr_vol;
1194  save.write("PPPcorr2vol.vol");
1195  save2().resize(save());
1196 #endif
1197 
1198  // Compute differences ..................................................
1199  mean_error = 0;
1200  double read_val;
1201  if (read_vol != nullptr)
1202  read_val = A3D_ELEM(*read_vol, 0, 0, 0);
1203  else
1204  read_val = 0;
1205  max_error = ABS(read_val - A3D_ELEM(*theo_vol, 0, 0, 0));
1206 
1207  double diff;
1208  int N = 0;
1209  FOR_ALL_ELEMENTS_IN_ARRAY3D(*theo_vol)
1210  {
1211  // Compute difference volume and error
1212  if (read_vol != nullptr)
1213  read_val = A3D_ELEM(*read_vol, k, i, j);
1214  else
1215  read_val = 0;
1216 
1217  if (mask_vol == nullptr)
1218  {
1219  diff = read_val - A3D_ELEM(*theo_vol, k, i, j);
1220  N++;
1221  }
1222  else
1223  if (A3D_ELEM(*mask_vol, k, i, j) == 1)
1224  {
1225  diff = read_val - A3D_ELEM(*theo_vol, k, i, j);
1226  N++;
1227  }
1228  else
1229  diff = 0;
1230 
1231  max_error = XMIPP_MAX(max_error, ABS(diff));
1232  mean_error += diff * diff;
1233 #ifdef DEBUG
1234 
1235  save(k, i, j) = diff;
1236  save2(k, i, j) = read_val;
1237 #endif
1238 
1239 
1240  // Compute the correction volume
1241  if (ABS(A3D_ELEM(*corr_vol, k, i, j)) < 1e-2)
1242  A3D_ELEM(*corr_vol, k, i, j) = SGN(A3D_ELEM(*corr_vol, k, i, j));
1243  A3D_ELEM(*corr_vol, k, i, j) =
1244  lambda * diff / A3D_ELEM(*corr_vol, k, i, j);
1245  }
1246 #ifdef DEBUG
1247  save.write("PPPdiffvol.vol");
1248  std::cout << "Diff stats:";
1249  save().printStats();
1250  std::cout << std::endl;
1251  save2.write("PPPreadvol.vol");
1252  std::cout << "Read stats:";
1253  save2().printStats();
1254  std::cout << std::endl;
1255  save() = *corr_vol;
1256  save.write("PPPcorrvol.vol");
1257  std::cout << "Corr stats:";
1258  save().printStats();
1259  std::cout << std::endl;
1260 #endif
1261 
1262  mean_error /= XMIPP_MAX(N, 1); // At worst, divided by 1
1263 
1264  // Backprojection of correction volume ..................................
1265  for (size_t i = 0; i < vol_in.VolumesNo(); i++)
1266  {
1267  slices_status = new int[(int)(ZZ(vol_out->grid(i).highest)-ZZ(vol_out->grid(i).lowest)+1)]();
1268  slices_processed = 0;
1269 
1270  for( int c = 0 ; c < threads ; c++ )
1271  {
1272  threads_d[c].vol_blobs = &((*vol_out)(i)());
1273  threads_d[c].grid = &(vol_out->grid(i));
1274  threads_d[c].blob = &blob;
1275  threads_d[c].vol_voxels = theo_vol;
1276  threads_d[c].D = D;
1277  threads_d[c].istep = 50;
1278  threads_d[c].vol_corr = corr_vol;
1279  threads_d[c].vol_mask = mask_vol;
1280  threads_d[c].FORW = false;
1281  threads_d[c].eq_mode = eq_mode;
1282  threads_d[c].thread_id = c;
1283  threads_d[c].threads_num = threads;
1284  threads_d[c].min_separation = 1;
1285 
1286  pthread_create( (th_ids+c), nullptr, blobs2voxels_SimpleGrid, (void *)(threads_d+c) );
1287  }
1288 
1289  // Wait for threads to finish
1290  for( int c = 0 ; c < threads ; c++ )
1291  {
1292  pthread_join(*(th_ids+c), nullptr);
1293  }
1294  delete[] slices_status;
1295  // blobs2voxels_SimpleGrid((*vol_out)(i)(), (*vol_out).grid(i), blob,
1296  // theo_vol, D, 50, corr_vol, mask_vol, BACKWARD, eq_mode);
1297 #ifdef DEBUG
1298 
1299  std::cout << "Blob grid no " << i << " stats: ";
1300  vol_in(i)().printStats();
1301  std::cout << std::endl;
1302 #endif
1303 
1304  }
1305  free(threads_d);
1306  free(th_ids);
1307 #ifdef DEBUG
1308  char c;
1309  std::cout << "Press any key to continue\n";
1310  std::cin >> c;
1311 #endif
1312 }
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
Matrix1D< double > highest
Definition: grids.h:161
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
doublereal * c
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)
The matrix is empty.
Definition: xmipp_error.h:151
T norm(const std::vector< T > &v)
Definition: vector_ops.h:399
Matrix1D< double > lowest
Definition: grids.h:158
#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
int * slices_status
Definition: blobs.cpp:33
#define A3D_ELEM(V, k, i, j)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
size_t VolumesNo() const
Definition: grids.h:1003
double sum_blob_Grid(const struct blobtype &blob, const Grid &grid, const Matrix2D< double > *D)
Definition: blobs.cpp:320
double * lambda
#define ABS(x)
Definition: xmipp_macros.h:142
free((char *) ob)
#define j
const SimpleGrid & grid(size_t n) const
Definition: grids.h:978
int slices_processed
Definition: blobs.cpp:34
#define SGN(x)
Definition: xmipp_macros.h:155
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
#define ZZ(v)
Definition: matrix1d.h:101
void * blobs2voxels_SimpleGrid(void *data)
Definition: blobs.cpp:452

◆ basvolume()

double basvolume ( double  a,
double  alpha,
int  m,
int  n 
)

Function actually computing the blob integral

Definition at line 215 of file blobs.cpp.

216 {
217  double hn;
218  double tpi;
219  double v;
220  hn = 0.5 * n;
221  tpi = 2.0 * PI;
222 
223  if (alpha == 0.0)
224  {
225  if ((n / 2)*2 == n) /* n even */
226  v = pow(tpi, hn) * in_zeroarg(n / 2 + m) / in_zeroarg(m);
227  else /* n odd */
228  v = pow(tpi, hn) * inph_zeroarg(n / 2 + m) / in_zeroarg(m);
229 
230  }
231  else
232  { /* alpha > 0.0 */
233  if ((n / 2)*2 == n) /* n even */
234  v = pow(tpi / alpha, hn) * i_n(n / 2 + m, alpha) / i_n(m, alpha);
235  else /* n odd */
236  v = pow(tpi / alpha, hn) * i_nph(n / 2 + m, alpha) / i_n(m, alpha);
237  }
238 
239  return v * pow(a, (double)n);
240 }
double alpha
Smoothness parameter.
Definition: blobs.h:121
double i_nph(int n, double x)
Definition: blobs.cpp:270
int m
double i_n(int n, double x)
Definition: blobs.cpp:244
double in_zeroarg(int n)
Definition: blobs.cpp:294
double inph_zeroarg(int n)
Definition: blobs.cpp:307
#define PI
Definition: tools.h:43
int * n
doublereal * a

◆ best_blob()

blobtype best_blob ( double  alpha_0,
double  alpha_F,
double  inc_alpha,
double  a_0,
double  a_F,
double  inc_a,
double  w,
double *  target_att,
int  target_length = 1 
)

Choose the best blob within a region. You must select a resolution limit, the maximum attenuation allowed at that frequency and then the blob with less computational cost is returned. m=2 always. The resolution criterion is given by w (remind that this w=Tm*w(cont)).

If there is no blob meeting the specification then alpha=a=-1.

Definition at line 363 of file blobs.cpp.

366 {
367  blobtype retval;
368  retval.order = 2;
369  int alpha_size = FLOOR((alpha_F - alpha_0) / inc_alpha + 1);
370  int a_size = FLOOR((a_F - a_0) / inc_a + 1);
371  Image<double> att;
372  Image<double> ops;
373  att().resize(alpha_size, a_size);
374  ops().resize(alpha_size, a_size);
375  int i;
376  int j;
377  double a;
378  double alpha;
379  double best_a = -1;
380  double best_alpha = -1;
381  double best_ops = 1e10;
382  double best_att = 0;
383  for (i = 0, alpha = alpha_0; i < alpha_size; alpha += inc_alpha, i++)
384  for (j = 0, a = a_0; j < a_size; a += inc_a, j++)
385  {
386  retval.radius = a;
387  retval.alpha = alpha;
388  A2D_ELEM(att(), i, j) = blob_att(w, retval);
389  A2D_ELEM(ops(), i, j) = blob_ops(w, retval);
390  if (j > 0)
391  for (int n = target_length - 1; n >= 0; n--)
392  if (A2D_ELEM(att(), i, j - 1) > target_att[n] &&
393  A2D_ELEM(att(), i, j) < target_att[n])
394  {
395  A2D_ELEM(att(), i, j) = 0;
396  if (A2D_ELEM(ops(), i, j - 1) < best_ops &&
397  A2D_ELEM(att(), i, j - 1) >= best_att)
398  {
399  best_alpha = alpha;
400  best_a = a - inc_a;
401  best_ops = A2D_ELEM(ops(), i, j - 1);
402  best_att = target_att[n];
403  }
404  }
405  }
406 #ifdef DEBUG
407  att.write((std::string)"att" + floatToString(w) + ".xmp");
408  ops.write((std::string)"ops" + floatToString(w) + ".xmp");
409 #endif
410 
411  retval.radius = best_a;
412  retval.alpha = best_alpha;
413  return retval;
414 }
#define A2D_ELEM(v, i, j)
double alpha
Smoothness parameter.
Definition: blobs.h:121
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)
doublereal * w
String floatToString(float F, int _width, int _prec)
#define i
#define FLOOR(x)
Definition: xmipp_macros.h:240
double blob_ops(double w, struct blobtype b)
Definition: blobs.cpp:342
double blob_att(double w, struct blobtype b)
Definition: blobs.cpp:336
#define j
int order
Derivation order and Bessel function order.
Definition: blobs.h:118
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
int * n
doublereal * a

◆ blob_att()

double blob_att ( double  w,
struct blobtype  b 
)

Attenuation of a blob. The Fourier transform of the blob at w is the Fourier transform at w=0 multiplied by the attenuation. This is the value returned. Remind that the frequency must be normalized by the sampling rate. Ie, Tm*w(cont)

Definition at line 336 of file blobs.cpp.

337 {
338  return blob_Fourier_val(w, b) / blob_Fourier_val(0, b);
339 }
doublereal * w
#define blob_Fourier_val(w, blob)
Definition: blobs.h:174

◆ blob_freq_zero()

double blob_freq_zero ( struct blobtype  b)

Blob pole. This is the normalized frequency at which the blob goes to 0.

Definition at line 330 of file blobs.cpp.

331 {
332  return sqrt(b.alpha*b.alpha + 6.9879*6.9879) / (2*PI*b.radius);
333 }
double alpha
Smoothness parameter.
Definition: blobs.h:121
void sqrt(Image< double > &op)
#define PI
Definition: tools.h:43
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115

◆ blob_ops()

double blob_ops ( double  w,
struct blobtype  b 
)

Number of operations for a blob. This is a number proportional to the number of operations that ART would need to make a reconstruction with this blob.

Definition at line 342 of file blobs.cpp.

343 {
344  return pow(b.alpha*b.alpha + 6.9879*6.9879, 1.5) / b.radius;
345 }
double alpha
Smoothness parameter.
Definition: blobs.h:121
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115

◆ blobs2space_coefficients()

void blobs2space_coefficients ( const GridVolume vol_blobs,
const struct blobtype blob,
MultidimArray< double > *  vol_coefs 
)

Blob coefficients as a voxel volume. This function returns a volume with the blob coefficients in their right position in space. The voxel size is g/2

Definition at line 1029 of file blobs.cpp.

1031 {
1032 
1033  // Compute vol_coefs shape
1034  Matrix1D<int> corner1;
1035  Matrix1D<int> size;
1036  voxel_volume_shape(vol_blobs, blob, nullptr, corner1, size);
1037  double g_2 = vol_blobs.grid(0).relative_size / 2;
1038  XX(corner1) = (int)(FLOOR(XX(corner1)) / g_2);
1039  XX(size) = (int)(CEIL(XX(size)) / g_2);
1040  YY(corner1) = (int)(FLOOR(YY(corner1)) / g_2);
1041  YY(size) = (int)(CEIL(YY(size)) / g_2);
1042  ZZ(corner1) = (int)(FLOOR(ZZ(corner1)) / g_2);
1043  ZZ(size) = (int)(CEIL(ZZ(size)) / g_2);
1044  (*vol_coefs).initZeros(ZZ(size), YY(size), XX(size));
1045  STARTINGX(*vol_coefs) = XX(corner1);
1046  STARTINGY(*vol_coefs) = YY(corner1);
1047  STARTINGZ(*vol_coefs) = ZZ(corner1);
1048 
1049  // Set all blob coefficients at the right position
1050  for (size_t n = 0; n < vol_blobs.VolumesNo(); n++)
1051  {
1052  auto ZZ_lowest = (int)ZZ(vol_blobs.grid(n).lowest);
1053  auto YY_lowest = (int)YY(vol_blobs.grid(n).lowest);
1054  auto XX_lowest = (int)XX(vol_blobs.grid(n).lowest);
1055  auto ZZ_highest = (int)ZZ(vol_blobs.grid(n).highest);
1056  auto YY_highest = (int)YY(vol_blobs.grid(n).highest);
1057  auto XX_highest = (int)XX(vol_blobs.grid(n).highest);
1058  for (int k = ZZ_lowest; k <= ZZ_highest; k++)
1059  for (int i = YY_lowest; i <= YY_highest; i++)
1060  for (int j = XX_lowest; j <= XX_highest; j++)
1061  {
1062  Matrix1D<double> grid_index(3);
1063  Matrix1D<double> univ_position(3),
1064  coef_position(3);
1065  VECTOR_R3(grid_index, j, i, k);
1066  vol_blobs.grid(n).grid2universe(grid_index, univ_position);
1067  V3_BY_CT(coef_position, univ_position, 1.0 / g_2);
1068  A3D_ELEM((*vol_coefs),
1069  (int)ZZ(coef_position),
1070  (int)YY(coef_position),
1071  (int)XX(coef_position) ) = A3D_ELEM(vol_blobs(n)(), k, i, j);
1072 #ifdef DEBUG
1073 
1074  std::cout << "Blob value at (" << j << "," << i << ","
1075  << k << ") (" << XX(univ_position)
1076  << "," << YY(univ_position) << ","
1077  << ZZ(univ_position) << ") ("
1078  << XX(coef_position) << "," << YY(coef_position) << ","
1079  << ZZ(coef_position) << ") --> "
1080  << A3D_ELEM(vol_blobs(n)(), (int)k, (int)i, (int)j) << std::endl;
1081 #endif
1082 
1083  }
1084  }
1085 }
void voxel_volume_shape(const GridVolume &vol_blobs, const struct blobtype &blob, const Matrix2D< double > *D, Matrix1D< int > &corner1, Matrix1D< int > &size)
Definition: blobs.cpp:851
Matrix1D< double > highest
Definition: grids.h:161
void grid2universe(const Matrix1D< double > &gv, Matrix1D< double > &uv) const
Definition: grids.h:318
Matrix1D< double > lowest
Definition: grids.h:158
#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
#define STARTINGY(v)
#define A3D_ELEM(V, k, i, j)
#define V3_BY_CT(a, b, c)
Definition: matrix1d.h:238
size_t VolumesNo() const
Definition: grids.h:1003
#define FLOOR(x)
Definition: xmipp_macros.h:240
#define XX(v)
Definition: matrix1d.h:85
#define CEIL(x)
Definition: xmipp_macros.h:225
double relative_size
Measuring unit in the grid coordinate system.
Definition: grids.h:163
#define j
#define YY(v)
Definition: matrix1d.h:93
const SimpleGrid & grid(size_t n) const
Definition: grids.h:978
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
#define STARTINGZ(v)
int * n
#define ZZ(v)
Definition: matrix1d.h:101

◆ blobs2voxels()

void blobs2voxels ( const GridVolume vol_blobs,
const struct blobtype blob,
MultidimArray< double > *  vol_voxels,
const Matrix2D< double > *  D = nullptr,
int  threads = 1,
int  Zdim = 0,
int  Ydim = 0,
int  Xdim = 0 
)

Blobs —> Voxels. The voxel size is defined between two coordinates (Gcorner1 and Gcorner2) which accomplish

XX(Gcorner1)=MIN(XX(SGcorner1(i)));
YY(Gcorner1)=MIN(YY(SGcorner1(i)));
ZZ(Gcorner1)=MIN(ZZ(SGcorner1(i)));
XX(Gcorner2)=MAX(XX(SGcorner2(i)));
YY(Gcorner2)=MAX(YY(SGcorner2(i)));
ZZ(Gcorner2)=MAX(ZZ(SGcorner2(i)));

where SGcorner1(i) and SGcorner2(i) are the lowest and highest corners of each subgrid. These corners are expressed in Universal coordinates.

This quantity is then enlarged to be an integer voxel position and to take into account that the former computed Gcorner1 and 2 are the furthest centers of blobs, ie, there will be voxels even further affected by these blobs.

Gcorner1 = CEILnD (Gcorner1 - blob.radius);
Gcorner2 = FLOORnD(Gcorner2 + blob.radius);

However, you might give a size, usually set to 0, i.e., no external size. If no size is provided a size is produced such that all blob centers fit into the output volume.

D is a 3x3 matrix specifying a volume deformation. It means that the sample at logical position (i,j,k) is really placed at space position D*(i,j,k)'.

Definition at line 926 of file blobs.cpp.

929 {
930 
931  // Resize and set starting corner .......................................
932  if (Zdim == 0 || Ydim == 0 || Xdim == 0)
933  {
934  Matrix1D<int> size;
935  Matrix1D<int> corner;
936  voxel_volume_shape(vol_blobs, blob, D, corner, size);
937  (*vol_voxels).initZeros(ZZ(size), YY(size), XX(size));
938  STARTINGX(*vol_voxels) = XX(corner);
939  STARTINGY(*vol_voxels) = YY(corner);
940  STARTINGZ(*vol_voxels) = ZZ(corner);
941  }
942  else
943  {
944  (*vol_voxels).initZeros(Zdim, Ydim, Xdim);
945  (*vol_voxels).setXmippOrigin();
946  }
947 
948  auto * th_ids = new pthread_t [threads];
949  auto * threads_d = new ThreadBlobsToVoxels [threads];
950 
951  // Convert each subvolume ...............................................
952  for (size_t i = 0; i < vol_blobs.VolumesNo(); i++)
953  {
954  int min_distance = (int)ceil((2*(vol_blobs.grid(i)).relative_size ) / blob.radius ) + 1;
955  slices_status = new int[(int)(ZZ(vol_blobs.grid(i).highest)-ZZ(vol_blobs.grid(i).lowest)+1)]();
956  slices_processed = 0;
957 
958  for( int c = 0 ; c < threads ; c++ )
959  {
960  threads_d[c].vol_blobs = &(vol_blobs(i)());
961  threads_d[c].grid = &(vol_blobs.grid(i));
962  threads_d[c].blob = &blob;
963  threads_d[c].vol_voxels = vol_voxels;
964  threads_d[c].D = D;
965  threads_d[c].istep = 50;
966  threads_d[c].vol_corr = nullptr;
967  threads_d[c].vol_mask = nullptr;
968  threads_d[c].FORW = true;
969  threads_d[c].eq_mode = VARTK;
970  threads_d[c].thread_id = c;
971  threads_d[c].threads_num = threads;
972  threads_d[c].min_separation = min_distance;
973 
974  pthread_create( (th_ids+c), nullptr, blobs2voxels_SimpleGrid, (void *)(threads_d+c) );
975  }
976 
977  // Wait for threads to finish
978  for( int c = 0 ; c < threads ; c++ )
979  {
980  pthread_join(*(th_ids+c),nullptr);
981  }
982 
983 #ifdef DEBUG
984  std::cout << "Blob grid no " << i << " stats: ";
985  vol_blobs(i)().printStats();
986  std::cout << std::endl;
987  std::cout << "So far vol stats: ";
988  (*vol_voxels).printStats();
989  std::cout << std::endl;
990  Image<double> save;
991  save() = *vol_voxels;
992  save.write((std::string)"PPPvoxels" + integerToString(i));
993 #endif
994 
995  delete[] slices_status;
996  }
997 
998  // Now normalise the resulting volume ..................................
999  double inorm = 1.0 / sum_blob_Grid(blob, vol_blobs.grid(), D); // Aqui tambien hay que multiplicar ****!!!!
1000  FOR_ALL_ELEMENTS_IN_ARRAY3D(*vol_voxels)
1001  A3D_ELEM(*vol_voxels, k, i, j) *= inorm;
1002 
1003  // Set voxels outside interest region to minimum value .................
1004  double R = vol_blobs.grid(0).get_interest_radius();
1005  if (R != -1)
1006  {
1007  double R2 = (R - 6) * (R - 6);
1008 
1009  // Compute minimum value within sphere
1010  double min_val = A3D_ELEM(*vol_voxels, 0, 0, 0);
1011  FOR_ALL_ELEMENTS_IN_ARRAY3D(*vol_voxels)
1012  if (j*j + i*i + k*k <= R2 - 4)
1013  min_val = XMIPP_MIN(min_val, A3D_ELEM(*vol_voxels, k, i, j));
1014 
1015  // Substitute minimum value
1016  R2 = (R - 2) * (R - 2);
1017  FOR_ALL_ELEMENTS_IN_ARRAY3D(*vol_voxels)
1018  if (j*j + i*i + k*k >= R2)
1019  A3D_ELEM(*vol_voxels, k, i, j) = min_val;
1020  }
1021 
1022  delete[] th_ids;
1023  delete[] threads_d;
1024 }
void voxel_volume_shape(const GridVolume &vol_blobs, const struct blobtype &blob, const Matrix2D< double > *D, Matrix1D< int > &corner1, Matrix1D< int > &size)
Definition: blobs.cpp:851
Matrix1D< double > highest
Definition: grids.h:161
doublereal * c
constexpr int VARTK
Definition: blobs.h:378
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)
String integerToString(int I, int _width, char fill_with)
Matrix1D< double > lowest
Definition: grids.h:158
#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
int * slices_status
Definition: blobs.cpp:33
#define STARTINGY(v)
#define A3D_ELEM(V, k, i, j)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
size_t VolumesNo() const
Definition: grids.h:1003
double sum_blob_Grid(const struct blobtype &blob, const Grid &grid, const Matrix2D< double > *D)
Definition: blobs.cpp:320
#define XX(v)
Definition: matrix1d.h:85
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
#define YY(v)
Definition: matrix1d.h:93
const SimpleGrid & grid(size_t n) const
Definition: grids.h:978
int slices_processed
Definition: blobs.cpp:34
double get_interest_radius() const
Get reconstruction radius.
Definition: grids.h:268
#define STARTINGZ(v)
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
#define ZZ(v)
Definition: matrix1d.h:101
void * blobs2voxels_SimpleGrid(void *data)
Definition: blobs.cpp:452

◆ footprint_blob()

void footprint_blob ( ImageOver blobprint,
const struct blobtype blob,
int  istep = 50,
int  normalise = 0 
)

Footprint of a blob. In the actual implementation of the 3D reconstruction one of the most important things to save time is to have a precomputed blob projection. As it is spherically symmetrical all projections from different directions of the same blob happen to be the same. This function makes this precalculation storing it in an oversampled image. This is done so because the blob footprint might not be centered with respect to the universal grid needing so, the footprint at non-integer positions. As parameters to this function you may give the sampling rate in each direction, and an optional normalisation (usually disabled) at the end of the computation which divides the whole image by the sum of the whole image. \ Ex:

ImageOver blobprint;
struct blobtype blob;
blob.radius = 1.7;
blob.order = 2;
blob.alpha = 3.6;
footprint_blob(blobprint, blob);

As the blob radius is 1.7, the function will create a normalised footprint of logical corners (-2,-2) to (2,2) (in the universal coord. system) (this size is the minimum integer number of pixels which contain entirely the blob), with 50 samples each pixel. The real size of the footprint is (550)x(550).

Definition at line 417 of file blobs.cpp.

424 {
425  // Resize output image and redefine the origin of it
426  int footmax = CEIL(blob.radius);
427  blobprint.init(-footmax, footmax, istep, -footmax, footmax, istep);
428 
429  // Run for Imge class indexes
430  for (int i = STARTINGY(blobprint()); i <= FINISHINGY(blobprint()); i++)
431  for (int j = STARTINGX(blobprint()); j <= FINISHINGX(blobprint()); j++)
432  {
433  // Compute oversampled index and blob value
434  double vi;
435  double ui;
436  IMG2OVER(blobprint, i, j, vi, ui);
437  double r = sqrt(vi * vi + ui * ui);
438  IMGPIXEL(blobprint, i, j) = blob_proj(r, blob);
439  }
440 
441  // Adjust the footprint structure
442  if (normalise)
443  blobprint() /= blobprint().sum();
444 }
#define FINISHINGX(v)
void init(int _umin, int _umax, int _uistep, int _vmin, int _vmax, int _vistep, int _wmin=0, int _wmax=0, int _wistep=1)
void sqrt(Image< double > &op)
#define STARTINGX(v)
#define i
#define STARTINGY(v)
#define CEIL(x)
Definition: xmipp_macros.h:225
#define IMG2OVER(IO, iv, iu, v, u)
#define j
#define FINISHINGY(v)
#define blob_proj(r, blob)
Definition: blobs.h:161
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
#define IMGPIXEL(I, i, j)

◆ i_n()

double i_n ( int  n,
double  x 
)

Bessel function I_n (x), n = 0, 1, 2, ... Use ONLY for small values of n

Definition at line 244 of file blobs.cpp.

245 {
246  int i;
247  double i_ns1;
248  double i_n;
249  double i_np1;
250 
251  if (n == 0)
252  return bessi0(x);
253  if (n == 1)
254  return bessi1(x);
255  if (x == 0.0)
256  return 0.0;
257  i_ns1 = bessi0(x);
258  i_n = bessi1(x);
259 
260  for (i = 1; i < n; i++)
261  {
262  i_np1 = i_ns1 - (2 * i) / x * i_n;
263  i_ns1 = i_n;
264  i_n = i_np1;
265  }
266  return i_n;
267 }
__device__ float bessi1(float x)
doublereal * x
#define i
__device__ float bessi0(float x)
double i_n(int n, double x)
Definition: blobs.cpp:244
int * n

◆ i_nph()

double i_nph ( int  n,
double  x 
)

Bessel function I_(n+1/2) (x), n = 0, 1, 2, ...

Definition at line 270 of file blobs.cpp.

271 {
272  int i;
273  double r2dpix;
274  double i_ns1;
275  double i_n;
276  double i_np1;
277 
278  if (x == 0.0)
279  return 0.0;
280  r2dpix = sqrt(2.0 / (PI * x));
281  i_ns1 = r2dpix * cosh(x);
282  i_n = r2dpix * sinh(x);
283 
284  for (i = 1; i <= n; i++)
285  {
286  i_np1 = i_ns1 - (2 * i - 1) / x * i_n;
287  i_ns1 = i_n;
288  i_n = i_np1;
289  }
290  return i_n;
291 }
void sqrt(Image< double > &op)
doublereal * x
#define i
double i_n(int n, double x)
Definition: blobs.cpp:244
#define PI
Definition: tools.h:43
int * n

◆ in_zeroarg()

double in_zeroarg ( int  n)

Limit (z->0) of (1/z)^n I_n(z) (needed by basvolume)

Definition at line 294 of file blobs.cpp.

295 {
296  int i;
297  double fact;
298  fact = 1.0;
299  for (i = 1; i <= n; i++)
300  {
301  fact *= 0.5 / i;
302  }
303  return fact;
304 }
#define i
size_t fact(int num)
int * n

◆ inph_zeroarg()

double inph_zeroarg ( int  n)

Limit (z->0) of (1/z)^(n+1/2) I_(n+1/2) (z) (needed by basvolume)

Definition at line 307 of file blobs.cpp.

308 {
309  int i;
310  double fact;
311  fact = 1.0;
312  for (i = 1; i <= n; i++)
313  {
314  fact *= 1.0 / (2 * i + 1.0);
315  }
316  return fact*sqrt(2.0 / PI);
317 }
void sqrt(Image< double > &op)
#define i
#define PI
Definition: tools.h:43
size_t fact(int num)
int * n

◆ kaiser_Fourier_value()

double kaiser_Fourier_value ( double  w,
double  a,
double  alpha,
int  m 
)

Function actually computing the blob Fourier transform.

Definition at line 144 of file blobs.cpp.

145 {
146  if (m != 2 && m !=0)
147  REPORT_ERROR(ERR_VALUE_INCORRECT, "m out of range in kaiser_Fourier_value()");
148  double sigma = sqrt(ABS(alpha * alpha - (2. * PI * a * w) * (2. * PI * a * w)));
149  if (m == 2)
150  {
151  if (2.*PI*a*w > alpha)
152  return pow(2.*PI, 3. / 2.)*pow(a, 3.)*pow(alpha, 2.)*bessj3_5(sigma)
153  / (bessi0(alpha)*pow(sigma, 3.5));
154  else
155  return pow(2.*PI, 3. / 2.)*pow(a, 3.)*pow(alpha, 2.)*bessi3_5(sigma)
156  / (bessi0(alpha)*pow(sigma, 3.5));
157  }
158  else if (m == 0)
159  {
160  if (2*PI*a*w > alpha)
161  return pow(2.*PI, 3. / 2.)*pow(a, 3)*bessj1_5(sigma)
162  / (bessi0(alpha)*pow(sigma, 1.5));
163  else
164  return pow(2.*PI, 3. / 2.)*pow(a, 3)*bessi1_5(sigma)
165  / (bessi0(alpha)*pow(sigma, 1.5));
166  }
167  else
168  REPORT_ERROR(ERR_ARG_INCORRECT,"Invalid blob order");
169 }
double alpha
Smoothness parameter.
Definition: blobs.h:121
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void sqrt(Image< double > &op)
doublereal * w
__device__ float bessi0(float x)
double bessi1_5(double x)
Incorrect argument received.
Definition: xmipp_error.h:113
#define ABS(x)
Definition: xmipp_macros.h:142
double bessj1_5(double x)
int m
double bessj3_5(double x)
double bessi3_5(double x)
#define PI
Definition: tools.h:43
Incorrect value received.
Definition: xmipp_error.h:195
doublereal * a

◆ kaiser_proj()

double kaiser_proj ( double  r,
double  a,
double  alpha,
int  m 
)

Function actually computing the blob projection.

Definition at line 94 of file blobs.cpp.

95 {
96  double sda;
97  double sdas;
98  double w;
99  double arg;
100  double p;
101 
102  sda = s / a;
103  sdas = sda * sda;
104  w = 1.0 - sdas;
105  if (w > 1.0e-10)
106  {
107  arg = alpha * sqrt(w);
108  if (m == 0)
109  {
110  if (alpha == 0.0)
111  p = 2.0 * a * sqrt(w);
112  else
113  p = (2.0 * a / alpha) * sinh(arg) / bessi0(alpha);
114 
115  }
116  else if (m == 1)
117  {
118  if (alpha == 0.0)
119  p = 2.0 * a * w * sqrt(w) * (2.0 / 3.0);
120  else
121  p = (2.0 * a / alpha) * sqrt(w) * (cosh(arg) - sinh(arg) / arg)
122  / bessi1(alpha);
123 
124  }
125  else if (m == 2)
126  {
127  if (alpha == 0.0)
128  p = 2.0 * a * w * w * sqrt(w) * (8.0 / 15.0);
129  else
130  p = (2.0 * a / alpha) * w *
131  ((3.0 / (arg * arg) + 1.0) * sinh(arg) - (3.0 / arg) * cosh(arg)) / bessi2(alpha);
132  }
133  else
134  REPORT_ERROR(ERR_VALUE_INCORRECT, "m out of range in kaiser_proj()");
135 
136  }
137  else
138  p = 0.0;
139 
140  return p;
141 }
double alpha
Smoothness parameter.
Definition: blobs.h:121
__device__ float bessi1(float x)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void sqrt(Image< double > &op)
doublereal * w
__device__ float bessi0(float x)
__device__ float bessi2(float x)
int m
Incorrect value received.
Definition: xmipp_error.h:195
doublereal * a

◆ kaiser_value()

double kaiser_value ( double  r,
double  a,
double  alpha,
int  m 
)

Function actually computing the blob value.

Definition at line 37 of file blobs.cpp.

38 {
39  double rda;
40  double rdas;
41  double arg;
42  double w;
43 
44  rda = r / a;
45  if (rda <= 1.0)
46  {
47  rdas = rda * rda;
48  arg = alpha * sqrt(1.0 - rdas);
49  if (m == 0)
50  {
51  w = bessi0(arg) / bessi0(alpha);
52  }
53  else if (m == 1)
54  {
55  w = sqrt (1.0 - rdas);
56  if (alpha != 0.0)
57  w *= bessi1(arg) / bessi1(alpha);
58  }
59  else if (m == 2)
60  {
61  w = sqrt (1.0 - rdas);
62  w = w * w;
63  if (alpha != 0.0)
64  w *= bessi2(arg) / bessi2(alpha);
65  }
66  else if (m == 3)
67  {
68  w = sqrt (1.0 - rdas);
69  w = w * w * w;
70  if (alpha != 0.0)
71  w *= bessi3(arg) / bessi3(alpha);
72  }
73  else if (m == 4)
74  {
75  w = sqrt (1.0 - rdas);
76  w = w * w * w *w;
77  if (alpha != 0.0)
78  w *= bessi4(arg) / bessi4(alpha);
79  }
80  else
81  REPORT_ERROR(ERR_VALUE_INCORRECT, "m out of range in kaiser_value()");
82 
83  }
84  else
85  w = 0.0;
86 
87  return w;
88 }
double alpha
Smoothness parameter.
Definition: blobs.h:121
__device__ float bessi1(float x)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void sqrt(Image< double > &op)
__device__ float bessi4(float x)
doublereal * w
__device__ float bessi0(float x)
__device__ float bessi3(float x)
__device__ float bessi2(float x)
int m
Incorrect value received.
Definition: xmipp_error.h:195
doublereal * a

◆ optimal_BCC_grid_relative_size()

double optimal_BCC_grid_relative_size ( struct blobtype  b)

Optimal BCC grid spastd::cing. This function returns the optimal grid relative size for the blob selected.

Definition at line 352 of file blobs.cpp.

353 {
354  return sqrt(8.0) / (2*blob_freq_zero(b));
355 }
void sqrt(Image< double > &op)
double blob_freq_zero(struct blobtype b)
Definition: blobs.cpp:330

◆ optimal_CC_grid_relative_size()

double optimal_CC_grid_relative_size ( struct blobtype  b)

Optimal CC grid spastd::cing. This function returns the optimal grid relative size for the blob selected.

Definition at line 348 of file blobs.cpp.

349 {
350  return 1 / blob_freq_zero(b);
351 }
double blob_freq_zero(struct blobtype b)
Definition: blobs.cpp:330

◆ optimal_FCC_grid_relative_size()

double optimal_FCC_grid_relative_size ( struct blobtype  b)

Optimal FCC grid spastd::cing. This function returns the optimal grid relative size for the blob selected.

Definition at line 356 of file blobs.cpp.

357 {
358  return sqrt(27.0) / (4*blob_freq_zero(b));
359 }
void sqrt(Image< double > &op)
double blob_freq_zero(struct blobtype b)
Definition: blobs.cpp:330

◆ sum_blob_Grid()

double sum_blob_Grid ( const struct blobtype blob,
const Grid grid,
const Matrix2D< double > *  D = nullptr 
)

Sum of a single blob over a grid. As a normalisation factor, the sum of the blob values over a given grid is needed. What this function does is put a blob at coordinate (0,0,0) and sums all the blob values at points of the grid which are inside the blob. It doesn't matter if the grid is compound or not. \ Ex:

// Blob definition
struct blobtype blob;
blob.radius = 2;
blob.order = 2;
blob.alpha = 3.6;
// Grid definition
Grid BCCgrid;
BCCgrid=BCC_grid(1.41,vectorR3(-5,-5,-5),vector_R3( 5, 5, 5));
std::cout << "The sum of a single blob over the grid is " <<
<< sum_blob_grid(blob, BCCgrid);

D is a 3x3 matrix specifying a volume deformation. It means that the sample at logical position (i,j,k) is really placed at space position D*(i,j,k)'.

Definition at line 320 of file blobs.cpp.

322 {
323  double sum = 0;
324  for (size_t i = 0; i < grid.GridsNo(); i++)
325  sum += sum_blob_SimpleGrid(blob, grid(i), D);
326  return sum;
327 }
size_t GridsNo() const
Definition: grids.h:536
#define i
double sum_blob_SimpleGrid(const struct blobtype &blob, const SimpleGrid &grid, const Matrix2D< double > *D)
Definition: blobs.cpp:175

◆ voxel_volume_shape()

void voxel_volume_shape ( const GridVolume vol_blobs,
const struct blobtype blob,
const Matrix2D< double > *  D,
Matrix1D< int > &  corner1,
Matrix1D< int > &  size 
)

Voxel shape for a blob volume. Given a blob volume this function returns the logical origin and size for the minimum voxel volume which holds it. See blobs2voxels for an explanation of the limit and V parameters.

Definition at line 851 of file blobs.cpp.

854 {
855  Matrix1D<double> Gcorner1(3);
856  Matrix1D<double> Gcorner2(3); // lowest and highest coord.
857 
858  corner1.resize(3);
859  size.resize(3);
860 
861  // Look for the lowest and highest volume coordinate
862  vol_blobs.grid().voxel_corners(Gcorner1, Gcorner2, D);
863 
864  // Add blob radius in each direction, and find the furthest integer
865  // samples => compute size
866  Gcorner1 -= blob.radius;
867  Gcorner1.selfCEIL();
868  Gcorner2 += blob.radius;
869  Gcorner2.selfFLOOR();
870 
871  XX(size) = (int)XX(Gcorner2) - (int)XX(Gcorner1) + 1;
872  YY(size) = (int)YY(Gcorner2) - (int)YY(Gcorner1) + 1;
873  ZZ(size) = (int)ZZ(Gcorner2) - (int)ZZ(Gcorner1) + 1;
874 #ifdef DEBUG
875 
876  std::cout << "Gcorner1 " << Gcorner1.transpose() << std::endl;
877  std::cout << "Gcorner2 " << Gcorner2.transpose() << std::endl;
878  std::cout << "Size of voxel volume " << (int)ZZ(size) << " x "
879  << (int)YY(size) << " x " << (int)XX(size) << std::endl;
880 #endif
881 
882 #ifdef NEVER_DEFINED
883  // In principle this limitation has been substituted by a direct
884  // specification of the output volume size, and should no longer
885  // be valid. However it is a beautiful piece of code to be removed
886  // already
887  if (limit != 0 && XX(size) != limit)
888  {
889  double diff = ((double)XX(size) - (double)limit) / 2;
890  if (diff == (int)diff)
891  {
892  Gcorner1 += diff;
893  Gcorner2 -= diff;
894  }
895  else
896  {
897  Gcorner1 += (diff - 0.5);
898  Gcorner2 -= (diff + 0.5);
899  }
900  XX(size) = (int)XX(Gcorner2) - (int)XX(Gcorner1) + 1;
901  YY(size) = (int)YY(Gcorner2) - (int)YY(Gcorner1) + 1;
902  ZZ(size) = (int)ZZ(Gcorner2) - (int)ZZ(Gcorner1) + 1;
903 #ifdef DEBUG
904 
905  std::cout << "Limiting to " << limit << " diff = " << diff << std::endl;
906  std::cout << "New Gcorner1 " << Gcorner1.transpose() << std::endl;
907  std::cout << "New Gcorner2 " << Gcorner2.transpose() << std::endl;
908 #endif
909 
910  }
911 #endif
912 
913  typeCast(Gcorner1, corner1);
914 
915 #ifdef DEBUG
916 
917  std::cout << "Final size of voxel volume " << (int)ZZ(size) << " x "
918  << (int)YY(size) << " x " << (int)XX(size) << std::endl;
919  std::cout << "Corner1= " << corner1.transpose() << std::endl;
920 #endif
921 }
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
#define XX(v)
Definition: matrix1d.h:85
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define YY(v)
Definition: matrix1d.h:93
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
const SimpleGrid & grid(size_t n) const
Definition: grids.h:978
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
#define ZZ(v)
Definition: matrix1d.h:101

◆ voxels2blobs()

void voxels2blobs ( const MultidimArray< double > *  vol_voxels,
const struct blobtype blob,
GridVolume vol_blobs,
int  grid_type,
double  grid_relative_size,
double  lambda,
const MultidimArray< double > *  vol_mask = nullptr,
const Matrix2D< double > *  D = nullptr,
double  final_error_change = 0.01,
int  tell = 0,
double  R = -1,
int  threads = 1 
)

Voxels —> Blobs. The voxels to blobs procedure is an iterative process resolved by ART as an iterative technique to solve an equation system. The blobs to voxels process is the BASIC way to solve this problem. This applies the whole ART process. You can set a debugging level by setting the flag SHOW_CONVERSION in the tell argument.

If the mask is NULL then it is assumed that all voxels in the input voxel volume must be adjusted by the blobs. If the input voxel volume is NULL the it is assumed that it is equal to 0 and only those corresponding to the 1 positions within the mask must be adjusted.

R is the interest radius. If it is -1 two superimposed grids are created, otherwise a single grid with tilted axis is.

Valid grid types are defined in Some useful grids

Definition at line 1316 of file blobs.cpp.

1322 {
1323  Image<double> theo_vol;
1324  Image<double> corr_vol;
1325  double mean_error;
1326  double mean_error_1;
1327  double max_error;
1328  int it = 1;
1329 
1330  tell = SHOW_CONVERSION;
1331 
1332  // Resize output volume .................................................
1333  Grid grid_blobs;
1334  if (R == -1)
1335  {
1336  Matrix1D<double> corner1(3);
1337  Matrix1D<double> corner2(3);
1338  XX(corner1) = STARTINGX(*vol_voxels);
1339  YY(corner1) = STARTINGY(*vol_voxels);
1340  ZZ(corner1) = STARTINGZ(*vol_voxels);
1341  XX(corner2) = FINISHINGX(*vol_voxels);
1342  YY(corner2) = FINISHINGY(*vol_voxels);
1343  ZZ(corner2) = FINISHINGZ(*vol_voxels);
1344 
1345  switch (grid_type)
1346  {
1347  case CC:
1348  grid_blobs = Create_CC_grid(grid_relative_size, corner1, corner2);
1349  break;
1350  case FCC:
1351  grid_blobs = Create_FCC_grid(grid_relative_size, corner1, corner2);
1352  break;
1353  case BCC:
1354  grid_blobs = Create_BCC_grid(grid_relative_size, corner1, corner2);
1355  break;
1356  }
1357  }
1358  else
1359 {
1360  switch (grid_type)
1361  {
1362  case CC:
1363  grid_blobs = Create_CC_grid(grid_relative_size, R);
1364  break;
1365  case FCC:
1366  grid_blobs = Create_FCC_grid(grid_relative_size, R);
1367  break;
1368  case BCC:
1369  grid_blobs = Create_BCC_grid(grid_relative_size, R);
1370  break;
1371  }
1372  }
1373  vol_blobs.adapt_to_grid(grid_blobs);
1374 
1375  // Convert ..............................................................
1376  std::cout << "Converting voxel volume to blobs\n";
1377  ART_voxels2blobs_single_step(vol_blobs, &vol_blobs, blob, D, lambda,
1378  &(theo_vol()), vol_voxels,
1379  &(corr_vol()), vol_mask, mean_error_1, max_error, VARTK, threads);
1380  if (tell && SHOW_CONVERSION)
1381  std::cout << " Finished iteration: " << it++
1382  << " Mean Error= " << mean_error_1
1383  << " Max_Error= " << max_error
1384  << std::endl;
1385  else
1386  std::cout << "0%";
1387  std::cout.flush();
1388 #ifdef DEBUG
1389 
1390  theo_vol.write("PPPtheo.vol");
1391  corr_vol.write("PPPcorr.vol");
1392  std::cout << "Press any key\n";
1393  char c;
1394  std::cin >> c;
1395 #endif
1396 
1397  double change;
1398  bool end_condition;
1399  do
1400 {
1401  ART_voxels2blobs_single_step(vol_blobs, &vol_blobs, blob, D, lambda,
1402  &(theo_vol()), vol_voxels,
1403  &(corr_vol()), vol_mask, mean_error, max_error, VARTK);
1404 #ifdef DEBUG
1405 
1406  theo_vol.write("PPPtheo.vol");
1407  corr_vol.write("PPPcorr.vol");
1408  std::cout << "Press any key\n";
1409  char c;
1410  std::cin >> c;
1411 #endif
1412 
1413  change = ABS(mean_error - mean_error_1) / mean_error_1;
1414  mean_error_1 = mean_error;
1415  if (tell && SHOW_CONVERSION)
1416  std::cout << " Finished iteration: " << it++
1417  << " Mean Error= " << mean_error
1418  << " Max_Error= " << max_error
1419  << std::endl;
1420  else
1421  {
1422  printf("\r");
1423  std::cout << 100 - change << "%";
1424  }
1425  std::cout.flush();
1426  end_condition = change <= final_error_change;
1427  }
1428  while (!end_condition);
1429  std::cout << std::endl;
1430 }
constexpr int SHOW_CONVERSION
Definition: blobs.h:353
#define FINISHINGX(v)
doublereal * c
SimpleGrid Create_CC_grid(double relative_size, const Matrix1D< double > &corner1, const Matrix1D< double > &corner2, const Matrix1D< double > &origin)
Definition: grids.cpp:196
void ART_voxels2blobs_single_step(GridVolume &vol_in, GridVolume *vol_out, const struct blobtype &blob, const Matrix2D< double > *D, double lambda, MultidimArray< double > *theo_vol, const MultidimArray< double > *read_vol, MultidimArray< double > *corr_vol, const MultidimArray< double > *mask_vol, double &mean_error, double &max_error, int eq_mode, int threads)
Definition: blobs.cpp:1094
constexpr int VARTK
Definition: blobs.h:378
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)
Definition: grids.h:479
#define FINISHINGZ(v)
#define CC
CC identifier.
Definition: grids.h:585
#define STARTINGX(v)
#define STARTINGY(v)
#define BCC
BCC identifier.
Definition: grids.h:589
void adapt_to_grid(const Grid &_grid)
Definition: grids.h:838
double * lambda
#define XX(v)
Definition: matrix1d.h:85
#define FCC
FCC identifier.
Definition: grids.h:587
#define ABS(x)
Definition: xmipp_macros.h:142
#define YY(v)
Definition: matrix1d.h:93
Grid Create_FCC_grid(double relative_size, const Matrix1D< double > &corner1, const Matrix1D< double > &corner2)
Definition: grids.cpp:306
Grid Create_BCC_grid(double relative_size, const Matrix1D< double > &corner1, const Matrix1D< double > &corner2)
Definition: grids.cpp:251
#define FINISHINGY(v)
#define STARTINGZ(v)
#define ZZ(v)
Definition: matrix1d.h:101

Variable Documentation

◆ SHOW_CONVERSION

constexpr int SHOW_CONVERSION = 1

Definition at line 353 of file blobs.h.

◆ VARTK

constexpr int VARTK = 1

Definition at line 378 of file blobs.h.

◆ VMAXARTK

constexpr int VMAXARTK = 2

Definition at line 379 of file blobs.h.