:mod:`ocelot.optics.wave` ========================= .. py:module:: ocelot.optics.wave .. autoapi-nested-parse:: wave optics Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: ocelot.optics.wave.RadiationField ocelot.optics.wave.WaistScanResults ocelot.optics.wave.TransferFunction ocelot.optics.wave.StokesParameters ocelot.optics.wave.HeightProfile ocelot.optics.wave.Spectrogram ocelot.optics.wave.WignerDistribution Functions ~~~~~~~~~ .. autoapisummary:: ocelot.optics.wave.bin_stokes ocelot.optics.wave.calc_stokes_out ocelot.optics.wave.calc_stokes_dfl ocelot.optics.wave.calc_stokes ocelot.optics.wave.average_stokes_l ocelot.optics.wave.sum_stokes_tr ocelot.optics.wave.generate_dfl ocelot.optics.wave.generate_gaussian_dfl ocelot.optics.wave.imitate_sase_dfl ocelot.optics.wave.calc_phase_delay_poly ocelot.optics.wave.screen2dfl ocelot.optics.wave.dfl_disperse ocelot.optics.wave.dfl_ap ocelot.optics.wave.dfl_ap_rect ocelot.optics.wave.dfl_ap_circ ocelot.optics.wave.dfl_prop ocelot.optics.wave.dfl_waistscan ocelot.optics.wave.dfl_interp ocelot.optics.wave.dfl_shift_z ocelot.optics.wave.dfl_pad_z ocelot.optics.wave.dfl_cut_z ocelot.optics.wave.dfl_fft_z ocelot.optics.wave.dfl_fft_xy ocelot.optics.wave.dfl_trf ocelot.optics.wave.trf_mult ocelot.optics.wave.calc_phase_delay ocelot.optics.wave.dfl_chirp_freq ocelot.optics.wave.generate_1d_profile ocelot.optics.wave.dfl_reflect_surface ocelot.optics.wave.trf_mult_mix ocelot.optics.wave.save_trf ocelot.optics.wave.calc_wigner ocelot.optics.wave.wigner_pad ocelot.optics.wave.wigner_out ocelot.optics.wave.wigner_dfl ocelot.optics.wave.wigner_stat ocelot.optics.wave.wigner_smear ocelot.optics.wave.calc_ph_sp_dens ocelot.optics.wave.imitate_1d_sase_like ocelot.optics.wave.imitate_1d_sase ocelot.optics.wave.dfldomain_check .. data:: _logger .. data:: nthread .. data:: fftw_avail :annotation: = True .. data:: __author__ :annotation: = Svitozar Serkez, Andrei Trebushinin, Mykola Veremchuk .. py:class:: RadiationField(shape=(0, 0, 0)) 3d or 2d coherent radiation distribution, *.fld variable is the same as Genesis dfl structure .. method:: fileName(self) .. method:: copy_param(self, dfl1, version=1) .. method:: __getitem__(self, i) .. method:: __setitem__(self, i, fld) .. method:: shape(self) returns the shape of fld attribute .. method:: domains(self) returns domains of the radiation field .. method:: Lz(self) full longitudinal mesh size .. method:: Ly(self) full transverse vertical mesh size .. method:: Lx(self) full transverse horizontal mesh size .. method:: Nz(self) number of points in z .. method:: Ny(self) number of points in y .. method:: Nx(self) number of points in x .. method:: intensity(self) 3d intensity, abs(fld)**2 .. method:: int_z(self) intensity projection on z power [W] or spectral density [arb.units] .. method:: ang_z_onaxis(self) on-axis phase .. method:: int_y(self) intensity projection on y .. method:: int_x(self) intensity projection on x .. method:: int_xy(self) .. method:: int_zx(self) .. method:: int_zy(self) .. method:: E(self) energy in the pulse [J] .. method:: scale_kx(self) .. method:: scale_ky(self) .. method:: scale_kz(self) .. method:: scale_x(self) .. method:: scale_y(self) .. method:: scale_z(self) .. method:: ph_sp_dens(self) .. method:: curve_wavefront(self, r=np.inf, plane='xy', domain_z=None) introduction of the additional wavefront curvature with radius r r can be scalar or vector with self.Nz() points r>0 -> converging wavefront plane is the plane in which wavefront is curved: 'x' - horizontal focusing 'y' - vertical focusing 'xy' - focusing in both planes domain_z is the domain in which wavefront curvature is introduced 'f' - frequency 't' - time None - original domain (default) .. method:: to_domain(self, domains='ts', **kwargs) tranfers radiation to specified domains *domains is a string with one or two letters: ("t" or "f") and ("s" or "k") where 't' (time); 'f' (frequency); 's' (space); 'k' (inverse space); e.g. 't'; 'f'; 's'; 'k'; 'ts'; 'fs'; 'tk'; 'fk' order does not matter **kwargs are passed down to self.fft_z and self.fft_xy .. method:: fft_z(self, method='mp', nthread=multiprocessing.cpu_count(), **kwargs) .. method:: fft_xy(self, method='mp', nthread=multiprocessing.cpu_count(), **kwargs) .. method:: prop(self, z, fine=1, return_result=0, return_orig_domains=1, **kwargs) Angular-spectrum propagation for fieldfile can handle wide spectrum (every slice in freq.domain is propagated according to its frequency) no kx**2+ky**2<0 -> forward direction .. method:: prop_m(self, z, m=1, fine=1, return_result=0, return_orig_domains=1, **kwargs) Angular-spectrum propagation for fieldfile can handle wide spectrum (every slice in freq.domain is propagated according to its frequency) no kx**2+ky**2<0 -> forward direction .. method:: mut_coh_func(self, norm=1, jit=1) calculates mutual coherence function consider downsampling the field first .. method:: coh(self, jit=0) calculates degree of transverse coherence consider downsampling the field first .. method:: tilt(self, angle=0, plane='x', return_orig_domains=True) deflects the radaition in given direction by given angle by introducing transverse phase chirp .. method:: disperse(self, disp=0, E_ph0=None, plane='x', return_orig_domains=True) introducing angular dispersion in given plane by deflecting the radaition by given angle depending on its frequency disp is the dispertion coefficient [rad/eV] E_ph0 is the photon energy in [eV] direction of which would not be changed (principal ray) .. py:class:: WaistScanResults .. method:: fileName(self) .. py:class:: TransferFunction data container for Fourier Optics transfer functions .. method:: ev(self) .. method:: __mul__(self, f) .. py:class:: StokesParameters .. method:: __getitem__(self, i) .. method:: P_pol(self) .. method:: P_pol_l(self) .. method:: deg_pol(self) .. method:: deg_pol_l(self) .. method:: deg_pol_c(self) .. method:: chi(self) .. method:: psi(self) .. method:: slice_2d(self, loc, plane='z') .. method:: slice_2d_idx(self, idx, plane='z') .. method:: proj(self, plane='x', mode='sum') .. py:class:: HeightProfile 1d surface of mirror .. method:: hrms(self) .. method:: set_hrms(self, rms) .. method:: psd(self) .. method:: save(self, path) .. method:: load(self, path, return_obj=False) .. function:: bin_stokes(S, bin_size) needs fix for 3d!!! .. function:: calc_stokes_out(out1, out2, pol='rl', on_axis=True) .. function:: calc_stokes_dfl(dfl1, dfl2, basis='xy', mode=(0, 0)) mode: (average_longitudinally, sum_transversely) .. function:: calc_stokes(E1, E2, s=None, basis='xy') .. function:: average_stokes_l(S, sc_range=None) .. function:: sum_stokes_tr(S) .. py:class:: Spectrogram spectrogram of the pulse (always positive!) .. method:: __init(self) .. py:class:: WignerDistribution calculated Wigner distribution (spectrogram) of the pulse in time/frequency domain as space/wavelength .. method:: freq_lamd(self) :property: .. method:: power(self) .. method:: spectrum(self) .. method:: energy(self) .. method:: fileName(self) .. method:: eval(self, method='mp') .. method:: inst_freq(self) .. method:: group_delay(self) .. method:: inst_bandwidth(self) .. function:: generate_dfl(*args, **kwargs) .. function:: generate_gaussian_dfl(xlamds=1e-09, shape=(51, 51, 100), dgrid=(0.001, 0.001, 5e-05), power_rms=(0.0001, 0.0001, 5e-06), power_center=(0, 0, None), power_angle=(0, 0), power_waistpos=(0, 0), wavelength=None, zsep=None, freq_chirp=0, en_pulse=None, power=1000000.0, **kwargs) generates RadiationField object narrow-bandwidth, paraxial approximations xlamds [m] - central wavelength shape (x,y,z) - shape of field matrix (reversed) to dfl.fld dgrid (x,y,z) [m] - size of field matrix power_rms (x,y,z) [m] - rms size of the radiation distribution (gaussian) power_center (x,y,z) [m] - position of the radiation distribution power_angle (x,y) [rad] - angle of further radiation propagation power_waistpos (x,y) [m] downstrean location of the waist of the beam wavelength [m] - central frequency of the radiation, if different from xlamds zsep (integer) - distance between slices in z as zsep*xlamds freq_chirp dw/dt=[1/fs**2] - requency chirp of the beam around power_center[2] en_pulse, power = total energy or max power of the pulse, use only one .. function:: imitate_sase_dfl(xlamds, rho=0.0002, seed=None, **kwargs) imitation of SASE radiation in 3D xlamds - wavelength of the substracted fast-varying component rho - half of the expected FEL bandwidth **kwargs identical to generate_dfl() returns RadiationField object .. function:: calc_phase_delay_poly(coeff, w, w0) Calculate the phase delay with given coefficients coeff --- coefficients in phase delay expression: w --- photon frequencies w0 --- photon frequency at which zero group delay is introduced The expression for the phase: delta_phi = coeff[0] + coeff[1]*(w - w0)**1/1!/(1e15)**1 + coeff[2]*(w - w0)**2/2!/(1e15)**2 + coeff[3]*(w - w0)**3/3!/(1e15)**3 + ... ... coeff[n]*(w - w0)**n/n!/(1e15)**n coeff is an array-like object with coeff[0] --- phase measured in [rad] coeff[1] --- group delay measured in [fs ^ 1] coeff[2] --- group delay dispersion (GDD) measured in [fs ^ 2] coeff[3] --- third-order dispersion (TOD) measured in [fs ^ 3] ... coeff[n] --- nth-order dispersion measured in [fs ^ n] @author Andrei Trebushinin .. function:: screen2dfl(screen, polarization='x') Function converts synchrotron radiation from ocelot.rad.screen.Screen to ocelot.optics.wave.RadiationField. New ocelot.optics.wave.RadiationField object will be generated without changing ocelot.rad.screen.Screen object. :param screen: ocelot.rad.screen.Screen object, electric field of which will be used to generate RadiationField :param polarization: polarization for conversion to RadiationField ('x' or 'y') :return: ocelot.optics.wave.RadiationField in domains = 'fs' .. function:: dfl_disperse(dfl, coeff, E_ph0=None, return_result=False) The function adds a phase shift to the fld object in the frequency domain dfl --- is a RadiationField object coeff --- coefficients in phase delay expression: The expression for the phase: delta_phi = coeff[0] + coeff[1]*(w - w0)**1/1!/(1e15)**1 + coeff[2]*(w - w0)**2/2!/(1e15)**2 + coeff[3]*(w - w0)**3/3!/(1e15)**3 + ... ... coeff[n]*(w - w0)**n/n!/(1e15)**n coeff is an array-like object with coeff[0] --- phase measured in [rad] coeff[1] --- group delay measured in [fs ^ 1] coeff[2] --- group delay dispersion (GDD) measured in [fs ^ 2] e.g. coeff[2]: (dt[fs] / dw[1/fs]) = 1e-6 * 1e15**2 * hr_eV_s / speed_of_light * (ds [um] / dE [eV]) coeff[3] --- third-order dispersion (TOD) measured in [fs ^ 3] ... coeff[n] --- nth-order dispersion measured in [fs ^ n] can be - a list (coeff[0], coeff[1], ... coeff[n]) - or a number, then coeff[2] is expected E_ph0 --- photon energy at which zero group delay is introduced can be: - None - when the carrier freq will be extracted from dfl object - center - when the carrier freq will be calculated as averaging over time - from dfl.int_z() and dfl.scale_z() - E_ph0 - a number in eV return_result --- a flag that is responsible for returning the dfl object if return_result is True: create a copy and return the modified copy without affecting the original object else: change the original dfl object @author Andrei Trebushinin .. function:: dfl_ap(*args, **kwargs) .. function:: dfl_ap_rect(dfl, ap_x=np.inf, ap_y=np.inf) model rectangular aperture to the radaition in either domain .. function:: dfl_ap_circ(dfl, r=np.inf, center=(0, 0)) apply circular aperture to the radaition in either domain .. function:: dfl_prop(dfl, z, fine=1, debug=1) LEGACY, WILL BE DEPRECATED, SEE METHOD Fourier propagator for fieldfile can handle wide spectrum (every slice in freq.domain is propagated according to its frequency) no kx**2+ky**2<0 ==> forward .. function:: dfl_waistscan(dfl, z_pos, projection=0, **kwargs) propagates the RadaitionField object dfl through the sequence of positions z_pos and calculates transverse distribution parameters such as peak photon density and sizes in both dimensions if projection==1, then size of projection is calculated otherwise - size across the central line passing through the mesh center .. function:: dfl_interp(dfl, interpN=(1, 1), interpL=(1, 1), newN=(None, None), newL=(None, None), method='cubic', return_result=1, **kwargs) 2d interpolation of the coherent radiation distribution interpN and interpL define the desired interpolation coefficients for transverse point __density__ and transverse mesh __size__ correspondingly newN and newL define the final desire number of points and size of the mesh when newN and newL are not None interpN and interpL values are ignored coordinate convention is (x,y) .. function:: dfl_shift_z(dfl, s, set_zeros=1, return_result=1) shift the radiation within the window in time domain dfl - initial RadiationField object s - longitudinal offset value in meters set_zeros - to set the values outside the time window to zeros .. function:: dfl_pad_z(dfl, padn, return_result=1) .. function:: dfl_cut_z(dfl, z=[-np.inf, np.inf], debug=1) .. function:: dfl_fft_z(dfl, method='mp', nthread=multiprocessing.cpu_count(), debug=1) LEGACY, WILL BE DEPRECATED, SEE METHOD .. function:: dfl_fft_xy(dfl, method='mp', nthread=multiprocessing.cpu_count(), debug=1) LEGACY, WILL BE DEPRECATED, SEE METHOD .. function:: dfl_trf(dfl, trf, mode, dump_proj=False) Multiplication of radiation field by given transfer function (transmission or ferlection, given by mode) dfl is RadiationField() object (will be mutated) trf is TransferFunction() object mode is either 'tr' for transmission or 'ref' for reflection .. function:: trf_mult(trf_list, embed_list=True) multiply transfer functions trf_list is a list of transfer functions embed_list == True will write the list of input transfer functions into the output transfer function as an trf.trf_list instance returns TransferFunction() object .. function:: calc_phase_delay(coeff, w, w0) expression for the phase -- coeff[0] + coeff[1]*(w - w0)/1! + coeff[2]*(w - w0)**2/2! + coeff[3]*(w - w0)**3/3! coeff is a list with coeff[0] =: measured in [rad] --- phase coeff[1] =: measured in [fm s ^ 1] --- group delay coeff[2] =: measured in [fm s ^ 2] --- group delay dispersion (GDD) coeff[3] =: measured in [fm s ^ 3] --- third-order dispersion (TOD) ... .. function:: dfl_chirp_freq(dfl, coeff, E_ph0=None, return_result=False) The function adds a phase shift to a fld object. The expression for the phase see in the calc_phase_delay function dfl --- is a fld object coeff --- coefficients in phase (see in the calc_phase_delay function) E_ph0 --- energy with respect to which the phase shift is calculated return_result --- a flag that is responsible for returning the modified dfl object if it is True or change the dfl function parameter if it is False .. function:: generate_1d_profile(hrms, length=0.1, points_number=1000, wavevector_cutoff=0, psd=None, seed=None) Function for generating HeightProfile of highly polished mirror surface :param hrms: [meters] height errors root mean square :param length: [meters] length of the surface :param points_number: number of points (pixels) at the surface :param wavevector_cutoff: [1/meters] point on k axis for cut off small wavevectors (large wave lengths) in the PSD (with default value 0 effects on nothing) :param psd: [meters^3] 1d array; power spectral density of surface (if not specified, will be generated) (if specified, must have shape = (points_number // 2 + 1, ), otherwise it will be cut to appropriate shape) :param seed: seed for np.random.seed() to allow reproducibility :return: HeightProfile object .. function:: dfl_reflect_surface(dfl, angle, hrms=None, height_profile=None, axis='x', seed=None, return_height_profile=False) Function models the reflection of ocelot.optics.wave.RadiationField from the mirror surface considering effects of mirror surface height errors. The method based on phase modulation. The input RadiationField object is modified :param dfl: RadiationField object from ocelot.optics.wave :param angle: [radians] angle of incidence with respect to the surface :param hrms: [meters] height root mean square of reflecting surface :param height_profile: HeightProfile object of the reflecting surface (if not specified, will be generated using hrms) :param axis: direction along which reflection takes place :param seed: seed for np.random.seed() to allow reproducibility :param return_height_profile: boolean type variable; if it equals True the function will return height_profile .. function:: trf_mult_mix(trf_list, mode_out='ref') multiply transfer functions in a mixed way: trf_list is list of tulpes, like [(trf1,'ref'),(trf2,'tr')], here 'ref' and 'tr' mean that reflectivity trom transter function trf1 is multiplied by transmissivity of transfer function trf2 mode_out is a string 'ref' or 'tr' that specifies into thich instance to write the multiplied output embed_list == True will write the list of input transfer functions into the output transfer function as an trf.trf_list instance returns TransferFunction() object .. function:: save_trf(trf, attr, flePath) .. function:: calc_wigner(field, method='mp', nthread=multiprocessing.cpu_count(), debug=1) calculation of the Wigner distribution input should be an amplitude and phase of the radiation as list of complex numbers with length N output is a real value of wigner distribution .. function:: wigner_pad(wig, pad) pads WignerDistribution with zeros in time domain .. function:: wigner_out(out, z=inf, method='mp', pad=1, debug=1, on_axis=1) returns WignerDistribution from GenesisOutput at z .. function:: wigner_dfl(dfl, method='mp', pad=1, **kwargs) returns on-axis WignerDistribution from dfl file .. function:: wigner_stat(out_stat, stage=None, z=inf, method='mp', debug=1, pad=1, **kwargs) returns averaged WignerDistribution from GenStatOutput at stage at z .. function:: wigner_smear(wig, sigma_s) Convolves wigner distribution with gaussian window function to obtain spectrogram, see https://arxiv.org/pdf/1811.11446.pdf :param wig: ocelot.optics.wave.WignerDistribution object which will be convolved with generated window func :param sigma_s: [meters] rms size of the s=-ct the gaussian window func :return: convolved ocelot.optics.wave.WignerDistribution object with gaussian window function .. function:: calc_ph_sp_dens(spec, freq_ev, n_photons, spec_squared=1) calculates number of photons per electronvolt .. function:: imitate_1d_sase_like(td_scale, td_env, fd_scale, fd_env, td_phase=None, fd_phase=None, phen0=None, en_pulse=None, fit_scale='td', n_events=1, **kwargs) Models FEL pulse(s) based on Gaussian statistics td_scale - scale of the pulse on time domain [m] td_env - expected pulse envelope in time domain [W] fd_scale - scale of the pulse in frequency domain [eV] fd_env - expected pulse envelope in frequency domain [a.u.] td_phase - additional phase chirp to be added in time domain fd_phase - additional phase chirp to be added in frequency domain phen0 - sampling wavelength expressed in photon energy [eV] en_pulse - expected average energy of the pulses [J] fit_scale - defines the scale in which outputs should be returned: 'td' - time domain scale td_scale is used for the outputs, frequency domain phase and envelope will be re-interpolated 'fd' - frequency domain scale fd_scale is used for the outputs, time domain phase and envelope will be re-interpolated n_events - number of spectra to be generated returns tuple of 4 arguments: (ph_en, fd, s, td) fd_scale - colunm of photon energies in eV fd - matrix of radiation in frequency domain with shape, normalized such that np.sum(abs(fd)**2) is photon spectral density, i.e: np.sum(abs(fd)**2)*fd_scale = N_photons td - matrix of radiation in time domain, normalized such that abs(td)**2 = radiation_power in [w] .. function:: imitate_1d_sase(spec_center=500, spec_res=0.01, spec_width=2.5, spec_range=(None, None), pulse_length=6, en_pulse=0.001, flattop=0, n_events=1, spec_extend=5, **kwargs) Models FEL pulse(s) based on Gaussian statistics spec_center - central photon energy in eV spec_res - spectral resolution in eV spec_width - width of spectrum in eV (fwhm of E**2) spec_range = (E1, E2) - energy range of the spectrum. If not defined, spec_range = (spec_center - spec_width * spec_extend, spec_center + spec_width * spec_extend) pulse_length - longitudinal size of the pulse in um (fwhm of E**2) en_pulse - expected average energy of the pulses in Joules flattop - if true, flat-top pulse in time domain is generated with length 'pulse_length' in um n_events - number of spectra to be generated return tuple of 4 arguments: (s, td, ph_en, fd) ph_en - colunm of photon energies in eV with size (spec_range[2]-spec_range[1])/spec_res fd - matrix of radiation in frequency domain with shape ((spec_range[2]-spec_range[1])/spec_res, n_events), normalized such that np.sum(abs(fd)**2) is photon spectral density, i.e: np.sum(abs(fd)**2)*spec_res = N_photons s - colunm of longitudinal positions along the pulse in yime domain in um td - matrix of radiation in time domain with shape ((spec_range[2]-spec_range[1])/spec_res, n_events), normalized such that abs(td)**2 = radiation_power .. function:: dfldomain_check(domains, both_req=False)