Example #1
0
def propagate_1D_fresnel_radius(wavefront, propagation_distance, eta):
    """
    1D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :return: a new 1D wavefront object with propagated wavefront
    """
    fft_scale = numpy.fft.fftfreq(wavefront.size()) / wavefront.delta()

    fft = numpy.fft.fft(wavefront.get_complex_amplitude())
    fft *= numpy.exp(1.0j * numpy.pi * wavefront.get_wavelength() *
                     propagation_distance *
                     (-fft_scale**2 + eta * fft_scale**2))
    H = numpy.fft.ifft(fft)
    H *= -1.0j * eta * propagation_distance / wavefront.get_wavelength(
    ) * numpy.exp(1.0j * numpy.pi / eta / propagation_distance /
                  wavefront.get_wavelength() * wavefront.get_abscissas()**2)
    ifft = numpy.fft.fft(H)
    ifft *= numpy.exp(1.0j * numpy.pi / eta / propagation_distance /
                      wavefront.get_wavelength() *
                      wavefront.get_abscissas()**2)

    return Wavefront1D(
        wavefront.get_wavelength(),
        ScaledArray.initialize_from_steps(ifft, wavefront.offset(),
                                          wavefront.delta()))
Example #2
0
def propagate_1D_integral(wavefront, propagation_distance, detector_abscissas=[None]):
    """
    1D Fresnel-Kirchhoff propagator via simplified integral
    :param wavefront:
    :param propagation_distance: propagation distance
    :param detector_abscissas: a numpy array with the anscissas at the image position. If undefined ([None])
                            it uses the same abscissas present in input wavefront.
    :return: a new 1D wavefront object with propagated wavefront
    """

    if detector_abscissas[0] == None:
        detector_abscissas = wavefront.get_abscissas()

    # 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) )
    wavenumber = numpy.pi*2/wavefront.get_wavelength()
    distances_matrix  = numpy.exp(1.j * wavenumber *  r)


    fieldComplexAmplitude = numpy.dot(wavefront.get_complex_amplitude(),distances_matrix)

    return Wavefront1D(wavefront.get_wavelength(), ScaledArray.initialize_from_steps(fieldComplexAmplitude, \
                            detector_abscissas[0], detector_abscissas[1]-detector_abscissas[0] ))
Example #3
0
def propagator1d_fourier_rescaling(wavefront, propagation_distance, m=1):

    wf = wavefront.duplicate()  # todo: cambiato da giovanni, controllare
    shape = wf.size()
    delta = wf.delta()
    wavenumber = wf.get_wavenumber()
    wavelength = wf.get_wavelength()

    fft_scale = numpy.fft.fftfreq(shape, d=delta)

    x = wf.get_abscissas()

    x_rescaling = wf.get_abscissas() * m

    r1sq = x**2 * (1 - m)
    r2sq = x_rescaling**2 * ((m - 1) / m)
    fsq = (fft_scale**2 / m)

    Q1 = wavenumber / 2 / propagation_distance * r1sq
    Q2 = numpy.exp(-1.0j * numpy.pi * wavelength * propagation_distance * fsq)
    Q3 = numpy.exp(1.0j * wavenumber / 2 / propagation_distance * r2sq)

    wf.add_phase_shift(Q1)

    fft = numpy.fft.fft(wf.get_complex_amplitude())

    ifft = numpy.fft.ifft(fft * Q2) * Q3 / numpy.sqrt(m)

    return Wavefront1D(
        wf.get_wavelength(),
        ScaledArray.initialize_from_steps(ifft, m * wf.offset(),
                                          m * wf.delta()))
Example #4
0
    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 [email protected] 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
Example #5
0
 def initialize_wavefront_from_steps(cls, x_start=0.0, x_step=0.0, number_of_points=1000, wavelength=1e-10):
     return Wavefront1D(
         wavelength,
         ScaledArray.initialize_from_steps(
             np_array=numpy.full(number_of_points, (1.0 + 0.0j), dtype=complex),
             initial_scale_value=x_start,
             scale_step=x_step,
         ),
     )
