Xmipp  v3.23.11-Nereus
basis.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "basis.h"
27 #include "numerical_tools.h"
28 #include <core/xmipp_fftw.h>
29 
31 {
32  setDefault();
33 }
34 
35 // Set default -------------------------------------------------------------
37 {
38  type = blobs;
39  blob.radius = 2;
40  blob.order = 2;
41  blob.alpha = 10.4;
42  VolPSF = nullptr;
43  D = nullptr;
44  blobprint.clear();
45  blobprint2.clear();
46  aux.resizeNoCopy(3);
47 }
48 
49 // Basis name --------------------------------------------------------------
51 {
52  switch (type)
53  {
54  case Basis::blobs:
55  return "blobs";
56  break;
57  case Basis::voxels:
58  return "voxels";
59  break;
60  case Basis::splines:
61  return "splines";
62  break;
63  default:
64  return "Unknown";
65  break;
66  }
67 }
68 
69 void Basis::defineParams(XmippProgram * program, const char* prefix, const char* comment)
70 {
71  char tempLine[256];
72  char lineOut[512];
73 
74  if(prefix == nullptr)
75  sprintf(tempLine, " [--basis <basis_type=blobs>] ");
76  else
77  sprintf(tempLine,"%s --basis <basis_type=blobs> ", prefix);
78 
79  //std::cerr << "DEBUG_JM: tempLine: " << tempLine << std::endl;
80 
81 
82  if (comment != nullptr)
83  sprintf(lineOut, "%s : %s", tempLine, comment);
84  else
85  sprintf(lineOut, "%s : Basis function to use for the reconstruction", tempLine);
86 
87  program->addParamsLine(lineOut);
88 
89  //std::cerr << "DEBUG_JM: tempLine: " << lineOut << std::endl;
90 
91  program->addParamsLine(" where <basis_type>");
92  program->addParamsLine(" blobs <radius=2> <Bessel_order=2> <alpha_param=10.4> : Default blob parameters and grid relative size adjusted to use small blobs");
93  program->addParamsLine(" voxels");
94  program->addParamsLine(" splines");
95  program->addParamsLine(" or --big_blobs : blob parameters and grid relative size adjusted to use big blobs (r=2, m=2, alpha=2.26, g=2.26)");
96  program->addParamsLine(" or --visual_blobs : blobs optimal for direct visualization (r=2.4, m=2, alpha=13.3633, g=1.41)");
97  program->addParamsLine(" or --tomo_blobs : blobs with high overlapping (r=3.469269, m=2, alpha=13.7385, g=1/sqrt(2))");
98 }
99 
101 {
102  String basisType = program->getParam("--basis");
103 
104  if (basisType == "blobs")
105  {
106  blob.radius = program->getDoubleParam("--basis", "blobs", 0);
107  blob.order = program->getIntParam("--basis", "blobs", 1);
108  blob.alpha = program->getDoubleParam("--basis", "blobs", 2);
109  }
110  if (!program->checkParam("--basis")) // Default is for small blobs
111  grid_relative_size = 1.41;
112 
113  if (program->checkParam("--big_blobs"))
114  {
115  blob.radius = 2;
116  blob.order = 2;
117  blob.alpha = 3.6;
118 
119  grid_relative_size = 2.26;
120  }
121  else if (program->checkParam("--visual_blobs"))
122  {
123  blob.radius = 2.4;
124  blob.order = 2;
125  blob.alpha = 13.3633;
126 
127  grid_relative_size = 1.41;
128  }
129  else if (program->checkParam("--tomo_blobs"))
130  {
131  blob.radius = 3.469269392209083;
132  blob.order = 2;
133  blob.alpha = 13.7385068372842;
134 
135  grid_relative_size = 1.0/sqrt(2);
136  }
137  else
138  {
139  if (basisType == "voxels")
140  {
141  type = voxels;
142  grid_relative_size = 1;
143  }
144  else if (basisType == "splines")
145  {
146  type = splines;
147  grid_relative_size = 1;
148  }
149  }
150 }
151 
152 // Set sampling rate -------------------------------------------------------
153 void Basis::setSamplingRate(double _Tm)
154 {
155  if (_Tm == 0)
156  REPORT_ERROR(ERR_VALUE_INCORRECT, "Basis::set_sampling_rate: Sampling rate cannot be 0");
157  Tm = _Tm;
158  blob.radius /= Tm;
159 }
160 
161 // Produce side information ------------------------------------------------
162 void Basis::produceSideInfo(const Grid &grid)
163 {
164  switch (type)
165  {
166  case blobs:
167  {
168  int subsampling = (VolPSF == nullptr )? BLOB_SUBSAMPLING : PIXEL_SUBSAMPLING;
169 
170  footprint_blob(blobprint, blob, subsampling);
171  sum_on_grid = sum_blob_Grid(blob, grid, D);
172  blobprint() /= sum_on_grid;
173 
174  if (VolPSF != nullptr)
175  {
176  // let adjust to the same resolution and size both blobprint and VolPSF
177  // selfScaleToSize(LINEAR, *VolPSF, XSIZE(*VolPSF)*BLOB_SUBSAMPLING,
178  // YSIZE(*VolPSF)*BLOB_SUBSAMPLING, ZSIZE(*VolPSF));
179 
180  blobprint().setXmippOrigin();
181 
182  if (XSIZE(blobprint()) < XSIZE(*VolPSF))
183  blobprint().selfWindow(STARTINGY(*VolPSF),
184  STARTINGX(*VolPSF),
186  STARTINGX(*VolPSF)+XSIZE(*VolPSF)-1);
187  else if (XSIZE(blobprint()) > XSIZE(*VolPSF))
189  STARTINGX(blobprint()),
192 
193  // creation of the 3D blobprint from convolution of blobprint and PSF
194  ImageOver footprintT;
195  footprintT.init(*VolPSF, subsampling);
196 
197  convolutionFFTStack(*VolPSF, blobprint(), footprintT());
198 
199  blobprint = footprintT;
200  }
201 
202  blobprint2() = blobprint();
203  blobprint2() *= blobprint();
204  break;
205  }
206  case voxels: sum_on_grid = 1;
207  break;
209  break;
210  }
211 
212 #ifdef DEBUG
213  std::cout << "Sum of a basis on the grid=" << sum_on_grid << std::endl;
214  std::cout << "D\n" << D << std::endl;
215  ImageXmipp save;
216  save() = blobprint();
217  save.write("footprint.xmp");
218 #endif
219 }
220 #undef DEBUG
221 
222 // Show --------------------------------------------------------------------
223 std::ostream & operator << (std::ostream & out, const Basis &basis)
224 {
225  switch (basis.type)
226  {
227  case Basis::blobs:
228  out << " Blobs: radius=" << basis.blob.radius << " pixels"
229  << " alpha=" << basis.blob.alpha
230  << " order=" << basis.blob.order << std::endl;
231  break;
232  case Basis::voxels:
233  out << "Voxels\n";
234  break;
235  case Basis::splines:
236  out << "Splines\n";
237  break;
238  }
239  return out;
240 }
241 
242 double Basis::maxLength() const
243 {
244  switch (type)
245  {
246  case blobs:
247  return blob.radius;
248  break;
249  case voxels:
250  return sqrt(3.0) * 0.5;
251  break;
252  case splines:
253  return sqrt(3.0) * 2.0;
254  break;
255  }
256  return 0.0;
257 }
258 
259 
260 // Change to voxels --------------------------------------------------------
262  int Zdim, int Ydim, int Xdim, int threads ) const
263 {
264  int xdiff;
265  int ydiff;
266  int zdiff;
267  switch (type)
268  {
269  case blobs:
270  blobs2voxels(vol_basis, blob, vol_voxels, D, threads , Zdim, Ydim, Xdim );
271  break;
272  case voxels:
273  *vol_voxels = vol_basis(0)();
274  xdiff = (Xdim - XSIZE(*vol_voxels)) / 2;
275  ydiff = (Ydim - YSIZE(*vol_voxels)) / 2;
276  zdiff = (Zdim - ZSIZE(*vol_voxels)) / 2;
277  vol_voxels->selfWindow(
278  STARTINGZ(*vol_voxels) - zdiff,
279  STARTINGY(*vol_voxels) - ydiff,
280  STARTINGX(*vol_voxels) - xdiff,
281  (int)(FINISHINGZ(*vol_voxels) + Zdim - ZSIZE(*vol_voxels) - zdiff),
282  (int)(FINISHINGY(*vol_voxels) + Ydim - YSIZE(*vol_voxels) - ydiff),
283  (int)(FINISHINGX(*vol_voxels) + Xdim - XSIZE(*vol_voxels) - xdiff));
284  break;
285  case splines:
286  spatial_Bspline032voxels(vol_basis, vol_voxels, Zdim, Ydim, Xdim);
287  break;
288  }
289 }
290 
291 // Change from voxels ------------------------------------------------------
293  GridVolume &vol_basis, int grid_type, double grid_relative_size,
294  const MultidimArray<double> *vol_mask,
295  const Matrix2D<double> *D, double R, int threads) const
296 {
297  Grid grid;
298  Matrix1D<double> corner1(3);
299  Matrix1D<double> corner2(3);
300  double R2 = R * R;
301  switch (type)
302  {
303  case blobs:
304  voxels2blobs(&vol_voxels, blob, vol_basis,
305  grid_type, grid_relative_size, 0.05, vol_mask,
306  D, 0.01, 0, R, threads);
307  break;
308  case voxels:
309  VECTOR_R3(corner1, STARTINGX(vol_voxels),
310  STARTINGY(vol_voxels), STARTINGZ(vol_voxels));
311  VECTOR_R3(corner2, FINISHINGX(vol_voxels),
312  FINISHINGY(vol_voxels), FINISHINGZ(vol_voxels));
313  grid = Create_CC_grid(1, corner1, corner2);
314  vol_basis.adapt_to_grid(grid);
315  vol_basis(0)() = vol_voxels;
316  if (R != -1)
317  FOR_ALL_ELEMENTS_IN_ARRAY3D(vol_voxels)
318  if (k*k + i*i + j*j > R2)
319  vol_basis(0)()(k, i, j) = 0;
320  if (vol_mask != nullptr)
321  FOR_ALL_ELEMENTS_IN_ARRAY3D(vol_voxels)
322  if ((*vol_mask)(k, i, j) == 0)
323  vol_basis(0)()(k, i, j) = 0;
324  break;
325  case splines:
327  /* TODO */
328  break;
329  }
330 }
331 
332 double Basis::valueAt(const Matrix1D<double> & r) const
333 {
334  double module_r;
335  switch (type)
336  {
337  case blobs:
338  {
339  module_r = sqrt(XX(r) * XX(r) + YY(r) * YY(r) + ZZ(r) * ZZ(r));
340  return blob_val(module_r, blob);
341  break;
342  }
343  case voxels:
344  {
345  if (-0.5 <= XX(r) && XX(r) < 0.5 &&
346  -0.5 <= YY(r) && YY(r) < 0.5 &&
347  -0.5 <= ZZ(r) && ZZ(r) < 0.5)
348  return 1.0;
349  else
350  return 0.0;
351  break;
352  }
353  case splines:
354  {
355  if (-2 <= XX(r) && XX(r) < 2 &&
356  -2 <= YY(r) && YY(r) < 2 &&
357  -2 <= ZZ(r) && ZZ(r) < 2)
358  return spatial_Bspline03LUT(r);
359  else
360  return 0.0;
361  break;
362  }
363  }
364  return 0.0;
365 }
366 
367 double Basis::projectionAt(const Matrix1D<double> & u, const Matrix1D<double> & r) const
368 {
369  const double p0 = 1.0 / (2 * PIXEL_SUBSAMPLING) - 0.5;
370  const double pStep = 1.0 / PIXEL_SUBSAMPLING;
371  const double pAvg = 1.0 / (PIXEL_SUBSAMPLING * PIXEL_SUBSAMPLING);
372  double module_r;
373  double px;
374  double py;
375  int i;
376  int j;
377  switch (type)
378  {
379  case blobs:
380  module_r = sqrt(XX(r) * XX(r) + YY(r) * YY(r) + ZZ(r) * ZZ(r));
381  return blob_proj(module_r, blob);
382  break;
383  case voxels:
384  {
385  double retval = 0;
386  ZZ(aux) = ZZ(r);
387  for (i = 0, px = p0; i < PIXEL_SUBSAMPLING; i++, px += pStep)
388  {
389  XX(aux) = XX(r) + px;
390  for (j = 0, py = p0; j < PIXEL_SUBSAMPLING; j++, py += pStep)
391  {
392  YY(aux) = YY(r) + py;
393  retval += intersection_unit_cube(u, aux);
394  }
395  }
396  return retval*pAvg;
397  break;
398  }
399  case splines:
400  return spatial_Bspline03_proj(r, u);
401  break;
402  }
403  return 0.0;
404 }
405 
406 void createZernike3DBasis(const MultidimArray<double> &Vin, MultidimArray<double> &Vbasis, int l1, int n, int l2, int m, int Rmax)
407 {
408  Vbasis.initZeros(Vin);
409  Vbasis.setXmippOrigin();
410  if (Rmax<0)
411  Rmax=XSIZE(Vin)/2;
412  double Rmax2=Rmax*Rmax;
413  double iRmax=1.0/Rmax;
414  for (int k=STARTINGZ(Vbasis); k<=FINISHINGZ(Vbasis); k++)
415  {
416  double k2=k*k;
417  if (k2>Rmax2)
418  continue;
419  double kr=k*iRmax;
420  for (int i=STARTINGY(Vbasis); i<=FINISHINGY(Vbasis); i++)
421  {
422  double k2i2=k2+i*i;
423  if (k2i2>Rmax2)
424  continue;
425  double ir=i*iRmax;
426  for (int j=STARTINGX(Vbasis); j<=FINISHINGX(Vbasis); j++)
427  {
428  double r2=k2i2+j*j;
429  if (r2>Rmax2)
430  continue;
431  double jr=j*iRmax;
432  A3D_ELEM(Vbasis,k,i,j)=ZernikeSphericalHarmonics(l1,n,l2,m,jr,ir,kr,sqrt(r2)*iRmax);
433  }
434  }
435 
436  }
437 }
void selfWindow(int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T init_value=0)
void createZernike3DBasis(const MultidimArray< double > &Vin, MultidimArray< double > &Vbasis, int l1, int n, int l2, int m, int Rmax)
Definition: basis.cpp:406
#define YSIZE(v)
double alpha
Smoothness parameter.
Definition: blobs.h:121
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
double getDoubleParam(const char *param, int arg=0)
#define FINISHINGX(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void blobs2voxels(const GridVolume &vol_blobs, const struct blobtype &blob, MultidimArray< double > *vol_voxels, const Matrix2D< double > *D, int threads, int Zdim, int Ydim, int Xdim)
Definition: blobs.cpp:926
SimpleGrid Create_CC_grid(double relative_size, const Matrix1D< double > &corner1, const Matrix1D< double > &corner2, const Matrix1D< double > &origin)
Definition: grids.cpp:196
double projectionAt(const Matrix1D< double > &u, const Matrix1D< double > &r) const
Definition: basis.cpp:367
double grid_relative_size
Relative size for the grid.
Definition: basis.h:64
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)
Basis()
Empty constructor. By default, blobs.
Definition: basis.cpp:30
void changeFromVoxels(const MultidimArray< double > &vol_voxels, GridVolume &vol_basis, int grid_type, double grid_relative_size, const MultidimArray< double > *vol_mask, const Matrix2D< double > *D, double R, int threads=1) const
Definition: basis.cpp:292
double sum_on_grid
Sum of the basis on the grid points.
Definition: basis.h:77
double spatial_Bspline03LUT(const Matrix1D< double > &r)
Definition: splines.h:60
struct blobtype blob
Blob parameters.
Definition: basis.h:61
void convolutionFFTStack(const MultidimArray< double > &img, const MultidimArray< double > &kernel, MultidimArray< double > &result)
Definition: xmipp_fftw.cpp:429
tBasisFunction type
Basis function to use.
Definition: basis.h:52
Definition: grids.h:479
double maxLength() const
Definition: basis.cpp:242
ImageOver blobprint2
Square of the footprint.
Definition: basis.h:74
#define FINISHINGZ(v)
void setDefault()
Default values.
Definition: basis.cpp:36
Matrix2D< double > * D
Definition: basis.h:68
#define STARTINGX(v)
void changeToVoxels(GridVolume &vol_basis, MultidimArray< double > *vol_voxels, int Zdim, int Ydim, int Xdim, int threads=1) const
Definition: basis.cpp:261
#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)
void adapt_to_grid(const Grid &_grid)
Definition: grids.h:838
#define A3D_ELEM(V, k, i, j)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
double sum_blob_Grid(const struct blobtype &blob, const Grid &grid, const Matrix2D< double > *D)
Definition: blobs.cpp:320
const char * getParam(const char *param, int arg=0)
#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
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, const Matrix2D< double > *D, double final_error_change, int tell, double R, int threads)
Definition: blobs.cpp:1316
Definition: basis.h:45
double Tm
Sampling rate.
Definition: basis.h:58
#define XSIZE(v)
#define ZSIZE(v)
String basisName() const
Basis name.
Definition: basis.cpp:50
double intersection_unit_cube(const Matrix1D< double > &u, const Matrix1D< double > &r)
Definition: geometry.cpp:1190
Matrix1D< double > aux
Auxiliary vector for projections.
Definition: basis.h:80
double valueAt(const Matrix1D< double > &r) const
Definition: basis.cpp:332
#define j
void footprint_blob(ImageOver &blobprint, const struct blobtype &blob, int istep, int normalise)
Definition: blobs.cpp:417
#define YY(v)
Definition: matrix1d.h:93
int m
void produceSideInfo(const Grid &grid)
Definition: basis.cpp:162
#define FINISHINGY(v)
#define blob_proj(r, blob)
Definition: blobs.h:161
void spatial_Bspline032voxels(const GridVolume &vol_splines, MultidimArray< double > *vol_voxels, int Zdim, int Ydim, int Xdim)
Definition: splines.cpp:386
double ZernikeSphericalHarmonics(int n, int m, double xr, double yr, double zr, double r)
std::string String
Definition: xmipp_strings.h:34
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
int order
Derivation order and Bessel function order.
Definition: blobs.h:118
static void defineParams(XmippProgram *program, const char *prefix=NULL, const char *comment=NULL)
Definition: basis.cpp:69
double sum_spatial_Bspline03_Grid(const Grid &grid)
Definition: splines.cpp:72
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
doublereal * u
double spatial_Bspline03_proj(const Matrix1D< double > &r, const Matrix1D< double > &u)
Definition: splines.cpp:103
bool checkParam(const char *param)
const int BLOB_SUBSAMPLING
Definition: basis.h:34
const int PIXEL_SUBSAMPLING
Definition: basis.h:35
float r2
void readParams(XmippProgram *program)
Definition: basis.cpp:100
void initZeros(const MultidimArray< T1 > &op)
#define blob_val(r, blob)
Definition: blobs.h:139
int getIntParam(const char *param, int arg=0)
Incorrect value received.
Definition: xmipp_error.h:195
#define STARTINGZ(v)
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
int * n
#define ZZ(v)
Definition: matrix1d.h:101
friend std::ostream & operator<<(std::ostream &out, const Basis &basis)
Show.
Definition: basis.cpp:223
void addParamsLine(const String &line)
int ir
ImageOver blobprint
Blob footprint.
Definition: basis.h:71
void setSamplingRate(double _Tm)
Definition: basis.cpp:153