Xmipp  v3.23.11-Nereus
mask.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 "mask.h"
27 #include "core/xmipp_program.h"
29 #include "core/transformations.h"
30 #include "data/wavelet.h"
31 #include "core/xmipp_funcs.h"
32 
33 /*---------------------------------------------------------------------------*/
34 /* Multidim Masks */
35 /*---------------------------------------------------------------------------*/
36 void RaisedCosineMask(MultidimArray<double> &mask, double r1, double r2,
37  int mode, double x0, double y0, double z0)
38 {
39  double K = PI / (r2 - r1);
40  double r1_2=r1*r1;
41  double r2_2=r2*r2;
42  for (int k=STARTINGZ(mask); k<=FINISHINGZ(mask); ++k)
43  {
44  double k2=(k - z0) * (k - z0);
45  for (int i=STARTINGY(mask); i<=FINISHINGY(mask); ++i)
46  {
47  double i2_k2=k2+(i - y0) * (i - y0);
48  for (int j=STARTINGX(mask); j<=FINISHINGX(mask); ++j)
49  {
50  double r2=i2_k2+(j - x0) * (j - x0);
51  if (r2 <= r1_2)
52  A3D_ELEM(mask, k, i, j) = 1;
53  else if (r2 < r2_2)
54  {
55  double r=sqrt(r2);
56  A3D_ELEM(mask, k, i, j) = 0.5*(1 + cos(K * (r - r1)));
57  }
58  else
59  A3D_ELEM(mask, k, i, j) = 0;
60  if (mode == OUTSIDE_MASK)
61  A3D_ELEM(mask, k, i, j) = 1 - A3D_ELEM(mask, k, i, j);
62  }
63  }
64  }
65 }
66 
68  double r1, double r2, double pix_width, int mode,
69  double x0, double y0, double z0)
70 {
71  RaisedCosineMask(mask, r1 - pix_width, r1 + pix_width, OUTSIDE_MASK, x0, y0, z0);
73  aux.resize(mask);
74  RaisedCosineMask(aux, r2 - pix_width, r2 + pix_width, INNER_MASK, x0, y0, z0);
76  {
77  A3D_ELEM(mask, k, i, j) *= A3D_ELEM(aux, k, i, j);
78  if (mode == OUTSIDE_MASK)
79  A3D_ELEM(mask, k, i, j) = 1 - A3D_ELEM(mask, k, i, j);
80  }
81 }
82 
83 void KaiserMask(MultidimArray<double> &mask, double delta, double Deltaw)
84 {
85  // Convert Deltaw from a frequency normalized to 1, to a freq. normalized to PI
86  Deltaw *= PI;
87 
88  // Design Kaiser selfWindow
89  double A = -20 * log10(delta);
90  int M = CEIL((A - 8) / (2.285 * Deltaw));
91  double beta;
92  if (A > 50)
93  beta = 0.1102 * (A - 8.7);
94  else if (A >= 21)
95  beta = 0.5842 * pow(A - 21, 0.4) + 0.07886 * (A - 21);
96  else
97  beta = 0;
98 
99  // "Draw" Kaiser selfWindow
100  if (YSIZE(mask)==1 && ZSIZE(mask)==1)
101  {
102  // 1D
103  mask.resize(2*M + 1);
104  }
105  else if (ZSIZE(mask)==1)
106  {
107  // 2D
108  mask.resize(2*M + 1, 2*M + 1);
109  }
110  else
111  {
112  // 3D
113  mask.resize(2*M + 1, 2*M + 1, 2*M + 1);
114  }
115 
116  mask.setXmippOrigin();
117  double iI0Beta = 1.0 / bessi0(beta);
119  {
120  double r = sqrt((double)(i * i + j * j + k * k));
121  if (r <= M)
122  A3D_ELEM(mask, k, i, j) = bessi0(beta * sqrt(1-(r/M)*(r/M))) * iI0Beta;
123  }
124 
125 }
126 
128  double omega, int mode, double x0, double y0, double z0)
129 {
131  {
132  double r = sqrt( (k - z0) * (k - z0) + (i - y0) * (i - y0) + (j - x0) * (j - x0) );
133  A3D_ELEM(mask, k, i, j) = omega/PI * SINC(omega/PI * r);
134  if (mode == OUTSIDE_MASK)
135  A3D_ELEM(mask, k, i, j) = 1 - A3D_ELEM(mask, k, i, j);
136  }
137 }
138 
140  double omega, double delta, double Deltaw)
141 {
142  MultidimArray<double> kaiser;
143  kaiser.resizeNoCopy(mask);
144  KaiserMask(kaiser, delta, Deltaw);
145  mask.resize(kaiser);
146  mask.setXmippOrigin();
147  SincMask(mask, omega*PI, INNER_MASK);
148  mask *= kaiser;
149 }
150 
152  double x0, double y0, double z0)
153 {
154  double Xdim2 = XMIPP_MAX(1, (XSIZE(mask) - 1) * (XSIZE(mask) - 1));
155  double Ydim2 = XMIPP_MAX(1, (YSIZE(mask) - 1) * (YSIZE(mask) - 1));
156  double Zdim2 = XMIPP_MAX(1, (ZSIZE(mask) - 1) * (ZSIZE(mask) - 1));
158  {
159  double r = sqrt((k - z0) * (k - z0) / Zdim2 + (i - y0) * (i - y0) / Xdim2 + (j - x0) * (j - x0) / Ydim2);
160  A3D_ELEM(mask, k, i, j) = 0.42 + 0.5 * cos(2 * PI * r) + 0.08 * cos(4 * PI * r);
161  if (mode == OUTSIDE_MASK)
162  A3D_ELEM(mask, k, i, j) = 1 - A3D_ELEM(mask, k, i, j);
163  }
164 }
165 
167  double omega, double power_percentage,
168  double x0, double y0, double z0)
169 {
170  MultidimArray<double> blackman;
171 
172  int N = CEIL(1 / omega * CEIL(-1 / 2 + 1 / (PI * (1 - power_percentage / 100))));
173 
174  if (ZSIZE(mask)==1)
175  {
176  // 2D
177  mask.resize(N, N);
178  blackman.resize(N, N);
179  }
180  else
181  {
182  // 3D
183  mask.resize(N, N, N);
184  blackman.resize(N, N, N);
185  }
186  mask.setXmippOrigin();
187  SincMask(mask,omega,INNER_MASK,x0,y0,z0);
188  blackman.setXmippOrigin();
189  BlackmanMask(blackman);
190  mask *= blackman;
191 }
192 
194  double radius, int mode, double x0, double y0, double z0)
195 {
196  mask.initZeros();
197  double radius2 = radius * radius;
198  for (int k=STARTINGZ(mask); k<=FINISHINGZ(mask); ++k)
199  {
200  double diff=k - z0;
201  double z2=diff*diff;
202  for (int i=STARTINGY(mask); i<=FINISHINGY(mask); ++i)
203  {
204  diff=i - y0;
205  double z2y2=z2+diff*diff;
206  for (int j=STARTINGX(mask); j<=FINISHINGX(mask); ++j)
207  {
208  diff=j - x0;
209  double r2 = z2y2+diff*diff;
210  if (r2 <= radius2 && mode == INNER_MASK)
211  A3D_ELEM(mask, k, i, j) = 1;
212  else if (r2 >= radius2 && mode == OUTSIDE_MASK)
213  A3D_ELEM(mask, k, i, j) = 1;
214  }
215  }
216  }
217 }
218 
220  double r1, blobtype blob, int mode,
221  double x0, double y0, double z0)
222 {
224  {
225  double r = sqrt((k - z0) * (k - z0) + (i - y0) * (i - y0) + (j - x0) * (j - x0));
226  if (mode == INNER_MASK)
227  {
228  if (r <= r1)
229  A3D_ELEM(mask, k, i, j) = 1;
230  else
231  A3D_ELEM(mask, k, i, j) = blob_val(r-r1, blob);
232  }
233  else
234  {
235  if (r >= r1)
236  A3D_ELEM(mask, k, i, j) = 1;
237  else
238  A3D_ELEM(mask, k, i, j) = blob_val(r1-r, blob);
239  }
240  }
241 
242 }
243 
245  double R1, double R2, int mode, double x0, double y0, double z0)
246 {
247  mask.initZeros();
248  double R12 = R1 * R1;
249  double R22 = R2 * R2;
251  {
252  double r2 = (k - z0) * (k - z0) + (i - y0) * (i - y0) + (j - x0) * (j - x0);
253  bool in_crown = (r2 >= R12 && r2 <= R22);
254  if (in_crown && mode == INNER_MASK)
255  A3D_ELEM(mask, k, i, j) = 1;
256  else if (!in_crown && mode == OUTSIDE_MASK)
257  A3D_ELEM(mask, k, i, j) = 1;
258  }
259 }
260 
261 void BinaryTubeMask(MultidimArray<int> &mask, double R1, double R2, double H,
262  int mode, double x0, double y0, double z0)
263 {
264  mask.initZeros();
265  double R12 = R1 * R1;
266  double R22 = R2 * R2;
268  {
269  double r2 = (i - y0) * (i - y0) + (j - x0) * (j - x0);
270  bool in_tube = (r2 >= R12 && r2 <= R22 && ABS(k)<H);
271  if (in_tube && mode == INNER_MASK)
272  A3D_ELEM(mask, k, i, j) = 1;
273  else if (!in_tube && mode == OUTSIDE_MASK)
274  A3D_ELEM(mask, k, i, j) = 1;
275  }
276 }
277 
279  double r1, double r2, blobtype blob, int mode,
280  double x0, double y0, double z0)
281 {
283  aux.resize(mask);
284  if (mode == INNER_MASK)
285  {
286  BlobCircularMask(mask, r1, blob,
287  OUTSIDE_MASK, x0, y0, z0);
288  BlobCircularMask(aux, r2, blob,
289  INNER_MASK, x0, y0, z0);
291  {
292  A3D_ELEM(mask, k, i, j) *= A3D_ELEM(aux, k, i, j);
293  }
294  }
295  else
296  {
297  BlobCircularMask(mask, r1, blob,
298  INNER_MASK, x0, y0, z0);
299  BlobCircularMask(aux, r2, blob,
300  OUTSIDE_MASK, x0, y0, z0);
302  {
303  A3D_ELEM(mask, k, i, j) += A3D_ELEM(aux, k, i, j);
304  }
305  }
306 
307 }
308 
309 void BinaryFrameMask(MultidimArray<int> &mask, int Xrect, int Yrect, int Zrect,
310  int mode, double x0, double y0, double z0)
311 {
312  mask.initZeros();
314  {
315  bool in_frame =
316  (j >= x0 + FIRST_XMIPP_INDEX(Xrect)) && (j <= x0 + LAST_XMIPP_INDEX(Xrect)) &&
317  (i >= y0 + FIRST_XMIPP_INDEX(Yrect)) && (i <= y0 + LAST_XMIPP_INDEX(Yrect)) &&
318  (k >= z0 + FIRST_XMIPP_INDEX(Zrect)) && (k <= z0 + LAST_XMIPP_INDEX(Zrect));
319 
320  if ((in_frame && mode == INNER_MASK) || (!in_frame && mode == OUTSIDE_MASK))
321  A3D_ELEM(mask, k, i, j) = 1;
322  }
323 }
324 
326  double sigma, int mode, double x0, double y0, double z0)
327 {
328  double sigma2 = sigma * sigma;
329 
330  double K = 1. / pow(sqrt(2.*PI)*sigma,(double)mask.getDim());
331 
333  {
334  double r2 = (k - z0) * (k - z0) + (i - y0) * (i - y0) + (j - x0) * (j - x0);
335  A3D_ELEM(mask, k, i, j) = K * exp(-0.5 * r2 / sigma2);
336 
337  if (mode == OUTSIDE_MASK)
338  A3D_ELEM(mask, k, i, j) = 1 - A3D_ELEM(mask, k, i, j);
339  }
340 }
341 
342 /*---------------------------------------------------------------------------*/
343 /* 2D Masks */
344 /*---------------------------------------------------------------------------*/
345 
346 #define DWTCIRCULAR2D_BLOCK(s,quadrant) \
347  SelectDWTBlock(s, mask, quadrant, \
348  XX(corner1),XX(corner2),YY(corner1),YY(corner2)); \
349  V2_PLUS_V2(center,corner1,corner2); \
350  V2_BY_CT(center,center,0.5); \
351  FOR_ALL_ELEMENTS_IN_ARRAY2D_BETWEEN(corner1,corner2) { \
352  double r2=(XX(r)-XX(center))*(XX(r)-XX(center))+ \
353  (YY(r)-YY(center))*(YY(r)-YY(center)); \
354  A2D_ELEM(mask,YY(r),XX(r))=(r2<=radius2); \
355  }
356 void BinaryDWTCircularMask2D(MultidimArray<int> &mask, double radius,
357  int smin, int smax, const std::string &quadrant)
358 {
359  double radius2 = radius * radius / (4 * (smin + 1));
360  mask.initZeros();
361  for (int s = smin; s <= smax; s++)
362  {
363  Matrix1D<int> corner1(2);
364  Matrix1D<int> corner2(2);
365  Matrix1D<int> r(2);
366  Matrix1D<double> center(2);
367  if (quadrant == "xx")
368  {
369  DWTCIRCULAR2D_BLOCK(s, "01");
370  DWTCIRCULAR2D_BLOCK(s, "10");
371  DWTCIRCULAR2D_BLOCK(s, "11");
372  }
373  else
374  DWTCIRCULAR2D_BLOCK(s, quadrant);
375  radius2 /= 4;
376  }
377 }
378 
380  double omega, double delta, double Deltaw)
381 {
382  // Convert Deltaw from a frequency normalized to 1, to a freq. normalized to PI
383  Deltaw *= PI;
384  omega *= PI;
385 
386  // Design Kaiser selfWindow
387  double A = -20 * log10(delta);
388  double M = CEIL((A - 8) / (2.285 * Deltaw));
389  double beta;
390  if (A > 50)
391  beta = 0.1102 * (A - 8.7);
392  else if (A >= 21)
393  beta = 0.5842 * pow(A - 21, 0.4) + 0.07886 * (A - 21);
394  else
395  beta = 0;
396 
397  // "Draw" Separable Kaiser Sinc selfWindow
398  mask.resize((size_t)(2*M + 1),(size_t)(2*M + 1));
399  mask.setXmippOrigin();
400  double iI0Beta = 1.0 / bessi0(beta);
402  {
403  mask(i, j) = omega/PI * SINC(omega/PI * i) * omega/PI * SINC(omega/PI * j) *
404  bessi0(beta * sqrt((double)(1 - (i / M) * (i / M)))) * iI0Beta *
405  bessi0(beta * sqrt((double)(1 - (j / M) * (j / M)))) * iI0Beta;
406  }
407 }
408 
409 void mask2D_4neig(MultidimArray<int> &mask, int value, int center)
410 {
411  mask.resize(3, 3);
412  mask.initZeros();
413  mask(0, 1) = mask(1, 0) = mask(1, 2) = mask(2, 1) = value;
414  mask(1, 1) = center;
415 
416 }
417 void mask2D_8neig(MultidimArray<int> &mask, int value1, int value2, int center)
418 {
419  mask.resize(3, 3);
420  mask.initZeros();
421  mask(0, 1) = mask(1, 0) = mask(1, 2) = mask(2, 1) = value1;
422  mask(0, 0) = mask(0, 2) = mask(2, 0) = mask(2, 2) = value2;
423  mask(1, 1) = center;
424 
425 }
426 
427 /*---------------------------------------------------------------------------*/
428 /* 3D Masks */
429 /*---------------------------------------------------------------------------*/
430 
431 #define DWTSPHERICALMASK_BLOCK(s,quadrant) \
432  SelectDWTBlock(s, mask, quadrant, \
433  XX(corner1),XX(corner2),YY(corner1),YY(corner2), \
434  ZZ(corner1),ZZ(corner2)); \
435  V3_PLUS_V3(center,corner1,corner2); \
436  V3_BY_CT(center,center,0.5); \
437  FOR_ALL_ELEMENTS_IN_ARRAY3D_BETWEEN(corner1,corner2) { \
438  double r2=(XX(r)-XX(center))*(XX(r)-XX(center))+ \
439  (YY(r)-YY(center))*(YY(r)-YY(center))+ \
440  (ZZ(r)-ZZ(center))*(ZZ(r)-ZZ(center)); \
441  A3D_ELEM(mask,ZZ(r),YY(r),XX(r))=(r2<=radius2); \
442  }
444  int smin, int smax, const std::string &quadrant)
445 {
446  mask.initZeros();
447  double radius2 = radius * radius / (4 * (smin + 1));
448  for (int s = smin; s <= smax; s++)
449  {
450  Matrix1D<int> corner1(3);
451  Matrix1D<int> corner2(3);
452  Matrix1D<int> r(3);
453  Matrix1D<double> center(3);
454  if (quadrant == "xxx")
455  {
456  DWTSPHERICALMASK_BLOCK(s, "001");
457  DWTSPHERICALMASK_BLOCK(s, "010");
458  DWTSPHERICALMASK_BLOCK(s, "011");
459  DWTSPHERICALMASK_BLOCK(s, "100");
460  DWTSPHERICALMASK_BLOCK(s, "101");
461  DWTSPHERICALMASK_BLOCK(s, "110");
462  DWTSPHERICALMASK_BLOCK(s, "111");
463  }
464  else
465  DWTSPHERICALMASK_BLOCK(s, quadrant);
466  radius2 /= 4;
467  }
468 }
469 
470 
472  double R, double H, int mode, double x0, double y0, double z0)
473 {
474  mask.initZeros();
475  double R2 = R * R;
476  double H_2 = H / 2;
478  {
479  double r2 = (i - y0) * (i - y0) + (j - x0) * (j - x0);
480  int in_cyilinder = (r2 <= R2 && ABS(k - z0) <= H_2);
481  if (in_cyilinder && mode == INNER_MASK)
482  A3D_ELEM(mask, k, i, j) = 1;
483  else if (!in_cyilinder && mode == OUTSIDE_MASK)
484  A3D_ELEM(mask, k, i, j) = 1;
485  }
486 }
487 
488 void BinaryConeMask(MultidimArray<int> &mask, double theta, int mode,bool centerOrigin)
489 {
490  int halfX = mask.xdim/2;
491  int halfY = mask.ydim/2;
492  int halfZ = mask.zdim/2;
493 
494  int minX = -halfX;
495  int minY = -halfY;
496  int minZ = -halfZ;
497 
498  int maxX = (int)((mask.xdim-0.5)/2);
499  int maxY = (int)((mask.ydim-0.5)/2);
500  int maxZ = (int)((mask.zdim-0.5)/2);
501 
503  {
504  int kpp = k;
505  int ipp = i;
506  int jpp = j;
507  if (centerOrigin)
508  {
509  kpp = intWRAP (k+halfZ,minZ,maxZ);
510  ipp = intWRAP (i+halfY,minY,maxY);
511  jpp = intWRAP (j+halfX,minX,maxX);
512  }
513 
514  double rad = tan(PI * theta / 180.) * (double)k;
515  if ((double)(i*i + j*j) < (rad*rad))
516  A3D_ELEM(mask, kpp, ipp, jpp) = 0;
517  else
518  A3D_ELEM(mask, kpp, ipp, jpp) = 1;
519  if (mode == OUTSIDE_MASK)
520  A3D_ELEM(mask, kpp, ipp, jpp) = 1 - A3D_ELEM(mask, kpp, ipp, jpp);
521  }
522 }
523 
524 void BinaryWedgeMask(MultidimArray<int> &mask, double theta0, double thetaF,
525  const Matrix2D<double> &A, bool centerOrigin)
526 {
527  int halfX = mask.xdim/2;
528  int halfY = mask.ydim/2;
529  int halfZ = mask.zdim/2;
530 
531  int minX = -halfX;
532  int minY = -halfY;
533  int minZ = -halfZ;
534 
535  int maxX = (int)((mask.xdim-0.5)/2);
536  int maxY = (int)((mask.ydim-0.5)/2);
537  int maxZ = (int)((mask.zdim-0.5)/2);
538 
539  auto tg0 = -tan(PI * (-90. - thetaF) / 180.);
540  auto tgF = -tan(PI * (90. - theta0) / 180.);
541  if (ABS(tg0) < XMIPP_EQUAL_ACCURACY)
542  tg0=0.;
543  if (ABS(tgF) < XMIPP_EQUAL_ACCURACY)
544  tgF=0.;
545  // ROB: A=A.inv(); A no const
547  {
548  auto di=(double)i;
549  auto dj=(double)j;
550  auto dk=(double)k;
551  auto xp = MAT_ELEM(A, 0, 0) * dj + MAT_ELEM(A, 0, 1) * di + MAT_ELEM(A, 0, 2) * dk;
552  auto zp = MAT_ELEM(A, 2, 0) * dj + MAT_ELEM(A, 2, 1) * di + MAT_ELEM(A, 2, 2) * dk;
553 
554  int kpp = k;
555  int ipp = i;
556  int jpp = j;
557 
558  if (centerOrigin)
559  {
560  kpp = intWRAP (k+halfZ,minZ,maxZ);
561  ipp = intWRAP (i+halfY,minY,maxY);
562  jpp = intWRAP (j+halfX,minX,maxX);
563  }
564 
565  auto limx0 = tg0 * zp;// + 0.5;
566  auto limxF = tgF * zp;// + 0.5;
567  if (zp >= 0)
568  {
569  if (xp <= limx0 || xp >= limxF)
570  {
571  A3D_ELEM(mask, kpp, ipp, jpp) = 1;
572  }
573  else
574  A3D_ELEM(mask, kpp, ipp, jpp) = 0;
575  }
576  else
577  {
578  if (xp <= limxF || xp >= limx0)
579  {
580  A3D_ELEM(mask, kpp, ipp, jpp) = 1;
581  }
582  else
583  A3D_ELEM(mask, kpp, ipp, jpp) = 0;
584  }
585  }
586 }
587 
588 
589 void mask3D_6neig(MultidimArray<int> &mask, int value, int center)
590 {
591  mask.resize(3, 3, 3);
592  mask.initZeros();
593  mask(1, 1, 1) = center;
594  mask(1, 1, 0) = mask(1, 1, 2) = mask(0, 1, 1) = mask(2, 1, 1) = mask(1, 0, 1) = mask(1, 2, 1) = value;
595 
596 }
597 
598 void mask3D_18neig(MultidimArray<int> &mask, int value1, int value2, int center)
599 {
600  mask.resize(3, 3, 3);
601  mask.initZeros();
602  mask(1, 1, 1) = center;
603  //Face neighbors
604  mask(1, 1, 0) = mask(1, 1, 2) = mask(0, 1, 1) = mask(2, 1, 1) = mask(1, 0, 1) = mask(1, 2, 1) = value1;
605  //Edge neighbors
606  mask(0, 1, 0) = mask(0, 0, 1) = mask(0, 1, 2) = mask(0, 2, 1) = value2;
607  mask(1, 0, 0) = mask(1, 2, 0) = mask(1, 0, 2) = mask(1, 2, 2) = value2;
608  mask(2, 1, 0) = mask(2, 0, 1) = mask(2, 1, 2) = mask(2, 2, 1) = value2;
609 
610 
611 }
612 void mask3D_26neig(MultidimArray<int> &mask, int value1, int value2, int value3,
613  int center)
614 {
615  mask.resize(3, 3, 3);
616  mask.initZeros();
617  mask(1, 1, 1) = center;
618  //Face neighbors
619  mask(1, 1, 0) = mask(1, 1, 2) = mask(0, 1, 1) = mask(2, 1, 1) = mask(1, 0, 1) = mask(1, 2, 1) = value1;
620  //Edge neighbors
621  mask(0, 1, 0) = mask(0, 0, 1) = mask(0, 1, 2) = mask(0, 2, 1) = value2;
622  mask(1, 0, 0) = mask(1, 2, 0) = mask(1, 0, 2) = mask(1, 2, 2) = value2;
623  mask(2, 1, 0) = mask(2, 0, 1) = mask(2, 1, 2) = mask(2, 2, 1) = value2;
624  //Vertex neighbors
625  mask(0, 0, 0) = mask(0, 0, 2) = mask(0, 2, 0) = mask(0, 2, 2) = value3;
626  mask(2, 0, 0) = mask(2, 0, 2) = mask(2, 2, 0) = mask(2, 2, 2) = value3;
627 
628 }
629 
630 /*---------------------------------------------------------------------------*/
631 /* Mask Type */
632 /*---------------------------------------------------------------------------*/
633 // Constructor -------------------------------------------------------------
634 Mask::Mask(int _allowed_data_types)
635 {
636  clear();
637  allowed_data_types = _allowed_data_types;
638 }
639 
640 // Default values ----------------------------------------------------------
642 {
643  type = NO_MASK;
644  mode = INNER_MASK;
645  H = R1 = R2 = sigma = 0;
646  imask.clear();
647  dmask.clear();
648  allowed_data_types = 0;
649  fn_mask = "";
650  x0 = y0 = z0 = 0;
651 }
652 
653 // Resize ------------------------------------------------------------------
654 void Mask::resize(size_t Xdim)
655 {
656  switch (datatype())
657  {
658  case INT_MASK:
659  imask.resize(Xdim);
661  break;
662  case DOUBLE_MASK:
663  dmask.resize(Xdim);
665  break;
666  }
667 }
668 
669 void Mask::resize(size_t Ydim, size_t Xdim)
670 {
671  switch (datatype())
672  {
673  case INT_MASK:
674  imask.resize(Ydim, Xdim);
676  break;
677  case DOUBLE_MASK:
678  dmask.resize(Ydim, Xdim);
680  break;
681  }
682 }
683 
684 void Mask::resize(size_t Zdim, size_t Ydim, size_t Xdim)
685 {
686  switch (datatype())
687  {
688  case INT_MASK:
689  imask.resize(Zdim, Ydim, Xdim);
691  break;
692  case DOUBLE_MASK:
693  dmask.resize(Zdim, Ydim, Xdim);
695  break;
696  }
697 }
698 
699 //#ifdef NEVER
700 // Read from command lines -------------------------------------------------
701 void Mask::read(int argc, const char **argv)
702 {
703  int i = paremeterPosition(argc, argv, "--center");
704  if (i != -1)
705  {
706  if (i + 3 >= argc)
707  REPORT_ERROR(ERR_UNCLASSIFIED, "Mask: Not enough parameters after -center");
708  x0 = textToFloat(argv[i+1]);
709  y0 = textToFloat(argv[i+2]);
710  z0 = textToFloat(argv[i+3]);
711  }
712  else
713  {
714  x0 = y0 = z0 = 0;
715  }
716 
717  i = paremeterPosition(argc, argv, "--mask");
718  if (i == -1)
719  {
720  clear();
721  return;
722  }
723  if (i + 1 >= argc)
724  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: --mask with no mask_type");
725  // Circular mask ........................................................
726  if (strcmp(argv[i+1], "circular") == 0)
727  {
728  if (i + 2 >= argc)
729  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: circular mask with no radius");
730  if (!(allowed_data_types & INT_MASK))
731  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
732  R1 = textToFloat(argv[i+2]);
733  if (R1 < 0)
734  {
735  mode = INNER_MASK;
736  R1 = ABS(R1);
737  }
738  else if (R1 > 0)
739  mode = OUTSIDE_MASK;
740  else
741  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: circular mask with radius 0");
743  // Circular DWT mask ....................................................
744  }
745  else if (strcmp(argv[i+1], "DWT_circular") == 0)
746  {
747  if (i + 5 >= argc)
748  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: DWT circular mask with not enough parameters");
749  if (!(allowed_data_types & INT_MASK))
750  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
751  R1 = ABS(textToFloat(argv[i+2]));
752  smin = textToInteger(argv[i+3]);
753  smax = textToInteger(argv[i+4]);
754  quadrant = argv[i+5];
756  // Rectangular mask .....................................................
757  }
758  else if (strcmp(argv[i+1], "rectangular") == 0)
759  {
760  if (i + 3 >= argc)
761  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: rectangular mask needs at least two dimensions");
762  if (!(allowed_data_types & INT_MASK))
763  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
764  Xrect = textToInteger(argv[i+2]);
765  Yrect = textToInteger(argv[i+3]);
766  if (i + 4 < argc)
767  {
768  Zrect = textToInteger(argv[i+4]);
769  if (argv[i+4][0] != '-')
770  Zrect = ABS(Zrect);
771  }
772  else
773  Zrect = 0;
774  if (Xrect < 0 && Yrect < 0 && Zrect <= 0)
775  {
776  mode = INNER_MASK;
777  Xrect = ABS(Xrect);
778  Yrect = ABS(Yrect);
779  Zrect = ABS(Zrect);
780  }
781  else if (Xrect > 0 && Yrect > 0 && Zrect >= 0)
782  mode = OUTSIDE_MASK;
783  else
784  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for rectangle");
786  // Cone mask ............................................................
787  }
788  else if (strcmp(argv[i+1], "cone") == 0)
789  {
790  if (i + 2 >= argc)
791  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: cone mask needs one angle");
792  if (!(allowed_data_types & INT_MASK))
793  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
794  R1 = textToFloat(argv[i+2]);
795  if (R1 < 0)
796  {
797  mode = INNER_MASK;
798  R1 = ABS(R1);
799  }
800  else
801  mode = OUTSIDE_MASK;
803  // Wedge mask ............................................................
804  }
805  else if (strcmp(argv[i+1], "wedge") == 0)
806  {
807  if (i + 3 >= argc)
808  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: wedge mask needs two angles");
810  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
811  R1 = textToFloat(argv[i+2]);
812  R2 = textToFloat(argv[i+3]);
814  // Crown mask ...........................................................
815  }
816  else if (strcmp(argv[i+1], "crown") == 0)
817  {
818  if (i + 3 >= argc)
819  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: crown mask needs two radii");
820  if (!(allowed_data_types & INT_MASK))
821  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
822  R1 = textToFloat(argv[i+2]);
823  R2 = textToFloat(argv[i+3]);
824  if (R1 < 0 && R2 < 0)
825  {
826  mode = INNER_MASK;
827  R1 = ABS(R1);
828  R2 = ABS(R2);
829  }
830  else if (R1 > 0 && R2 > 0)
831  mode = OUTSIDE_MASK;
832  else
833  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for crown");
835  // Cylinder mask ........................................................
836  }
837  else if (strcmp(argv[i+1], "cylinder") == 0)
838  {
839  if (i + 3 >= argc)
840  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: cylinder mask needs a radius and a height");
841  if (!(allowed_data_types & INT_MASK))
842  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
843  R1 = textToFloat(argv[i+2]);
844  H = textToFloat(argv[i+3]);
845  if (R1 < 0 && H < 0)
846  {
847  mode = INNER_MASK;
848  R1 = ABS(R1);
849  H = ABS(H);
850  }
851  else if (R1 > 0 && H > 0)
852  mode = OUTSIDE_MASK;
853  else
854  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for cylinder");
856  // Gaussian mask ........................................................
857  }
858  else if (strcmp(argv[i+1], "tube") == 0)
859  {
860  if (i + 4 >= argc)
861  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: tube mask needs two radii and a height");
862  if (!(allowed_data_types & INT_MASK))
863  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
864  R1 = textToFloat(argv[i+2]);
865  R2 = textToFloat(argv[i+3]);
866  H = textToFloat(argv[i+4]);
867  if (R1 < 0 && R2 < 0 && H<0)
868  {
869  mode = INNER_MASK;
870  R1 = ABS(R1);
871  R2 = ABS(R2);
872  H=ABS(H);
873  }
874  else if (R1 > 0 && R2 > 0 && H>0)
875  mode = OUTSIDE_MASK;
876  else
877  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for crown");
878  type = BINARY_TUBE;
879  // Cylinder mask ........................................................
880  }
881  else if (strcmp(argv[i+1], "gaussian") == 0)
882  {
883  if (i + 2 >= argc)
884  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: gaussian mask needs a sigma");
886  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
887  sigma = textToFloat(argv[i+2]);
888  if (sigma < 0)
889  {
890  mode = INNER_MASK;
891  sigma = ABS(sigma);
892  }
893  else
894  mode = OUTSIDE_MASK;
896  // Raised cosine mask ...................................................
897  }
898  else if (strcmp(argv[i+1], "raised_cosine") == 0)
899  {
900  if (i + 3 >= argc)
901  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: raised_cosine mask needs two radii");
902  if (!(allowed_data_types & INT_MASK))
903  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
904  R1 = textToFloat(argv[i+2]);
905  R2 = textToFloat(argv[i+3]);
906  if (R1 < 0 && R2 < 0)
907  {
908  mode = INNER_MASK;
909  R1 = ABS(R1);
910  R2 = ABS(R2);
911  }
912  else if (R1 > 0 && R2 > 0)
913  mode = OUTSIDE_MASK;
914  else
915  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for raised_cosine");
917  // Raised crown mask ....................................................
918  }
919  else if (strcmp(argv[i+1], "raised_crown") == 0)
920  {
921  if (i + 4 >= argc)
922  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: raised_crown mask needs two radii & a width");
923  if (!(allowed_data_types & INT_MASK))
924  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
925  R1 = textToFloat(argv[i+2]);
926  R2 = textToFloat(argv[i+3]);
927  pix_width = textToFloat(argv[i+4]);
928  if (R1 < 0 && R2 < 0)
929  {
930  mode = INNER_MASK;
931  R1 = ABS(R1);
932  R2 = ABS(R2);
933  }
934  else if (R1 > 0 && R2 > 0)
935  mode = OUTSIDE_MASK;
936  else
937  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for raised_cosine");
939  // Blob circular mask ....................................................
940  }
941  else if (strcmp(argv[i+1], "blob_circular") == 0)
942  {
943  if (i + 3 >= argc)
944  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: blob_circular mask needs one radius and a width");
945  if (!(allowed_data_types & INT_MASK))
946  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
947  R1 = textToFloat(argv[i+2]);
948  double aux = textToFloat(argv[i+3]);
949  blob_radius= ABS(aux);
950  if (aux < 0)
951  mode = INNER_MASK;
952  else if (aux > 0)
953  mode = OUTSIDE_MASK;
954  else
955  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for blob_circular");
957  blob_order= textToInteger(getParameter(argc, argv, "-m", "2"));
958  blob_alpha= textToFloat(getParameter(argc, argv, "-a", "10.4"));
959 
960  // Raised crown mask ....................................................
961  }
962  else if (strcmp(argv[i+1], "blob_crown") == 0)
963  {
964  if (i + 4 >= argc)
965  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: blob_crown mask needs two radii and a with");
966  if (!(allowed_data_types & INT_MASK))
967  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
968  R1 = textToFloat(argv[i+2]);
969  R2 = textToFloat(argv[i+3]);
970  double aux = textToFloat(argv[i+4]);
971  blob_radius= ABS(aux);
972  if (aux < 0)
973  mode = INNER_MASK;
974  else if (aux > 0)
975  mode = OUTSIDE_MASK;
976  else
977  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for blob_crown");
979  blob_order= textToInteger(getParameter(argc, argv, "-m", "2"));
980  blob_alpha= textToFloat(getParameter(argc, argv, "-a", "10.4"));
981 
982  // Blackman mask ........................................................
983  }
984  else if (strcmp(argv[i+1], "blackman") == 0)
985  {
986  mode = INNER_MASK;
988  // Sinc mask ............................................................
989  }
990  else if (strcmp(argv[i+1], "sinc") == 0)
991  {
992  if (i + 2 >= argc)
993  REPORT_ERROR(ERR_ARG_MISSING, "MaskProgram: sinc mask needs a frequency");
994  if (!(allowed_data_types & INT_MASK))
995  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
996  omega = textToFloat(argv[i+2]);
997  if (omega < 0)
998  {
999  mode = INNER_MASK;
1000  omega = ABS(omega);
1001  }
1002  else
1003  mode = OUTSIDE_MASK;
1004  type = SINC_MASK;
1005  }
1006  else if (strcmp(argv[i+1], "binary_file") == 0)
1007  {
1008  fn_mask = argv[i+2];
1010  }
1011  else if (strcmp(argv[i+1], "real_file") == 0)
1012  {
1013  fn_mask = argv[i+2];
1014  type = READ_REAL_MASK;
1015  }
1016  else
1017  REPORT_ERROR(ERR_ARG_INCORRECT,"Incorrect mask type");
1018 }
1019 //#endif
1020 // Show --------------------------------------------------------------------
1021 void Mask::show() const
1022 {
1023 #define SHOW_MODE \
1024  if (mode==INNER_MASK) std::cout << " mode=INNER MASK\n"; \
1025  else std::cout << " mode=OUTER MASK\n";
1026 #define SHOW_CENTER \
1027  std::cout << " (x0,y0,z0)=(" << x0 << "," << y0 << "," << z0 << ")\n";
1028  switch (type)
1029  {
1030  case NO_MASK:
1031  std::cout << "Mask type: No mask\n";
1032  break;
1033  case BINARY_CIRCULAR_MASK:
1034  std::cout << "Mask type: Binary circular\n"
1035  << " R=" << R1 << std::endl;
1036  SHOW_MODE;
1037  SHOW_CENTER;
1038  break;
1040  std::cout << "Mask type: Binary DWT circular\n"
1041  << " R=" << R1 << std::endl
1042  << " smin=" << smin << std::endl
1043  << " smax=" << smax << std::endl
1044  << " quadrant=" << quadrant << std::endl;
1045  break;
1046  case BINARY_CROWN_MASK:
1047  std::cout << "Mask type: Binary crown\n"
1048  << " R1=" << R1 << std::endl
1049  << " R2=" << R2 << std::endl;
1050  SHOW_MODE;
1051  SHOW_CENTER;
1052  break;
1053  case BINARY_CYLINDER_MASK:
1054  std::cout << "Mask type: Cylinder\n"
1055  << " R1=" << R1 << std::endl
1056  << " H=" << H << std::endl;
1057  SHOW_MODE;
1058  SHOW_CENTER;
1059  break;
1060  case BINARY_TUBE:
1061  std::cout << "Mask type: Tube\n"
1062  << " R1=" << R1 << std::endl
1063  << " R2=" << R2 << std::endl
1064  << " H=" << H << std::endl;
1065  SHOW_MODE;
1066  SHOW_CENTER;
1067  break;
1068  case BINARY_FRAME_MASK:
1069  std::cout << "Mask type: Frame\n"
1070  << " Xrect=" << Xrect << std::endl
1071  << " Yrect=" << Yrect << std::endl;
1072  SHOW_MODE;
1073  SHOW_CENTER;
1074  break;
1075  case GAUSSIAN_MASK:
1076  std::cout << "Mask type: Gaussian\n"
1077  << " sigma=" << sigma << std::endl;
1078  SHOW_MODE;
1079  SHOW_CENTER;
1080  break;
1081  case RAISED_COSINE_MASK:
1082  std::cout << "Mask type: Raised cosine\n"
1083  << " R1=" << R1 << std::endl
1084  << " R2=" << R2 << std::endl;
1085  SHOW_MODE;
1086  SHOW_CENTER;
1087  break;
1088  case RAISED_CROWN_MASK:
1089  std::cout << "Mask type: Raised crown\n"
1090  << " R1=" << R1 << std::endl
1091  << " R2=" << R2 << std::endl
1092  << " pixwidth=" << pix_width << std::endl;
1093  SHOW_MODE;
1094  SHOW_CENTER;
1095  break;
1096  case BLOB_CIRCULAR_MASK:
1097  std::cout << "Mask type: Blob circular\n"
1098  << " R1=" << R1 << std::endl
1099  << " blob radius=" << blob_radius << std::endl
1100  << " blob order=" << blob_order << std::endl
1101  << " blob alpha=" << blob_alpha << std::endl;
1102  SHOW_MODE;
1103  SHOW_CENTER;
1104  break;
1105  case BLOB_CROWN_MASK:
1106  std::cout << "Mask type: Blob crown\n"
1107  << " R1=" << R1 << std::endl
1108  << " R2=" << R2 << std::endl
1109  << " blob radius=" << blob_radius << std::endl
1110  << " blob order=" << blob_order << std::endl
1111  << " blob alpha=" << blob_alpha << std::endl;
1112  SHOW_MODE;
1113  SHOW_CENTER;
1114  break;
1115  case BLACKMAN_MASK:
1116  std::cout << "Mask type: Blackman\n";
1117  SHOW_MODE;
1118  SHOW_CENTER;
1119  break;
1120  case SINC_MASK:
1121  std::cout << "Mask type: Sinc\n"
1122  << " w=" << omega << std::endl;
1123  SHOW_MODE;
1124  SHOW_CENTER;
1125  break;
1126  default:
1127  std::cout << "Mask type: Read from disk\n"
1128  << " File=" << fn_mask << std::endl;
1129  break;
1130  }
1131 }
1132 
1133 // Usage -------------------------------------------------------------------
1134 void Mask::usage() const
1135 {
1136  std::cerr << "Mask usage:\n";
1137  std::cerr << " [-center <x0=0> <y0=0> <z0=0>]: Center of the mask\n";
1139  std::cerr << " [-mask circular <R> : circle/sphere mask\n"
1140  << " if R>0 => outside R\n"
1141  << " if R<0 => inside R\n"
1142  << " [-mask DWT_circular <R> <smin> <smax>: circle/sphere mask\n"
1143  << " smin and smax define the scales\n"
1144  << " to be kept\n"
1145  << " |-mask rectangular <Xrect> <Yrect> [<Zrect>]: 2D or 3D rectangle\n"
1146  << " if X,Y,Z > 0 => outside rectangle\n"
1147  << " if X,Y,Z < 0 => inside rectangle\n"
1148  << " |-mask crown <R1> <R2> : 2D or 3D crown\n"
1149  << " if R1,R2 > 0 => outside crown\n"
1150  << " if R1,R2 < 0 => inside crown\n"
1151  << " |-mask cylinder <R> <H> : 2D circle or 3D cylinder\n"
1152  << " if R,H > 0 => outside cylinder\n"
1153  << " if R,H < 0 => inside cylinder\n"
1154  << " |-mask tube <R1> <R2> <H> : 2D or 3D tube\n"
1155  << " if R1,R2,H > 0 => outside tube\n"
1156  << " if R1,R2,H < 0 => inside tube\n"
1157  << " |-mask cone <theta> : 3D cone (parallel to Z) \n"
1158  << " if theta > 0 => outside cone\n"
1159  << " if theta < 0 => inside cone\n"
1160  << " |-mask wedge <th0> <thF> : 3D missing-wedge mask for data \n"
1161  << " collected between tilting angles \n"
1162  << " th0 and thF (around the Y-axis) \n"
1163  << " |-mask <binary file> : Read from file\n"
1164  ;
1166  std::cerr << " |-mask gaussian <sigma> : 2D or 3D gaussian\n"
1167  << " if sigma > 0 => outside gaussian\n"
1168  << " if sigma < 0 => inside gaussian\n"
1169  << " |-mask raised_cosine <R1> <R2>: 2D or 3D raised_cosine\n"
1170  << " if R1,R2 > 0 => outside sphere\n"
1171  << " if R1,R2 < 0 => inside sphere\n"
1172  << " |-mask raised_crown <R1> <R2> <pixwidth>: 2D or 3D raised_crown\n"
1173  << " if R1,R2 > 0 => outside crown\n"
1174  << " if R1,R2 < 0 => inside crown\n"
1175  << " |-mask blob_circular <R1> <blob_radius>: 2D or 3D blob circular\n"
1176  << " if blob_radius > 0 => outside blob\n"
1177  << " if blob_radius < 0 => inside blob\n"
1178  << " |-mask blob_crown <R1> <R2> <blob_radius>: 2D or 3D blob_crown\n"
1179  << " if blob_radius > 0 => outside crown\n"
1180  << " if blob_radius < 0 => inside crown\n"
1181  << " [ -m <blob_order=2> : Order of blob\n"
1182  << " [ -a <blob_alpha=10.4> : Alpha of blob\n"
1183  << " |-mask blackman : 2D or 3D Blackman mask\n"
1184  << " always inside blackman\n"
1185  << " |-mask sinc <w>] : 2D or 3D sincs\n"
1186  << " if w > 0 => outside sinc\n"
1187  << " if w < 0 => inside sinc\n"
1188  ;
1189 }
1190 
1191 // Write -------------------------------------------------------------------
1193 {
1194  Image<double> img;
1195  if (datatype() == INT_MASK)
1196  typeCast(imask, img());
1197  else if (datatype() == DOUBLE_MASK)
1198  img()=dmask;
1199  img.write(fn);
1200 }
1201 
1202 
1204  const char* prefix, const char* comment, bool moreOptions)
1205 {
1206  char tempLine[256];
1207  char tempLine2[512];
1208 
1209  char advanced=' ';
1210  if (moreOptions)
1211  advanced='+';
1212  if(prefix == nullptr)
1213  sprintf(tempLine, " [--mask%c <mask_type=circular>] ",advanced);
1214  else
1215  sprintf(tempLine,"%s --mask%c <mask_type=circular> ", prefix,advanced);
1216  if (comment != nullptr)
1217  sprintf(tempLine2, "%s : %s", tempLine, comment);
1218  else
1219  strcpy(tempLine2,tempLine);
1220 
1221  program->addParamsLine(tempLine2);
1222  program->addParamsLine(" where <mask_type> ");
1223  // program->addParamsLine("== INT MASK ==");
1224  if (allowed_data_types & INT_MASK)
1225  {
1226  program->addParamsLine(" circular <R> : circle/sphere mask");
1227  program->addParamsLine(" :if R>0 => outside R");
1228  program->addParamsLine(" :if R<0 => inside R");
1229  program->addParamsLine(" DWT_circular <R> <smin> <smax>: circle/sphere mask");
1230  program->addParamsLine(" : smin and smax define the scales to be kept");
1231  program->addParamsLine(" rectangular <Xrect> <Yrect> <Zrect=-1>: 2D or 3D rectangle");
1232  program->addParamsLine(" :if X,Y,Z > 0 => outside rectangle");
1233  program->addParamsLine(" :if X,Y,Z < 0 => inside rectangle");
1234  program->addParamsLine(" crown <R1> <R2> : 2D or 3D crown");
1235  program->addParamsLine(" :if R1,R2 > 0 => outside crown");
1236  program->addParamsLine(" :if R1,R2 < 0 => inside crown");
1237  program->addParamsLine(" cylinder <R> <H> : 2D circle or 3D cylinder");
1238  program->addParamsLine(" :if R,H > 0 => outside cylinder");
1239  program->addParamsLine(" :if R,H < 0 => inside cylinder");
1240  program->addParamsLine(" tube <R1> <R2> <H> : 3D tube");
1241  program->addParamsLine(" :if R1,R2,H > 0 => outside tube");
1242  program->addParamsLine(" :if R1,R2,H < 0 => inside tube");
1243  program->addParamsLine(" cone <theta> : 3D cone (parallel to Z) ");
1244  program->addParamsLine(" :if theta > 0 => outside cone");
1245  program->addParamsLine(" :if theta < 0 => inside cone");
1246  program->addParamsLine(" wedge <th0> <thF> : 3D missing-wedge mask for data ");
1247  program->addParamsLine(" :collected between tilting angles ");
1248  program->addParamsLine(" :th0 and thF (around the Y-axis) ");
1249  program->addParamsLine(" binary_file <binary_file> : Read from file and cast to binary");
1250  }
1251  //program->addParamsLine("== DOUBLE MASK ==");
1252  if (allowed_data_types & DOUBLE_MASK)
1253  {
1254  program->addParamsLine(" real_file <float_file> : Read from file and do not cast");
1255  program->addParamsLine(" gaussian <sigma> : 2D or 3D gaussian");
1256  program->addParamsLine(" :if sigma > 0 => outside gaussian");
1257  program->addParamsLine(" : if sigma < 0 => inside gaussian");
1258  program->addParamsLine(" raised_cosine <R1> <R2>: 2D or 3D raised_cosine");
1259  program->addParamsLine(" : if R1,R2 > 0 => outside sphere");
1260  program->addParamsLine(" : if R1,R2 < 0 => inside sphere");
1261  program->addParamsLine(" raised_crown <R1> <R2> <pixwidth>: 2D or 3D raised_crown");
1262  program->addParamsLine(" : if R1,R2 > 0 => outside sphere");
1263  program->addParamsLine(" : if R1,R2 < 0 => inside sphere");
1264  program->addParamsLine(" blob_circular <R1> <blob_radius>: 2D or 3D blob circular");
1265  program->addParamsLine(" : if blob_radius > 0 => outside sphere");
1266  program->addParamsLine(" : if blob_radius < 0 => inside sphere");
1267  program->addParamsLine(" blob_crown <R1> <R2> <blob_radius>: 2D or 3D blob_crown");
1268  program->addParamsLine(" : if blob_radius > 0 => outside sphere");
1269  program->addParamsLine(" : if blob_radius < 0 => inside sphere");
1270  program->addParamsLine(" blackman : 2D or 3D Blackman mask");
1271  program->addParamsLine(" : always inside blackman");
1272  program->addParamsLine(" sinc <w> : 2D or 3D sincs");
1273  program->addParamsLine(" : if w > 0 => outside sinc");
1274  program->addParamsLine(" : if w < 0 => inside sinc");
1275  sprintf(tempLine, " [ -m%c <blob_order=2>] : Order of blob",advanced);
1276  program->addParamsLine(tempLine);
1277  sprintf(tempLine, " [ -a%c <blob_alpha=10.4>] : Alpha of blob",advanced);
1278  program->addParamsLine(tempLine);
1279  }
1280  sprintf(tempLine, " [--center%c <x0=0> <y0=0> <z0=0>]: mask center",advanced);
1281  program->addParamsLine(tempLine);
1282 }
1283 
1285 {
1286  x0 = y0 = z0 = 0;
1287  x0 = program->getDoubleParam("--center",0);
1288  y0 = program->getDoubleParam("--center",1);
1289  z0 = program->getDoubleParam("--center",2);
1290  mask_type = program->getParam("--mask");
1291 
1292  /* Circular mask ........................................................*/
1293  if (mask_type == "circular")
1294  {
1295  if (!(allowed_data_types & INT_MASK))
1296  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1297  R1 = program->getDoubleParam("--mask","circular");
1298  if (R1 < 0)
1299  {
1301  R1 = ABS(R1);
1302  }
1303  else if (R1 > 0)
1305  else
1306  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: circular mask with radius 0");
1308  }
1309  /*// Circular DWT mask ....................................................*/
1310  else if (mask_type == "DWT_circular")
1311  {
1312  if (!(allowed_data_types & INT_MASK))
1313  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1314  R1 = program->getDoubleParam("--mask","DWT_circular",0);
1315  smin = program->getIntParam("--mask","DWT_circular",1);
1316  smax = program->getIntParam("--mask","DWT_circular",2);
1317  quadrant = program->getParam("--mask","DWT_circular",3);
1319  }
1320  /*// Rectangular mask .....................................................*/
1321  else if (mask_type == "rectangular")
1322  {
1323  if (!(allowed_data_types & INT_MASK))
1324  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1325  Xrect = program->getIntParam("--mask","rectangular",0);
1326  Yrect = program->getIntParam("--mask","rectangular",1);
1327  Zrect = program->getIntParam("--mask","rectangular",2);
1328  if (Xrect < 0 && Yrect < 0 && Zrect <= 1)
1329  {
1331  Xrect = ABS(Xrect);
1332  Yrect = ABS(Yrect);
1333  Zrect = ABS(Zrect);
1334  }
1335  else if (Xrect > 0 && Yrect > 0 && Zrect >= -1)
1337  else
1338  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for rectangle");
1340  }
1341  /*// Cone mask ............................................................*/
1342  else if (mask_type == "cone")
1343  {
1344  if (!(allowed_data_types & INT_MASK))
1345  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1346  R1 = program->getDoubleParam("--mask","cone");
1347  if (R1 < 0)
1348  {
1350  R1 = ABS(R1);
1351  }
1352  else
1355  }
1356  /*// Wedge mask ............................................................*/
1357  else if (mask_type == "wedge")
1358  {
1360  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1361  R1 = program->getDoubleParam("--mask","wedge",0);
1362  R2 = program->getDoubleParam("--mask","wedge",1);
1364  }
1365  /*// Crown mask ...........................................................*/
1366  else if (mask_type == "crown")
1367  {
1368  if (!(allowed_data_types & INT_MASK))
1369  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1370 
1371  R1 = program->getDoubleParam("--mask","crown",0);
1372  R2 = program->getDoubleParam("--mask","crown",1);
1373 
1374  if (R1 < 0 && R2 < 0)
1375  {
1377  R1 = ABS(R1);
1378  R2 = ABS(R2);
1379  }
1380  else if (R1 > 0 && R2 > 0)
1382  else
1383  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for crown");
1384 
1386  }
1387  /*// Cylinder mask ........................................................*/
1388  else if (mask_type == "cylinder")
1389  {
1390  if (!(allowed_data_types & INT_MASK))
1391  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1392 
1393  R1 = program->getDoubleParam("--mask","cylinder",0);
1394  H = program->getDoubleParam("--mask","cylinder",1);
1395 
1396  if (R1 < 0 && H < 0)
1397  {
1399  R1 = ABS(R1);
1400  H = ABS(H);
1401  }
1402  else if (R1 > 0 && H > 0)
1404  else
1405  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for cylinder");
1406 
1408  }
1409  /*// Crown mask ...........................................................*/
1410  else if (mask_type == "tube")
1411  {
1412  if (!(allowed_data_types & INT_MASK))
1413  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1414 
1415  R1 = program->getDoubleParam("--mask","tube",0);
1416  R2 = program->getDoubleParam("--mask","tube",1);
1417  H = program->getDoubleParam("--mask","tube",2);
1418 
1419  if (R1 < 0 && R2 < 0 && H<0)
1420  {
1422  R1 = ABS(R1);
1423  R2 = ABS(R2);
1424  H=ABS(H);
1425  }
1426  else if (R1 > 0 && R2 > 0 && H>0)
1428  else
1429  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for tube");
1430 
1431  type = BINARY_TUBE;
1432  }
1433  /*// Gaussian mask ........................................................*/
1434  else if (mask_type == "gaussian")
1435  {
1437  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
1438 
1439  sigma = program->getDoubleParam("--mask","gaussian");
1440 
1441  if (sigma < 0)
1442  {
1444  sigma = ABS(sigma);
1445  }
1446  else
1448 
1449  type = GAUSSIAN_MASK;
1450  }
1451  /*// Raised cosine mask ...................................................*/
1452  else if (mask_type == "raised_cosine")
1453  {
1454  if (!(allowed_data_types & INT_MASK))
1455  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
1456 
1457  R1 = program->getDoubleParam("--mask","raised_cosine",0);
1458  R2 = program->getDoubleParam("--mask","raised_cosine",1);
1459 
1460  if (R1 < 0 && R2 < 0)
1461  {
1463  R1 = ABS(R1);
1464  R2 = ABS(R2);
1465  }
1466  else if (R1 > 0 && R2 > 0)
1468  else
1469  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for raised_cosine");
1470 
1472  }
1473  /*// Raised crown mask ....................................................*/
1474  else if (mask_type == "raised_crown")
1475  {
1476  if (!(allowed_data_types & INT_MASK))
1477  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
1478 
1479  R1 = program->getDoubleParam("--mask","raised_crown",0);
1480  R2 = program->getDoubleParam("--mask","raised_crown",1);
1481  pix_width = program->getDoubleParam("--mask","raised_crown",2);
1482 
1483  if (R1 < 0 && R2 < 0)
1484  {
1486  R1 = ABS(R1);
1487  R2 = ABS(R2);
1488  }
1489  else if (R1 > 0 && R2 > 0)
1491  else
1492  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for raised_cosine");
1493 
1495  }
1496  /*// Blob circular mask ....................................................*/
1497  else if (mask_type == "blob_circular")
1498  {
1499  if (!(allowed_data_types & INT_MASK))
1500  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
1501 
1502  R1 = program->getDoubleParam("--mask","blob_circular",0);
1503  double aux = program->getDoubleParam("--mask","blob_circular",1);
1504  blob_radius= ABS(aux);
1505 
1506  if (aux < 0)
1508  else if (aux > 0)
1510  else
1511  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for blob_circular");
1512 
1514  blob_order= program->getIntParam("-m");
1515  blob_alpha= program->getIntParam("-a");
1516  }
1517  /*// Raised crown mask ....................................................*/
1518  else if (mask_type == "blob_crown")
1519  {
1520  if (!(allowed_data_types & INT_MASK))
1521  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: continuous masks are not allowed");
1522 
1523  R1 = program->getDoubleParam("--mask","blob_crown",0);
1524  R2 = program->getDoubleParam("--mask","blob_crown",1);
1525  double aux = program->getDoubleParam("--mask","blob_crown",2);
1526  blob_radius= ABS(aux);
1527 
1528  if (aux < 0)
1530  else if (aux > 0)
1532  else
1533  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: cannot determine mode for blob_crown");
1534 
1536  blob_order= program->getIntParam("-m");
1537  blob_alpha= program->getDoubleParam("-a");
1538  }
1539  /*// Blackman mask ........................................................*/
1540  else if (mask_type == "blackman")
1541  {
1543  type = BLACKMAN_MASK;
1544  }
1545  /*// Sinc mask ............................................................*/
1546  else if (mask_type == "sinc")
1547  {
1548  if (!(allowed_data_types & INT_MASK))
1549  REPORT_ERROR(ERR_ARG_INCORRECT, "MaskProgram: binary masks are not allowed");
1550 
1551  omega = program->getDoubleParam("--mask","sinc");
1552 
1553  if (omega < 0)
1554  {
1556  omega = ABS(omega);
1557  }
1558  else
1560 
1561  type = SINC_MASK;
1562  }
1563  else if (mask_type == "binary_file")
1564  {
1565  fn_mask = program->getParam("--mask","binary_file");
1567  }
1568  else if (mask_type == "real_file")
1569  {
1570  fn_mask = program->getParam("--mask","real_file");
1571  type = READ_REAL_MASK;
1572  }
1573  else
1574  REPORT_ERROR(ERR_DEBUG_IMPOSIBLE,"You should never see this meessage, Mask::readParams ");
1575 }
1576 // Generate mask --------------------------------------------------------
1577 void Mask::generate_mask(bool apply_geo)
1578 {
1579  ImageGeneric img;
1580  Matrix2D<double> AA(4, 4);
1581  AA.initIdentity();
1582  blobtype blob;
1584  {
1585  blob.radius = blob_radius;
1586  blob.order = blob_order;
1587  blob.alpha = blob_alpha;
1588  }
1589 
1590  switch (type)
1591  {
1592  case NO_MASK:
1593  imask.initConstant(1);
1594  break;
1595  case BINARY_CIRCULAR_MASK:
1597  break;
1600  break;
1603  break;
1604  case BINARY_CROWN_MASK:
1605  BinaryCrownMask(imask, R1, R2, mode, x0, y0, z0);
1606  break;
1607  case BINARY_CYLINDER_MASK:
1609  break;
1610  case BINARY_TUBE:
1611  BinaryTubeMask(imask, R1, R2, H, mode, x0, y0, z0);
1612  break;
1613  case BINARY_FRAME_MASK:
1615  break;
1616  case BINARY_CONE_MASK:
1618  break;
1619  case BINARY_WEDGE_MASK:
1620  BinaryWedgeMask(imask, R1, R2, AA);
1621  break;
1622  case GAUSSIAN_MASK:
1624  break;
1625  case RAISED_COSINE_MASK:
1627  break;
1628  case RAISED_CROWN_MASK:
1630  break;
1631  case BLOB_CIRCULAR_MASK:
1632  BlobCircularMask(dmask, R1, blob, mode, x0, y0, z0);
1633  break;
1634  case BLOB_CROWN_MASK:
1635  BlobCrownMask(dmask, R1, R2, blob, mode, x0, y0, z0);
1636  break;
1637  case BLACKMAN_MASK:
1638  BlackmanMask(dmask, mode, x0, y0, z0);
1639  break;
1640  case SINC_MASK:
1641  SincMask(dmask, omega, mode, x0, y0, z0);
1642  break;
1643  case READ_BINARY_MASK:
1644  img.readMapped(fn_mask);
1645  img().getImage(imask);
1647  break;
1648  case READ_REAL_MASK://ROB
1649  img.readMapped(fn_mask);
1650  img().getImage(dmask);
1652  break;
1653  default:
1654  REPORT_ERROR(ERR_VALUE_INCORRECT, "MaskProgram::generate_mask: Unknown mask type :"
1655  + integerToString(type));
1656  }
1657 
1658  if (apply_geo)
1659  {
1660  switch (datatype())
1661  {
1662  case INT_MASK:
1663  if (ZSIZE(imask) > 1)
1664  REPORT_ERROR(ERR_NOT_IMPLEMENTED,"Error: apply_geo only implemented for 2D masks");
1666  break;
1667  case DOUBLE_MASK:
1668  if (ZSIZE(dmask) > 1)
1669  REPORT_ERROR(ERR_NOT_IMPLEMENTED,"Error: apply_geo only implemented for 2D masks");
1671  break;
1672  }
1673  }
1674 }
1675 
1676 
1677 /*---------------------------------------------------------------------------*/
1678 /* Mask tools */
1679 /*---------------------------------------------------------------------------*/
1680 
1681 // Apply geometric transformation to a binary mask ========================
1683  const Matrix2D<double> &A)
1684 {
1686  tmp.resize(mask);
1687  typeCast(mask, tmp);
1688  double outside = DIRECT_A2D_ELEM(tmp, 0, 0);
1689  MultidimArray<double> tmp2;
1690  tmp2 = tmp;
1691  // Instead of IS_INV for images use IS_NOT_INV for masks!
1692  applyGeometry(xmipp_transformation::LINEAR, tmp, tmp2, A, xmipp_transformation::IS_NOT_INV, xmipp_transformation::DONT_WRAP, outside);
1693  // The type cast gives strange results here, using round instead
1694  //typeCast(tmp, mask);
1696  {
1697  dAij(mask,i,j)=ROUND(dAij(tmp,i,j));
1698  // std::cout << "i, j = " << i << "," << j <<std::endl;
1699  }
1700 }
1701 
1702 // Apply geometric transformation to a continuous mask =====================
1704  const Matrix2D<double> &A)
1705 {
1706  double outside = DIRECT_A2D_ELEM(mask, 0, 0);
1707  MultidimArray<double> tmp = mask;
1708  // Instead of IS_INV for images use IS_NOT_INV for masks!
1709  applyGeometry(xmipp_transformation::LINEAR, tmp, mask, A, xmipp_transformation::IS_NOT_INV, xmipp_transformation::DONT_WRAP, outside);
1710 }
1711 
1713  const MultidimArray< std::complex<double> > &m,
1714  int mode, double th1, double th2)
1715 {
1717  int N = 0;
1719  if (A2D_ELEM(mask, i, j))
1720  switch (mode)
1721  {
1722  case COUNT_ABOVE:
1723  if (abs(A3D_ELEM(m, k, i, j)) >= th1)
1724  N++;
1725  break;
1726  case COUNT_BELOW:
1727  if (abs(A3D_ELEM(m, k, i, j)) <= th1)
1728  N++;
1729  break;
1730  case COUNT_BETWEEN:
1731  if (abs(A3D_ELEM(m, k, i, j)) >= th1 && abs(A3D_ELEM(m, k, i, j)) <= th2)
1732  N++;
1733  break;
1734  }
1735  return N;
1736 }
1737 
1739  const MultidimArray<double> &m1,
1741 {
1742  Matrix2D<double> A(2, 2);
1743  A.initZeros();
1744  Matrix1D<double> b(2);
1745  b.initZeros();
1747  // Compute Least squares solution
1748  if (mask == nullptr)
1749  {
1751  {
1752  A(0, 0) += m2(k, i, j) * m2(k, i, j);
1753  A(0, 1) += m2(k, i, j);
1754  A(1, 1) += 1;
1755  b(0) += m1(k, i, j) * m2(k, i, j);
1756  b(1) += m1(k, i, j);
1757  }
1758  A(1, 0) = A(0, 1);
1759  }
1760  else
1761  {
1763  {
1764  if ((*mask)(k, i, j))
1765  {
1766  A(0, 0) += m2(k, i, j) * m2(k, i, j);
1767  A(0, 1) += m2(k, i, j);
1768  A(1, 1) += 1;
1769  b(0) += m1(k, i, j) * m2(k, i, j);
1770  b(1) += m1(k, i, j);
1771  }
1772  }
1773  A(1, 0) = A(0, 1);
1774  }
1775  b = A.inv() * b;
1776 
1777  // Apply to m2
1778  FOR_ALL_ELEMENTS_IN_ARRAY3D(m2) m2(k, i, j) = b(0) * m2(k, i, j) + b(1);
1779 }
1780 
1781 /************** Program Mask implementation ***********************/
1782 /* Define Parameters ----------------------------------------------------------------- */
1784 {
1785  each_image_produces_an_output = true;
1786  save_metadata_stack = true;
1787  keep_input_columns = true;
1789  Mask::defineParams(this);
1790 
1791  addUsageLine("Create or Apply a mask. Count pixels/voxels within a mask");
1792  addUsageLine("+ ");
1793  addUsageLine("+You do not need to give the dimensions of the mask but you simply provide ");
1794  addUsageLine("+an example of image/volume you are going to apply the mask to, then the dimensions ");
1795  addUsageLine("+are taken from this file and the mask is created. In the creation of the mask, ");
1796  addUsageLine("+a file with the mask is written to disk but it is not applied to the input file.");
1797  addUsageLine("+ ");
1798  addUsageLine("+You can generate blank images/volumes with the size of the sample one if you do not ");
1799  addUsageLine("+supply any mask type.You may also apply masks without having to generate the corresponding");
1800  addUsageLine("+files (but you also can save them)");
1801  addUsageLine("+ ");
1802  addUsageLine("+This utility also allows you to count the number of pixels/voxels in an image/volume");
1803  addUsageLine("+which are inside a given mask and whose value is below|above or both some threshold.");
1804  addUsageLine("+ ");
1805  addUsageLine("+See [[http://xmipp.cnb.csic.es/twiki/bin/view/Xmipp/Transform_mask_v3][here]] for more information about the program.");
1806 
1807  addExampleLine("Sample at circular mask inside radius 72:", false);
1808  addExampleLine("xmipp_transform_mask -i reference.vol -o output_volume.vol --mask circular -72");
1809  addExampleLine("As above but save mask:", false);
1810  addExampleLine("xmipp_transform_mask -i reference.vol --create_mask output_mask.vol --mask circular -25");
1811  addExampleLine("Mask and overwrite a selection file:", false);
1812  addExampleLine("xmipp_transform_mask -i t7_10.sel --mask circular -72");
1813  addExampleLine("Mask using rectangular mask:", false);
1814  addExampleLine("xmipp_transform_mask -i singleImage.spi -o salida20.spi --mask rectangular -10 -10");
1815 
1816  addParamsLine(" [--create_mask <output_mask_file>] : Don't apply and save mask");
1817  addParamsLine(" [--count_above <th>] : Voxels within mask >= th");
1818  addParamsLine(" [--count_below <th>] : Voxels within mask <= th");
1819  addParamsLine(" [--substitute <val=\"0\">] : Value outside the mask: userProvidedValue|min|max|avg");
1820 
1821 }
1822 
1823 /* Read Parameters ----------------------------------------------------------------- */
1825 {
1827  mask.readParams(this);
1828 
1829  count_above = checkParam("--count_above");
1830  if (count_above)
1831  th_above = getDoubleParam("-count_above");
1832  count_below = checkParam("--count_below");
1833  if (count_below)
1834  th_below = getDoubleParam("--count_below");
1835  create_mask = checkParam("--create_mask");
1836  if (create_mask)
1837  fn_mask = getParam("--create_mask");
1838  //mask.read(argc, argv);
1839  str_subs_val = getParam("--substitute");
1840  count = count_below || count_above;
1841 }
1842 
1843 
1844 /* Preprocess ------------------------------------------------------------- */
1846 {
1847  if (create_mask && input_is_stack)
1848  REPORT_ERROR(ERR_MD_NOOBJ, "Mask: Cannot create a mask for a selection file\n");
1849 }
1850 
1851 /* Postprocess ------------------------------------------------------------- */
1853 {
1854  if (!count)
1855  progress_bar(mdInSize);
1856 }
1857 
1858 /* Process image ------------------------------------------------------------- */
1859 void ProgMask::processImage(const FileName &fnImg, const FileName &fnImgOut,
1860  const MDRow &rowIn, MDRow &rowOut)
1861 {
1862  static size_t imageCount = 0;
1863  ++imageCount;
1864  Image<double> image;
1865  image.readApplyGeo(fnImg, rowIn);
1866  image().setXmippOrigin();
1867 
1868  // Generate mask
1869  if (ZSIZE(image()) > 1)
1870  apply_geo=false;
1871  if (apply_geo)
1872  {
1873  if (mask.x0 + mask.y0 != 0.)
1874  REPORT_ERROR(ERR_ARG_INCORRECT, "Mask: -center option cannot be combined with apply_geo; use -dont_apply_geo");
1875  else
1876  // Read geometric transformation from the image and store for mask
1877  image.getTransformationMatrix(mask.mask_geo);
1878  }
1879  mask.generate_mask(image());
1880 
1881  // Apply mask
1882  if (!create_mask)
1883  {
1884  if (str_subs_val=="min")
1885  subs_val=image().computeMin();
1886  else if (str_subs_val=="max")
1887  subs_val=image().computeMax();
1888  else if (str_subs_val=="avg")
1889  subs_val=image().computeAvg();
1890  else
1891  subs_val=textToFloat(str_subs_val);
1892 
1893  mask.apply_mask(image(), image(), subs_val, apply_geo);
1894  if (!count)
1895  image.write(fnImgOut);
1896  }
1897  else
1898  mask.write_mask(fn_mask);
1899 
1900  // Count
1901  if (count)
1902  {
1903  if (mask.datatype() == INT_MASK)
1904  {
1905  int count=0;
1906  std::string elem_type="pixels";
1907  if (ZSIZE(image())>1)
1908  elem_type="voxels";
1909  if (count_above && !count_below)
1910  {
1911  std::cout << stringToString(fn_in,max_length)
1912  << " number of " << elem_type << " above " << th_above;
1913  count=count_with_mask_above(mask.get_binary_mask(),
1914  image(),th_above);
1915  }
1916  else if (count_below && !count_above)
1917  {
1918  std::cout << stringToString(fn_in,max_length)
1919  << " number of " << elem_type << " below " << th_below;
1920  count=count_with_mask_below(mask.get_binary_mask(),
1921  image(),th_below);
1922  }
1923  else if (count_below && count_above)
1924  {
1925  std::cout << stringToString(fn_in,max_length)
1926  << " number of " << elem_type << " above " << th_above
1927  << " and below " << th_below << " = ";
1928  count=count_with_mask_between(mask.get_binary_mask(),
1929  image(),th_above,th_below);
1930  }
1931  std::cout << " = " << count << std::endl;
1932  }
1933  else
1934  std::cerr << "Cannot count pixels with a continuous mask\n";
1935  }
1936 
1937  if (imageCount % 25 == 0 && !count)
1938  progress_bar(imageCount);
1939 }
1940 
Argument missing.
Definition: xmipp_error.h:114
double z0
Definition: mask.h:462
Just to locate unclassified errors.
Definition: xmipp_error.h:192
void SeparableSincKaiserMask2D(MultidimArray< double > &mask, double omega, double delta, double Deltaw)
Definition: mask.cpp:379
#define count_with_mask_between(mask, m, th1, th2)
Definition: mask.h:968
void BinaryConeMask(MultidimArray< int > &mask, double theta, int mode, bool centerOrigin)
Definition: mask.cpp:488
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
double alpha
Smoothness parameter.
Definition: blobs.h:121
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
void BlobCircularMask(MultidimArray< double > &mask, double r1, blobtype blob, int mode, double x0, double y0, double z0)
Definition: mask.cpp:219
Matrix2D< double > mask_geo
Definition: mask.h:491
double getDoubleParam(const char *param, int arg=0)
int smin
Definition: mask.h:474
#define BINARY_TUBE
Definition: mask.h:383
#define BLACKMAN_MASK
Definition: mask.h:371
void BinaryCrownMask(MultidimArray< int > &mask, double R1, double R2, int mode, double x0, double y0, double z0)
Definition: mask.cpp:244
int Xrect
Definition: mask.h:451
#define FINISHINGX(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
void BinaryDWTSphericalMask3D(MultidimArray< int > &mask, double radius, int smin, int smax, const std::string &quadrant)
Definition: mask.cpp:443
FileName fn_mask
Definition: mask.h:487
double R2
Definition: mask.h:418
void resizeNoCopy(const MultidimArray< T1 > &v)
#define dAij(M, i, j)
No exist requested object.
Definition: xmipp_error.h:156
int smax
Definition: mask.h:478
void BinaryWedgeMask(MultidimArray< int > &mask, double theta0, double thetaF, const Matrix2D< double > &A, bool centerOrigin)
Definition: mask.cpp:524
double beta(const double a, const double b)
Just for debugging, situation that can&#39;t happens.
Definition: xmipp_error.h:120
void sqrt(Image< double > &op)
#define BINARY_CROWN_MASK
Definition: mask.h:366
void BinaryCircularMask(MultidimArray< int > &mask, double radius, int mode, double x0, double y0, double z0)
Definition: mask.cpp:193
#define BLOB_CROWN_MASK
Definition: mask.h:382
#define RAISED_COSINE_MASK
Definition: mask.h:370
#define BINARY_CYLINDER_MASK
Definition: mask.h:367
void applyGeometry(int SplineDegree, MultidimArray< std::complex< double > > &V2, const MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside, MultidimArray< double > *BcoeffsPtr)
void SincMask(MultidimArray< double > &mask, double omega, int mode, double x0, double y0, double z0)
Definition: mask.cpp:127
#define DIRECT_A2D_ELEM(v, i, j)
double sigma
Definition: mask.h:442
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)
int allowed_data_types
Definition: mask.h:495
void resize(size_t Xdim)
Definition: mask.cpp:654
#define BINARY_FRAME_MASK
Definition: mask.h:368
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
void initConstant(T val)
void abs(Image< double > &op)
void apply_geo_cont_2D_mask(MultidimArray< double > &mask, const Matrix2D< double > &A)
Definition: mask.cpp:1703
String integerToString(int I, int _width, char fill_with)
#define z0
#define FINISHINGZ(v)
#define SINC_MASK
Definition: mask.h:372
int paremeterPosition(int argc, const char **argv, const char *param)
Definition: args.cpp:111
#define NO_MASK
Definition: mask.h:364
double H
Definition: mask.h:437
double * di
#define STARTINGX(v)
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
#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
void postProcess()
Definition: mask.cpp:1852
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
double theta
static void defineParams(XmippProgram *program, int allowed_data_types=ALL_KINDS, const char *prefix=nullptr, const char *comment=nullptr, bool moreOptions=false)
Definition: mask.cpp:1203
#define STARTINGY(v)
#define SHOW_CENTER
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
#define A3D_ELEM(V, k, i, j)
double blob_alpha
Definition: mask.h:432
__device__ float bessi0(float x)
void read(int argc, const char **argv)
Definition: mask.cpp:701
void mask3D_6neig(MultidimArray< int > &mask, int value, int center)
Definition: mask.cpp:589
MultidimArray< double > dmask
Definition: mask.h:503
#define RAISED_CROWN_MASK
Definition: mask.h:376
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
doublereal * b
#define BINARY_CONE_MASK
Definition: mask.h:379
constexpr int COUNT_BETWEEN
Definition: mask.h:944
const char * getParameter(int argc, const char **argv, const char *param, const char *option)
Definition: args.cpp:30
#define y0
const char * getParam(const char *param, int arg=0)
#define x0
double y0
Definition: mask.h:466
#define READ_BINARY_MASK
Definition: mask.h:374
Mask(int _allowed_data_type=ALL_KINDS)
Definition: mask.cpp:634
#define READ_REAL_MASK
Definition: mask.h:375
#define CEIL(x)
Definition: xmipp_macros.h:225
float textToFloat(const char *str)
Incorrect argument received.
Definition: xmipp_error.h:113
void preProcess()
Definition: mask.cpp:1845
double R1
Definition: mask.h:413
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
#define DOUBLE_MASK
Definition: mask.h:386
void BlackmanMask(MultidimArray< double > &mask, int mode, double x0, double y0, double z0)
Definition: mask.cpp:151
double x0
Definition: mask.h:470
#define XSIZE(v)
#define DWTSPHERICALMASK_BLOCK(s, quadrant)
Definition: mask.cpp:431
void progress_bar(long rlen)
#define BINARY_DWT_SPHERICAL_MASK
Definition: mask.h:378
void BlobCrownMask(MultidimArray< double > &mask, double r1, double r2, blobtype blob, int mode, double x0, double y0, double z0)
Definition: mask.cpp:278
int type
Definition: mask.h:402
#define SHOW_MODE
#define ABS(x)
Definition: xmipp_macros.h:142
void readParams()
Definition: mask.cpp:1824
void defineParams()
Definition: mask.cpp:1783
#define ZSIZE(v)
#define ROUND(x)
Definition: xmipp_macros.h:210
int Yrect
Definition: mask.h:455
void mask2D_8neig(MultidimArray< int > &mask, int value1, int value2, int center)
Definition: mask.cpp:417
void BinaryDWTCircularMask2D(MultidimArray< int > &mask, double radius, int smin, int smax, const std::string &quadrant)
Definition: mask.cpp:356
std::string quadrant
Definition: mask.h:483
void readParams(XmippProgram *program)
Definition: mask.cpp:1284
#define count_with_mask_below(mask, m, th)
Definition: mask.h:959
void GaussianMask(MultidimArray< double > &mask, double sigma, int mode, double x0, double y0, double z0)
Definition: mask.cpp:325
void log10(Image< double > &op)
String stringToString(const String &str, size_t _width)
void mode
double omega
Definition: mask.h:447
void initZeros()
Definition: matrix1d.h:592
#define BINARY_DWT_CIRCULAR_MASK
Definition: mask.h:377
void BinaryCylinderMask(MultidimArray< int > &mask, double R, double H, int mode, double x0, double y0, double z0)
Definition: mask.cpp:471
#define j
void SincBlackmanMask(MultidimArray< double > &mask, double omega, double power_percentage, double x0, double y0, double z0)
Definition: mask.cpp:166
int m
#define BLOB_CIRCULAR_MASK
Definition: mask.h:381
std::string mask_type
Definition: mask.h:507
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
Definition: mask.cpp:1859
void RaisedCrownMask(MultidimArray< double > &mask, double r1, double r2, double pix_width, int mode, double x0, double y0, double z0)
Definition: mask.cpp:67
double pix_width
Definition: mask.h:423
void apply_geo_binary_2D_mask(MultidimArray< int > &mask, const Matrix2D< double > &A)
Definition: mask.cpp:1682
#define DWTCIRCULAR2D_BLOCK(s, quadrant)
Definition: mask.cpp:346
#define FINISHINGY(v)
void rangeAdjust_within_mask(const MultidimArray< double > *mask, const MultidimArray< double > &m1, MultidimArray< double > &m2)
Definition: mask.cpp:1738
void generate_mask(bool apply_geo=false)
Definition: mask.cpp:1577
void BinaryTubeMask(MultidimArray< int > &mask, double R1, double R2, double H, int mode, double x0, double y0, double z0)
Definition: mask.cpp:261
#define GAUSSIAN_MASK
Definition: mask.h:369
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
int Zrect
Definition: mask.h:459
#define BINARY_CIRCULAR_MASK
Definition: mask.h:365
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
int blob_order
Definition: mask.h:428
int datatype()
Definition: mask.h:544
#define INT_MASK
Definition: mask.h:385
double blob_radius
Definition: mask.h:431
void usage() const
Definition: mask.cpp:1134
int order
Derivation order and Bessel function order.
Definition: blobs.h:118
void initZeros()
Definition: matrix2d.h:626
int textToInteger(const char *str)
int count_with_mask(const MultidimArray< int > &mask, const MultidimArray< std::complex< double > > &m, int mode, double th1, double th2)
Definition: mask.cpp:1712
constexpr int COUNT_BELOW
Definition: mask.h:943
constexpr int OUTSIDE_MASK
Definition: mask.h:48
void write_mask(const FileName &fn)
Definition: mask.cpp:1192
void getTransformationMatrix(Matrix2D< double > &A, bool only_apply_shifts=false, const size_t n=0)
MultidimArray< int > imask
Definition: mask.h:499
void KaiserMask(MultidimArray< double > &mask, double delta, double Deltaw)
Definition: mask.cpp:83
constexpr int K
float r2
#define SPEED_UP_tempsInt
Definition: xmipp_macros.h:408
void mask3D_18neig(MultidimArray< int > &mask, int value1, int value2, int center)
Definition: mask.cpp:598
void initZeros(const MultidimArray< T1 > &op)
#define blob_val(r, blob)
Definition: blobs.h:139
void mask3D_26neig(MultidimArray< int > &mask, int value1, int value2, int value3, int center)
Definition: mask.cpp:612
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
#define FOR_ALL_ELEMENTS_IN_COMMON_IN_ARRAY3D(V1, V2)
constexpr int COUNT_ABOVE
Definition: mask.h:942
void mask2D_4neig(MultidimArray< int > &mask, int value, int center)
Definition: mask.cpp:409
#define PI
Definition: tools.h:43
void RaisedCosineMask(MultidimArray< double > &mask, double r1, double r2, int mode, double x0, double y0, double z0)
Definition: mask.cpp:36
int getIntParam(const char *param, int arg=0)
#define BINARY_WEDGE_MASK
Definition: mask.h:380
Incorrect value received.
Definition: xmipp_error.h:195
#define STARTINGZ(v)
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
int readMapped(const FileName &name, size_t select_img=ALL_IMAGES, int mode=WRITE_READONLY)
void clear()
Definition: mask.cpp:641
void show() const
Definition: mask.cpp:1021
#define intWRAP(x, x0, xF)
Definition: xmipp_macros.h:272
void addParamsLine(const String &line)
void initIdentity()
Definition: matrix2d.h:673
void BinaryFrameMask(MultidimArray< int > &mask, int Xrect, int Yrect, int Zrect, int mode, double x0, double y0, double z0)
Definition: mask.cpp:309
int mode
Definition: mask.h:407
#define SINC(x)
Definition: xmipp_macros.h:362
double * delta
void SincKaiserMask(MultidimArray< double > &mask, double omega, double delta, double Deltaw)
Definition: mask.cpp:139
float r1
constexpr int INNER_MASK
Definition: mask.h:47
#define count_with_mask_above(mask, m, th)
Definition: mask.h:951