def undulator(self, method, npixels_x, npixels_y, pixelsize_x, pixelsize_y, wavelength, sigma, m, m_x, m_y, propagation_distance, radius, show, image_source, apply_lens): wavefront = Wavefront2D.initialize_wavefront_from_range( x_min=-pixelsize_x * npixels_x / 2, x_max=pixelsize_x * npixels_x / 2, y_min=-pixelsize_y * npixels_y / 2, y_max=pixelsize_y * npixels_y / 2, number_of_points=(npixels_x, npixels_y), wavelength=wavelength) wavefront.set_spherical_wave(radius=radius) if image_source == False: X = wavefront.get_mesh_x() Y = wavefront.get_mesh_y() wavefront.rescale_amplitude( numpy.exp(-(X**2 + Y**2) / (2 * sigma**2)) ) # applichiamo intensita' con profilo gaussiano print("Input intensity: ", wavefront.get_intensity().sum()) if apply_lens == True: wavefront.apply_ideal_lens(focal_length_x=propagation_distance, focal_length_y=propagation_distance) print("Intensity after lens: ", wavefront.get_intensity().sum()) if method == 'fft': output_wf = propagate_2D_fresnel( wavefront, propagation_distance=propagation_distance) elif method == 'rescaling': output_wf = propagator2d_fourier_rescaling( wavefront, propagation_distance=propagation_distance, m=m) elif method == 'rescaling_xy': output_wf = propagator2d_fourier_rescaling_xy( wavefront, propagation_distance=propagation_distance, m_x=m_x, m_y=m_y) plot_undulator(output_wf, method=method, show=show) horizontal_profile_wf = line_image(wavefront.get_intensity(), horizontal_or_vertical='H') vertical_profile_wf = line_image(wavefront.get_intensity(), horizontal_or_vertical='V') horizontal_phase_profile_wf = line_image(wavefront.get_phase(), horizontal_or_vertical='H') if image_source == True: return wavefront.get_coordinate_x( ), horizontal_profile_wf, horizontal_phase_profile_wf
def test_initializers(self,do_plot=do_plot): print("# ") print("# Tests for initializars (2D) ") print("# ") x = numpy.linspace(-100,100,50) y = numpy.linspace(-50,50,200) XY = numpy.meshgrid(x,y) X = XY[0].T Y = XY[1].T sigma = 10 Z = numpy.exp(- (X**2 + Y**2)/2/sigma**2) * 1j print("Shapes x,y,z: ",x.shape,y.shape,Z.shape) wf0 = Wavefront2D.initialize_wavefront_from_steps(x[0],numpy.abs(x[1]-x[0]),y[0],numpy.abs(y[1]-y[0]),number_of_points=Z.shape) wf0.set_complex_amplitude(Z) wf1 = Wavefront2D.initialize_wavefront_from_range(x[0],x[-1],y[0],y[-1],number_of_points=Z.shape) wf1.set_complex_amplitude(Z) wf2 = Wavefront2D.initialize_wavefront_from_arrays(x,y,Z) if do_plot: from srxraylib.plot.gol import plot_image plot_image(wf0.get_intensity(),wf0.get_coordinate_x(),wf0.get_coordinate_y(), title="initialize_wavefront_from_steps",show=0) plot_image(wf1.get_intensity(),wf1.get_coordinate_x(),wf1.get_coordinate_y(), title="initialize_wavefront_from_range",show=0) plot_image(wf2.get_intensity(),wf2.get_coordinate_x(),wf2.get_coordinate_y(), title="initialize_wavefront_from_arrays",show=1) numpy.testing.assert_almost_equal(numpy.abs(Z)**2,wf0.get_intensity(),11) numpy.testing.assert_almost_equal(numpy.abs(Z)**2,wf1.get_intensity(),11) numpy.testing.assert_almost_equal(numpy.abs(Z)**2,wf2.get_intensity(),11) numpy.testing.assert_almost_equal(x,wf0.get_coordinate_x(),11) numpy.testing.assert_almost_equal(x,wf1.get_coordinate_x(),11) numpy.testing.assert_almost_equal(x,wf2.get_coordinate_x(),11) numpy.testing.assert_almost_equal(y,wf0.get_coordinate_y(),11) numpy.testing.assert_almost_equal(y,wf1.get_coordinate_y(),11) numpy.testing.assert_almost_equal(y,wf2.get_coordinate_y(),11)
def propagate_2D_fresnel(self, do_plot, method='fft', wavelength=1.24e-10, aperture_type='square', aperture_diameter=40e-6, pixelsize_x=1e-6, pixelsize_y=1e-6, npixels_x=1024, npixels_y=1024, propagation_distance=30.0, m=1, m_x=1, m_y=1, show=0): method_label = "fresnel (%s)" % method print( "\n# ") print("# 2D near field fresnel (%s) diffraction from a %s aperture " % (method_label, aperture_type)) print("# ") # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2, # x_step=pixelsize_x, # y_start=-pixelsize_y*npixels_y/2, # y_step=pixelsize_y, # wavelength=wavelength, # number_of_points=(npixels_x,npixels_y)) wf = Wavefront2D.initialize_wavefront_from_range( x_min=-pixelsize_x * npixels_x / 2, x_max=pixelsize_x * npixels_x / 2, y_min=-pixelsize_y * npixels_y / 2, y_max=pixelsize_y * npixels_y / 2, number_of_points=(npixels_x, npixels_y), wavelength=wavelength) wf.set_plane_wave_from_complex_amplitude((1.0 + 0j)) if aperture_type == 'circle': wf.apply_pinhole(aperture_diameter / 2) elif aperture_type == 'square': wf.apply_slit(-aperture_diameter / 2, aperture_diameter / 2, -aperture_diameter / 2, aperture_diameter / 2) else: raise Exception("Not implemented! (accepted: circle, square)") if method == 'fft': wf1 = propagate_2D_fresnel(wf, propagation_distance) elif method == 'rescaling': wf1 = propagator2d_fourier_rescaling(wf, propagation_distance, m=m) elif method == 'rescaling_xy': wf1 = propagator2d_fourier_rescaling_xy(wf, propagation_distance, m_x=m_x, m_y=m_y) else: raise Exception("Not implemented method: %s" % method) if do_plot: from srxraylib.plot.gol import plot_image plot_image(wf.get_intensity(), 1e6 * wf.get_coordinate_x(), 1e6 * wf.get_coordinate_y(), title="aperture intensity (%s), Diameter=%5.1f um" % (aperture_type, 1e6 * aperture_diameter), xtitle="X [um]", ytitle="Y [um]", show=0) plot_image( wf1.get_intensity(), 1e6 * wf1.get_coordinate_x() / propagation_distance, 1e6 * wf1.get_coordinate_y() / propagation_distance, title= "Diffracted intensity (%s) by a %s slit of aperture %3.1f um" % (aperture_type, method_label, 1e6 * aperture_diameter), xtitle="X [urad]", ytitle="Y [urad]", show=0) # get the theoretical value angle_x = wf.get_coordinate_x() / propagation_distance intensity_theory = get_theoretical_diffraction_pattern( angle_x, aperture_type=aperture_type, aperture_diameter=aperture_diameter, wavelength=wavelength, normalization=True) intensity_calculated = wf1.get_intensity()[:, int(wf1.size()[1] / 2)] intensity_calculated /= intensity_calculated.max() if do_plot: from srxraylib.plot.gol import plot plot( wf1.get_coordinate_x() * 1e6 / propagation_distance, intensity_calculated, angle_x * 1e6, intensity_theory, legend=[ "%s H profile" % method_label, "Theoretical (far field)" ], legend_position=(0.60, 0.95), title= "%s diffraction of a %s slit of %3.1f um at wavelength of %3.1f A" % (method_label, aperture_type, aperture_diameter * 1e6, wavelength * 1e10), xtitle="X (urad)", ytitle="Intensity", xrange=[-20, 20], show=show) if method == 'rescaling_xy' and do_plot: angle_y = wf.get_coordinate_y() / propagation_distance intensity_calculated_v = wf1.get_intensity()[int(wf1.size()[1] / 2), :] intensity_calculated_v /= intensity_calculated_v.max() from srxraylib.plot.gol import plot plot( wf1.get_coordinate_y() * 1e6 / propagation_distance, intensity_calculated_v, angle_y * 1e6, intensity_theory, legend=[ "%s V profile" % method_label, "Theoretical (far field)" ], legend_position=(0.60, 0.95), title= "%s diffraction of a %s slit of %3.1f um at wavelength of %3.1f A" % (method_label, aperture_type, aperture_diameter * 1e6, wavelength * 1e10), xtitle="Y (urad)", ytitle="Intensity", xrange=[-20, 20], show=show) return wf1.get_coordinate_x( ) / propagation_distance, intensity_calculated, angle_x, intensity_theory
def main(beamline,pixels=100): npixels_x = pixels npixels_y = npixels_x pixelsize_x = beamline['gapH'] / npixels_x pixelsize_y = beamline['gapV'] / npixels_y print("pixelsize X=%f,Y=%f: "%(pixelsize_x,pixelsize_y)) propagation_distance = beamline['distance'] # # initialize wavefronts of dimension equal to the lens # wf_fft = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=1e-10) gamma = beamline['ElectronEnergy'] / (codata_mee * 1e-3) print ("Gamma: %f \n"%(gamma)) # photon_wavelength = (1 + beamline['Kv']**2 / 2.0) / 2 / gamma**2 * beamline["PeriodID"] / beamline['harmonicID'] photon_wavelength = m2ev / beamline["photonEnergy"] print ("Photon wavelength [A]: %g \n"%(1e10*photon_wavelength)) print ("Photon energy [eV]: %g \n"%(beamline["photonEnergy"])) myBeam = ElectronBeam(Electron_energy=beamline['ElectronEnergy'], I_current=beamline['ElectronCurrent']) myUndulator = MagneticStructureUndulatorPlane(K=beamline['Kv'], period_length=beamline['PeriodID'], length=beamline['PeriodID']*beamline['NPeriods']) XX = wf_fft.get_mesh_x() YY = wf_fft.get_mesh_y() X = wf_fft.get_coordinate_x() Y = wf_fft.get_coordinate_y() source = SourceUndulatorPlane(undulator=myUndulator, electron_beam=myBeam, magnetic_field=None) omega = beamline["photonEnergy"] * codata.e / codata.hbar Nb_pts_trajectory = int(source.choose_nb_pts_trajectory(0.01,photon_frequency=omega)) print("Number of trajectory points: ",Nb_pts_trajectory) traj_fact = TrajectoryFactory(Nb_pts=Nb_pts_trajectory,method=TRAJECTORY_METHOD_ODE, initial_condition=None) print("Number of trajectory points: ",traj_fact.Nb_pts) if (traj_fact.initial_condition == None): traj_fact.initial_condition = source.choose_initial_contidion_automatic() print("Number of trajectory points: ",traj_fact.Nb_pts,traj_fact.initial_condition) #print('step 2') rad_fact = RadiationFactory(method=RADIATION_METHOD_NEAR_FIELD, photon_frequency=omega) #print('step 3') trajectory = traj_fact.create_from_source(source=source) #print('step 4') radiation = rad_fact.create_for_one_relativistic_electron(trajectory=trajectory, source=source, XY_are_list=False,distance=beamline['distance'], X=X, Y=Y) efield = rad_fact.calculate_electrical_field(trajectory=trajectory,source=source, distance=beamline['distance'],X_array=XX,Y_array=YY) tmp = efield.electrical_field()[:,:,0] wf_fft.set_photon_energy(beamline["photonEnergy"]) wf_fft.set_complex_amplitude( tmp ) # plot plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="UND source at lens plane",show=1) # apply lens focal_length = propagation_distance / 2 wf_fft.apply_ideal_lens(focal_length,focal_length) plot_image(wf_fft.get_phase(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), title="Phase just after the lens",xtitle="X um",ytitle="Y um",show=1) wf_fft, x_fft, y_fft = propagation_to_image(wf_fft,do_plot=0,method='fft', propagation_steps=1, propagation_distance = propagation_distance, defocus_factor=1.0) plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), title="Intensity at image plane",xtitle="X um",ytitle="Y um",show=1) if do_plot: plot_table(1e6*x_fft,y_fft,ytitle="Intensity",xtitle="x coordinate [um]", title="Comparison 1:1 focusing ")
def test_propagate_2D_fraunhofer(self,do_plot=do_plot,aperture_type='square',aperture_diameter=40e-6, pixelsize_x=1e-6,pixelsize_y=1e-6,npixels_x=1024,npixels_y=1024,wavelength=1.24e-10): """ :param do_plot: 0=No plot, 1=Do plot :param aperture_type: 'circle' 'square' 'gaussian' (Gaussian sigma = aperture_diameter/2.35) :param aperture_diameter: :param pixelsize_x: :param pixelsize_y: :param npixels_x: :param npixels_y: :param wavelength: :return: """ print("\n# ") print("# far field 2D (fraunhofer) diffraction from a square aperture ") print("# ") method = "fraunhofer" print("Fraunhoffer diffraction valid for distances > > a^2/lambda = %f m"%((aperture_diameter/2)**2/wavelength)) # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2, # x_step=pixelsize_x, # y_start=-pixelsize_y*npixels_y/2, # y_step=pixelsize_y, # wavelength=wavelength, # number_of_points=(npixels_x,npixels_y)) wf = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) wf.set_plane_wave_from_complex_amplitude((1.0+0j)) if aperture_type == 'circle': wf.apply_pinhole(aperture_diameter/2) elif aperture_type == 'square': wf.apply_slit(-aperture_diameter/2, aperture_diameter/2,-aperture_diameter/2, aperture_diameter/2) elif aperture_type == 'gaussian': X = wf.get_mesh_x() Y = wf.get_mesh_y() window = numpy.exp(- (X*X + Y*Y)/2/(aperture_diameter/2.35)**2) wf.rescale_amplitudes(window) else: raise Exception("Not implemented! (accepted: circle, square, gaussian)") wf1 = propagate_2D_fraunhofer(wf, propagation_distance=1.0) # propagating at 1 m means the result is like in angles if do_plot: plot_image(wf.get_intensity(),1e6*wf.get_coordinate_x(),1e6*wf.get_coordinate_y(), title="aperture intensity (%s), Diameter=%5.1f um"% (aperture_type,1e6*aperture_diameter),xtitle="X [um]",ytitle="Y [um]", show=0) plot_image(wf1.get_intensity(),1e6*wf1.get_coordinate_x(),1e6*wf1.get_coordinate_y(), title="2D Diffracted intensity (%s) by a %s slit of aperture %3.1f um"% (aperture_type,method,1e6*aperture_diameter), xtitle="X [urad]",ytitle="Y [urad]", show=0) angle_x = wf1.get_coordinate_x() # + 0.5*wf1.delta()[0] # shifted of half-pixel!!! intensity_theory = get_theoretical_diffraction_pattern(angle_x, aperture_type=aperture_type,aperture_diameter=aperture_diameter, wavelength=wavelength,normalization=True) intensity_calculated = wf1.get_intensity()[:,wf1.size()[1]/2] intensity_calculated /= intensity_calculated.max() if do_plot: plot(wf1.get_coordinate_x()*1e6,intensity_calculated, angle_x*1e6,intensity_theory, legend=["Calculated (FT) H profile","Theoretical"],legend_position=(0.95, 0.95), title="2D Fraunhofer Diffraction of a %s slit of %3.1f um at wavelength of %3.1f A"% (aperture_type,aperture_diameter*1e6,wavelength*1e10), xtitle="X (urad)", ytitle="Intensity",xrange=[-80,80]) numpy.testing.assert_almost_equal(intensity_calculated,intensity_theory,1)
def propagation_with_lens(self,do_plot=do_plot,method='fft', wavelength=1.24e-10, pixelsize_x=1e-6,npixels_x=2000,pixelsize_y=1e-6,npixels_y=2000, propagation_distance=30.0,defocus_factor=1.0,propagation_steps=1,show=1): method_label = "fresnel (%s)"%method print("\n# ") print("# near field fresnel (%s) diffraction and focusing "%(method_label)) print("# ") # \ | / # * | | | * # / | \ # <------- d ---------------><--------- d -------> # d is propagation_distance # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2, # x_step=pixelsize_x, # y_start=-pixelsize_y*npixels_y/2, # y_step=pixelsize_y, # wavelength=wavelength, # number_of_points=(npixels_x,npixels_y)) wf = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) spherical_or_plane_and_lens = 0 if spherical_or_plane_and_lens == 0: # set spherical wave at the lens entrance (radius=distance) wf.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance) else: # apply lens that will focus at propagation_distance downstream the lens. # Note that the vertical is a bit defocused wf.set_plane_wave_from_complex_amplitude(1.0+0j) focal_length = propagation_distance # / 2 wf.apply_ideal_lens(focal_length,focal_length) print("Incident intensity: ",wf.get_intensity().sum()) # propagation downstream the lens to image plane for i in range(propagation_steps): if propagation_steps > 1: print(">>> Propagating step %d of %d; propagation_distance=%g m"%(i+1,propagation_steps, propagation_distance*defocus_factor/propagation_steps)) if method == 'fft': wf = propagate_2D_fresnel(wf, propagation_distance*defocus_factor/propagation_steps) elif method == 'convolution': wf = propagate_2D_fresnel_convolution(wf, propagation_distance*defocus_factor/propagation_steps) elif method == 'srw': wf = propagate_2D_fresnel_srw(wf, propagation_distance*defocus_factor/propagation_steps) elif method == 'fraunhofer': wf = propagate_2D_fraunhofer(wf, propagation_distance*defocus_factor/propagation_steps) else: raise Exception("Not implemented method: %s"%method) horizontal_profile = wf.get_intensity()[:,wf.size()[1]/2] horizontal_profile /= horizontal_profile.max() print("FWHM of the horizontal profile: %g um"%(1e6*line_fwhm(horizontal_profile)*wf.delta()[0])) vertical_profile = wf.get_intensity()[wf.size()[0]/2,:] vertical_profile /= vertical_profile.max() print("FWHM of the vertical profile: %g um"%(1e6*line_fwhm(vertical_profile)*wf.delta()[1])) if do_plot: from srxraylib.plot.gol import plot,plot_image plot_image(wf.get_intensity(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='intensity (%s)'%method,show=0) # plot_image(wf.get_amplitude(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='amplitude (%s)'%method,show=0) plot_image(wf.get_phase(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='phase (%s)'%method,show=0) plot(wf.get_coordinate_x(),horizontal_profile, wf.get_coordinate_y(),vertical_profile, legend=['Horizontal profile','Vertical profile'],title="%s"%method,show=show) print("Output intensity: ",wf.get_intensity().sum()) return wf.get_coordinate_x(),horizontal_profile
def propagate_2D_fresnel(self,do_plot=do_plot,method='fft', wavelength=1.24e-10,aperture_type='square',aperture_diameter=40e-6, pixelsize_x=1e-6,pixelsize_y=1e-6,npixels_x=1024,npixels_y=1024, propagation_distance = 30.0,show=1): method_label = "fresnel (%s)"%method print("\n# ") print("# 2D near field fresnel (%s) diffraction from a %s aperture "%(method_label,aperture_type)) print("# ") # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2, # x_step=pixelsize_x, # y_start=-pixelsize_y*npixels_y/2, # y_step=pixelsize_y, # wavelength=wavelength, # number_of_points=(npixels_x,npixels_y)) wf = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) wf.set_plane_wave_from_complex_amplitude((1.0+0j)) if aperture_type == 'circle': wf.apply_pinhole(aperture_diameter/2) elif aperture_type == 'square': wf.apply_slit(-aperture_diameter/2, aperture_diameter/2,-aperture_diameter/2, aperture_diameter/2) elif aperture_type == 'gaussian': X = wf.get_mesh_x() Y = wf.get_mesh_y() window = numpy.exp(- (X*X + Y*Y)/2/(aperture_diameter/2.35)**2) wf.rescale_amplitudes(window) else: raise Exception("Not implemented! (accepted: circle, square, gaussian)") if method == 'fft': wf1 = propagate_2D_fresnel(wf, propagation_distance) elif method == 'convolution': wf1 = propagate_2D_fresnel_convolution(wf, propagation_distance) elif method == 'srw': wf1 = propagate_2D_fresnel_srw(wf, propagation_distance) elif method == 'integral': wf1 = propagate_2D_integral(wf, propagation_distance) else: raise Exception("Not implemented method: %s"%method) if do_plot: from srxraylib.plot.gol import plot_image plot_image(wf.get_intensity(),1e6*wf.get_coordinate_x(),1e6*wf.get_coordinate_y(), title="aperture intensity (%s), Diameter=%5.1f um"% (aperture_type,1e6*aperture_diameter),xtitle="X [um]",ytitle="Y [um]", show=0) plot_image(wf1.get_intensity(), 1e6*wf1.get_coordinate_x()/propagation_distance, 1e6*wf1.get_coordinate_y()/propagation_distance, title="Diffracted intensity (%s) by a %s slit of aperture %3.1f um"% (aperture_type,method_label,1e6*aperture_diameter), xtitle="X [urad]",ytitle="Y [urad]", show=0) # get the theoretical value angle_x = wf1.get_coordinate_x() / propagation_distance intensity_theory = get_theoretical_diffraction_pattern(angle_x,aperture_type=aperture_type,aperture_diameter=aperture_diameter, wavelength=wavelength,normalization=True) intensity_calculated = wf1.get_intensity()[:,wf1.size()[1]/2] intensity_calculated /= intensity_calculated.max() if do_plot: from srxraylib.plot.gol import plot plot(wf1.get_coordinate_x()*1e6/propagation_distance,intensity_calculated, angle_x*1e6,intensity_theory, legend=["%s H profile"%method_label,"Theoretical (far field)"], legend_position=(0.95, 0.95), title="%s diffraction of a %s slit of %3.1f um at wavelength of %3.1f A"% (method_label,aperture_type,aperture_diameter*1e6,wavelength*1e10), xtitle="X (urad)", ytitle="Intensity",xrange=[-20,20], show=show) return wf1.get_coordinate_x()/propagation_distance,intensity_calculated,angle_x,intensity_theory
def propagate_2D_fresnel_srw(wavefront, propagation_distance, srw_autosetting=0): """ 2D Fresnel propagator using convolution via Fourier transform :param wavefront: :param propagation_distance: :param srw_autosetting:set to 1 for automatic SRW redimensionate wavefront :return: """ # # convolving with the Fresnel kernel via SRW package # from srxraylib.waveoptics.NumpyToSRW import numpyArrayToSRWArray, SRWWavefrontFromElectricField, SRWEFieldAsNumpy import scipy.constants as codata angstroms_to_eV = codata.h * codata.c / codata.e * 1e10 srw_wfr = SRWWavefrontFromElectricField( wavefront.get_coordinate_x()[0], wavefront.get_coordinate_x()[-1], wavefront.get_complex_amplitude(), wavefront.get_coordinate_y()[0], wavefront.get_coordinate_y()[-1], numpy.zeros_like(wavefront.get_complex_amplitude()), angstroms_to_eV / (wavefront.get_wavelength() * 1e10), 1.0, 1.0, 1e-3, 1.0, 1e-3) # # propagation # optDrift = srwlib.SRWLOptD(propagation_distance) #Drift space #Wavefront Propagation Parameters: #[0]: Auto-Resize (1) or not (0) Before propagation #[1]: Auto-Resize (1) or not (0) After propagation #[2]: Relative Precision for propagation with Auto-Resizing (1. is nominal) #[3]: Allow (1) or not (0) for semi-analytical treatment of the quadratic (leading) phase terms at the propagation #[4]: Do any Resizing on Fourier side, using FFT, (1) or not (0) #[5]: Horizontal Range modification factor at Resizing (1. means no modification) #[6]: Horizontal Resolution modification factor at Resizing #[7]: Vertical Range modification factor at Resizing #[8]: Vertical Resolution modification factor at Resizing #[9]: Type of wavefront Shift before Resizing (not yet implemented) #[10]: New Horizontal wavefront Center position after Shift (not yet implemented) #[11]: New Vertical wavefront Center position after Shift (not yet implemented) if srw_autosetting: # 0 1 2 3 4 5 6 7 8 9 10 11 propagParDrift = [1, 1, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0] else: # 0 1 2 3 4 5 6 7 8 9 10 11 propagParDrift = [0, 0, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0] optBL = srwlib.SRWLOptC( [optDrift], [propagParDrift] ) #"Beamline" - Container of Optical Elements (together with the corresponding wavefront propagation instructions) print(' Simulating Electric Field Wavefront Propagation by SRW ... ', end='\n') srwlib.srwl.PropagElecField(srw_wfr, optBL) wavefront2 = Wavefront2D.initialize_wavefront_from_range( srw_wfr.mesh.xStart, srw_wfr.mesh.xFin, srw_wfr.mesh.yStart, srw_wfr.mesh.yFin, number_of_points=(srw_wfr.mesh.nx, srw_wfr.mesh.ny), wavelength=wavefront.get_wavelength()) amplitude2 = SRWEFieldAsNumpy(srw_wfr) amplitude2 = amplitude2[0, :, :, 0] wavefront2.set_complex_amplitude(amplitude2) return wavefront2
def test_polarization(self, do_plot=0): print("# ") print("# Tests polarization ") print("# ") # # from steps # x = numpy.linspace(-10, 10, 100) y = numpy.linspace(-20, 20, 50) # XY = numpy.meshgrid(y,x) # sigma = 3.0 # Z = numpy.exp(- (XY[0]**2+XY[1]**2)/2/sigma**2) xy = numpy.meshgrid(x, y) X = xy[0].T Y = xy[1].T sigma = 3.0 Z = numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) Zp = 0.5 * numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) print("shape of Z", Z.shape) wf = Wavefront2D.initialize_wavefront_from_steps(x[0], x[1] - x[0], y[0], y[1] - y[0], number_of_points=(100, 50)) print("wf shape: ", wf.size()) wf.set_complex_amplitude(Z, polarization=Polarization.SIGMA) wf.set_complex_amplitude(Zp, polarization=Polarization.PI) print("Total intensity: ", wf.get_intensity(polarization=Polarization.TOTAL).sum()) print("Sigma intensity: ", wf.get_intensity(polarization=Polarization.SIGMA).sum()) print("Pi intensity: ", wf.get_intensity(polarization=Polarization.PI).sum()) self.assertAlmostEqual(wf.get_intensity(polarization=Polarization.TOTAL).sum(), wf.get_intensity(polarization=Polarization.SIGMA).sum() +\ wf.get_intensity(polarization=Polarization.PI).sum()) # # from range # x = numpy.linspace(-100, 100, 50) y = numpy.linspace(-50, 50, 200) X = numpy.outer(x, numpy.ones_like(y)) Y = numpy.outer(numpy.ones_like(x), y) sigma = 10 Z = numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j Zp = 0.3333 * numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j print("Shapes x,y,z: ", x.shape, y.shape, Z.shape) wf1 = Wavefront2D.initialize_wavefront_from_range( x[0], x[-1], y[0], y[-1], number_of_points=Z.shape, polarization=Polarization.SIGMA) wf1.set_complex_amplitude(Z, polarization=Polarization.SIGMA) wf1.set_complex_amplitude(Zp, polarization=Polarization.PI) print("Total intensity: ", wf1.get_intensity(polarization=Polarization.TOTAL).sum()) print("Sigma intensity: ", wf1.get_intensity(polarization=Polarization.SIGMA).sum()) print("Pi intensity: ", wf1.get_intensity(polarization=Polarization.PI).sum()) self.assertAlmostEqual(wf1.get_intensity(polarization=Polarization.TOTAL).sum(), wf1.get_intensity(polarization=Polarization.SIGMA).sum() +\ wf1.get_intensity(polarization=Polarization.PI).sum()) # # from arrays # wf2 = Wavefront2D.initialize_wavefront_from_arrays(x, y, Z, Zp) self.assertAlmostEqual(wf2.get_intensity(polarization=Polarization.TOTAL).sum(), wf2.get_intensity(polarization=Polarization.SIGMA).sum() +\ wf2.get_intensity(polarization=Polarization.PI).sum())
def propagation_with_lens(self, do_plot=do_plot, method='fft', wavelength=1.24e-10, pixelsize_x=1e-6, npixels_x=2000, pixelsize_y=1e-6, npixels_y=2000, propagation_distance=30.0, defocus_factor=1.0, propagation_steps=1, show=1): method_label = "fresnel (%s)" % method print( "\n# ") print("# near field fresnel (%s) diffraction and focusing " % (method_label)) print("# ") # \ | / # * | | | * # / | \ # <------- d ---------------><--------- d -------> # d is propagation_distance # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2, # x_step=pixelsize_x, # y_start=-pixelsize_y*npixels_y/2, # y_step=pixelsize_y, # wavelength=wavelength, # number_of_points=(npixels_x,npixels_y)) wf = Wavefront2D.initialize_wavefront_from_range( x_min=-pixelsize_x * npixels_x / 2, x_max=pixelsize_x * npixels_x / 2, y_min=-pixelsize_y * npixels_y / 2, y_max=pixelsize_y * npixels_y / 2, number_of_points=(npixels_x, npixels_y), wavelength=wavelength) spherical_or_plane_and_lens = 0 if spherical_or_plane_and_lens == 0: # set spherical wave at the lens entrance (radius=distance) wf.set_spherical_wave(complex_amplitude=1.0, radius=-propagation_distance) else: # apply lens that will focus at propagation_distance downstream the lens. # Note that the vertical is a bit defocused wf.set_plane_wave_from_complex_amplitude(1.0 + 0j) focal_length = propagation_distance # / 2 wf.apply_ideal_lens(focal_length, focal_length) print("Incident intensity: ", wf.get_intensity().sum()) # propagation downstream the lens to image plane for i in range(propagation_steps): if propagation_steps > 1: print( ">>> Propagating step %d of %d; propagation_distance=%g m" % (i + 1, propagation_steps, propagation_distance * defocus_factor / propagation_steps)) if method == 'fft': wf = propagate_2D_fresnel( wf, propagation_distance * defocus_factor / propagation_steps) elif method == 'convolution': wf = propagate_2D_fresnel_convolution( wf, propagation_distance * defocus_factor / propagation_steps) elif method == 'srw': wf = propagate_2D_fresnel_srw( wf, propagation_distance * defocus_factor / propagation_steps) elif method == 'fraunhofer': wf = propagate_2D_fraunhofer( wf, propagation_distance * defocus_factor / propagation_steps) else: raise Exception("Not implemented method: %s" % method) horizontal_profile = wf.get_intensity()[:, int(wf.size()[1] / 2)] horizontal_profile /= horizontal_profile.max() print("FWHM of the horizontal profile: %g um" % (1e6 * line_fwhm(horizontal_profile) * wf.delta()[0])) vertical_profile = wf.get_intensity()[int(wf.size()[0] / 2), :] vertical_profile /= vertical_profile.max() print("FWHM of the vertical profile: %g um" % (1e6 * line_fwhm(vertical_profile) * wf.delta()[1])) if do_plot: from srxraylib.plot.gol import plot, plot_image plot_image(wf.get_intensity(), wf.get_coordinate_x(), wf.get_coordinate_y(), title='intensity (%s)' % method, show=0) # plot_image(wf.get_amplitude(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='amplitude (%s)'%method,show=0) plot_image(wf.get_phase(), wf.get_coordinate_x(), wf.get_coordinate_y(), title='phase (%s)' % method, show=0) plot(wf.get_coordinate_x(), horizontal_profile, wf.get_coordinate_y(), vertical_profile, legend=['Horizontal profile', 'Vertical profile'], title="%s" % method, show=show) print("Output intensity: ", wf.get_intensity().sum()) return wf.get_coordinate_x(), horizontal_profile
pixelsize_y = 1e-7 npixels_x = 2024 npixels_y = 2024 propagation_distance = 1.0 show = 1 method_label = "fresnel (fft)" print("\n# ") print("# 2D near field fresnel (%s) diffraction from a a circular stop " % (method_label)) print("# ") wf = Wavefront2D.initialize_wavefront_from_range( x_min=-pixelsize_x * npixels_x / 2, x_max=pixelsize_x * npixels_x / 2, y_min=-pixelsize_y * npixels_y / 2, y_max=pixelsize_y * npixels_y / 2, number_of_points=(npixels_x, npixels_y), wavelength=wavelength) wf.set_plane_wave_from_complex_amplitude((1.0 + 0j)) wf.apply_pinhole(aperture_diameter / 2, negative=True) wf1 = propagate_2D_fresnel(wf, propagation_distance) plot_image(wf.get_intensity(), 1e6 * wf.get_coordinate_x(), 1e6 * wf.get_coordinate_y(), title="intensity at screen/aperture plane, Diameter=%5.1f um" % (1e6 * aperture_diameter),
def main(mode_wavefront_before_lens): lens_diameter = 0.002 # 0.001 # 0.002 if mode_wavefront_before_lens == 'Undulator with lens': npixels_x = 512 else: npixels_x = int(2048*1.5) pixelsize_x = lens_diameter / npixels_x print("pixelsize: ",pixelsize_x) pixelsize_y = pixelsize_x npixels_y = npixels_x wavelength = 1.24e-10 propagation_distance = 30.0 defocus_factor = 1.0 # 1.0 is at focus propagation_steps = 1 # for Gaussian source sigma_x = lens_diameter / 400 # 5e-6 sigma_y = sigma_x # 5e-6 # for Hermite-Gauss, the H and V mode index (start from 0) hm = 3 hn = 1 # # initialize wavefronts of dimension equal to the lens # wf_fft = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) wf_convolution = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) if SRWLIB_AVAILABLE: wf_srw = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) # # calculate/define wavefront at zero distance downstream the lens # if mode_wavefront_before_lens == 'convergent spherical': # no need to propagate nor define lens wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance) wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance) if SRWLIB_AVAILABLE: wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance) elif mode_wavefront_before_lens == 'divergent spherical with lens': # define wavefront at zero distance upstream the lens and apply lens focal_length = propagation_distance / 2. wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance) wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance) wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'plane with lens': # define wavefront at zero distance upstream the lens and apply lens focal_length = propagation_distance wf_fft.set_plane_wave_from_complex_amplitude(1.0+0j) wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.set_plane_wave_from_complex_amplitude(1.0+0j) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.set_plane_wave_from_complex_amplitude(1.0+0j) wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'Gaussian with lens': # define wavefront at source point, propagate to the lens and apply lens X = wf_fft.get_mesh_x() Y = wf_fft.get_mesh_y() intensity = numpy.exp( - X**2/(2*sigma_x**2)) * numpy.exp( - Y**2/(2*sigma_y**2)) wf_fft.set_complex_amplitude( numpy.sqrt(intensity) ) wf_convolution.set_complex_amplitude( numpy.sqrt(intensity) ) if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(intensity) ) # plot plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[1]),title="Gaussian source",show=1) wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") if SRWLIB_AVAILABLE: wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um",title="Before lens fft",show=1) plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um (%d pixels)"%(wf_convolution.size()[0]),ytitle="Y um",title="Before lens convolution",show=1) focal_length = propagation_distance / 2 wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'Hermite with lens': # define wavefront at source point, propagate to the lens and apply lens X = wf_fft.get_mesh_x() Y = wf_fft.get_mesh_y() efield = (hermite(hm)(numpy.sqrt(2)*X/sigma_x)*numpy.exp(-X**2/sigma_x**2))**2 \ * (hermite(hn)(numpy.sqrt(2)*Y/sigma_y)*numpy.exp(-Y**2/sigma_y**2))**2 wf_fft.set_complex_amplitude( efield ) wf_convolution.set_complex_amplitude( efield ) if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( efield ) # plot plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="Hermite-Gauss source",show=1) wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") if SRWLIB_AVAILABLE: wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="Before lens fft",show=1) plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="Before lens convolution",show=1) focal_length = propagation_distance / 2 wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'Undulator with lens': beamline = {} beamline['ElectronCurrent'] = 0.2 beamline['ElectronEnergy'] = 6.0 beamline['Kv'] = 1.68 # 1.87 beamline['NPeriods'] = 111 # 14 beamline['PeriodID'] = 0.018 # 0.035 beamline['distance'] = propagation_distance gamma = beamline['ElectronEnergy'] / (codata_mee * 1e-3) print ("Gamma: %f \n"%(gamma)) resonance_wavelength = (1 + beamline['Kv']**2 / 2.0) / 2 / gamma**2 * beamline["PeriodID"] resonance_energy = m2ev / resonance_wavelength print ("Resonance wavelength [A]: %g \n"%(1e10*resonance_wavelength)) print ("Resonance energy [eV]: %g \n"%(resonance_energy)) # red shift 100 eV resonance_energy = resonance_energy - 100 myBeam = ElectronBeam(Electron_energy=beamline['ElectronEnergy'], I_current=beamline['ElectronCurrent']) myUndulator = MagneticStructureUndulatorPlane(K=beamline['Kv'], period_length=beamline['PeriodID'], length=beamline['PeriodID']*beamline['NPeriods']) XX = wf_fft.get_mesh_x() YY = wf_fft.get_mesh_y() X = wf_fft.get_coordinate_x() Y = wf_fft.get_coordinate_y() source = SourceUndulatorPlane(undulator=myUndulator, electron_beam=myBeam, magnetic_field=None) omega = resonance_energy * codata.e / codata.hbar Nb_pts_trajectory = int(source.choose_nb_pts_trajectory(0.01,photon_frequency=omega)) print("Number of trajectory points: ",Nb_pts_trajectory) traj_fact = TrajectoryFactory(Nb_pts=Nb_pts_trajectory,method=TRAJECTORY_METHOD_ODE, initial_condition=None) print("Number of trajectory points: ",traj_fact.Nb_pts) if (traj_fact.initial_condition == None): traj_fact.initial_condition = source.choose_initial_contidion_automatic() print("Number of trajectory points: ",traj_fact.Nb_pts,traj_fact.initial_condition) #print('step 2') rad_fact = RadiationFactory(method=RADIATION_METHOD_NEAR_FIELD, photon_frequency=omega) #print('step 3') trajectory = traj_fact.create_from_source(source=source) #print('step 4') radiation = rad_fact.create_for_one_relativistic_electron(trajectory=trajectory, source=source, XY_are_list=False,distance=beamline['distance'], X=X, Y=Y) efield = rad_fact.calculate_electrical_field(trajectory=trajectory,source=source, distance=beamline['distance'],X_array=XX,Y_array=YY) tmp = efield.electrical_field()[:,:,0] wf_fft.set_photon_energy(resonance_energy) wf_convolution.set_photon_energy(resonance_energy) if SRWLIB_AVAILABLE: wf_srw.set_photon_energy(resonance_energy) wf_fft.set_complex_amplitude( tmp ) wf_convolution.set_complex_amplitude( numpy.sqrt(tmp) ) if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(tmp) ) # plot plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="UND source at lens plane",show=1) # apply lens focal_length = propagation_distance / 2 wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length) else: raise Exception("Unknown mode") plot_image(wf_fft.get_phase(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), title="Phase just after the lens",xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),show=1) wf_fft, x_fft, y_fft = propagation_to_image(wf_fft,do_plot=0,method='fft', propagation_steps=propagation_steps, propagation_distance = propagation_distance, defocus_factor=defocus_factor) wf_convolution, x_convolution, y_convolution = propagation_to_image(wf_convolution,do_plot=0,method='convolution', propagation_steps=propagation_steps, propagation_distance = propagation_distance, defocus_factor=defocus_factor) if SRWLIB_AVAILABLE: wf_srw, x_srw, y_srw = propagation_to_image(wf_srw,do_plot=0,method='srw', propagation_steps=propagation_steps, propagation_distance = propagation_distance, defocus_factor=defocus_factor) plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), title="Intensity at image plane",xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),show=1) if do_plot: if SRWLIB_AVAILABLE: x = x_fft y = numpy.vstack((y_fft,y_srw,y_convolution)) plot_table(1e6*x,y,legend=["fft","srw","convolution"],ytitle="Intensity",xtitle="x coordinate [um]", title="Comparison 1:1 focusing "+mode_wavefront_before_lens) else: x = x_fft y = numpy.vstack((y_fft,y_convolution)) plot_table(1e6*x,y,legend=["fft","convolution"],ytitle="Intensity",xtitle="x coordinate [um]", title="Comparison 1:1 focusing "+mode_wavefront_before_lens)
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 main(mode_wavefront_before_lens): lens_diameter = 0.002 # 0.001 # 0.002 if mode_wavefront_before_lens == 'Undulator with lens': npixels_x = 512 else: npixels_x = 2048*1.5 pixelsize_x = lens_diameter / npixels_x print("pixelsize: ",pixelsize_x) pixelsize_y = pixelsize_x npixels_y = npixels_x wavelength = 1.24e-10 propagation_distance = 30.0 defocus_factor = 1.0 # 1.0 is at focus propagation_steps = 1 # for Gaussian source sigma_x = lens_diameter / 400 # 5e-6 sigma_y = sigma_x # 5e-6 # for Hermite-Gauss, the H and V mode index (start from 0) hm = 3 hn = 1 # # initialize wavefronts of dimension equal to the lens # wf_fft = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) wf_convolution = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) if SRWLIB_AVAILABLE: wf_srw = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2, y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2, number_of_points=(npixels_x,npixels_y),wavelength=wavelength) # # calculate/define wavefront at zero distance downstream the lens # if mode_wavefront_before_lens == 'convergent spherical': # no need to propagate nor define lens wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance) wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance) if SRWLIB_AVAILABLE: wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance) elif mode_wavefront_before_lens == 'divergent spherical with lens': # define wavefront at zero distance upstream the lens and apply lens focal_length = propagation_distance / 2. wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance) wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance) wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'plane with lens': # define wavefront at zero distance upstream the lens and apply lens focal_length = propagation_distance wf_fft.set_plane_wave_from_complex_amplitude(1.0+0j) wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.set_plane_wave_from_complex_amplitude(1.0+0j) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.set_plane_wave_from_complex_amplitude(1.0+0j) wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'Gaussian with lens': # define wavefront at source point, propagate to the lens and apply lens X = wf_fft.get_mesh_x() Y = wf_fft.get_mesh_y() intensity = numpy.exp( - X**2/(2*sigma_x**2)) * numpy.exp( - Y**2/(2*sigma_y**2)) wf_fft.set_complex_amplitude( numpy.sqrt(intensity) ) wf_convolution.set_complex_amplitude( numpy.sqrt(intensity) ) if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(intensity) ) # plot plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="Gaussian source",show=1) wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") if SRWLIB_AVAILABLE: wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="Before lens fft",show=1) plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="Before lens convolution",show=1) focal_length = propagation_distance / 2 wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'Hermite with lens': # define wavefront at source point, propagate to the lens and apply lens X = wf_fft.get_mesh_x() Y = wf_fft.get_mesh_y() efield = (hermite(hm)(numpy.sqrt(2)*X/sigma_x)*numpy.exp(-X**2/sigma_x**2))**2 \ * (hermite(hn)(numpy.sqrt(2)*Y/sigma_y)*numpy.exp(-Y**2/sigma_y**2))**2 wf_fft.set_complex_amplitude( efield ) wf_convolution.set_complex_amplitude( efield ) if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( efield ) # plot plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="Hermite-Gauss source",show=1) wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") if SRWLIB_AVAILABLE: wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance, do_plot=0,plot_title="Before lens") plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="Before lens fft",show=1) plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="Before lens convolution",show=1) focal_length = propagation_distance / 2 wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length) elif mode_wavefront_before_lens == 'Undulator with lens': beamline = {} # beamline['name'] = "ESRF_NEW_OB" # beamline['ElectronBeamDivergenceH'] = 5.2e-6 # these values are not used (zero emittance) # beamline['ElectronBeamDivergenceV'] = 1.4e-6 # these values are not used (zero emittance) # beamline['ElectronBeamSizeH'] = 27.2e-6 # these values are not used (zero emittance) # beamline['ElectronBeamSizeV'] = 3.4e-6 # these values are not used (zero emittance) # beamline['ElectronEnergySpread'] = 0.001 # these values are not used (zero emittance) beamline['ElectronCurrent'] = 0.2 beamline['ElectronEnergy'] = 6.0 beamline['Kv'] = 1.68 # 1.87 beamline['NPeriods'] = 111 # 14 beamline['PeriodID'] = 0.018 # 0.035 beamline['distance'] = propagation_distance # beamline['gapH'] = pixelsize_x*npixels_x # beamline['gapV'] = pixelsize_x*npixels_x gamma = beamline['ElectronEnergy'] / (codata_mee * 1e-3) print ("Gamma: %f \n"%(gamma)) resonance_wavelength = (1 + beamline['Kv']**2 / 2.0) / 2 / gamma**2 * beamline["PeriodID"] resonance_energy = m2ev / resonance_wavelength print ("Resonance wavelength [A]: %g \n"%(1e10*resonance_wavelength)) print ("Resonance energy [eV]: %g \n"%(resonance_energy)) # red shift 100 eV resonance_energy = resonance_energy - 100 myBeam = ElectronBeam(Electron_energy=beamline['ElectronEnergy'], I_current=beamline['ElectronCurrent']) myUndulator = MagneticStructureUndulatorPlane(K=beamline['Kv'], period_length=beamline['PeriodID'], length=beamline['PeriodID']*beamline['NPeriods']) XX = wf_fft.get_mesh_x() YY = wf_fft.get_mesh_y() X = wf_fft.get_coordinate_x() Y = wf_fft.get_coordinate_y() source = SourceUndulatorPlane(undulator=myUndulator, electron_beam=myBeam, magnetic_field=None) omega = resonance_energy * codata.e / codata.hbar Nb_pts_trajectory = int(source.choose_nb_pts_trajectory(0.01,photon_frequency=omega)) print("Number of trajectory points: ",Nb_pts_trajectory) traj_fact = TrajectoryFactory(Nb_pts=Nb_pts_trajectory,method=TRAJECTORY_METHOD_ODE, initial_condition=None) print("Number of trajectory points: ",traj_fact.Nb_pts) if (traj_fact.initial_condition == None): traj_fact.initial_condition = source.choose_initial_contidion_automatic() print("Number of trajectory points: ",traj_fact.Nb_pts,traj_fact.initial_condition) #print('step 2') rad_fact = RadiationFactory(method=RADIATION_METHOD_NEAR_FIELD, photon_frequency=omega) #print('step 3') trajectory = traj_fact.create_from_source(source=source) #print('step 4') radiation = rad_fact.create_for_one_relativistic_electron(trajectory=trajectory, source=source, XY_are_list=False,distance=beamline['distance'], X=X, Y=Y) efield = rad_fact.calculate_electrical_field(trajectory=trajectory,source=source, distance=beamline['distance'],X_array=XX,Y_array=YY) tmp = efield.electrical_field()[:,:,0] wf_fft.set_photon_energy(resonance_energy) wf_convolution.set_photon_energy(resonance_energy) if SRWLIB_AVAILABLE: wf_srw.set_photon_energy(resonance_energy) wf_fft.set_complex_amplitude( tmp ) wf_convolution.set_complex_amplitude( numpy.sqrt(tmp) ) if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(tmp) ) # plot plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), xtitle="X um",ytitle="Y um",title="UND source at lens plane",show=1) # apply lens focal_length = propagation_distance / 2 wf_fft.apply_ideal_lens(focal_length,focal_length) wf_convolution.apply_ideal_lens(focal_length,focal_length) if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length) else: raise Exception("Unknown mode") plot_image(wf_fft.get_phase(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), title="Phase just after the lens",xtitle="X um",ytitle="Y um",show=1) wf_fft, x_fft, y_fft = propagation_to_image(wf_fft,do_plot=0,method='fft', propagation_steps=propagation_steps, propagation_distance = propagation_distance, defocus_factor=defocus_factor) wf_convolution, x_convolution, y_convolution = propagation_to_image(wf_convolution,do_plot=0,method='convolution', propagation_steps=propagation_steps, propagation_distance = propagation_distance, defocus_factor=defocus_factor) if SRWLIB_AVAILABLE: wf_srw, x_srw, y_srw = propagation_to_image(wf_srw,do_plot=0,method='srw', propagation_steps=propagation_steps, propagation_distance = propagation_distance, defocus_factor=defocus_factor) plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(), title="Intensity at image plane",xtitle="X um",ytitle="Y um",show=1) if do_plot: if SRWLIB_AVAILABLE: x = x_fft y = numpy.vstack((y_fft,y_srw,y_convolution)) plot_table(1e6*x,y,legend=["fft","srw","convolution"],ytitle="Intensity",xtitle="x coordinate [um]", title="Comparison 1:1 focusing "+mode_wavefront_before_lens) else: x = x_fft y = numpy.vstack((y_fft,y_convolution)) plot_table(1e6*x,y,legend=["fft","convolution"],ytitle="Intensity",xtitle="x coordinate [um]", title="Comparison 1:1 focusing "+mode_wavefront_before_lens)
def test_propagate_2D_fraunhofer(self, do_plot=do_plot, aperture_type='square', aperture_diameter=40e-6, pixelsize_x=1e-6, pixelsize_y=1e-6, npixels_x=1024, npixels_y=1024, wavelength=1.24e-10): """ :param do_plot: 0=No plot, 1=Do plot :param aperture_type: 'circle' 'square' 'gaussian' (Gaussian sigma = aperture_diameter/2.35) :param aperture_diameter: :param pixelsize_x: :param pixelsize_y: :param npixels_x: :param npixels_y: :param wavelength: :return: """ print( "\n# ") print( "# far field 2D (fraunhofer) diffraction from a square aperture ") print("# ") method = "fraunhofer" print( "Fraunhoffer diffraction valid for distances > > a^2/lambda = %f m" % ((aperture_diameter / 2)**2 / wavelength)) # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2, # x_step=pixelsize_x, # y_start=-pixelsize_y*npixels_y/2, # y_step=pixelsize_y, # wavelength=wavelength, # number_of_points=(npixels_x,npixels_y)) wf = Wavefront2D.initialize_wavefront_from_range( x_min=-pixelsize_x * npixels_x / 2, x_max=pixelsize_x * npixels_x / 2, y_min=-pixelsize_y * npixels_y / 2, y_max=pixelsize_y * npixels_y / 2, number_of_points=(npixels_x, npixels_y), wavelength=wavelength) wf.set_plane_wave_from_complex_amplitude((1.0 + 0j)) if aperture_type == 'circle': wf.apply_pinhole(aperture_diameter / 2) elif aperture_type == 'square': wf.apply_slit(-aperture_diameter / 2, aperture_diameter / 2, -aperture_diameter / 2, aperture_diameter / 2) elif aperture_type == 'gaussian': X = wf.get_mesh_x() Y = wf.get_mesh_y() window = numpy.exp(-(X * X + Y * Y) / 2 / (aperture_diameter / 2.35)**2) wf.rescale_amplitudes(window) else: raise Exception( "Not implemented! (accepted: circle, square, gaussian)") wf1 = propagate_2D_fraunhofer( wf, propagation_distance=1.0 ) # propagating at 1 m means the result is like in angles if do_plot: plot_image(wf.get_intensity(), 1e6 * wf.get_coordinate_x(), 1e6 * wf.get_coordinate_y(), title="aperture intensity (%s), Diameter=%5.1f um" % (aperture_type, 1e6 * aperture_diameter), xtitle="X [um]", ytitle="Y [um]", show=0) plot_image( wf1.get_intensity(), 1e6 * wf1.get_coordinate_x(), 1e6 * wf1.get_coordinate_y(), title= "2D Diffracted intensity (%s) by a %s slit of aperture %3.1f um" % (aperture_type, method, 1e6 * aperture_diameter), xtitle="X [urad]", ytitle="Y [urad]", show=0) angle_x = wf1.get_coordinate_x( ) # + 0.5*wf1.delta()[0] # shifted of half-pixel!!! intensity_theory = get_theoretical_diffraction_pattern( angle_x, aperture_type=aperture_type, aperture_diameter=aperture_diameter, wavelength=wavelength, normalization=True) intensity_calculated = wf1.get_intensity()[:, int(wf1.size()[1] / 2)] intensity_calculated /= intensity_calculated.max() if do_plot: plot( wf1.get_coordinate_x() * 1e6, intensity_calculated, angle_x * 1e6, intensity_theory, legend=["Calculated (FT) H profile", "Theoretical"], legend_position=(0.95, 0.95), title= "2D Fraunhofer Diffraction of a %s slit of %3.1f um at wavelength of %3.1f A" % (aperture_type, aperture_diameter * 1e6, wavelength * 1e10), xtitle="X (urad)", ytitle="Intensity", xrange=[-80, 80]) numpy.testing.assert_almost_equal(intensity_calculated, intensity_theory, 1)
def propagate_2D_fresnel_srw(wavefront, propagation_distance, srw_autosetting=0): """ 2D Fresnel propagator using convolution via Fourier transform :param wavefront: :param propagation_distance: :param srw_autosetting:set to 1 for automatic SRW redimensionate wavefront :return: """ # # convolving with the Fresnel kernel via SRW package # from srxraylib.waveoptics.NumpyToSRW import numpyArrayToSRWArray, SRWWavefrontFromElectricField, SRWEFieldAsNumpy import scipy.constants as codata angstroms_to_eV = codata.h*codata.c/codata.e*1e10 srw_wfr = SRWWavefrontFromElectricField( wavefront.get_coordinate_x()[0],wavefront.get_coordinate_x()[-1],wavefront.get_complex_amplitude(), wavefront.get_coordinate_y()[0],wavefront.get_coordinate_y()[-1],numpy.zeros_like(wavefront.get_complex_amplitude()), angstroms_to_eV/(wavefront.get_wavelength()*1e10), 1.0, 1.0, 1e-3, 1.0, 1e-3) # # propagation # optDrift = srwlib.SRWLOptD(propagation_distance) #Drift space #Wavefront Propagation Parameters: #[0]: Auto-Resize (1) or not (0) Before propagation #[1]: Auto-Resize (1) or not (0) After propagation #[2]: Relative Precision for propagation with Auto-Resizing (1. is nominal) #[3]: Allow (1) or not (0) for semi-analytical treatment of the quadratic (leading) phase terms at the propagation #[4]: Do any Resizing on Fourier side, using FFT, (1) or not (0) #[5]: Horizontal Range modification factor at Resizing (1. means no modification) #[6]: Horizontal Resolution modification factor at Resizing #[7]: Vertical Range modification factor at Resizing #[8]: Vertical Resolution modification factor at Resizing #[9]: Type of wavefront Shift before Resizing (not yet implemented) #[10]: New Horizontal wavefront Center position after Shift (not yet implemented) #[11]: New Vertical wavefront Center position after Shift (not yet implemented) if srw_autosetting: # 0 1 2 3 4 5 6 7 8 9 10 11 propagParDrift = [1, 1, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0] else: # 0 1 2 3 4 5 6 7 8 9 10 11 propagParDrift = [0, 0, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0] optBL = srwlib.SRWLOptC([optDrift], [propagParDrift]) #"Beamline" - Container of Optical Elements (together with the corresponding wavefront propagation instructions) print(' Simulating Electric Field Wavefront Propagation by SRW ... ', end='\n') srwlib.srwl.PropagElecField(srw_wfr, optBL) wavefront2 = Wavefront2D.initialize_wavefront_from_range(srw_wfr.mesh.xStart, srw_wfr.mesh.xFin, srw_wfr.mesh.yStart, srw_wfr.mesh.yFin, number_of_points=(srw_wfr.mesh.nx,srw_wfr.mesh.ny), wavelength=wavefront.get_wavelength()) amplitude2 = SRWEFieldAsNumpy(srw_wfr) amplitude2 = amplitude2[0,:,:,0] wavefront2.set_complex_amplitude(amplitude2) return wavefront2
def test_initializers(self, do_plot=do_plot): print("# ") print("# Tests for initializars (2D) ") print("# ") x = numpy.linspace(-100, 100, 50) y = numpy.linspace(-50, 50, 200) XY = numpy.meshgrid(x, y) X = XY[0].T Y = XY[1].T sigma = 10 Z = numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j print("Shapes x,y,z: ", x.shape, y.shape, Z.shape) wf0 = Wavefront2D.initialize_wavefront_from_steps( x[0], numpy.abs(x[1] - x[0]), y[0], numpy.abs(y[1] - y[0]), number_of_points=Z.shape) wf0.set_complex_amplitude(Z) wf1 = Wavefront2D.initialize_wavefront_from_range( x[0], x[-1], y[0], y[-1], number_of_points=Z.shape) wf1.set_complex_amplitude(Z) wf2 = Wavefront2D.initialize_wavefront_from_arrays(x, y, Z) if do_plot: from srxraylib.plot.gol import plot_image plot_image(wf0.get_intensity(), wf0.get_coordinate_x(), wf0.get_coordinate_y(), title="initialize_wavefront_from_steps", show=0) plot_image(wf1.get_intensity(), wf1.get_coordinate_x(), wf1.get_coordinate_y(), title="initialize_wavefront_from_range", show=0) plot_image(wf2.get_intensity(), wf2.get_coordinate_x(), wf2.get_coordinate_y(), title="initialize_wavefront_from_arrays", show=1) numpy.testing.assert_almost_equal( numpy.abs(Z)**2, wf0.get_intensity(), 11) numpy.testing.assert_almost_equal( numpy.abs(Z)**2, wf1.get_intensity(), 11) numpy.testing.assert_almost_equal( numpy.abs(Z)**2, wf2.get_intensity(), 11) numpy.testing.assert_almost_equal(x, wf0.get_coordinate_x(), 11) numpy.testing.assert_almost_equal(x, wf1.get_coordinate_x(), 11) numpy.testing.assert_almost_equal(x, wf2.get_coordinate_x(), 11) numpy.testing.assert_almost_equal(y, wf0.get_coordinate_y(), 11) numpy.testing.assert_almost_equal(y, wf1.get_coordinate_y(), 11) numpy.testing.assert_almost_equal(y, wf2.get_coordinate_y(), 11)