Xmipp  v3.23.11-Nereus
image_operate.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: J.M. de la Rosa Trevin (jmdelarosa@cnb.csic.es) x 0.95
4  * Joaquin Oton (joton@cnb.csic.es) x 0.05
5  *
6  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  * 02111-1307 USA
22  *
23  * All comments concerning this program package may be sent to the
24  * e-mail address 'xmipp@cnb.csic.es'
25  ***************************************************************************/
26 
27 #include "image_operate.h"
28 #include "core/transformations.h"
29 #include "core/xmipp_fft.h"
30 #include "data/numerical_tools.h"
32 
33 void minus(Image<double> &op1, const Image<double> &op2)
34 {
35  op1() -= op2();
36 }
37 
39 {
40 public:
43 };
44 
45 double minusAdjusted_L1(double *x, void *_prm)
46 {
47  double a=x[1];
48  double b=x[2];
49 
50  double retval=0;
51  auto *prm = (MinusAdjustedPrm *) _prm;
52  const MultidimArray<double> &pI1=*(prm->I1);
53  const MultidimArray<double> &pI2=*(prm->I2);
55  retval+=fabs(DIRECT_MULTIDIM_ELEM(pI1,n)-(a*DIRECT_MULTIDIM_ELEM(pI2,n)+b));
56  return retval;
57 }
58 
59 
61 {
62  MultidimArray<double> &pI1=op1();
63  const MultidimArray<double> &pI2=op2();
64 
66  prm.I1=&op1();
67  prm.I2=&op2();
68 
69  Matrix1D<double> p(2);
71  p(0)=1; // a in I'=a*I+b
72  p(1)=0; // b in I'=a*I+b
73  steps.initConstant(1);
74  double cost;
75  int iter;
76  powellOptimizer(p, 1, 2, &minusAdjusted_L1, &prm, 0.01, cost, iter, steps, false);
77 
78  double a=p(0);
79  double b=p(1);
82 }
83 
84 
86 {
87  double dot=op1().dotProduct(op2());
88  std::cout << "<" << op1.name() << "," << op2.name() << ">=" << dot << std::endl;
89 }
90 
91 double pDropout;
93 {
94  if (pDropout>0.0 && pDropout<1.0)
95  {
96  MultidimArray<double> &mOp1 = op1();
98  if (rnd_unif()<pDropout)
99  dAi(mOp1, n) = 0.0;
100  }
101 }
102 
103 void plus(Image<double> &op1, const Image<double> &op2)
104 {
105  op1() += op2();
106 }
107 
108 void mult(Image<double> &op1, const Image<double> &op2)
109 {
110  op1() *= op2();
111 }
112 
113 void divide(Image<double> &op1, const Image<double> &op2)
114 {
115  op1() /= op2();
116 }
117 
118 void min(Image<double> &op1, const Image<double> &op2)
119 {
120  MultidimArray<double> &mOp1 = op1();
121  const MultidimArray<double> &mOp2 = op2();
123  {
124  dAi(mOp1, n) = XMIPP_MIN(dAi(mOp1, n), dAi(mOp2, n));
125  }
126 }
127 
128 void max(Image<double> &op1, const Image<double> &op2)
129 {
130  MultidimArray<double> &mOp1 = op1();
131  const MultidimArray<double> &mOp2 = op2();
133  {
134  dAi(mOp1, n) = XMIPP_MAX(dAi(mOp1, n), dAi(mOp2, n));
135  }
136 }
137 
138 void compare(Image<double> &op1, const Image<double> &op2)
139 {
140  MultidimArray<double> &mOp1 = op1();
141  const MultidimArray<double> &mOp2 = op2();
143  {
144  dAi(mOp1, n) = dAi(mOp1, n) == dAi(mOp2, n) ? 0 : (dAi(mOp1, n) < dAi(mOp2, n) ? -1 : 1 );
145  }
146 }
147 
149 void eq(Image<double> &op1, const Image<double> &op2)
150 {
151  MultidimArray<double> &mOp1 = op1();
152  const MultidimArray<double> &mOp2 = op2();
154  {
155  dAi(mOp1, n) = dAi(mOp1, n) == dAi(mOp2, n) ? 1 : 0;
156  }
157 }
158 
159 void ne(Image<double> &op1, const Image<double> &op2)
160 {
161  MultidimArray<double> &mOp1 = op1();
162  const MultidimArray<double> &mOp2 = op2();
164  {
165  dAi(mOp1, n) = dAi(mOp1, n) != dAi(mOp2, n) ? 1 : 0;
166  }
167 }
168 
169 void lt(Image<double> &op1, const Image<double> &op2)
170 {
171  MultidimArray<double> &mOp1 = op1();
172  const MultidimArray<double> &mOp2 = op2();
174  {
175  dAi(mOp1, n) = dAi(mOp1, n) < dAi(mOp2, n) ? 1 : 0;
176  }
177 }
178 
179 void le(Image<double> &op1, const Image<double> &op2)
180 {
181  MultidimArray<double> &mOp1 = op1();
182  const MultidimArray<double> &mOp2 = op2();
184  {
185  dAi(mOp1, n) = dAi(mOp1, n) <= dAi(mOp2, n) ? 1 : 0;
186  }
187 }
188 
189 void gt(Image<double> &op1, const Image<double> &op2)
190 {
191  MultidimArray<double> &mOp1 = op1();
192  const MultidimArray<double> &mOp2 = op2();
194  {
195  dAi(mOp1, n) = dAi(mOp1, n) > dAi(mOp2, n) ? 1 : 0;
196  }
197 }
198 
199 void ge(Image<double> &op1, const Image<double> &op2)
200 {
201  MultidimArray<double> &mOp1 = op1();
202  const MultidimArray<double> &mOp2 = op2();
204  {
205  dAi(mOp1, n) = dAi(mOp1, n) >= dAi(mOp2, n) ? 1 : 0;
206  }
207 }
208 
209 
211 {
212  MultidimArray<double> &mOp = op();
214  {
215  dAi(mOp, n) = sqrt(dAi(mOp, n));
216  }
217 }
218 
220 {
221  MultidimArray<double> &mOp = op();
223  {
224  dAi(mOp, n) = ABS(dAi(mOp, n));
225  }
226 }
227 
229 {
230  MultidimArray<double> &mOp = op();
232  {
233  dAi(mOp, n) = log(dAi(mOp, n));
234  }
235 }
236 
238 {
239  MultidimArray<double> &mOp = op();
241  {
242  dAi(mOp, n) = log10(dAi(mOp, n));
243  }
244 }
245 
246 double powerExp = 2;
248 {
249  MultidimArray<double> &mOp = op();
251  {
252  dAi(mOp, n) = pow(dAi(mOp, n), powerExp);
253  }
254 }
255 
256 int nSlice;
257 char axis;
259 {
260  MultidimArray<double> &mOp = op();
261  MultidimArray<double> imAux;
262 
263  mOp.getSlice(nSlice, imAux, axis);
264  mOp = imAux;
265 }
266 
267 
270 {
271  MultidimArray<double> &mOp = op();
272  mOp.setXmippOrigin();
273  Matrix1D<int> center(3);
274  center.initZeros();
275  MultidimArray<double> radial_mean;
276  MultidimArray<int> radial_count;
277  radialAverage(mOp, center, radial_mean, radial_count);
278  radial_mean.write((fnOut.withoutExtension()).addExtension("txt"));
279 
280  int my_rad;
282  {
283  my_rad = (int)floor(sqrt((double)(i * i + j * j + k * k)));
284  op(k, i, j) = radial_mean(my_rad);
285  }
286 }
287 
289 {
290  MultidimArray<double> &mOp = op();
291  CenterFFT(mOp,true);
292  mOp.selfLog10();
293  mOp.setXmippOrigin();
294  Matrix1D<int> center(3);
295  center.initZeros();
296  MultidimArray<double> radial_mean;
297  MultidimArray<int> radial_count;
298  radialAverage(mOp, center, radial_mean, radial_count);
299  radial_mean.write((fnOut.withoutExtension()).addExtension("txt"));
300 
301  int my_rad;
303  {
304  my_rad = (int)floor(sqrt((double)(i * i + j * j + k * k)));
305  op(k, i, j) = radial_mean(my_rad);
306  }
307 }
308 
310 {
311  op().initZeros();
312 }
313 
315 {
316  each_image_produces_an_output = true;
317  save_metadata_stack = true;
318  keep_input_columns = true;
319  addUsageLine("A simple Xmipp images calculator. Binary and unary operations");
321  addParamsLine("== Binary operations: ==");
322  addParamsLine(" --plus <file_or_value> :Sums two images, volumes or adds a numerical value to an image");
323  addParamsLine("or --minus <file_or_value> :Subtracts two images, volumes or subtracts a numerical value to an image");
324  addParamsLine("or --minusAdjusted <file> :Subtracts two sets of images adjusting the gray values so that error is minimized");
325  addParamsLine(" : If you are comparing a set of noisy and clean images, put the noisy images in -i");
326  addParamsLine("or --mult <file_or_value> :Multiplies two images, volumes, or multiplies per a given number");
327  addParamsLine("or --divide <file_or_value> :Divides two images, volumes, or divides per a given number");
328  addParamsLine("or --min <file_or_value> :Minimum of two images, volumes, or number (pixel-wise)");
329  addParamsLine("or --max <file_or_value> :Maximum of two images, volumes, or number (pixel-wise)");
330  addParamsLine("or --compare <file_or_value> :Returns -1 if the left value is less, 0 if are equal or 1 if greater.(pixel-wise)");
331  addParamsLine("or --dot_product <file> :Dot product between two images or volumes");
332  addParamsLine("or --dropout <p> :Set to 0.0 the values of the input with probability p");
333  addParamsLine("==+ Relational operations: ==");
334  addParamsLine("or --eq <file_or_value> :Returns 1 if the pixels values are equal, 0 otherwise (pixel-wise)");
335  addParamsLine("or --le <file_or_value> :Returns 1 if the pixels values are less or equal, 0 otherwise (pixel-wise)");
336  addParamsLine("or --lt <file_or_value> :Returns 1 if the pixels values are less than, 0 otherwise (pixel-wise)");
337  addParamsLine("or --ge <file_or_value> :Returns 1 if the pixels values are greater or equal, 0 otherwise (pixel-wise)");
338  addParamsLine("or --gt <file_or_value> :Returns 1 if the pixels values are greater, 0 otherwise (pixel-wise)");
339  addParamsLine("or --ne <file_or_value> :Returns 1 if the pixels values are not equal, 0 otherwise (pixel-wise)");
340 
341  addParamsLine("== Unary operations: ==");
342  addParamsLine("or --log :Computes the natural logarithm of an image");
343  addParamsLine("or --log10 :Computes the decimal logarithm of an image");
344  addParamsLine("or --sqrt :Computes the square root of an image");
345  addParamsLine("or --abs :Computes the absolute value of an image");
346  addParamsLine("or --pow <value=2> :Computes the power of an image");
347  addParamsLine("or --slice <value> :Extracts a given slice from a volume (first slice=0)");
348  addParamsLine("or --column <value> :Extracts a given column from a image or volume");
349  addParamsLine("or --row <value> :Extracts a given row from a image or volume");
350  addParamsLine("or --radial_avg :Compute the radial average of an image");
351  addParamsLine("or --psd_radial_avg :Compute the radial average of an image");
352  addParamsLine("or --reset :Set the image to 0");
353 
354  addExampleLine("Sum two volumes and save result", false);
355  addExampleLine("xmipp_image_operate -i volume1.vol --plus volume2.vol -o result.vol");
356  addExampleLine("Calculate the log10 of an image called example.xmp and store the resulting one in example_log.xmp", false);
357  addExampleLine("xmipp_image_operate -i example.xmp --log10 -o example_log.xmp");
358  addExampleLine("Calculate the square root of a volume called example.vol and store it in expample_sq.vol", false);
359  addExampleLine("xmipp_image_operate -i example.vol --sqrt -o expample_sq.vol");
360  addExampleLine("Extract the slice number 10 of a set of of volumes given in the sel file called volumes.sel. The names of the output images its supposed to be in the selfile images.sel", false);
361  addExampleLine("xmipp_image_operate -i volumes.sel --slice 10 -o images.sel");
362  addExampleLine("Sum 5 to every image in images.sel and rewrite the input images", false);
363  addExampleLine("xmipp_image_operate -i images.sel --plus 5");
364  addExampleLine("Subtract two volumes:", false);
365  addExampleLine("xmipp_image_operate -i volume1.vol --minus volume2.vol -o volume3.vol");
366  addExampleLine("Multiply an image by 2 in every pixel:", false);
367  addExampleLine("xmipp_image_operate -i image.xmp --mult 2 -o image2.xmp");
368  addExampleLine("Divide 2 by the value of every pixel in the image:", false);
369  addExampleLine("xmipp_image_operate -i 2 -divide image.xmp -o image2.xmp");
370  addExampleLine(" Rotational average", false);
371  addExampleLine("xmipp_image_operate -i image.xmp --radial_avg -o radial_avg.xmp");
372  addExampleLine("where radial_avg.txt is an ascii file for plotting the radial_averaged profile, radial_avg.xmp a radial_averaged image", false);
373  addExampleLine("xmipp_image_operate -i micrograph.psd --psd_radial_avg -o radial_psd.xmp");
374  addExampleLine("where radial_psd.txt is an ascii file for plotting the radial_averaged profile, radial_psd.xmp a radial_averaged image", false);
375 }
376 
378 {
380  binaryOperator = nullptr;
381  unaryOperator = nullptr;
382  isValue = false;
383  // Check operation to do
384  //Binary operations
385  if (checkParam("--plus"))
386  {
387  file_or_value = getParam("--plus");
388  binaryOperator = plus;
389  }
390  else if (checkParam("--minus"))
391  {
392  file_or_value = getParam("--minus");
393  binaryOperator = minus;
394  }
395  else if (checkParam("--minusAdjusted"))
396  {
397  file_or_value = getParam("--minusAdjusted");
398  binaryOperator = minusAdjusted;
399  }
400  else if (checkParam("--mult"))
401  {
402  file_or_value = getParam("--mult");
403  binaryOperator = mult;
404  }
405  else if (checkParam("--divide"))
406  {
407  file_or_value = getParam("--divide");
408  binaryOperator = divide;
409  }
410  else if (checkParam("--max"))
411  {
412  file_or_value = getParam("--max");
413  binaryOperator = max;
414  }
415  else if (checkParam("--min"))
416  {
417  file_or_value = getParam("--min");
418  binaryOperator = min;
419  }
420  else if (checkParam("--compare"))
421  {
422  file_or_value = getParam("--compare");
423  binaryOperator = compare;
424  }
425  else if (checkParam("--dot_product"))
426  {
427  file_or_value = getParam("--dot_product");
428  binaryOperator = imageDotProduct;
429  }
430  else if (checkParam("--dropout"))
431  {
432  pDropout = getDoubleParam("--dropout");
433  unaryOperator = dropOut;
434  }
436  else if (checkParam("--eq"))
437  {
438  file_or_value = getParam("--eq");
439  binaryOperator = eq;
440  }
441  else if (checkParam("--ne"))
442  {
443  file_or_value = getParam("--ne");
444  binaryOperator = ne;
445  }
446  else if (checkParam("--lt"))
447  {
448  file_or_value = getParam("--lt");
449  binaryOperator = lt;
450  }
451  else if (checkParam("--le"))
452  {
453  file_or_value = getParam("--le");
454  binaryOperator = le;
455  }
456  else if (checkParam("--gt"))
457  {
458  file_or_value = getParam("--gt");
459  binaryOperator = gt;
460  }
461  else if (checkParam("--ge"))
462  {
463  file_or_value = getParam("--ge");
464  binaryOperator = ge;
465  }
467  else if (checkParam("--log10"))
468  unaryOperator = log10;
469  else if (checkParam("--sqrt"))
470  unaryOperator = sqrt;
471  else if (checkParam("--abs"))
472  unaryOperator = abs;
473  else if (checkParam("--pow"))
474  {
475  powerExp = getDoubleParam("--pow");
476  unaryOperator = power;
477  }
478  else if (checkParam("--slice"))
479  {
480  axis = 'Z';
481  nSlice = getIntParam("--slice");
482  unaryOperator = getSlice;
483  }
484  else if (checkParam("--column"))
485  {
486  axis = 'X';
487  nSlice = getIntParam("--column");
488  unaryOperator = getSlice;
489  }
490  else if (checkParam("--row"))
491  {
492  axis = 'Y';
493  nSlice = getIntParam("--row");
494  unaryOperator = getSlice;
495  }
496  else if (checkParam("--radial_avg"))
497  {
498  fnOut = fn_out;
499  unaryOperator = radialAvg;
500  }
501  else if (checkParam("--psd_radial_avg"))
502  {
503  fnOut = fn_out;
504  unaryOperator = psdRadialAvg;
505  }
506  else if (checkParam("--reset"))
507  {
508  fnOut = fn_out;
509  unaryOperator = reset;
510  }
511  else if (checkParam("--log"))
512  unaryOperator = log;
513  else if (checkParam("--log10"))
514  unaryOperator = log10;
515  else
516  {
517  doRun = false;
518  REPORT_ERROR(ERR_VALUE_INCORRECT, "No valid operation specified");
519  }
520  int dotProduct = false;
521  if (binaryOperator != nullptr)
522  {
523  if (!file_or_value.exists())
524  {
525  isValue = true;
526  try {
527  value = textToFloat(file_or_value);
528  } catch (XmippError &XE)
529  {
530  doRun = false;
531  REPORT_ERROR(ERR_ARG_INCORRECT, (String)"Cannot understand "+file_or_value+". Either it is not a number or it is a non-existing file.");
532  }
533  img2().resizeNoCopy(zdimOut, ydimOut, xdimOut);
534  img2().initConstant(value);
535  }
536  else
537  {
538  dotProduct = true;
539  isValue = false;
540  fn2 = file_or_value;
541  md2.read(fn2);
542  if (md2.isMetadataFile || md2.size() > 1)
543  {
544  if (mdInSize != md2.size())
545  {
546  doRun = false;
547  REPORT_ERROR(ERR_MD, "Both metadatas operands should be of same size.");
548  }
549  md2IdIterator = memoryUtils::make_unique<MetaDataVec::id_iterator>(md2.ids().begin());
550  }
551  else
552  {
553  isValue = true;
554  img2.read(fn2);
555  }
556  }
557  if (!dotProduct && checkParam("--dot_product"))
558  {
559  doRun = false;
560  REPORT_ERROR(ERR_ARG_INCORRECT,"Dot product can only be computed between two files");
561  }
562  }
563 }
564 
565 void ProgOperate::processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
566 {
567  Image<double> img;
568  img.readApplyGeo(fnImg, rowIn);
569 
570  if (unaryOperator != nullptr)
571  unaryOperator(img);
572  else
573  {
574  if (!isValue)
575  {
576  img2.readApplyGeo(md2, **md2IdIterator);
577  ++(*md2IdIterator);
578  }
579  binaryOperator(img, img2);
580  }
581  img.write(fnImgOut);
582 }
#define dAi(v, i)
void radialAvg(Image< double > &op)
void min(Image< double > &op1, const Image< double > &op2)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
void dropOut(Image< double > &op1)
void le(Image< double > &op1, const Image< double > &op2)
const MultidimArray< double > * I1
__host__ __device__ float2 floor(const float2 v)
void mult(Image< double > &op1, const Image< double > &op2)
void getSlice(int k, MultidimArray< T1 > &M, char axis='Z', bool reverse=false, size_t n=0) const
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void sqrt(Image< double > &op)
void plus(Image< double > &op1, const Image< double > &op2)
void ne(Image< double > &op1, const Image< double > &op2)
void reset(Image< double > &op)
void minusAdjusted(Image< double > &op1, const Image< double > &op2)
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)
void compare(Image< double > &op1, const Image< double > &op2)
void abs(Image< double > &op)
void readParams()
Read input parameters.
const FileName & name() const
void ge(Image< double > &op1, const Image< double > &op2)
void powellOptimizer(Matrix1D< double > &p, int i0, int n, double(*f)(double *x, void *), void *prm, double ftol, double &fret, int &iter, const Matrix1D< double > &steps, bool show)
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
Process one image.
glob_prnt iter
double pDropout
doublereal * x
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 gt(Image< double > &op1, const Image< double > &op2)
void defineParams()
Define parameters.
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
double rnd_unif()
void minus(Image< double > &op1, const Image< double > &op2)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
doublereal * b
void log(Image< double > &op)
char axis
float textToFloat(const char *str)
Incorrect argument received.
Definition: xmipp_error.h:113
FileName fnOut
double powerExp
void write(const FileName &fn) const
void eq(Image< double > &op1, const Image< double > &op2)
Be careful with integer images for relational operations...due to double comparisons.
void max(Image< double > &op1, const Image< double > &op2)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
MetaData error.
Definition: xmipp_error.h:154
void radialAverage(const MultidimArray< double > &VolFourierMag, const MultidimArray< double > &V, MultidimArray< double > &radial_mean)
#define ABS(x)
Definition: xmipp_macros.h:142
#define DIRECT_MULTIDIM_ELEM(v, n)
int nSlice
void log10(Image< double > &op)
void psdRadialAvg(Image< double > &op)
void initZeros()
Definition: matrix1d.h:592
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
double steps
void power(Image< double > &op)
FileName withoutExtension() const
T dotProduct(const Matrix1D< T > &v1, const Matrix1D< T > &v2)
Definition: matrix1d.h:1140
std::string String
Definition: xmipp_strings.h:34
const MultidimArray< double > * I2
ProgClassifyCL2D * prm
double minusAdjusted_L1(double *x, void *_prm)
void imageDotProduct(Image< double > &op1, const Image< double > &op2)
void divide(Image< double > &op1, const Image< double > &op2)
Incorrect value received.
Definition: xmipp_error.h:195
void lt(Image< double > &op1, const Image< double > &op2)
void initConstant(T val)
Definition: matrix1d.cpp:83
int * n
void getSlice(Image< double > &op)
doublereal * a
__host__ __device__ float dot(float2 a, float2 b)