Example #6
0
    def initialize_wavefront_from_arrays(cls, x_array, y_array, wavelength=1e-10):
        if x_array.size != y_array.size:
            raise Exception("Unmatched shapes for x and y")

        return Wavefront1D(
            wavelength,
            ScaledArray.initialize_from_steps(
                np_array=y_array, initial_scale_value=x_array[0], scale_step=numpy.abs(x_array[1] - x_array[0])
            ),
        )
Example #7
0
 def initialize_wavefront_from_steps(cls,
                                     x_start=0.0,
                                     x_step=0.0,
                                     number_of_points=1000,
                                     wavelength=1e-10):
     return Wavefront1D(
         wavelength,
         ScaledArray.initialize_from_steps(np_array=numpy.full(
             number_of_points, (1.0 + 0.0j), dtype=complex),
                                           initial_scale_value=x_start,
                                           scale_step=x_step))
Example #8
0
def propagate_1D_integral(wavefront,
                          propagation_distance,
                          detector_abscissas=[None],
                          method=0,
                          magnification=1.0,
                          npoints_exit=None):
    """
    1D Fresnel-Kirchhoff propagator via integral implemented as sum
    :param wavefront:
    :param propagation_distance: propagation distance
    :param detector_abscissas: a numpy array with the abscissas at the image position. If undefined ([None])
                            it uses the same abscissas present in input wavefront.
    :param method: 0 (default_ makes a loop over detector coordinates, 1: makes matrices (outer products) so
                            it is more memory hungry.
    :param magnification: if detector_abscissas is [None], the detector abscissas range is the input
                            wavefront range times this magnification factor. Default =1
    :param npoints_exit: if detector_abscissas is [None], the number of points of detector abscissas.
                            Default=None meaning that the same number of points than wavefront are used.
    :return: a new 1D wavefront object with propagated wavefront
    """

    if detector_abscissas[0] == None:

        x = wavefront.get_abscissas()
        if npoints_exit is None:
            npoints_exit = x.size
        detector_abscissas = numpy.linspace(magnification * x[0],
                                            magnification * x[-1],
                                            npoints_exit)

    wavenumber = numpy.pi * 2 / wavefront.get_wavelength()
    if method == 0:
        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)

    return Wavefront1D(wavefront.get_wavelength(), ScaledArray.initialize_from_steps(fieldComplexAmplitude, \
                            detector_abscissas[0], detector_abscissas[1]-detector_abscissas[0] ))
Example #9
0
    def propagate_wavefront(cls, wavefront, propagation_distance):

        fft_scale = numpy.fft.fftfreq(wavefront.size()) / wavefront.delta()

        fft = numpy.fft.fft(wavefront.get_complex_amplitude())
        fft *= numpy.exp((-1.0j) * numpy.pi * wavefront.get_wavelength() *
                         propagation_distance * fft_scale**2)
        ifft = numpy.fft.ifft(fft)

        return GenericWavefront1D(
            wavefront.get_wavelength(),
            ScaledArray.initialize_from_steps(ifft, wavefront.offset(),
                                              wavefront.delta()))
Example #10
0
    def initialize_wavefront_from_steps(cls,
                                        x_start=-1.0,
                                        x_step=0.002,
                                        number_of_points=1000,
                                        wavelength=1e-10,
                                        polarization=Polarization.SIGMA):

        sA = ScaledArray.initialize_from_steps(np_array=numpy.full(
            number_of_points, (1.0 + 0.0j), dtype=complex),
                                               initial_scale_value=x_start,
                                               scale_step=x_step)
        if ((polarization == Polarization.PI)
                or (polarization == Polarization.TOTAL)):
            sA_pi = ScaledArray.initialize_from_steps(
                np_array=numpy.full(number_of_points, (0.0 + 0.0j),
                                    dtype=complex),
                initial_scale_value=x_start,
                scale_step=x_step)
        else:
            sA_pi = None

        return GenericWavefront1D(wavelength, sA, sA_pi)
