Source code for wofryimpl.propagator.propagators1D.integral

"""
Integral1D — 1-D Kirchhoff-Fresnel integral propagator (direct numerical integration, slow but accurate).
"""
import numpy

from srxraylib.util.data_structures import ScaledArray
from wofry.propagator.wavefront1D.generic_wavefront import GenericWavefront1D
from wofry.propagator.propagator import Propagator1D

[docs] class Integral1D(Propagator1D): HANDLER_NAME = "INTEGRAL_1D"
[docs] def get_handler_name(self): return self.HANDLER_NAME
[docs] def do_specific_progation_after(self, wavefront, propagation_distance, parameters, element_index=None): return self.do_specific_progation(wavefront, propagation_distance, parameters, element_index=element_index)
[docs] def do_specific_progation_before(self, wavefront, propagation_distance, parameters, element_index=None): return self.do_specific_progation( wavefront, propagation_distance, parameters, element_index=element_index)
# 1D Fresnel-Kirchhoff propagator via simplified integral
[docs] def do_specific_progation(self, wavefront, propagation_distance, parameters, element_index=None): magnification_N = self.get_additional_parameter("magnification_N",1.0,parameters,element_index=element_index) magnification_x = self.get_additional_parameter("magnification_x",1.0,parameters,element_index=element_index) return self.propagate_wavefront(wavefront,propagation_distance,magnification_x=magnification_x, magnification_N=magnification_N)
[docs] @classmethod def propagate_wavefront(cls,wavefront,propagation_distance,magnification_x=1.0,magnification_N=1.0): method = 0 wavenumber = numpy.pi*2/wavefront.get_wavelength() x = wavefront.get_abscissas() if magnification_N != 1.0: npoints_exit = int(magnification_N * x.size) else: npoints_exit = x.size detector_abscissas = numpy.linspace(magnification_x*x[0],magnification_x*x[-1],npoints_exit) if method == 0: # calculate via loop pver detector coordinates x1 = wavefront.get_abscissas() x2 = detector_abscissas fieldComplexAmplitude = numpy.zeros_like(x2,dtype=complex) for ix,x in enumerate(x2): r = numpy.sqrt( numpy.power(x1-x,2) + numpy.power(propagation_distance,2) ) distances_array = numpy.exp(1.j * wavenumber * r) fieldComplexAmplitude[ix] = (wavefront.get_complex_amplitude() * distances_array).sum() elif method == 1: # calculate via outer product, it spreads over a lot of memory, but it is OK for 1D x1 = numpy.outer(wavefront.get_abscissas(),numpy.ones(detector_abscissas.size)) x2 = numpy.outer(numpy.ones(wavefront.size()),detector_abscissas) r = numpy.sqrt( numpy.power(x1-x2,2) + numpy.power(propagation_distance,2) ) distances_matrix = numpy.exp(1.j * wavenumber * r) fieldComplexAmplitude = numpy.dot(wavefront.get_complex_amplitude(),distances_matrix) wavefront_out = GenericWavefront1D(wavefront.get_wavelength(), ScaledArray.initialize_from_steps(fieldComplexAmplitude, detector_abscissas[0], detector_abscissas[1]-detector_abscissas[0])) # added srio@esrf.eu 2018-03-23 to conserve energy - TODO: review method! # wavefront_out.rescale_amplitude( numpy.sqrt(wavefront.get_intensity().sum() / # wavefront_out.get_intensity().sum() # / magnification_x)) wavefront_out.rescale_amplitude( (1/numpy.sqrt(1j*wavefront.get_wavelength()*propagation_distance))*(x1[1]-x1[0]) * \ numpy.exp(1j * wavenumber * propagation_distance)) return wavefront_out