def propagate_wavefront(cls, wavefront1, propagation_distance, magnification_x=1.0): wavefront = wavefront1.duplicate() shape = wavefront.size() delta = wavefront.delta() wavenumber = wavefront.get_wavenumber() wavelength = wavefront.get_wavelength() fft_scale = numpy.fft.fftfreq(shape) / delta x = wavefront.get_abscissas() x_rescaling = wavefront.get_abscissas() * magnification_x r1sq = x**2 * (1 - magnification_x) r2sq = x_rescaling**2 * ((magnification_x - 1) / magnification_x) fsq = (fft_scale**2 / magnification_x) 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) wavefront.add_phase_shift(Q1) fft = numpy.fft.fft(wavefront.get_complex_amplitude()) ifft = numpy.fft.ifft(fft * Q2) * Q3 / numpy.sqrt(magnification_x) wf_propagated = GenericWavefront1D.initialize_wavefront_from_arrays( x_rescaling, ifft, wavelength=wavelength) return wf_propagated
def propagate_wavefront(cls, wavefront, propagation_distance, shift_half_pixel=False): shape = wavefront.size() delta = wavefront.delta() wavelength = wavefront.get_wavelength() wavenumber = wavefront.get_wavenumber() fft_scale = numpy.fft.fftfreq(shape, d=delta) fft_scale = numpy.fft.fftshift(fft_scale) x2 = fft_scale * propagation_distance * wavelength if shift_half_pixel: x2 = x2 - 0.5 * numpy.abs(x2[1] - x2[0]) p1 = numpy.exp(1.0j * wavenumber * propagation_distance) p2 = numpy.exp(1.0j * wavenumber / 2 / propagation_distance * x2**2) p3 = 1.0j * wavelength * propagation_distance fft = numpy.fft.fft(wavefront.get_complex_amplitude()) fft = fft * p1 * p2 / p3 fft2 = numpy.fft.fftshift(fft) wavefront_out = GenericWavefront1D.initialize_wavefront_from_arrays( x2, fft2, wavelength=wavefront.get_wavelength()) # 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
def get_eigenvector_wavefront(self, mode): complex_amplitude = self.get_eigenvectors()[mode, :] * np.sqrt( self.get_eigenvalue(mode)) wf = GenericWavefront1D.initialize_wavefront_from_arrays( self.abscissas, complex_amplitude) wf.set_photon_energy(self.photon_energy) return wf
def _calculate_far_field(self): # # undulator emission # out = self.calculate_undulator_emission( electron_energy=self.electron_energy, electron_current=self.electron_current, undulator_period=self.undulator_period, undulator_nperiods=self.undulator_nperiods, K=self.K, photon_energy=self.photon_energy, abscissas_interval_in_far_field=self. _abscissas_interval_in_far_field, number_of_points=self.number_of_points, distance_to_screen=self.distance_to_screen, scan_direction=self.scan_direction, ) # # # from wofry.propagator.wavefront1D.generic_wavefront import GenericWavefront1D input_wavefront = GenericWavefront1D.initialize_wavefront_from_arrays( out["abscissas"], out["electric_field"][:, 0]) input_wavefront.set_photon_energy(photon_energy=self.photon_energy) self.far_field_wavefront = input_wavefront
def propagator1D_offaxis(input_wavefront, x2_oe, y2_oe, p, q, theta_grazing_in, theta_grazing_out=None, zoom_factor=1.0, normalize_intensities=False): from wofry.propagator.wavefront1D.generic_wavefront import GenericWavefront1D if theta_grazing_out is None: theta_grazing_out = theta_grazing_in x1 = input_wavefront.get_abscissas() field1 = input_wavefront.get_complex_amplitude() wavelength = input_wavefront.get_wavelength() x1_oe = -p * numpy.cos(theta_grazing_in) + x1 * numpy.sin(theta_grazing_in) y1_oe = p * numpy.sin(theta_grazing_in) + x1 * numpy.cos(theta_grazing_in) # field2 is the electric field in the mirror field2 = goFromToSequential(field1, x1_oe, y1_oe, x2_oe, y2_oe, wavelength=wavelength, normalize_intensities=normalize_intensities) x3 = x1 * zoom_factor x3_oe = q * numpy.cos(theta_grazing_out) + x3 * numpy.sin(theta_grazing_out) y3_oe = q * numpy.sin(theta_grazing_out) + x3 * numpy.cos(theta_grazing_out) # field2 is the electric field in the image plane field3 = goFromToSequential(field2, x2_oe, y2_oe, x3_oe, y3_oe, wavelength=wavelength, normalize_intensities=normalize_intensities) output_wavefront = GenericWavefront1D.initialize_wavefront_from_arrays(x3, field3 / numpy.sqrt(zoom_factor), wavelength=wavelength) return output_wavefront
def toGenericWavefront(self): wavelength = self.wise_computation_result.Lambda position = self.wise_computation_result.S electric_field = numpy.real( self.wise_computation_result.Field) + 1j * numpy.imag( self.wise_computation_result.Field) return GenericWavefront1D.initialize_wavefront_from_arrays( x_array=position, y_array=electric_field, wavelength=wavelength)
def test_initializers(self, do_plot=do_plot): print("# ") print("# Tests for initializars (1D) ") print("# ") x = numpy.linspace(-100, 100, 50) y = numpy.abs(x)**1.5 + 1j * numpy.abs(x)**1.8 wf0 = GenericWavefront1D.initialize_wavefront_from_steps( x[0], numpy.abs(x[1] - x[0]), y.size) wf0.set_complex_amplitude(y) wf1 = GenericWavefront1D.initialize_wavefront_from_range( x[0], x[-1], y.size) wf1.set_complex_amplitude(y) wf2 = GenericWavefront1D.initialize_wavefront_from_arrays(x, y) print("wavefront sizes: ", wf1.size(), wf1.size(), wf2.size()) if do_plot: from srxraylib.plot.gol import plot plot(wf0.get_abscissas(), wf0.get_intensity(), title="initialize_wavefront_from_steps", show=0) plot(wf1.get_abscissas(), wf1.get_intensity(), title="initialize_wavefront_from_range", show=0) plot(wf2.get_abscissas(), wf2.get_intensity(), title="initialize_wavefront_from_arrays", show=1) numpy.testing.assert_almost_equal(wf0.get_intensity(), numpy.abs(y)**2, 5) numpy.testing.assert_almost_equal(wf1.get_intensity(), numpy.abs(y)**2, 5) numpy.testing.assert_almost_equal(x, wf1.get_abscissas(), 11) numpy.testing.assert_almost_equal(x, wf2.get_abscissas(), 11)
def propagate_wavefront(cls, wavefront1, propagation_distance1, magnification_x=1.0, radius=1e6): wavefront = wavefront1.duplicate() shape = wavefront.size() delta = wavefront.delta() wavenumber = wavefront.get_wavenumber() wavelength = wavefront.get_wavelength() # radius = -50.0 magnification = (propagation_distance1 + radius) / radius propagation_distance = propagation_distance1 / magnification # # make plane wave by adding a spherical wavefront with radius -R # new_phase = 1.0 * wavefront.get_wavenumber() * ( wavefront.get_abscissas()**2) / (-2 * radius) wavefront.add_phase_shifts(new_phase) # # main 2 FFT block # fft_scale = numpy.fft.fftfreq(shape) / delta x = wavefront.get_abscissas() x_rescaling = wavefront.get_abscissas() * magnification_x r1sq = x**2 * (1 - magnification_x) r2sq = x_rescaling**2 * ((magnification_x - 1) / magnification_x) fsq = (fft_scale**2 / magnification_x) 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) wavefront.add_phase_shift(Q1) fft = numpy.fft.fft(wavefront.get_complex_amplitude()) ifft = numpy.fft.ifft(fft * Q2) * Q3 / numpy.sqrt(magnification_x) # # # # # calculate new phase term and scale coordinates # k = wavefront.get_wavenumber() PHASE1 = numpy.ones( wavefront.get_abscissas().size) * (k * propagation_distance * (1 - 1 / magnification)) PHASE2 = k / 2 / propagation_distance * ( magnification - 1) / magnification * (wavefront.get_abscissas() * magnification)**2 PHASE = PHASE2 + PHASE1 wf_propagated = GenericWavefront1D.initialize_wavefront_from_arrays( x_rescaling * magnification, ifft / numpy.sqrt(magnification) * numpy.exp(1j * PHASE), wavelength=wavelength) return wf_propagated
def propagate_wavefront_new( cls, wavefront, propagation_distance, fraunhofer_kernel=True, # set to False for far field propagator shift_half_pixel=None, # not more used, kept for version compatibility ): # # check validity # x = wavefront.get_abscissas() deltax = wavefront.delta() # # compute Fourier transform # # frequency for axis 1 npixels = wavefront.size() pixelsize = wavefront.delta() wavenumber = wavefront.get_wavenumber() wavelength = wavefront.get_wavelength() freq_nyquist = 0.5 / pixelsize if numpy.mod(npixels, 2) == 0: freq_n = numpy.arange(-npixels // 2, npixels // 2, 1) / (npixels // 2) else: freq_n = numpy.arange(-(npixels - 1) // 2, (npixels + 1) // 2, 1) / ((npixels - 1) // 2) freq_x = freq_n * freq_nyquist x2 = freq_x * propagation_distance * wavelength P1 = numpy.exp(1.0j * wavenumber * propagation_distance) # fsq = freq_x ** 2 # P2 = numpy.exp(-1.0j * wavenumber / 2 / propagation_distance * fsq) P2 = numpy.exp(1.0j * wavenumber / 2 / propagation_distance * x**2) P3 = 1.0j * wavelength * propagation_distance if fraunhofer_kernel: exponential = 1.0 + 0j else: exponential = numpy.exp(1j * wavenumber / 2 / propagation_distance * x**2) F1 = numpy.fft.fft(exponential * wavefront.get_complex_amplitude() ) # Take the fourier transform of the image. # Now shift the quadrants around so that low spatial frequencies are in # the center of the 2D fourier transformed image. F1 *= P1 F1 *= P2 F1 /= numpy.sqrt(P3) # this is 1D -> no sqrt for 2D F2 = numpy.fft.fftshift(F1) F2 *= deltax # why?? wavefront_out = GenericWavefront1D.initialize_wavefront_from_arrays( x_array=x2, y_array=F2, wavelength=wavelength) # 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
def calculate_output_wavefront_after_GSM_1D(input_wavefront, shape=1, radius=10000.0, wavy_amplitude=1e-9, wavy_ripples=1.0, grazing_angle=1.5e-3, grazing_angle_out=1.5e-3, lines_per_meter=None, error_flag=0, error_file="", error_edge_management=0, write_profile=""): import numpy from scipy import interpolate abscissas = input_wavefront.get_abscissas().copy() abscissas_on_mirror = abscissas / numpy.sin(grazing_angle) abscissas_on_output_plane = abscissas_on_mirror * numpy.sin( grazing_angle_out) output_wavefront = GenericWavefront1D.initialize_wavefront_from_arrays( abscissas_on_output_plane, input_wavefront.get_complex_amplitude(), wavelength=input_wavefront.get_wavelength(), ) # )input_wavefront.duplicate() if shape == 0: height = numpy.zeros_like(abscissas_on_mirror) elif shape == 1: if radius >= 0: height = radius - numpy.sqrt(radius**2 - abscissas_on_mirror**2) else: height = radius + numpy.sqrt(radius**2 - abscissas_on_mirror**2) elif shape > 1: if wavy_ripples == 0.0: height = numpy.zeros_like(abscissas_on_mirror) else: period = (abscissas_on_mirror[-1] - abscissas_on_mirror[0]) / wavy_ripples if shape == 2: y = numpy.cos(2 * numpy.pi * abscissas_on_mirror / period) elif shape == 3: y = numpy.sin(2 * numpy.pi * abscissas_on_mirror / period) y -= y.min() y /= y.max() y *= wavy_amplitude height = y else: raise Exception("Wrong shape") if error_flag: a = numpy.loadtxt(error_file) # extrapolation if error_edge_management == 0: finterpolate = interpolate.interp1d( a[:, 0], a[:, 1], fill_value="extrapolate" ) # fill_value=(0,0),bounds_error=False) elif error_edge_management == 1: finterpolate = interpolate.interp1d(a[:, 0], a[:, 1], fill_value=(0, 0), bounds_error=False) else: # crop raise Exception("Bad value of error_edge_management") height_interpolated = finterpolate(abscissas_on_mirror) height += height_interpolated #>>>>>>>>>>>>>>>>>>> # phi = -2 * output_wavefront.get_wavenumber() * height * numpy.sin(grazing_angle) # Ken's Eq. 7 if lines_per_meter is None: delta_grating = 0 else: order = 1 grating_period = 1.0 / lines_per_meter delta_grating = order * output_wavefront.get_wavelength( ) / grating_period * abscissas_on_mirror delta_s = abscissas_on_mirror * (numpy.cos(grazing_angle) - numpy.cos(grazing_angle_out)) \ - height * (numpy.sin(grazing_angle) + numpy.sin(grazing_angle_out)) phi = output_wavefront.get_wavenumber() * (delta_s + delta_grating) #>>>>>>>>>>>>>>>>>>> output_wavefront.add_phase_shifts(phi) if error_flag: profile_limits = a[-1, 0] - a[0, 0] profile_limits_projected = (a[-1, 0] - a[0, 0]) * numpy.sin(grazing_angle) wavefront_dimension = output_wavefront.get_abscissas( )[-1] - output_wavefront.get_abscissas()[0] print("profile deformation dimension: %f m" % (profile_limits)) print( "profile deformation projected perpendicular to optical axis: %f um" % (1e6 * profile_limits_projected)) print("wavefront window dimension: %f um" % (1e6 * wavefront_dimension)) if wavefront_dimension <= profile_limits_projected: print( "\nWavefront window inside error profile domain: no action needed" ) else: if error_edge_management == 0: print( "\nProfile deformation extrapolated to fit wavefront dimensions" ) else: output_wavefront.clip(a[0, 0] * numpy.sin(grazing_angle), a[-1, 0] * numpy.sin(grazing_angle)) print( "\nWavefront clipped to projected limits of profile deformation" ) # output files if write_profile != "": f = open(write_profile, "w") for i in range(height.size): f.write("%g %g\n" % (abscissas_on_mirror[i], height[i])) f.close() print("File %s written to disk." % write_profile) return output_wavefront, abscissas_on_mirror, height