Xmipp  v3.23.11-Nereus
volume_apply_coefficient_zernike3d.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: David Herreros Calero dherreros@cnb.csic.es
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18  * 02111-1307 USA
19  *
20  * All comments concerning this program package may be sent to the
21  * e-mail address 'xmipp@cnb.uam.es'
22  ***************************************************************************/
23 
24 #include <data/numerical_tools.h>
25 #include <data/basis.h>
27 #include <data/numerical_tools.h>
28 #include <fstream>
29 #include "data/mask.h"
30 
31 void ProgApplyCoeffZernike3D::defineParams()
32 {
33  addUsageLine("Deform a PDB according to a list of SPH deformation coefficients");
34  addParamsLine("-i <volume> : Volume to deform");
35  addParamsLine(" [--mask <m=\"\">] : Reference volume");
36  addParamsLine("--clnm <metadata_file> : List of deformation coefficients");
37  addParamsLine("-o <volume> : Deformed volume");
38  addParamsLine(" [--step <step=1>] : Voxel index step");
39  addParamsLine(" [--blobr <b=4>] : Blob radius for forward mapping splatting");
40  addExampleLine("xmipp_apply_deform_sph -i input.vol -o volume_deformed.vol --clnm coefficients.txt");
41 }
42 
43 void ProgApplyCoeffZernike3D::readParams()
44 {
45  fn_vol=getParam("-i");
46  fn_sph=getParam("--clnm");
47  fn_mask = getParam("--mask");
48  blob_r = getDoubleParam("--blobr");
49  loop_step = getIntParam("--step");
50  fn_out=getParam("-o");
51 }
52 
53 void ProgApplyCoeffZernike3D::show() const
54 {
55  if (verbose==0)
56  return;
57  std::cout
58  << "Volume: " << fn_vol << std::endl
59  << "Reference mask: " << fn_mask << std::endl
60  << "Coefficient list: " << fn_sph << std::endl
61  << "Step: " << loop_step << std::endl
62  << "Blob radius: " << blob_r << std::endl
63  << "Output: " << fn_out << std::endl
64  ;
65 }
66 
67 void ProgApplyCoeffZernike3D::run()
68 {
69  Image<double> VI;
70  Image<double> VO;
71  MultidimArray<int> V_mask;
72  VI.read(fn_vol);
73  VI().setXmippOrigin();
74  VO().initZeros(VI());
75  VO().setXmippOrigin();
76 
77  // Blob
78  blob.radius = blob_r; // Blob radius in voxels
79  blob.order = 2; // Order of the Bessel function
80  blob.alpha = 3.6; // Smoothness parameter
81 
82  std::string line;
83  line = readNthLine(0);
84  basisParams = string2vector(line);
85  line = readNthLine(1);
86  clnm = string2vector(line);
87  fillVectorTerms();
88  size_t idxY0=(clnm.size())/3;
89  size_t idxZ0=2*idxY0;
90  const MultidimArray<double> &mVI=VI();
91  MultidimArray<double> &mVO=VO();
92  double voxelI=0.0;
93  double Rmax=basisParams[2];
94  double Rmax2=Rmax*Rmax;
95  double iRmax=1.0/Rmax;
96 
97  Mask mask;
99  mask.mode = INNER_MASK;
100  if (fn_mask != "") {
101  Image<double> aux;
102  aux.read(fn_mask);
103  typeCast(aux(), V_mask);
104  V_mask.setXmippOrigin();
105  for (int k=STARTINGZ(V_mask); k<=FINISHINGZ(V_mask); k++) {
106  for (int i=STARTINGY(V_mask); i<=FINISHINGY(V_mask); i++) {
107  for (int j=STARTINGX(V_mask); j<=FINISHINGX(V_mask); j++) {
108  double r2 = k*k + i*i + j*j;
109  if (r2>=Rmax2)
110  A3D_ELEM(V_mask,k,i,j) = 0;
111  }
112  }
113  }
114  }
115  else {
116  mask.R1 = Rmax;
117  mask.generate_mask(VI());
118  V_mask = mask.get_binary_mask();
119  V_mask.setXmippOrigin();
120  }
121 
122  double deformation = 0.0;
123  double Ncount = 0.0;
124  for (int k=STARTINGZ(mVI); k<=FINISHINGZ(mVI); k+=loop_step)
125  {
126  for (int i=STARTINGY(mVI); i<=FINISHINGY(mVI); i+=loop_step)
127  {
128  for (int j=STARTINGX(mVI); j<=FINISHINGX(mVI); j+=loop_step)
129  {
130  if (A3D_ELEM(V_mask,k,i,j) == 1) {
131  double gx=0.0;
132  double gy=0.0;
133  double gz=0.0;
134  double k2=k*k;
135  double kr=k*iRmax;
136  double k2i2=k2+i*i;
137  double ir=i*iRmax;
138  double r2=k2i2+j*j;
139  double jr=j*iRmax;
140  double rr=std::sqrt(r2)*iRmax;
141  if (r2<Rmax2)
142  {
143  for (size_t idx=0; idx<idxY0; idx++)
144  {
145  auto l1 = VEC_ELEM(vL1,idx);
146  auto n = VEC_ELEM(vN,idx);
147  auto l2 = VEC_ELEM(vL2,idx);
148  auto m = VEC_ELEM(vM,idx);
149  auto zsph=ZernikeSphericalHarmonics(l1,n,l2,m,jr,ir,kr,rr);
150  if (rr>0 || l2==0)
151  {
152  gx += clnm[idx] *zsph;
153  gy += clnm[idx+idxY0] *zsph;
154  gz += clnm[idx+idxZ0] *zsph;
155  }
156  }
157  }
158 
159  auto pos = std::array<double, 3>{};
160  pos[0] = (double)j + gx;
161  pos[1] = (double)i + gy;
162  pos[2] = (double)k + gz;
163  double voxel_mV = A3D_ELEM(mVI,k,i,j);
164  splattingAtPos(pos, voxel_mV, mVO);
165  deformation += gx*gx+gy*gy+gz*gz;
166  Ncount++;
167 
168  }
169  }
170  }
171  }
172  deformation = sqrt(deformation/Ncount);
173  std::cout << "Deformation = " << deformation << std::endl;
174  VO.write(fn_out);
175 }
176 
177 std::string ProgApplyCoeffZernike3D::readNthLine(int N) const
178 {
179  std::ifstream in(fn_sph.getString());
180  std::string s;
181 
182  //skip N lines
183  for(int i = 0; i < N; ++i)
184  std::getline(in, s);
185 
186  std::getline(in,s);
187  return s;
188 }
189 
190 std::vector<double> ProgApplyCoeffZernike3D::string2vector(std::string const &s) const
191 {
192  std::stringstream iss(s);
193  double number;
194  std::vector<double> v;
195  while (iss >> number)
196  v.push_back(number);
197  return v;
198 }
199 
200 void ProgApplyCoeffZernike3D::fillVectorTerms()
201 {
202  int idx = 0;
203  auto vecSize = (int)((clnm.size())/3);
204  vL1.initZeros(vecSize);
205  vN.initZeros(vecSize);
206  vL2.initZeros(vecSize);
207  vM.initZeros(vecSize);
208  for (int h=0; h<=basisParams[1]; h++)
209  {
210  int totalSPH = 2*h+1;
211  auto aux = (int)(std::floor(totalSPH/2));
212  for (int l=h; l<=basisParams[0]; l+=2)
213  {
214  for (int m=0; m<totalSPH; m++)
215  {
216  VEC_ELEM(vL1,idx) = l;
217  VEC_ELEM(vN,idx) = h;
218  VEC_ELEM(vL2,idx) = h;
219  VEC_ELEM(vM,idx) = m-aux;
220  idx++;
221  }
222  }
223  }
224 }
225 
226 void ProgApplyCoeffZernike3D::splattingAtPos(std::array<double, 3> r, double weight, const MultidimArray<double> &mVO) {
227  // Find the part of the volume that must be updated
228  double x_pos = r[0];
229  double y_pos = r[1];
230  double z_pos = r[2];
231  int k0 = XMIPP_MAX(FLOOR(z_pos - blob_r), STARTINGZ(mVO));
232  int kF = XMIPP_MIN(CEIL(z_pos + blob_r), FINISHINGZ(mVO));
233  int i0 = XMIPP_MAX(FLOOR(y_pos - blob_r), STARTINGY(mVO));
234  int iF = XMIPP_MIN(CEIL(y_pos + blob_r), FINISHINGY(mVO));
235  int j0 = XMIPP_MAX(FLOOR(x_pos - blob_r), STARTINGX(mVO));
236  int jF = XMIPP_MIN(CEIL(x_pos + blob_r), FINISHINGX(mVO));
237  // Perform splatting at this position r
238  for (int k = k0; k <= kF; k++)
239  {
240  double z_val = bspline1(k - z_pos);
241  for (int i = i0; i <= iF; i++)
242  {
243  double y_val = bspline1(i - y_pos);
244  for (int j = j0; j <= jF; j++)
245  {
246  double x_val = bspline1(j - x_pos);
247  A3D_ELEM(mVO,k, i, j) += weight * x_val * y_val * z_val;
248  }
249  }
250  }
251 }
252 
253 double ProgApplyCoeffZernike3D::bspline1(double x)
254 {
255  double m = 1 / blob_r;
256  if (0. < x && x < blob_r)
257  return m * (blob_r - x);
258  else if (-blob_r < x && x <= 0.)
259  return m * (blob_r + x);
260  else
261  return 0.;
262 }
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
double alpha
Smoothness parameter.
Definition: blobs.h:121
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
double getDoubleParam(const char *param, int arg=0)
__host__ __device__ float2 floor(const float2 v)
#define FINISHINGX(v)
Definition: mask.h:360
void sqrt(Image< double > &op)
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 FINISHINGZ(v)
#define STARTINGX(v)
doublereal * x
#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 FLOOR(x)
Definition: xmipp_macros.h:240
const char * getParam(const char *param, int arg=0)
#define CEIL(x)
Definition: xmipp_macros.h:225
int in
double R1
Definition: mask.h:413
int type
Definition: mask.h:402
void addExampleLine(const char *example, bool verbatim=true)
int verbose
Verbosity level.
void initZeros()
Definition: matrix1d.h:592
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
int m
#define FINISHINGY(v)
void generate_mask(bool apply_geo=false)
Definition: mask.cpp:1577
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
#define BINARY_CIRCULAR_MASK
Definition: mask.h:365
double ZernikeSphericalHarmonics(int n, int m, double xr, double yr, double zr, double r)
String getString() const
int order
Derivation order and Bessel function order.
Definition: blobs.h:118
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
float r2
void addUsageLine(const char *line, bool verbatim=false)
const MultidimArray< int > & get_binary_mask() const
Definition: mask.h:707
int getIntParam(const char *param, int arg=0)
#define STARTINGZ(v)
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
int * n
void addParamsLine(const String &line)
int ir
int mode
Definition: mask.h:407
constexpr int INNER_MASK
Definition: mask.h:47