Xmipp  v3.23.11-Nereus
psf_xr.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Joaquin Oton (joton@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 "psf_xr.h"
27 #include "core/metadata_vec.h"
28 #include "core/xmipp_program.h"
29 #include "core/args.h"
30 #include "core/xmipp_fftw.h"
31 #include "core/transformations.h"
32 
34 {
35  init();
36 }
37 
39 {
40  clear();
41 }
42 
43 /* Definition of command line parameters
44  */
46 {
47  // program->addParamsLine(" [-file <psf_param_file>] : Read X-ray psf parameters from file.");
48  program->addParamsLine(" [--lambda <v=2.43>] : X-ray wavelength (nm).");
49  program->addParamsLine(" [--out_width <deltaR=40>] : Outermost zone width of the X-ray Fresnel lens (nm).");
50  program->addParamsLine(" [--zones <N=560>] : Number of zones of the X-ray Fresnel lens.");
51  program->addParamsLine(" [--mag <Ms=2304>] : Magnification of the X-ray microscope.");
52  program->addParamsLine(" [--sampling <dxy=10> <dz=dxy>] : Sampling rate in X-Y plane and Z axis (nm).");
53  program->addParamsLine(" [--zshift <deltaZ=0>] : Longitudinal displacement along Z axis in microns.");
54  program->addParamsLine(" [--size <x> <y=x> <z=x>] : Size of the X-ray PSF volume.");
55  program->addParamsLine(" [--type <lens_type=ideal>] : Lens type to generate the PSF.");
56  program->addParamsLine(" where <lens_type>");
57  program->addParamsLine(" ideal : Ideal phase Fresnel lens.");
58  program->addParamsLine(" zp : Fresnel Zone Plate lens.");
59 
60 }
61 
62 /* Read params
63  */
65 {
66  lambda = program->getDoubleParam("--lambda")*1e-9;
67  deltaR = program->getDoubleParam("--out_width")*1e-9;
68  Nzp = program->getDoubleParam("--zones");
69  Ms = program->getDoubleParam("--mag");
70  dxoPSF = program->getDoubleParam("--sampling",0)*1e-9;
71  dzoPSF = STR_EQUAL(program->getParam("--sampling", 1), "dxy") ? dxoPSF : program->getDoubleParam("--sampling", 1)*1e-9;
72  DeltaZo = program->getDoubleParam("--zshift")*1e-6;
73  Nox = program->getIntParam("--size",0);
74  Noy = STR_EQUAL(program->getParam("--size", 1),"x") ? Nox : program->getIntParam("--size", 1);
75  Noz = STR_EQUAL(program->getParam("--size", 2),"x") ? Nox : program->getIntParam("--size", 2);
76  type = STR_EQUAL(program->getParam("--type"), "zp") ? ANALYTIC_ZP : IDEAL_FRESNEL_LENS;
77 
78  verbose = program->getIntParam("-v");
79 }
80 
81 /* Read -------------------------------------------------------------------- */
82 void XRayPSF::read(const FileName &fn, bool readVolume)
83 {
84 
85  if (fn == "")
86  {
87  clear();
88  return;
89  }
90 
91  if (fn.isMetaData())
92  {
93  MetaDataVec MD;
94  MD.read(fn);
95  size_t id = MD.firstRowId();
96 
97  FileName fnPSF;
98  if ( MD.getValue(MDL_IMAGE,fnPSF, id) && readVolume )
99  {
101  psfGen.readMapped(fn.getDir()+fnPSF);
102  ArrayDim aDim;
103  psfGen.getDimensions(aDim);
104  // MULTIDIM_ARRAY(psfVol).getDimensions(aDim);
105  Nox = aDim.xdim;
106  Noy = aDim.ydim;
107  Noz = aDim.zdim;
108 
109  psfGen().setXmippOrigin();
110 
111  // MULTIDIM_ARRAY(psfVol).setXmippOrigin();
112  }
113  else
114  {
115  std::vector<double> dimV;
116  if (!MD.getValue(MDL_CTF_DIMENSIONS,dimV, id))
117  REPORT_ERROR(ERR_ARG_MISSING, MDL::label2Str(MDL_CTF_DIMENSIONS) + " argument not present.");
118  Nox = (int)dimV[0];
119  Noy = (int)dimV[1];
120  Noz = (int)dimV[2];
121  }
122  String typeS;
123  if (!MD.getValue(MDL_CTF_XRAY_LENS_TYPE, typeS, id))
125  if (typeS == "ZP")
126  type = ANALYTIC_ZP;
127  else
129 
130  if (!MD.getValue(MDL_CTF_LAMBDA,lambda, id))
131  REPORT_ERROR(ERR_ARG_MISSING, MDL::label2Str(MDL_CTF_LAMBDA) + " argument not present.");
132  lambda *= 1e-9;
135  deltaR *= 1e-9;
138  if (!MD.getValue(MDL_MAGNIFICATION,Ms, id))
139  REPORT_ERROR(ERR_ARG_MISSING, MDL::label2Str(MDL_MAGNIFICATION) + " argument not present.");
142  dxoPSF *= 1e-9;
145  dzoPSF *= 1e-9;
148  DeltaZo *= 1e-6;
149  }
150  else
151  {
152  FILE *fh_param;
153  if ((fh_param = fopen(fn.c_str(), "r")) == nullptr)
155  (std::string)"XmippXROTF::read: There is a problem "
156  "opening the file " + fn);
157 
158  try
159  {
160  lambda = textToFloat(getParameter(fh_param, "lambda", 0, "2.43"))* 1e-9;
161  deltaR = textToFloat(getParameter(fh_param, "outer_zone_width", 0, "40")) * 1e-9;
162  Nzp = textToFloat(getParameter(fh_param, "zones_number", 0, "560"));
163  Ms = textToFloat(getParameter(fh_param, "magnification", 0, "2304"));
164  dxoPSF = textToFloat(getParameter(fh_param, "sampling_rate", 0, "1")) *1e-9;
165  if (checkParameter(fh_param, "z_sampling_rate"))
166  dzoPSF = textToFloat(getParameter(fh_param, "z_sampling_rate", 0)) *1e-9;
167  else
168  dzoPSF = dxoPSF;
169  DeltaZo = textToFloat(getParameter(fh_param, "z_axis_shift", 0, "0")) *1e-6;
170 
171  Nox = textToInteger(getParameter(fh_param, "x_dim", 0, "0"));
172 
173  }
174  catch (XmippError &XE)
175  {
176  std::cout << XE << std::endl;
177  REPORT_ERROR(ERR_IO_NOREAD, (std::string)"There is an error reading " + fn);
178  }
179  fclose(fh_param);
180  }
181 }
182 
183 /* Write ------------------------------------------------------------------- */
184 void XRayPSF::write(const FileName &fn)
185 {
186  MetaDataVec MD;
187  MD.setColumnFormat(false);
188  size_t id = MD.addObject();
189 
190  FileName fnPSF = fn.withoutExtension().addExtension("vol");
191 
192  MD.setValue(MDL_IMAGE, fnPSF, id);
193  String typeS = (type==ANALYTIC_ZP)? "ZP": "ideal";
194  MD.setValue(MDL_CTF_XRAY_LENS_TYPE, typeS, id);
195  MD.setValue(MDL_CTF_LAMBDA,lambda*1e9, id);
198  MD.setValue(MDL_MAGNIFICATION,Ms, id);
202  std::vector<double> dimV(3);
203  dimV[0] = Nox;
204  dimV[1] = Noy;
205  dimV[2] = Noz;
206  MD.setValue(MDL_CTF_DIMENSIONS,dimV, id);
207 
208  MD.write(fn.withoutExtension().addExtension("xmd"));
209  // PSF->write(fnPSF);
210  psfVol.write(fnPSF);
211 }
212 
213 /* Show -------------------------------------------------------------------- */
214 std::ostream & operator <<(std::ostream &out, const XRayPSF &psf)
215 {
216 
217  out << std::endl
218  << "--------------------------------------" << std::endl
219  << "XrayPSF:: X-Ray Microscope parameters:" << std::endl
220  << "--------------------------------------" << std::endl
221  << "type = " << ((psf.type==ANALYTIC_ZP)? "ZP": "ideal") << std::endl
222  << "lambda = " << psf.lambda * 1e9 << " nm" << std::endl
223  << "zones_number = " << psf.Nzp << std::endl
224  << "outer_zone_width = " << psf.deltaR * 1e9 << " nm" << std::endl
225  << "magnification = " << psf.Ms << std::endl
226  << "sampling_rate = " << psf.dxo * 1e9 << " nm" << std::endl
227  << "z_sampling_rate = " << psf.dzo * 1e9 << " nm" << std::endl
228  << "z_axis_shift = " << psf.DeltaZo * 1e6 << " um" << std::endl
229  << std::endl
230  << "focal_length = " << psf.Flens * 1e3 << " mm" << std::endl
231  << "Lens Radius = " << psf.Rlens * 1e6 << " um" << std::endl
232  << "Zo = " << psf.Zo * 1e3 << " mm" << std::endl
233  << "Zi = " << psf.Zi * 1e3 << " mm" << std::endl
234  << "Depth_of_Focus = " << psf.DoF * 1e6 << " um" << std::endl
235  << std::endl
236  << "dxi = " << psf.dxi * 1e6 << " um" << std::endl
237  << "dxiMax = " << psf.dxiMax * 1e6 << " um" << std::endl
238  ;
239 
240  return out;
241 }
242 
243 /* Show the microscope parameters------------------------------------------- */
245 {
246  std::cout << *this << std::endl;
247 }
248 
249 /* Initialization of parameters ------------------------------------------- */
251 {
252  lambda = 2.43e-9;
253  // Flens = 1.4742e-3;
254  deltaR = 40e-9;
255  Nzp = 560;
256  Ms = 2304;
257  dzo = dxo = 1e-9;
258  DeltaZo = 0;
259  pupileSizeMin = 5;
260 
261  mode = GENERATE_PSF;
263 
264  // ftGenOTF.setNormalizationSign(FFTW_BACKWARD);
265 }
266 /* Default values ---------------------------------------------------------- */
268 {
269  psfVol.clear();
270  init();
271 }
272 
273 void XRayPSF::setFocalShift(double zShift)
274 {
275  DeltaZo -= zShift;
276 }
277 
278 /* Produce Side Information ------------------------------------------------ */
279 void XRayPSF::calculateParams(double _dxo, double _dzo, double threshold)
280 {
281 
282  dxo = (_dxo > 0)? _dxo : dxoPSF;
283  dzo = (_dzo > 0)? _dzo : dxo;
284 
286 
287  Rlens = (4 * Nzp * deltaR)*0.5; // Eq. 9.13 from Soft X-rays and .... David Attwood
288  Flens = (2 * Rlens * deltaR)/lambda;
289 
290  Zo = (1 + 1 / Ms) * Flens;
291  Zi = Zo * Ms;
292  dxi = dxo * Ms;
293  dxiMax = lambda * Zi / (2 * Rlens);
294  DoF = 4*deltaR*deltaR/lambda;
295 
296  if(verbose > 0)
297  {
298  show();
299  verbose++; // Show only once the param adjust info
300  }
301 
302  if (mode == PSF_FROM_FILE)
303  {
304  T.initIdentity(4);
305  double scaleFactor = dxo/dxoPSF;
306  // double scaleFactorZ = dxo/dzoPSF;
307  double scaleFactorZ = 1;
308 
309  dMij(T, 0, 0) = scaleFactor;
310  dMij(T, 1, 1) = scaleFactor;
311  dMij(T, 2, 2) = scaleFactorZ;
315  MultidimArray<double> &mdaPsfVol = psfVol();
316 
317  mdaPsfVol.resize(1, (size_t)(Noz/scaleFactorZ),
318  (size_t)(Noy/scaleFactor),
319  (size_t)(Nox/scaleFactor), false);
320 
321  mdaPsfVol.setXmippOrigin();
322 
324  xmipp_transformation::IS_INV, xmipp_transformation::DONT_WRAP);
325 
326  psfGen.clear(); // Free mem in case image is not mapped
327 
328  // Rescale the PSF values to keep the normalization in each X-Y plane
329  mdaPsfVol *= scaleFactor*scaleFactor;
330 
331  // Reset the sampling values so now psfVol matches input phantom's sampling
332  dxoPSF = dxo;
333  // dzoPSF = dzo;
334  T.initIdentity(4);
335 
336  if (threshold != 0.)
337  reducePSF2Slabs(threshold);
338  }
339  else // Mask is used when creating PSF on demand
340  {
342  }
343 }
344 
346 {
347  // find max position
348  ArrayCoord maxPos;
349  MultidimArray<double> &mdaPsfVol = psfVol();
350 
351  //MULTIDIM_ARRAY_GENERIC(PSFGen).maxIndex(maxPos);
352  mdaPsfVol.maxIndex(maxPos);
353  double maxValue = A3D_ELEM(mdaPsfVol,maxPos.z,maxPos.y,maxPos.x);
354  threshold *= maxValue;
355  slabIndex.clear();
356 
357  double maxTemp = maxValue;
358  for (int k = 0; k > STARTINGZ(mdaPsfVol); --k)
359  {
360  double tempV = A3D_ELEM(mdaPsfVol,k,maxPos.y,maxPos.x);
361  if ( maxTemp - tempV > threshold)
362  {
363  slabIndex.insert(slabIndex.begin(), k);
364  maxTemp = tempV;
365  }
366  }
367  slabIndex.insert(slabIndex.begin(), STARTINGZ(mdaPsfVol));
368 
369  maxTemp = maxValue;
370  for (int k = 0; k < FINISHINGZ(mdaPsfVol); ++k)
371  {
372  double tempV = A3D_ELEM(mdaPsfVol,k,maxPos.y,maxPos.x);
373  if ( maxTemp - tempV > threshold)
374  {
375  slabIndex.push_back(k);
376  maxTemp = tempV;
377  }
378  }
379  slabIndex.push_back(FINISHINGZ(mdaPsfVol));
380 
381 } //reducePSF2Slabs
382 
383 /* Apply the OTF to an image ----------------------------------------------- */
384 void XRayPSF::applyOTF(MultidimArray<double> &Im, const double sliceOffset) const
385 {
386  // double Z;
387  // MultidimArray< std::complex<double> > OTF;
388 
389  if (mode == GENERATE_PSF)
390  REPORT_ERROR(ERR_VALUE_NOTSET, "XrayPSF::applyOTF: a PSF from file must be read.");
391 
392  double Z = Zo + DeltaZo + sliceOffset;
393 
395  generateOTF(OTF, Z);
396 
398  FourierTransformer FTransAppOTF(FFTW_BACKWARD);
399 
400  //#define DEBUG
401 #ifdef DEBUG
402 
403  Image<double> _Im;
404  _Im() = Im;
405 
406  _Im.write(("psfxr-ImIn.spi"));
407 #endif
408 
409  FTransAppOTF.FourierTransform(Im, ImFT, false);
410 
412 #ifdef DEBUG
413 
414  _Im() = Im;
415 
416  _Im.write(("psfxr-ImIn_after.spi"));
417 
418  // Image<double> _Im;
419  _Im().clear();
420  _Im().resizeNoCopy(OTF);
422  dAij(_Im(),i,j) = abs(dAij(OTF,i,j));
423  _Im.write("psfxr-otf.spi");
424 
425  _Im().resizeNoCopy(ImFT);
427  dAij(_Im(),i,j) = abs(dAij(ImFT,i,j));
428  _Im.write(("psfxr-imft1.spi"));
429 #endif
430 
431  // double normSize = MULTIDIM_SIZE(OTF);
432 
434  dAij(ImFT,i,j) *= dAij(OTF,i,j);
435 
436 #ifdef DEBUG
437 
438  _Im().resize(ImFT);
440  dAij(_Im(),i,j) = abs(dAij(ImFT,i,j));
441  _Im.write(("psfxr-imft2.spi"));
442 #endif
443 
444  FTransAppOTF.inverseFourierTransform();
445 
446 #ifdef DEBUG
447 
448  _Im() = Im;
449 
450  // _Im().resize(Im);
451  // FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(Im)
452  // dAij(_Im(),i,j) = abs(dAij(Im,i,j));
453  _Im.write(("psfxr-imout.spi"));
454 #endif
455 #undef DEBUG
456 }
457 
458 void XRayPSF::generateOTF(MultidimArray<std::complex<double> > &OTF, double Zpos) const
459 {
460 
462  FourierTransformer ftGenOTF(FFTW_BACKWARD);
463  switch (mode)
464  {
465  case GENERATE_PSF:
466  {
467  if (type == IDEAL_FRESNEL_LENS)
468  generatePSFIdealLens(PSFi, Zpos);
469  break;
470  }
471  case PSF_FROM_FILE:
472  {
473  PSFi.resizeNoCopy(Niy, Nix);
474  PSFi.setXmippOrigin();
475 
476  const MultidimArray<double> &mPsfVol = MULTIDIM_ARRAY(psfVol);
477 
478  double zIndexPSF = (Zo - Zpos)/dzoPSF; // Slice index for Zpos
479 
480  if (zIndexPSF < STARTINGZ(mPsfVol) ||
481  zIndexPSF > FINISHINGZ(mPsfVol))
482  PSFi.initConstant(1/YXSIZE(PSFi));
483  else
484  { /* Actually T transform matrix is set to identity, as sampling is the same for both psfVol and phantom
485  * It is only missing to set Z shift to select the slice */
486  dMij(T, 2, 3) = zIndexPSF; // Distance from the focal plane
488  xmipp_transformation::IS_INV, xmipp_transformation::DONT_WRAP, dAkij(mPsfVol,0,0,0));
489  CenterFFT(PSFi, true);
490  }
491  break;
492  }
493  }
494 
495  ftGenOTF.FourierTransform(PSFi, OTF);
496 
497  //#define DEBUG
498 #ifdef DEBUG
499 
500  Image<double> _Im;
501  // _Im() = PSFi;
502  CenterFFT(PSFi, false);
503  _Im().alias(PSFi);
504  _Im.write("psfxr-psfi.spi");
505  // FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(PSFi)
506  // dAij(_Im(),i,j) = abs(dAij(PSFi,i,j));
507  // _Im.write("psfxr-psfi.spi");
508  // CenterOriginFFT(OTFTemp,1);
509  // _Im().resize(OTFTemp);
510  // FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(OTFTemp)
511  // dAij(_Im(),i,j) = abs(dAij(OTFTemp,i,j));
512  // _Im.write("psfxr-otf1.spi");
513  // CenterOriginFFT(OTFTemp,0);
514  _Im.clear();
515  _Im().resize(OTF);
517  dAij(_Im(),i,j) = abs(dAij(OTF,i,j));
518  _Im.write("psfxr-otf2.spi");
519 
520 #endif
521 #undef DEBUG
522 }
523 
524 /* Generate the Intensity PSF for a specific XR microscope configuration ------------- */
526 {
528  adjustParam();
529 
530  // PSF = new Image<double>(Nox, Noy, Noz);
531  // VOLMATRIX(*PSF).setXmippOrigin();
532 
534  mPsfVol.resize(1,Noz, Niy, Nix, false);
535  mPsfVol.setXmippOrigin();
536 
538 
539  init_progress_bar(ZSIZE(mPsfVol));
540 
541  for (int k = STARTINGZ(mPsfVol), k2 = 0; k <= FINISHINGZ(mPsfVol); k++, k2++)
542  {
543  /* We keep sign of Z, Zo and DeltaZo positives in object space for the sake of simplicity in calculations,
544  * it is, they increase opposite to Zdim in Xmipp reference system, so this is the reason to calculate
545  * the plane Z by subtracting k*dzoPSF which keeps positive in XMIPP system.
546  */
547 
548  double Z = Zo + DeltaZo - k*dzoPSF;
549 
550  switch (type)
551  {
552  case IDEAL_FRESNEL_LENS:
553  {
554  generatePSFIdealLens(PSFi, Z);
555  break;
556  }
557  case ANALYTIC_ZP:
558  {
559  REPORT_ERROR(ERR_NOT_IMPLEMENTED, "Zone plates algorithm not implemented yet.");
560  break;
561  }
562  }
563 
564  CenterFFT(PSFi, false);
565  mPsfVol.setSlice(k, PSFi);
566 
567  progress_bar(k2+1);
568  }
569 
570  /* When PSF is generated from IDEAL_FRESNEL_LENS, dimensions are adjusted to avoid subsampling,
571  * in that case it is not recommended to crop XY plane to avoid the loss of normalization in PSF plane. */
572 
573  // if (Nix != Nox || Niy != Noy)
574  // mPsfVol.selfWindow(STARTINGZ(mPsfVol),
575  // FIRST_XMIPP_INDEX(Noy),FIRST_XMIPP_INDEX(Nox),
576  // FINISHINGZ(mPsfVol),
577  // FIRST_XMIPP_INDEX(Noy)+Noy-1,FIRST_XMIPP_INDEX(Nox)+Nox-1);
578 }
579 
580 /* Generate the PSF for a ideal lens --------------------------------------- */
582 {
583  double focalEquiv = 1/(1/Zpos - 1/Zo); // inverse of defocus = 1/Z - 1/Zo
584 
587  // Mask_Params mask_prm; TODO do we have to include masks using this class?
588 
589  lensPD(OTFTemp, focalEquiv, lambda, dxl, dyl);
590 
591  // Apply the Shape mask
593  {
594  if (dAi(*mask,n) == 0)
595  dAi(OTFTemp,n) = 0;
596  }
597 
598  //#define DEBUG
599 #ifdef DEBUG
600  Image<double> _Im;
601  _Im().resize(OTFTemp);
603  dAij(_Im(),i,j) = arg(dAij(OTFTemp,i,j));
604  _Im.write("phase_lens.spi");
606  dAij(_Im(),i,j) = abs(dAij(OTFTemp,i,j));
607  _Im.write("abs_lens.spi");
608 #endif
609 #undef DEBUG
610 
611  FourierTransformer transformer(FFTW_BACKWARD);
612  transformer.FourierTransform(OTFTemp, PSFiTemp, false);
613  double norm=0;
614  double iNorm;
615 
616  PSFi.resizeNoCopy(PSFiTemp);
617 
618 #ifdef DEBUG
619 
620  _Im.data.resizeNoCopy(PSFiTemp);
623  _Im.write("psfitemp.spi");
624 #endif
625 
626  double aux;
627  double aux2;
629  {
630  aux=abs(DIRECT_MULTIDIM_ELEM(PSFiTemp,n));
631  DIRECT_MULTIDIM_ELEM(PSFi,n)=aux2=aux*aux;
632  norm += aux2;
633  }
634 
635  iNorm = 1/norm;
637  DIRECT_MULTIDIM_ELEM(PSFi,n) *= iNorm;
638 
639  //#define DEBUG
640 #ifdef DEBUG
641 
642  _Im() = PSFi;
643  CenterFFT(_Im(),0);
644  _Im.write("generate-psfi.spi");
645 #endif
646 #undef DEBUG
647 
648 
649 #ifdef DEBUG
650 
651  transformer.inverseFourierTransform();
652 
653  CenterOriginFFT(OTFTemp,0);
655  {
657  }
658  _Im.write("otftemp.spi");
659 #endif
660 
661 #undef DEBUG
662 }
663 
665 {
666  Nox = XSIZE(vol);
667  Noy = YSIZE(vol);
668  Noz = ZSIZE(vol);
669 
670  adjustParam();
671 }
672 
674 {
675  Nix = Nox;
676  Niy = Noy;
678 
679  if (mode == GENERATE_PSF)
680  {
681  switch (type)
682  {
683  case IDEAL_FRESNEL_LENS:
684  {
685  // Reset the image plane sampling value
686  dxi = dxo * Ms;
687 
688  dxl = lambda*Zi / (Nox * dxi); // Pixel X-size en the plane of lens aperture
689  dyl = lambda*Zi / (Noy * dxi); // Pixel Y-size en the plane of lens aperture
690 
691  deltaZMaxX = Zo*((Rlens*2*dxl)/(Rlens*2*dxl - Zo*lambda) - 1);
692  deltaZMaxY = Zo*((Rlens*2*dyl)/(Rlens*2*dyl - Zo*lambda) - 1);
693  deltaZMinX = Zo*((Rlens*2*dxl)/(Rlens*2*dxl + Zo*lambda) - 1);
694  deltaZMinY = Zo*((Rlens*2*dyl)/(Rlens*2*dyl + Zo*lambda) - 1);
695 
696 
697  if (verbose > 1)
698  {
699  std::cout << std::endl;
700  std::cout << "----------------------" << std::endl;
701  std::cout << "XrayPSF::Param adjust:" << std::endl;
702  std::cout << "----------------------" << std::endl;
703  std::cout << "(Nox,Noy,Nz) = (" << Nox << "," << Noy << "," << Noz << ")" << std::endl;
704  std::cout << "Larger volume Z plane to be calculated = " << (ABS(DeltaZo)+(Noz-1)/2*dzo)*1e6 << " um" << std::endl;
705  std::cout << "Larger allowed discrete Z plane (x,y) = (" << deltaZMaxX*1e6 << ", " << deltaZMaxY*1e6 << ") um" << std::endl;
706  }
707 
708  if (dxi>dxiMax)
709  {
710  Nix = (size_t)ceil(Nox * dxi/dxiMax);
711  Niy = (size_t)ceil(Noy * dxi/dxiMax);
712 
713  dxi *= Nox/Nix;
714 
716 
717  if (verbose > 1)
718  std::cout << "XrayPSF: Image plane sampling too small: increasing resolution" << std::endl;
719 
720  }
721  else
722  {
723  if (dxi < pupileSizeMin/Nox * dxiMax)
724  {
725  Nix = (size_t)ceil(pupileSizeMin * dxiMax/dxi);
727  }
728  if (dxi < pupileSizeMin/Noy * dxiMax)
729  {
730  Niy = (size_t)ceil(pupileSizeMin * dxiMax/dxi);
732  }
733  if (DeltaZo + Noz/2*dzo > deltaZMaxX)
734  {
735  Nix = std::max(Nix,(size_t)ceil(Zi*Rlens*2*fabs(DeltaZo+Noz/2*dzo)/(Zo*dxi*(Zo+DeltaZo+Noz/2*dzo))));
737  }
738  if (DeltaZo - Noz/2*dzo < deltaZMinX)
739  {
740  Nix = std::max(Nix,(size_t)ceil(Zi*Rlens*2*fabs(DeltaZo-Noz/2*dzo)/(Zo*dxi*(Zo+DeltaZo-Noz/2*dzo))));
742  }
743  if (DeltaZo + Noz/2*dzo > deltaZMaxY)
744  {
745  Niy = std::max(Niy,(size_t)ceil(Zi*Rlens*2*fabs(DeltaZo+Noz/2*dzo)/(Zo*dxi*(Zo+DeltaZo+Noz/2*dzo))));
747  }
748  if ( DeltaZo - Noz/2*dzo < deltaZMinY)
749  {
750  Niy = std::max(Niy,(size_t)ceil(Zi*Rlens*2*fabs(DeltaZo-Noz/2*dzo)/(Zo*dxi*(Zo+DeltaZo-Noz/2*dzo))));
752  }
753  }
754 
755  dxl = lambda*Zi / (Nix * dxi); // Pixel X-size en the plane of lens aperture
756  dyl = lambda*Zi / (Niy * dxi); // Pixel Y-size en the plane of lens aperture
757 
758  if (verbose > 1)
759  {
760  if (AdjustType!=PSFXR_STD)
761  {
762  if (AdjustType==PSFXR_ZPAD)
763  std::cout << "XrayPSF: Image plane size too small: increasing size" << std::endl;
764  std::cout << "New slice dimensions: " << "(Nix, Niy) = (" << Nix << ", " << Niy << ")" << std::endl;
765  }
766  std::cout << "(dxl, dyl) = (" << dxl*1e6 << ", " << dyl*1e6 << ") um" << std::endl;
767  std::cout << "Pupile Diameter in pixels (NpX, NpY) = (" << ceil(2*Rlens / dxl)
768  << ", " << ceil(2*Rlens / dyl) << ")" << std::endl;
769  std::cout << std::endl;
770  }
771 
772  // Calculate the mask to be applied when generating PSFIdealLens
773 
774  mask->initZeros(Niy,Nix);
775  mask->setXmippOrigin();
776 
777  double Rlens2 = Rlens*Rlens;
778  // double auxY = dyl*(1 - (int)Niy);
779  // double auxX = dxl*(1 - (int)Nix);
780 
781  for (int i = STARTINGY(*mask); i <= FINISHINGY(*mask); ++i)
782  {
783  double y = dyl * i;
784  double y2 = y * y;
785  for (int j = STARTINGX(*mask); j <= FINISHINGX(*mask); ++j)// Circular mask
786  {
788  double x = dxl * j;
789  if (x*x + y2 <= Rlens2)
790  A2D_ELEM(*mask,i,j) = 1;
791  }
792  }
793 
794 
795  break;
796  }
797  case ANALYTIC_ZP:
798  {
799  REPORT_ERROR(ERR_NOT_IMPLEMENTED, "Zone Plate algorithm not implemented yet.");
800  break;
801  }
802  }
803  }
804  else
805  {
806  // OTF.clear(); // Only for each projection
807  }
808 
809  if (verbose > 1)
810  --verbose;
811 }
812 
813 /* Generate the quadratic phase distribution of an ideal lens ------------- */
814 void lensPD(MultidimArray<std::complex<double> > &Im, double Flens, double lambda, double dx, double dy)
815 {
816 
817  double x;
818  double y;
819  double phase;
820 
821  Im.setXmippOrigin();
822 
823  double K = (-PI / (lambda * Flens));
824 
825  for (int i = STARTINGY(Im); i <= FINISHINGY(Im); ++i)
826  {
827  y = dy * i;
828  double y2 = y * y;
829 
830  for (int j = STARTINGX(Im); j <= FINISHINGX(Im); ++j)
831  {
832  x = dx * j;
833  phase = K * (x * x + y2);
834  A2D_ELEM(Im,i,j) = std::complex<double>(cos(phase),sin(phase));
835  }
836  }
837 }
838 #undef DEBUG
Argument missing.
Definition: xmipp_error.h:114
bool checkParameter(int argc, const char **argv, const char *param)
Definition: args.cpp:97
#define dAi(v, i)
void init_progress_bar(long total)
double pupileSizeMin
Minimum diameter size of the microscope pupile in the lens plane, measured in pixels.
Definition: psf_xr.h:173
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
Algorithm used to generate Xray PSF.
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
size_t xdim
double getDoubleParam(const char *param, int arg=0)
double lambda
Lambda of illumination.
Definition: psf_xr.h:180
~XRayPSF()
Definition: psf_xr.cpp:38
double DeltaZo
Z axis global shift.
Definition: psf_xr.h:192
void generateOTF(MultidimArray< std::complex< double > > &OTF, double Zpos) const
Generate the Optical Transfer Function (OTF) for a slice according to Microscope and Im parameters...
Definition: psf_xr.cpp:458
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
#define FINISHINGX(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
double Zi
Object plane.
Definition: psf_xr.h:146
PsfType type
Define the selected PSF generation algorithm.
Definition: psf_xr.h:117
double dxiMax
Definition: psf_xr.h:159
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
void resizeNoCopy(const MultidimArray< T1 > &v)
#define dAij(M, i, j)
void applyOTF(MultidimArray< double > &Im, const double sliceOffset) const
Apply the OTF to the image, by means of the convolution.
Definition: psf_xr.cpp:384
void generatePSF()
Generate the 3D Point Spread Function (PSF) according to Microscope parameters.
Definition: psf_xr.cpp:525
static double * y
FileName addExtension(const String &ext) const
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)
double deltaR
Outermost zone width.
Definition: psf_xr.h:188
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 maxIndex(int &jmax) const
#define MULTIDIM_ARRAY(v)
void initConstant(T val)
void abs(Image< double > &op)
double dxoPSF
object space XY-plane sampling rate of the PSF Volume
Definition: psf_xr.h:207
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
Image< double > psfVol
3D PSF read from file
Definition: psf_xr.h:123
void init()
Definition: psf_xr.cpp:250
void setFocalShift(double zShift)
Add focal shift to previously read psf zshift.
Definition: psf_xr.cpp:273
#define FINISHINGZ(v)
double dyl
Pixel size in Y-dim in lens plane.
Definition: psf_xr.h:163
T norm(const std::vector< T > &v)
Definition: vector_ops.h:399
#define STARTINGX(v)
double deltaZMaxY
Definition: psf_xr.h:166
double dxo
object space XY-plane sampling rate
Definition: psf_xr.h:197
double Nzp
Number of zones in zone plate.
Definition: psf_xr.h:186
static void defineParams(XmippProgram *program)
Definition: psf_xr.cpp:45
doublereal * x
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
#define STARTINGY(v)
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
void threshold(double *phi, unsigned long nvox, double limit)
Definition: lib_vwk.cpp:524
#define A3D_ELEM(V, k, i, j)
MultidimArray< T > data
Definition: xmipp_image.h:55
Standard mode, image size does not changes.
Definition: psf_xr.h:44
Sampling rate in Z direction.
double psf
void reducePSF2Slabs(double threshold)
Calculate the width of the slabs to reduce computing time and the mean PSF for each.
Definition: psf_xr.cpp:345
double Zo
Object plane on Focus (Reference)
Definition: psf_xr.h:142
const char * getParameter(int argc, const char **argv, const char *param, const char *option)
Definition: args.cpp:30
const char * getParam(const char *param, int arg=0)
std::vector< int > slabIndex
Z positions in the original PSF Volume to determine de slabs.
Definition: psf_xr.h:131
void read(const FileName &fn, bool readVolume=true)
Definition: psf_xr.cpp:82
size_t zdim
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const
size_t Noz
Z size of the input image (object plane size)
Definition: psf_xr.h:156
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
Longitudinal displacement.
float textToFloat(const char *str)
double DoF
Depth of focus. Only for information purposes.
Definition: psf_xr.h:148
void readParams(XmippProgram *program)
Definition: psf_xr.cpp:64
size_t Nix
Size of the image in image plane, to be rescaled if needed.
Definition: psf_xr.h:203
void setSlice(int k, const MultidimArray< T1 > &v, size_t n=0)
#define dMij(m, i, j)
Definition: matrix2d.h:139
size_t firstRowId() const override
#define XSIZE(v)
void progress_bar(long rlen)
double dx
void max(Image< double > &op1, const Image< double > &op2)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
Outermost zone width of the X-ray Fresnel lens (nm)
#define dAkij(V, k, i, j)
#define ABS(x)
Definition: xmipp_macros.h:142
double Rlens
Lens Aperture Radius.
Definition: psf_xr.h:140
#define ZSIZE(v)
#define DIRECT_MULTIDIM_ELEM(v, n)
double deltaZMaxX
Z limits around Zo in the psf generation due to Nyquist Limit.
Definition: psf_xr.h:165
int verbose
Switch to control verbose mode.
Definition: psf_xr.h:212
Couldn&#39;t read from file.
Definition: xmipp_error.h:139
operMode mode
Definition: psf_xr.h:114
double deltaZMinY
Definition: psf_xr.h:168
#define STR_EQUAL(str1, str2)
Definition: xmipp_strings.h:42
void calculateParams(double _dxo, double _dzo=-1, double threshold=0.)
Produce Side information.
Definition: psf_xr.cpp:279
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
double Flens
Focal length.
Definition: psf_xr.h:184
Wavelength (nm)
#define j
void show()
Show the microscope parameters.
Definition: psf_xr.cpp:244
double deltaZMinX
Definition: psf_xr.h:167
Matrix2D< double > T
Definition: psf_xr.h:133
void adjustParam()
Calculate if a resize of the X-Y plane is needed to avoid the Nyquist Limit.
Definition: psf_xr.cpp:673
bool getValue(MDObject &mdValueOut, size_t id) const override
size_t Niy
Definition: psf_xr.h:204
File cannot be open.
Definition: xmipp_error.h:137
void clear()
Clear.
Definition: psf_xr.cpp:267
virtual void setColumnFormat(bool column)
#define FINISHINGY(v)
ImageGeneric psfGen
Definition: psf_xr.h:121
bool isMetaData(bool failIfNotExists=true) const
size_t Nox
X size of the input image (object plane size)
Definition: psf_xr.h:152
Increasing the image size by Interpolating.
Definition: psf_xr.h:45
Value has not been set.
Definition: xmipp_error.h:196
FileName withoutExtension() const
void write(const FileName &fn)
Definition: psf_xr.cpp:184
void lensPD(MultidimArray< std::complex< double > > &Im, double Flens, double lambda, double dx, double dy)
Generate the quadratic phase distribution of a ideal lens.
Definition: psf_xr.cpp:814
std::string String
Definition: xmipp_strings.h:34
double dzo
object space Z sampling rate
Definition: psf_xr.h:201
int textToInteger(const char *str)
double dxl
Pixel size in X-dim in lens plane.
Definition: psf_xr.h:161
FileName getDir() const
double dzoPSF
object space Z sampling rate of the PSF Volume
Definition: psf_xr.h:209
XRayPSF()
Definition: psf_xr.cpp:33
size_t ydim
constexpr int K
static String label2Str(const MDLabel &label)
PsfxrAdjust AdjustType
Parameters to change image size to avoid Nyquist limit.
Definition: psf_xr.h:171
void generatePSFIdealLens(MultidimArray< double > &PSFi, double Zpos) const
Generate the PSF for a single plane according to a ideal lens.
Definition: psf_xr.cpp:581
void initZeros(const MultidimArray< T1 > &op)
friend std::ostream & operator<<(std::ostream &out, const XRayPSF &psf)
Show.
Definition: psf_xr.cpp:214
#define PI
Definition: tools.h:43
double dxi
Image space XY-plane sampling rate.
Definition: psf_xr.h:199
int getIntParam(const char *param, int arg=0)
#define YXSIZE(v)
#define STARTINGZ(v)
int readMapped(const FileName &name, size_t select_img=ALL_IMAGES, int mode=WRITE_READONLY)
int * n
Name of an image (std::string)
size_t Noy
Y size of the input image (object plane size)
Definition: psf_xr.h:154
double Ms
Magnification.
Definition: psf_xr.h:190
void clear()
Definition: xmipp_image.h:144
void addParamsLine(const String &line)
MultidimArray< double > * mask
Lens shape Mask.
Definition: psf_xr.h:136
void initIdentity()
Definition: matrix2d.h:673
void CenterOriginFFT(MultidimArray< std::complex< double > > &v, bool forward)
Definition: xmipp_fft.cpp:386