Example #11
0
    def initialize_wavefront_from_arrays(cls,
                                         x_array,
                                         y_array,
                                         y_array_pi=None,
                                         wavelength=1e-10):
        if x_array.size != y_array.size:
            raise Exception("Unmatched shapes for x and y")

        sA = ScaledArray.initialize_from_steps(
            np_array=y_array,
            initial_scale_value=x_array[0],
            scale_step=numpy.abs(x_array[1] - x_array[0]))

        if y_array_pi is not None:
            sA_pi = ScaledArray.initialize_from_steps(
                np_array=y_array_pi,
                initial_scale_value=x_array[0],
                scale_step=numpy.abs(x_array[1] - x_array[0]))
        else:
            sA_pi = None

        return GenericWavefront1D(wavelength, sA, sA_pi)
Example #12
0
def propagate_1D_fresnel(wavefront, propagation_distance):
    """
    1D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :return: a new 1D wavefront object with propagated wavefront
    """
    fft_scale = numpy.fft.fftfreq(wavefront.size())/wavefront.delta()

    fft = numpy.fft.fft(wavefront.get_complex_amplitude())
    fft *= numpy.exp((-1.0j) * numpy.pi * wavefront.get_wavelength() * propagation_distance * fft_scale**2)
    ifft = numpy.fft.ifft(fft)

    return Wavefront1D(wavefront.get_wavelength(), ScaledArray.initialize_from_steps(ifft, wavefront.offset(), wavefront.delta()))
Example #13
0
    def initialize_wavefront_from_arrays(
        cls,
        x_array,
        y_array,
        wavelength=1e-10,
    ):
        if x_array.size != y_array.size:
            raise Exception("Unmatched shapes for x and y")

        return Wavefront1D(
            wavelength,
            ScaledArray.initialize_from_steps(
                np_array=y_array,
                initial_scale_value=x_array[0],
                scale_step=numpy.abs(x_array[1] - x_array[0])))
Example #14
0
def propagate_1D_fresnel_convolution(wavefront, propagation_distance):
    """
    1D Fresnel propagator using direct convolution
    :param wavefront:
    :param propagation_distance:
    :return:
    """

    # instead of numpy.convolve, this can be used:
    # from scipy.signal import fftconvolve

    kernel = numpy.exp(1j*2*numpy.pi/wavefront.get_wavelength() * wavefront.get_abscissas()**2 / 2 / propagation_distance)
    kernel *= numpy.exp(1j*2*numpy.pi/wavefront.get_wavelength() * propagation_distance)
    kernel /=  1j * wavefront.get_wavelength() * propagation_distance
    tmp = numpy.convolve(wavefront.get_complex_amplitude(),kernel,mode='same')

    return Wavefront1D(wavefront.get_wavelength(), ScaledArray.initialize_from_steps(tmp, wavefront.offset(), wavefront.delta()))
Example #15
0
    def propagate_wavefront(cls, wavefront, propagation_distance):

        kernel = numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                           wavefront.get_abscissas()**2 / 2 /
                           propagation_distance)
        kernel *= numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                            propagation_distance)
        kernel /= 1j * wavefront.get_wavelength() * propagation_distance
        tmp = numpy.convolve(wavefront.get_complex_amplitude(),
                             kernel,
                             mode='same')

        wavefront_out = GenericWavefront1D(
            wavefront.get_wavelength(),
            ScaledArray.initialize_from_steps(tmp, wavefront.offset(),
                                              wavefront.delta()))

        # added [email protected] 2018-03-23 to conserve energy - TODO: review method!
        wavefront_out.rescale_amplitude(
            numpy.sqrt(wavefront.get_intensity().sum() /
                       wavefront_out.get_intensity().sum()))

        return wavefront_out
Example #16
0
def propagate_1D_fresnel_convolution(wavefront, propagation_distance):
    """
    1D Fresnel propagator using direct convolution
    :param wavefront:
    :param propagation_distance:
    :return:
    """

    # instead of numpy.convolve, this can be used:
    # from scipy.signal import fftconvolve

    kernel = numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                       wavefront.get_abscissas()**2 / 2 / propagation_distance)
    kernel *= numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                        propagation_distance)
    kernel /= 1j * wavefront.get_wavelength() * propagation_distance
    tmp = numpy.convolve(wavefront.get_complex_amplitude(),
                         kernel,
                         mode='same')

    return Wavefront1D(
        wavefront.get_wavelength(),
        ScaledArray.initialize_from_steps(tmp, wavefront.offset(),
                                          wavefront.delta()))
Example #17
0
def propagate_2D(calculation_parameters, input_parameters):
    shadow_oe = calculation_parameters.shadow_oe_end

    if calculation_parameters.do_ff_z and calculation_parameters.do_ff_x:
        global_phase_shift_profile = None

        if shadow_oe._oe.F_MOVE == 1 and shadow_oe._oe.X_ROT != 0.0:
            if input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
                global_phase_shift_profile = calculation_parameters.w_mirr_2D_values
            elif input_parameters.ghy_calcType == 2:
                global_phase_shift_profile = ScaledMatrix.initialize_from_range(numpy.zeros((3, 3)),
                                                                                shadow_oe._oe.RWIDX2, shadow_oe._oe.RWIDX1,
                                                                                shadow_oe._oe.RLEN2,  shadow_oe._oe.RLEN1)

            for x_index in range(global_phase_shift_profile.size_x()):
                global_phase_shift_profile.z_values[x_index, :] += global_phase_shift_profile.get_y_values()*numpy.sin(numpy.radians(-shadow_oe._oe.X_ROT))
        elif input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
            global_phase_shift_profile = calculation_parameters.w_mirr_2D_values

        # only tangential slopes
        if input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
            rms_slope = hy_findrmsslopefromheight(ScaledArray(np_array=global_phase_shift_profile.z_values[int(global_phase_shift_profile.size_x()/2), :],
                                                              scale=global_phase_shift_profile.get_y_values()))

            print("Using RMS slope = " + str(rms_slope))

        # ------------------------------------------
        # far field calculation
        # ------------------------------------------
        focallength_ff = calculate_focal_length_ff_2D(calculation_parameters.ghy_x_min,
                                                      calculation_parameters.ghy_x_max,
                                                      calculation_parameters.ghy_z_min,
                                                      calculation_parameters.ghy_z_max,
                                                      input_parameters.ghy_npeak,
                                                      calculation_parameters.gwavelength)

        if (input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4) and rms_slope != 0:
            focallength_ff = min(focallength_ff,(calculation_parameters.ghy_z_max-calculation_parameters.ghy_z_min) / 16 / rms_slope ) #xshi changed
        elif input_parameters.ghy_calcType == 2 and not global_phase_shift_profile is None:
            focallength_ff = min(focallength_ff, input_parameters.ghy_distance*4) #TODO: PATCH to be found with a formula

        print("FF: calculated focal length: " + str(focallength_ff))

        fftsize_x = int(calculate_fft_size(calculation_parameters.ghy_x_min,
                                           calculation_parameters.ghy_x_max,
                                           calculation_parameters.gwavelength,
                                           focallength_ff,
                                           input_parameters.ghy_fftnpts,
                                           factor=20))

        fftsize_z = int(calculate_fft_size(calculation_parameters.ghy_z_min,
                                        calculation_parameters.ghy_z_max,
                                        calculation_parameters.gwavelength,
                                        focallength_ff,
                                        input_parameters.ghy_fftnpts,
                                        factor=20))

        print("FF: creating plane wave begin, fftsize_x = " +  str(fftsize_x) + ", fftsize_z = " +  str(fftsize_z))

        wavefront = Wavefront2D.initialize_wavefront_from_range(wavelength=calculation_parameters.gwavelength,
                                                                number_of_points=(fftsize_x, fftsize_z),
                                                                x_min=calculation_parameters.ghy_x_min,
                                                                x_max=calculation_parameters.ghy_x_max,
                                                                y_min=calculation_parameters.ghy_z_min,
                                                                y_max=calculation_parameters.ghy_z_max)

        try:
            for i in range(0, len(wavefront.electric_field_array.x_coord)):
                for j in range(0, len(wavefront.electric_field_array.y_coord)):
                    interpolated = calculation_parameters.wIray_2d.interpolate_value(wavefront.electric_field_array.x_coord[i],
                                                                                     wavefront.electric_field_array.y_coord[j])
                    wavefront.electric_field_array.set_z_value(i, j, numpy.sqrt(0.0 if interpolated < 0 else interpolated))
        except IndexError:
            raise Exception("Unexpected Error during interpolation: try reduce Number of bins for I(Tangential) histogram")

        wavefront.apply_ideal_lens(focallength_ff, focallength_ff)

        shadow_oe = calculation_parameters.shadow_oe_end

        if input_parameters.ghy_calcType == 3 or \
                (input_parameters.ghy_calcType == 2 and not global_phase_shift_profile is None):
            print("FF: calculating phase shift due to Height Error Profile")

            phase_shifts = numpy.zeros(wavefront.size())

            for index in range(0, phase_shifts.shape[0]):
                np_array = numpy.zeros(global_phase_shift_profile.shape()[1])
                for j in range(0, len(np_array)):
                    np_array[j] = global_phase_shift_profile.interpolate_value(wavefront.get_coordinate_x()[index], calculation_parameters.w_mirr_2D_values.get_y_value(j))

                global_phase_shift_profile_z = ScaledArray.initialize_from_steps(np_array,
                                                                                 global_phase_shift_profile.y_coord[0],
                                                                                 global_phase_shift_profile.y_coord[1] - global_phase_shift_profile.y_coord[0])

                phase_shifts[index, :] = get_mirror_phase_shift(wavefront.get_coordinate_y(),
                                                                calculation_parameters.gwavelength,
                                                                calculation_parameters.wangle_z,
                                                                calculation_parameters.wl_z,
                                                                global_phase_shift_profile_z)
            wavefront.add_phase_shifts(phase_shifts)
        elif input_parameters.ghy_calcType == 4:
            print("FF: calculating phase shift due to Height Error Profile")

            phase_shifts = numpy.zeros(wavefront.size())

            for index in range(0, phase_shifts.shape[0]):
                global_phase_shift_profile_z = ScaledArray.initialize_from_steps(global_phase_shift_profile.z_values[index, :],
                                                                                 global_phase_shift_profile.y_coord[0],
                                                                                 global_phase_shift_profile.y_coord[1] - global_phase_shift_profile.y_coord[0])

                phase_shifts[index, :] = get_grating_phase_shift(wavefront.get_coordinate_y(),
                                                                 calculation_parameters.gwavelength,
                                                                 calculation_parameters.wangle_z,
                                                                 calculation_parameters.wangle_ref_z,
                                                                 calculation_parameters.wl_z,
                                                                 global_phase_shift_profile_z)
            wavefront.add_phase_shifts(phase_shifts)
        elif input_parameters.ghy_calcType == 6:
            for w_mirr_2D_values in calculation_parameters.w_mirr_2D_values:
                phase_shift = get_crl_phase_shift(w_mirr_2D_values,
                                                  input_parameters,
                                                  calculation_parameters,
                                                  [wavefront.get_coordinate_x(), wavefront.get_coordinate_y()])

                wavefront.add_phase_shift(phase_shift)

        print("calculated plane wave: begin FF propagation (distance = " +  str(focallength_ff) + ")")

        propagated_wavefront = propagator2D.propagate_2D_fresnel(wavefront, focallength_ff)

        print("dif_zp: begin calculation")

        imagesize_x = min(abs(calculation_parameters.ghy_x_max), abs(calculation_parameters.ghy_x_min)) * 2
        imagesize_x = min(imagesize_x,
                          input_parameters.ghy_npeak*2*0.88*calculation_parameters.gwavelength*focallength_ff/abs(calculation_parameters.ghy_x_max-calculation_parameters.ghy_x_min))

        # TODO: this is a patch: to be rewritten
        if shadow_oe._oe.F_MOVE==1 and not shadow_oe._oe.Y_ROT==0:
            imagesize_x = max(imagesize_x, 8*(focallength_ff*numpy.tan(numpy.radians(numpy.abs(shadow_oe._oe.Y_ROT))) + numpy.abs(shadow_oe._oe.OFFX)))

        delta_x = propagated_wavefront.delta()[0]
        imagenpts_x = int(round(imagesize_x/delta_x/2) * 2 + 1)

        imagesize_z = min(abs(calculation_parameters.ghy_z_max), abs(calculation_parameters.ghy_z_min)) * 2
        imagesize_z = min(imagesize_z,
                          input_parameters.ghy_npeak*2*0.88*calculation_parameters.gwavelength*focallength_ff/abs(calculation_parameters.ghy_z_max-calculation_parameters.ghy_z_min))

        # TODO: this is a patch: to be rewritten
        if shadow_oe._oe.F_MOVE==1 and not shadow_oe._oe.X_ROT==0:
            imagesize_z = max(imagesize_z, 8*(focallength_ff*numpy.tan(numpy.radians(numpy.abs(shadow_oe._oe.X_ROT))) + numpy.abs(shadow_oe._oe.OFFZ)))

        delta_z = propagated_wavefront.delta()[1]
        imagenpts_z = int(round(imagesize_z/delta_z/2) * 2 + 1)

        dif_xpzp = ScaledMatrix.initialize_from_range(numpy.ones((imagenpts_x, imagenpts_z)),
                                                      min_scale_value_x = -(imagenpts_x - 1) / 2 * delta_x,
                                                      max_scale_value_x =(imagenpts_x - 1) / 2 * delta_x,
                                                      min_scale_value_y = -(imagenpts_z - 1) / 2 * delta_z,
                                                      max_scale_value_y =(imagenpts_z - 1) / 2 * delta_z)

        for i in range(0, dif_xpzp.shape()[0]):
            for j in range(0, dif_xpzp.shape()[1]):
                dif_xpzp.set_z_value(i, j, numpy.absolute(propagated_wavefront.get_interpolated_complex_amplitude(
                                                               dif_xpzp.x_coord[i],
                                                               dif_xpzp.y_coord[j]))**2
                                                           )

        dif_xpzp.set_scale_from_range(0,
                                      -(imagenpts_x - 1) / 2 * delta_x / focallength_ff,
                                      (imagenpts_x - 1) / 2 * delta_x / focallength_ff)

        dif_xpzp.set_scale_from_range(1,
                                      -(imagenpts_z - 1) / 2 * delta_z / focallength_ff,
                                      (imagenpts_z - 1) / 2 * delta_z / focallength_ff)

        calculation_parameters.dif_xpzp = dif_xpzp
    def test_ScaledArray(self,do_plot=do_plot):



        #
        # ScaledArray.initialize + set_scale_from_steps
        #
        test_array = numpy.arange(15.0, 18.8, 0.2)


        print("\nTesting ScaledArray.initialize + set_scale_from_steps...")


        scaled_array = ScaledArray.initialize(test_array)
        scaled_array.set_scale_from_steps(test_array[0],0.2)

        print("Using array: ",test_array)
        print("Stored array: ",scaled_array.get_values())

        print("Using array: ",test_array)
        print("Stored abscissas: ",scaled_array.get_abscissas())

        numpy.testing.assert_almost_equal(test_array,scaled_array.get_values(),11)
        numpy.testing.assert_almost_equal(test_array,scaled_array.get_abscissas(),11)
        self.assertAlmostEqual(0.2,scaled_array.delta(),11)
        self.assertAlmostEqual(15.0,scaled_array.offset(),11)

        x_in =   (18.80,16.22,22.35)
        x_good = (18.80,16.22,18.8)

        for i,x in enumerate(x_in):
            print("interpolated at %3.2f is: %3.2f (must give %3.2f)"%( x,scaled_array.interpolate_value(x), x_good[i] ))
            self.assertAlmostEqual(scaled_array.interpolate_value(x), x_good[i], 2)


        #
        # ScaledArray.initialize + set_scale_from_range ; interpolate vectorized
        #
        print("\nTesting ScaledArray.initialize + set_scale_from_range ; interpolate vectorized...")
        scaled_array = ScaledArray.initialize(test_array)
        scaled_array.set_scale_from_range(test_array[0],test_array[-1])

        x_in =   (18.80,16.22,22.35)
        x_good = (18.80,16.22,18.8)

        for i,x in enumerate(x_in):
            print("interpolated at %3.2f is: %3.2f (must give %3.2f)"%( x,scaled_array.interpolate_value(x), x_good[i] ))
            self.assertAlmostEqual(scaled_array.interpolate_value(x), x_good[i], 2)


        #
        # ScaledArray.initialize_from_steps
        #
        print("\nTesting ScaledArray.initialize_from_steps...")
        scaled_array = ScaledArray.initialize_from_steps(test_array, test_array[0], 0.2)

        x_in =   (18.80,16.22,22.35)
        x_good = (18.80,16.22,18.8)

        for i,x in enumerate(x_in):
            print("interpolated at %3.2f is: %3.2f (must give %3.2f)"%( x,scaled_array.interpolate_value(x), x_good[i] ))
            self.assertAlmostEqual(scaled_array.interpolate_value(x), x_good[i], 2)

        #
        # ScaledArray.initialize_from_steps
        #
        print("\nTesting ScaledArray.initialize_from_range...")
        scaled_array = ScaledArray.initialize_from_range(test_array,test_array[0], test_array[-1])

        x_in =   (18.80,16.22,22.35)
        x_good = (18.80,16.22,18.8)

        for i,x in enumerate(x_in):
            print("interpolated at %3.2f is: %3.2f (must give %3.2f)"%( x,scaled_array.interpolate_value(x), x_good[i] ))
            self.assertAlmostEqual(scaled_array.interpolate_value(x), x_good[i], 2)


        #
        # interpolator
        #
        print("\nTesting interpolator...")
        x = numpy.arange(-5.0, 18.8, 3)
        y = x**2

        scaled_array = ScaledArray.initialize_from_range(y,x[0],x[-1])

        print("for interpolation; x=",x)
        print("for interpolation; offset, delta:=",scaled_array.offset(),scaled_array.delta())
        print("for interpolation; abscissas:=",scaled_array.get_abscissas())

        x1 = numpy.concatenate( ( numpy.arange(-6, -4, 0.1) , [0], numpy.arange(11, 20.0, 0.1) ) )

        y1 = scaled_array.interpolate_values(x1)

        if do_plot:
            from srxraylib.plot.gol import plot
            plot(x,y,x1,y1,legend=["Data",'Interpolated'],legend_position=[0.4,0.8],
                 marker=['','o'],linestyle=['-',''],xrange=[-6,21],yrange=[-5,375])

        for i in range(len(x1)):
            y2 = x1[i]**2

            if x1[i] <= x[0]:
                y2 = y[0]

            if x1[i] >= x[-1]:
                y2 = y[-1]

            print("   interpolated at x=%g is: %g (expected: %g)"%(x1[i],y1[i],y2))
            self.assertAlmostEqual(1e-3*y1[i], 1e-3*y2, 2)


        # interpolate on same grid
        print("\nTesting interpolation on the same grid...")



        y1 = scaled_array.interpolate_values(scaled_array.get_abscissas())
        if do_plot:
            from srxraylib.plot.gol import plot
            plot(scaled_array.get_abscissas(),scaled_array.get_values(),
                 scaled_array.get_abscissas(),y1,legend=["Data",'Interpolated on same grid'],legend_position=[0.4,0.8],
                 marker=['','o'],linestyle=['-',''])

        numpy.testing.assert_almost_equal(scaled_array.get_values(),y1,5)