def plot_wiggler_results(self): if self.plot_graph == 1: try: try: congruence.checkFile("tmp.traj") except: return data = numpy.loadtxt("tmp.traj",skiprows=15) energy, flux, temp = srfunc.wiggler_spectrum(data.T, enerMin=self.e_min, enerMax=self.e_max, nPoints=500, electronCurrent=self.electron_current/1000, outFile="spectrum.dat", elliptical=False) self.plot_wiggler_histo(20, data[:, 1], data[:, 7], plot_canvas_index=0, title="Magnetic Field (in vertical) Bz(Y)", xtitle=r'Y [m]', ytitle=r'B [T]') self.plot_wiggler_histo(40, data[:, 1], data[:, 6], plot_canvas_index=1, title="Electron Curvature", xtitle=r'Y [m]', ytitle=r'curvature [m^-1]') self.plot_wiggler_histo(60, data[:, 1], data[:, 3], plot_canvas_index=2, title="Electron Velocity BetaX(Y)", xtitle=r'Y [m]', ytitle=r'BetaX') self.plot_wiggler_histo(80, data[:, 1], data[:, 0], plot_canvas_index=3, title="Electron Trajectory X(Y)", xtitle=r'Y [m]', ytitle=r'X [m]') self.plot_wiggler_histo(100, energy , flux , plot_canvas_index=4, title="Wiggler Spectrum (current = " + str(self.electron_current) + " mA)", xtitle=r'E [eV]', ytitle=r'Flux [phot/s/0.1%bw]', is_log_log=True) except Exception as exception: QtGui.QMessageBox.critical(self, "Error", str(exception), QtGui.QMessageBox.Ok)
def xoppy_calc_wigg(FIELD=0,NPERIODS=12,ULAMBDA=0.125,K=14.0,ENERGY=6.04,PHOT_ENERGY_MIN=100.0,\ PHOT_ENERGY_MAX=100100.0,NPOINTS=100,NTRAJPOINTS=101,CURRENT=200.0,FILE="?"): print("Inside xoppy_calc_wigg. ") outFileTraj = "xwiggler_traj.spec" outFile = "xwiggler.spec" if FIELD == 0: t0,p = srfunc.wiggler_trajectory(b_from=0, nPer=NPERIODS, nTrajPoints=NTRAJPOINTS, \ ener_gev=ENERGY, per=ULAMBDA, kValue=K, \ trajFile=outFileTraj) if FIELD == 1: # magnetic field from B(s) map t0,p = srfunc.wiggler_trajectory(b_from=1, nPer=NPERIODS, nTrajPoints=NTRAJPOINTS, \ ener_gev=ENERGY, inData=FILE, trajFile=outFileTraj) if FIELD == 2: # magnetic field from harmonics # hh = srfunc.wiggler_harmonics(b_t,Nh=41,fileOutH="tmp.h") t0,p = srfunc.wiggler_trajectory(b_from=2, nPer=NPERIODS, nTrajPoints=NTRAJPOINTS, \ ener_gev=ENERGY, per=ULAMBDA, inData="", trajFile=outFileTraj) print(p) # # now spectra # e, f0, p0 = srfunc.wiggler_spectrum(t0, enerMin=PHOT_ENERGY_MIN, enerMax=PHOT_ENERGY_MAX, nPoints=NPOINTS, \ electronCurrent=CURRENT*1e-3, outFile=outFile, elliptical=False) try: cumulated_power = p0.cumsum() * numpy.abs(e[0] - e[1]) except: cumulated_power = 0.0 print("\nPower from integral of spectrum (sum rule): %8.3f W" % (cumulated_power[-1])) return e, f0, p0 , cumulated_power
def xoppy_calc_xwiggler(FIELD=0,NPERIODS=12,ULAMBDA=0.125,K=14.0,ENERGY=6.04,PHOT_ENERGY_MIN=100.0,\ PHOT_ENERGY_MAX=100100.0,NPOINTS=100,NTRAJPOINTS=101,CURRENT=200.0,FILE="?"): print("Inside xoppy_calc_xwiggler. ") outFileTraj = "xwiggler_traj.spec" outFile = "xwiggler.spec" if FIELD == 0: t0,p = srfunc.wiggler_trajectory(b_from=0, nPer=NPERIODS, nTrajPoints=NTRAJPOINTS, \ ener_gev=ENERGY, per=ULAMBDA, kValue=K, \ trajFile=outFileTraj) if FIELD == 1: # magnetic field from B(s) map t0,p = srfunc.wiggler_trajectory(b_from=1, nPer=NPERIODS, nTrajPoints=NTRAJPOINTS, \ ener_gev=ENERGY, inData=FILE, trajFile=outFileTraj) if FIELD == 2: # magnetic field from harmonics # hh = srfunc.wiggler_harmonics(b_t,Nh=41,fileOutH="tmp.h") t0,p = srfunc.wiggler_trajectory(b_from=2, nPer=NPERIODS, nTrajPoints=NTRAJPOINTS, \ ener_gev=ENERGY, per=ULAMBDA, inData="", trajFile=outFileTraj) print(p) # # now spectra # e, f0, p0 = srfunc.wiggler_spectrum(t0, enerMin=PHOT_ENERGY_MIN, enerMax=PHOT_ENERGY_MAX, nPoints=NPOINTS, \ electronCurrent=CURRENT*1e-3, outFile=outFile, elliptical=False) print("\nPower from integral of spectrum: %8.3f W" % (f0.sum() * 1e3 * codata.e * (e[1] - e[0]))) return e, f0, p0
def calculate_spectrum(self, output_file=""): traj, pars = self.get_trajectory() wig = self.get_magnetic_structure() e_min, e_max, ne = wig.get_energy_box() ring = self.get_electron_beam() if traj is not None: e, f, w = wiggler_spectrum(traj, enerMin=e_min, enerMax=e_max, nPoints=ne, electronCurrent=ring.current(), outFile=output_file, elliptical=False) return e, f, w else: raise Exception("Cannot compute spectrum")
def calc_wiggler_spectrum(ener_gev=6.0,e_min=100.0,e_max=100000.00,file_field="",output_file=""): (traj, pars) = srfunc.wiggler_trajectory(b_from=1, inData=file_field, nPer=1, nTrajPoints=501, ener_gev=ener_gev, per=None, kValue=None, trajFile="tmp.traj") x,y = srfunc.wiggler_spectrum(traj, enerMin=e_min, enerMax=e_max,nPoints=500, \ electronCurrent=0.2, outFile="", elliptical=False) # tmp = (numpy.vstack((x,y))) print(tmp.shape) numpy.savetxt(output_file,tmp.T) xx = numpy.array((5000.,10000,20000,40000,80000)) return numpy.interp(xx,x,y)
def plot_wiggler_results(self): if self.plot_graph == 1: try: try: congruence.checkFile("tmp.traj") except: return data = numpy.loadtxt("tmp.traj",skiprows=15) energy, flux, temp = srfunc.wiggler_spectrum(data.T, enerMin=self.e_min, enerMax=self.e_max, nPoints=500, electronCurrent=self.electron_current/1000, outFile="spectrum.dat", elliptical=False) self.plot_wiggler_histo(15, data[:, 1], data[:, 7], plot_canvas_index=0, title="Magnetic Field (in vertical) Bz(Y)", xtitle=r'Y [m]', ytitle=r'B [T]') self.plot_wiggler_histo(30, data[:, 1], data[:, 6], plot_canvas_index=1, title="Electron Curvature", xtitle=r'Y [m]', ytitle=r'curvature [m^-1]') self.plot_wiggler_histo(45, data[:, 1], data[:, 3], plot_canvas_index=2, title="Electron Velocity BetaX(Y)", xtitle=r'Y [m]', ytitle=r'BetaX') self.plot_wiggler_histo(60, data[:, 1], data[:, 0], plot_canvas_index=3, title="Electron Trajectory X(Y)", xtitle=r'Y [m]', ytitle=r'X [m]') self.plot_wiggler_histo(80, energy , flux , plot_canvas_index=4, title="Wiggler Spectrum (current = " + str(self.electron_current) + " mA)", xtitle=r'E [eV]', ytitle=r'Flux [phot/s/0.1%bw]', is_log_log=False) self.plot_wiggler_histo(100, energy, flux*1e3*codata.e, plot_canvas_index=5, title="Spectral Power (current = " + str(self.electron_current) + " mA)", xtitle=r'E [eV]', ytitle=r'Spectral Power [W/eV]', is_log_log=False) print("\nTotal power (from integral of spectrum): %f W"%(numpy.trapz(flux*1e3*codata.e,x=energy))) print("\nTotal number of photons (from integral of spectrum): %g"%(numpy.trapz(flux/(energy*1e-3),x=energy))) except Exception as exception: QtWidgets.QMessageBox.critical(self, "Error", str(exception), QtWidgets.QMessageBox.Ok)
def run_shadow4(self): nTrajPoints = 501 # # syned # syned_electron_beam = self.get_syned_electron_beam() print(syned_electron_beam.info()) # B from file if self.magnetic_field_source == 0: syned_wiggler = Wiggler(K_vertical=self.k_value, K_horizontal=0.0, period_length=self.id_period, number_of_periods=self.number_of_periods) elif self.magnetic_field_source == 1: syned_wiggler = MagneticStructure1DField.initialize_from_file( self.file_with_b_vs_y) elif self.magnetic_field_source == 2: raise Exception(NotImplemented) print(syned_wiggler.info()) sw = SourceWiggler() sourcewiggler = SourceWiggler(name="test", syned_electron_beam=syned_electron_beam, syned_wiggler=syned_wiggler, flag_emittance=True, emin=self.e_min, emax=self.e_max, ng_e=100, ng_j=nTrajPoints) if self.e_min == self.e_max: sourcewiggler.set_energy_monochromatic(self.e_min) # sourcewiggler.set_electron_initial_conditions_by_label(velocity_label="value_at_zero", # position_label="value_at_zero",) sourcewiggler.set_electron_initial_conditions( shift_x_flag=self.shift_x_flag, shift_x_value=self.shift_x_value, shift_betax_flag=self.shift_betax_flag, shift_betax_value=self.shift_betax_value) # sourcewiggler.calculate_radiation() print(sourcewiggler.info()) t00 = time.time() print(">>>> starting calculation...") rays = sourcewiggler.calculate_rays(NRAYS=self.n_rays) t11 = time.time() - t00 print(">>>> time for %d rays: %f s, %f min, " % (self.n_rays, t11, t11 / 60)) print(">>> Results of calculate_radiation") print(">>> trajectory.shape: ", sourcewiggler._result_trajectory.shape) print(">>> cdf: ", sourcewiggler._result_cdf.keys()) calculate_spectrum = True if calculate_spectrum: e, f, w = wiggler_spectrum(sourcewiggler._result_trajectory, enerMin=self.e_min, enerMax=self.e_max, nPoints=500, electronCurrent=self.ring_current, outFile="", elliptical=False) # from srxraylib.plot.gol import plot # plot(e, f, xlog=False, ylog=False, show=False, # xtitle="Photon energy [eV]", ytitle="Flux [Photons/s/0.1%bw]", title="Flux") # plot(e, w, xlog=False, ylog=False, show=True, # xtitle="Photon energy [eV]", ytitle="Spectral Power [E/eV]", title="Spectral Power") beam = Beam3.initialize_from_array(rays) # # wiggler plots # self.plot_widget_all(sourcewiggler, e, f, w) self.shadowoui_beam = ShadowBeam(oe_number=0, beam=beam, number_of_rays=0) self.plot_shadow_all() self.send("Beam", self.shadowoui_beam)
def run_source_wiggler(): from srxraylib.sources import srfunc (traj, pars) = srfunc.wiggler_trajectory(b_from=1, inData="/home/manuel/Oasys/BM_only7.b", nPer=1, nTrajPoints=501, ener_gev=2.0, per=0.01, kValue=1.0, trajFile="tmp.traj", shift_x_flag=4, shift_x_value=0.042, shift_betax_flag=4, shift_betax_value=0.035) # # calculate cdf and write file for Shadow/Source # srfunc.wiggler_cdf(traj, enerMin=1000.0, enerMax=1000.1, enerPoints=1001, outFile=b'/home/manuel/Oasys/xshwig.sha', elliptical=False) calculate_spectrum = False if calculate_spectrum: e, f, w = srfunc.wiggler_spectrum(traj, enerMin=1000.0, enerMax=1000.1, nPoints=500, electronCurrent=500.0 * 1e-3, outFile="spectrum.dat", elliptical=False) from srxraylib.plot.gol import plot plot(e, f, xlog=False, ylog=False, show=False, xtitle="Photon energy [eV]", ytitle="Flux [Photons/s/0.1%bw]", title="Flux") plot(e, w, xlog=False, ylog=False, show=True, xtitle="Photon energy [eV]", ytitle="Spectral Power [E/eV]", title="Spectral Power") # # end script # # write (1) or not (0) SHADOW files start.xx end.xx star.xx iwrite = 0 # # initialize shadow3 source (oe0) and beam # beam = Shadow.Beam() oe0 = Shadow.Source() # # Define variables. See meaning of variables in: # https://raw.githubusercontent.com/srio/shadow3/master/docs/source.nml # https://raw.githubusercontent.com/srio/shadow3/master/docs/oe.nml # oe0.BENER = 2.0 oe0.CONV_FACT = 1.0 oe0.EPSI_X = 70e-12 oe0.EPSI_Z = 70e-12 oe0.FDISTR = 0 oe0.FILE_TRAJ = b'/home/manuel/Oasys/xshwig.sha' oe0.FSOUR = 0 oe0.FSOURCE_DEPTH = 0 oe0.F_COLOR = 0 oe0.F_PHOT = 0 oe0.F_WIGGLER = 1 oe0.HDIV1 = 1.0 oe0.HDIV2 = 1.0 oe0.IDO_VX = 0 oe0.IDO_VZ = 0 oe0.IDO_X_S = 0 oe0.IDO_Y_S = 0 oe0.IDO_Z_S = 0 oe0.ISTAR1 = 5676561 oe0.NCOL = 0 oe0.NPOINT = 50000 oe0.N_COLOR = 0 oe0.PH1 = 1000.0 oe0.PH2 = 1000.1 oe0.POL_DEG = 0.0 oe0.SIGMAX = 7e-06 oe0.SIGMAY = 0.0 oe0.SIGMAZ = 1e-05 oe0.VDIV1 = 1.0 oe0.VDIV2 = 1.0 oe0.WXSOU = 0.0 oe0.WYSOU = 0.0 oe0.WZSOU = 0.0 #Run SHADOW to create the source if iwrite: oe0.write("start.00") beam.genSource(oe0) if iwrite: oe0.write("end.00") beam.write("begin.dat") return beam
def xoppy_calc_wiggler_radiation( ELECTRONENERGY=3.0, ELECTRONCURRENT=0.1, PERIODID=0.120, NPERIODS=37.0, KV=22.416, DISTANCE=30.0, HSLITPOINTS=500, VSLITPOINTS=500, PHOTONENERGYMIN=100.0, PHOTONENERGYMAX=100100.0, PHOTONENERGYPOINTS=101, NTRAJPOINTS=1001, FIELD=0, FILE="/Users/srio/Oasys/Bsin.txt", POLARIZATION=0, # 0=total, 1=parallel (s), 2=perpendicular (p) SHIFT_X_FLAG=0, SHIFT_X_VALUE=0.0, SHIFT_BETAX_FLAG=0, SHIFT_BETAX_VALUE=0.0, CONVOLUTION=1, PASSEPARTOUT=3.0, h5_file="wiggler_radiation.h5", h5_entry_name="XOPPY_RADIATION", h5_initialize=True, h5_parameters=None, do_plot=False, ): # calculate wiggler trajectory if FIELD == 0: (traj, pars) = srfunc.wiggler_trajectory( b_from=0, inData="", nPer=int(NPERIODS), #37, nTrajPoints=NTRAJPOINTS, ener_gev=ELECTRONENERGY, per=PERIODID, kValue=KV, trajFile="", shift_x_flag=SHIFT_X_FLAG, shift_x_value=SHIFT_X_VALUE, shift_betax_flag=SHIFT_BETAX_FLAG, shift_betax_value=SHIFT_BETAX_VALUE) if FIELD == 1: # magnetic field from B(s) map (traj, pars) = srfunc.wiggler_trajectory(b_from=1, nPer=1, nTrajPoints=NTRAJPOINTS, ener_gev=ELECTRONENERGY, inData=FILE, trajFile="", shift_x_flag=SHIFT_X_FLAG, shift_x_value=SHIFT_X_VALUE, shift_betax_flag=SHIFT_BETAX_FLAG, shift_betax_value=SHIFT_BETAX_FLAG) if FIELD == 2: raise ("Not implemented") energy, flux, power = srfunc.wiggler_spectrum( traj, enerMin=PHOTONENERGYMIN, enerMax=PHOTONENERGYMAX, nPoints=PHOTONENERGYPOINTS, electronCurrent=ELECTRONCURRENT, outFile="", elliptical=False, polarization=POLARIZATION) try: cumulated_power = power.cumsum() * numpy.abs(energy[0] - energy[1]) except: cumulated_power = 0.0 print("\nPower from integral of spectrum (sum rule): %8.3f W" % (cumulated_power[-1])) try: cumulated_power = cumtrapz(power, energy, initial=0) except: cumulated_power = 0.0 print("Power from integral of spectrum (trapezoid rule): %8.3f W" % (cumulated_power[-1])) codata_mee = 1e-6 * codata.m_e * codata.c**2 / codata.e # electron mass in meV gamma = ELECTRONENERGY * 1e3 / codata_mee Y = traj[1, :].copy() divX = traj[3, :].copy() By = traj[7, :].copy() # rho = (1e9 / codata.c) * ELECTRONENERGY / By # Ec0 = 3 * codata.h * codata.c * gamma**3 / (4 * numpy.pi * rho) / codata.e # Ec = 665.0 * ELECTRONENERGY**2 * numpy.abs(By) # Ecmax = 665.0 * ELECTRONENERGY** 2 * (numpy.abs(By)).max() coeff = 3 / ( 4 * numpy.pi) * codata.h * codata.c**2 / codata_mee**3 / codata.e # ~665.0 Ec = coeff * ELECTRONENERGY**2 * numpy.abs(By) Ecmax = coeff * ELECTRONENERGY**2 * (numpy.abs(By)).max() # approx formula for divergence (first formula in pag 43 of Tanaka's paper) sigmaBp = 0.597 / gamma * numpy.sqrt(Ecmax / PHOTONENERGYMIN) # we use vertical interval 6*sigmaBp and horizontal interval = vertical + trajectory interval divXX = numpy.linspace(divX.min() - PASSEPARTOUT * sigmaBp, divX.max() + PASSEPARTOUT * sigmaBp, HSLITPOINTS) divZZ = numpy.linspace(-PASSEPARTOUT * sigmaBp, PASSEPARTOUT * sigmaBp, VSLITPOINTS) e = numpy.linspace(PHOTONENERGYMIN, PHOTONENERGYMAX, PHOTONENERGYPOINTS) p = numpy.zeros((PHOTONENERGYPOINTS, HSLITPOINTS, VSLITPOINTS)) for i in range(e.size): Ephoton = e[i] # vertical divergence intensity = srfunc.sync_g1(Ephoton / Ec, polarization=POLARIZATION) Ecmean = (Ec * intensity).sum() / intensity.sum() fluxDivZZ = srfunc.sync_ang(1, divZZ * 1e3, polarization=POLARIZATION, e_gev=ELECTRONENERGY, i_a=ELECTRONCURRENT, hdiv_mrad=1.0, energy=Ephoton, ec_ev=Ecmean) if do_plot: from srxraylib.plot.gol import plot plot(divZZ, fluxDivZZ, title="min intensity %f" % fluxDivZZ.min(), xtitle="divZ", ytitle="fluxDivZZ", show=1) # horizontal divergence after Tanaka if False: e_over_ec = Ephoton / Ecmax uudlim = 1.0 / gamma uud = numpy.linspace(-uudlim * 0.99, uudlim * 0.99, divX.size) uu = e_over_ec / numpy.sqrt(1 - gamma**2 * uud**2) plot(uud, 2 * numpy.pi / numpy.sqrt(3) * srfunc.sync_g1(uu)) # horizontal divergence # intensity = srfunc.sync_g1(Ephoton / Ec, polarization=POLARIZATION) intensity_interpolated = interpolate_multivalued_function( divX, intensity, divXX, Y, ) if CONVOLUTION: # do always convolution! intensity_interpolated.shape = -1 divXX_window = divXX[-1] - divXX[0] divXXCC = numpy.linspace(-0.5 * divXX_window, 0.5 * divXX_window, divXX.size) fluxDivZZCC = srfunc.sync_ang(1, divXXCC * 1e3, polarization=POLARIZATION, e_gev=ELECTRONENERGY, i_a=ELECTRONCURRENT, hdiv_mrad=1.0, energy=Ephoton, ec_ev=Ecmax) fluxDivZZCC.shape = -1 intensity_convolved = numpy.convolve( intensity_interpolated / intensity_interpolated.max(), fluxDivZZCC / fluxDivZZCC.max(), mode='same') else: intensity_convolved = intensity_interpolated if i == 0: print( "\n\n============ sizes vs photon energy =======================" ) print( "Photon energy/eV FWHM X'/urad FWHM Y'/urad FWHM X/mm FWHM Z/mm " ) print("%16.3f %12.3f %12.3f %9.2f %9.2f" % (Ephoton, 1e6 * get_fwhm(intensity_convolved, divXX)[0], 1e6 * get_fwhm(fluxDivZZ, divZZ)[0], 1e3 * get_fwhm(intensity_convolved, divXX)[0] * DISTANCE, 1e3 * get_fwhm(fluxDivZZ, divZZ)[0] * DISTANCE)) if do_plot: plot(divX, intensity / intensity.max(), divXX, intensity_interpolated / intensity_interpolated.max(), divXX, intensity_convolved / intensity_convolved.max(), divXX, fluxDivZZCC / fluxDivZZCC.max(), title="min intensity %f, Ephoton=%6.2f" % (intensity.min(), Ephoton), xtitle="divX", ytitle="intensity", legend=["orig", "interpolated", "convolved", "kernel"], show=1) # combine H * V INTENSITY = numpy.outer( intensity_convolved / intensity_convolved.max(), fluxDivZZ / fluxDivZZ.max()) p[i, :, :] = INTENSITY if do_plot: from srxraylib.plot.gol import plot_image, plot_surface, plot_show plot_image(INTENSITY, divXX, divZZ, aspect='auto', title="E=%6.2f" % Ephoton, show=1) # to create oasys icon... # plot_surface(INTENSITY, divXX, divZZ, title="", show=0) # import matplotlib.pylab as plt # plt.xticks([]) # plt.yticks([]) # plt.axis('off') # plt.tick_params(axis='both', left='off', top='off', right='off', bottom='off', labelleft='off', # labeltop='off', labelright='off', labelbottom='off') # # plot_show() # h = divXX * DISTANCE * 1e3 # in mm for the h5 file v = divZZ * DISTANCE * 1e3 # in mm for the h5 file print("\nWindow size: %f mm [H] x %f mm [V]" % (h[-1] - h[0], v[-1] - v[0])) print("Window size: %g rad [H] x %g rad [V]" % (divXX[-1] - divXX[0], divZZ[-1] - divZZ[0])) # normalization and total flux for i in range(e.size): INTENSITY = p[i, :, :] # norm = INTENSITY.sum() * (h[1] - h[0]) * (v[1] - v[0]) norm = trapezoidal_rule_2d_1darrays(INTENSITY, h, v) p[i, :, :] = INTENSITY / norm * flux[i] # fit fit_ok = False try: power = p.sum(axis=0) * (e[1] - e[0]) * codata.e * 1e3 print( "\n\n============= Fitting power density to a 2D Gaussian. ==============\n" ) print( "Please use these results with care: check if the original data looks like a Gaussian." ) fit_parameters = fit_gaussian2d(power, h, v) print(info_params(fit_parameters)) H, V = numpy.meshgrid(h, v) data_fitted = twoD_Gaussian((H, V), *fit_parameters) print(" Total power (sum rule) in the fitted data [W]: ", data_fitted.sum() * (h[1] - h[0]) * (v[1] - v[0])) # plot_image(data_fitted.reshape((h.size,v.size)),h, v,title="FIT") print("====================================================\n") fit_ok = True except: pass # output file if h5_file != "": try: if h5_initialize: h5w = H5SimpleWriter.initialize_file( h5_file, creator="xoppy_wigglers.py") else: h5w = H5SimpleWriter(h5_file, None) h5w.create_entry(h5_entry_name, nx_default=None) h5w.add_stack(e, h, v, p, stack_name="Radiation", entry_name=h5_entry_name, title_0="Photon energy [eV]", title_1="X gap [mm]", title_2="Y gap [mm]") h5w.create_entry("parameters", root_entry=h5_entry_name, nx_default=None) if h5_parameters is not None: for key in h5_parameters.keys(): h5w.add_key(key, h5_parameters[key], entry_name=h5_entry_name + "/parameters") h5w.create_entry("trajectory", root_entry=h5_entry_name, nx_default="transversal trajectory") h5w.add_key("traj", traj, entry_name=h5_entry_name + "/trajectory") h5w.add_dataset(traj[1, :], traj[0, :], dataset_name="transversal trajectory", entry_name=h5_entry_name + "/trajectory", title_x="s [m]", title_y="X [m]") h5w.add_dataset(traj[1, :], traj[3, :], dataset_name="transversal velocity", entry_name=h5_entry_name + "/trajectory", title_x="s [m]", title_y="Vx/c") h5w.add_dataset(traj[1, :], traj[7, :], dataset_name="Magnetic field", entry_name=h5_entry_name + "/trajectory", title_x="s [m]", title_y="Bz [T]") if fit_ok: h5w.add_image(power, h, v, image_name="PowerDensity", entry_name=h5_entry_name, title_x="X [mm]", title_y="Y [mm]") h5w.add_image(data_fitted.reshape(h.size, v.size), h, v, image_name="PowerDensityFit", entry_name=h5_entry_name, title_x="X [mm]", title_y="Y [mm]") h5w.add_key("fit_info", info_params(fit_parameters), entry_name=h5_entry_name + "/PowerDensityFit") print("File written to disk: %s" % h5_file) except: print("ERROR initializing h5 file") return e, h, v, p, traj
def calculate_flux(y, B, select_mode=0, energy_GeV=2.0, do_plot=False): # analyse M1 B3 = B.copy() # if M==1: # ibad = numpy.argwhere(y > -0.2) # B3[ibad] = 0.0 # elif M==2: # ibad = numpy.argwhere( numpy.abs(y) > 0.2) # B3[ibad] = 0.0 # elif M==3: # ibad = numpy.argwhere(y < 0.2) # B3[ibad] = 0.0 # else: # pass # select_mode = 2 # 0=all, 1=Mag7, 2=Mag8, 3=both RB only, 4=RB1, 5=RB2 if select_mode == 0: pass elif select_mode == 1: ibad = numpy.where(y < -0.3) B3[ibad] = 0.0 ibad = numpy.where(y > 0.3) B3[ibad] = 0.0 elif select_mode == 2: ibad = numpy.where(y < 0.66) B3[ibad] = 0.0 elif select_mode == 3: ibad = numpy.where(numpy.abs(y) < 0.3) B3[ibad] = 0.0 ibad = numpy.where(y > 0.66) B3[ibad] = 0.0 elif select_mode == 4: ibad = numpy.where(y > -0.3) B3[ibad] = 0.0 elif select_mode == 5: ibad = numpy.where(y < 0.3) B3[ibad] = 0.0 ibad = numpy.where(y > 0.66) B3[ibad] = 0.0 if do_plot: from srxraylib.plot.gol import plot, set_qt plot(y, B3, title="select_mode=%d" % select_mode) tmp = numpy.vstack((y, B3)).T print(">>>>", tmp.shape, tmp[:, 0]) (traj, pars) = srfunc.wiggler_trajectory( b_from=1, inData=tmp, #"BM_first.b", nPer=1, nTrajPoints=501, ener_gev=energy_GeV, per=0.01, kValue=1.0, trajFile="tmp.traj", shift_x_flag=5, shift_x_value=0.042, shift_betax_flag=4, shift_betax_value=0.0324) calculate_spectrum = True if calculate_spectrum: e, f, w = srfunc.wiggler_spectrum(traj, enerMin=0.0010, enerMax=10000.1, nPoints=500, electronCurrent=500.0 * 1e-3, outFile="spectrum.dat", elliptical=False) from srxraylib.plot.gol import plot return e, f, w
def __calculate_rays(self, user_unit_to_m=1.0, F_COHER=0, NRAYS=5000, SEED=123456, EPSI_DX=0.0, EPSI_DZ=0.0, psi_interval_in_units_one_over_gamma=None, psi_interval_number_of_points=1001, verbose=True): """ compute the rays in SHADOW matrix (shape (npoints,18) ) :param F_COHER: set this flag for coherent beam :param user_unit_to_m: default 1.0 (m) :return: rays, a numpy.array((npoits,18)) """ if self.__result_cdf is None: self.__calculate_radiation() if verbose: print(">>> Results of calculate_radiation") print(">>> trajectory.shape: ", self.__result_trajectory.shape) print(">>> cdf: ", self.__result_cdf.keys()) wiggler = self.get_magnetic_structure() syned_electron_beam = self.get_electron_beam() sampled_photon_energy, sampled_theta, sampled_phi = self._sample_photon_energy_theta_and_phi( NRAYS) if verbose: print( ">>> sampled sampled_photon_energy,sampled_theta,sampled_phi: ", sampled_photon_energy, sampled_theta, sampled_phi) if SEED != 0: numpy.random.seed(SEED) sigmas = syned_electron_beam.get_sigmas_all() rays = numpy.zeros((NRAYS, 18)) # # sample sizes (cols 1-3) # # if wiggler._FLAG_EMITTANCE: if numpy.array(numpy.abs(sigmas)).sum() == 0: wiggler._FLAG_EMITTANCE = False if wiggler._FLAG_EMITTANCE: x_electron = numpy.random.normal(loc=0.0, scale=sigmas[0], size=NRAYS) y_electron = 0.0 z_electron = numpy.random.normal(loc=0.0, scale=sigmas[2], size=NRAYS) else: x_electron = 0.0 y_electron = 0.0 z_electron = 0.0 # traj[0,ii] = yx[i] # traj[1,ii] = yy[i]+j * per - start_len # traj[2,ii] = 0.0 # traj[3,ii] = betax[i] # traj[4,ii] = betay[i] # traj[5,ii] = 0.0 # traj[6,ii] = curv[i] # traj[7,ii] = bz[i] PATH_STEP = self.__result_cdf["step"] X_TRAJ = self.__result_cdf["x"] Y_TRAJ = self.__result_cdf["y"] SEEDIN = self.__result_cdf["cdf"] ANGLE = self.__result_cdf["angle"] CURV = self.__result_cdf["curv"] EPSI_PATH = numpy.arange( CURV.size) * PATH_STEP # self._result_trajectory[7,:] # ! C We define the 5 arrays: # ! C Y_X(5,N) ---> X(Y) # ! C Y_XPRI(5,N) ---> X'(Y) # ! C Y_CURV(5,N) ---> CURV(Y) # ! C Y_PATH(5,N) ---> PATH(Y) # ! C F(1,N) contains the array of Y values where the nodes are located. # CALL PIECESPL(SEED_Y, Y_TEMP, NP_SY, IER) # CALL CUBSPL (Y_X, X_TEMP, NP_TRAJ, IER) # CALL CUBSPL (Y_Z, Z_TEMP, NP_TRAJ, IER) # CALL CUBSPL (Y_XPRI, ANG_TEMP, NP_TRAJ, IER) # CALL CUBSPL (Y_ZPRI, ANG2_TEMP, NP_TRAJ, IER) # CALL CUBSPL (Y_CURV, C_TEMP, NP_TRAJ, IER) # CALL CUBSPL (Y_PATH, P_TEMP, NP_TRAJ, IER) SEED_Y = interp1d(SEEDIN, Y_TRAJ, kind='linear') Y_X = interp1d(Y_TRAJ, X_TRAJ, kind='cubic') Y_XPRI = interp1d(Y_TRAJ, ANGLE, kind='cubic') Y_CURV = interp1d(Y_TRAJ, CURV, kind='cubic') Y_PATH = interp1d(Y_TRAJ, EPSI_PATH, kind='cubic') # ! C+++ # ! C Compute the path length to the middle (origin) of the wiggler. # ! C We need to know the "center" of the wiggler coordinate. # ! C input: Y_PATH ---> spline array # ! C NP_TRAJ ---> # of points # ! C Y_TRAJ ---> calculation point (ind. variable) # ! C output: PATH0 ---> value of Y_PATH at X = Y_TRAJ. If # ! C Y_TRAJ = 0, then PATH0 = 1/2 length # ! C of trajectory. # ! C+++ Y_TRAJ = 0.0 # CALL SPL_INT (Y_PATH, NP_TRAJ, Y_TRAJ, PATH0, IER) PATH0 = Y_PATH(Y_TRAJ) # ! C # ! C These flags are set because of the original program structure. # ! C # F_PHOT = 0 # F_COLOR = 3 # FSOUR = 3 # FDISTR = 4 ws_ev, ws_f, tmp = wiggler_spectrum( self.__result_trajectory, enerMin=wiggler._EMIN, enerMax=wiggler._EMAX, nPoints=500, # per=self.syned_wiggler.period_length(), electronCurrent=syned_electron_beam._current, outFile="", elliptical=False) ws_flux_per_ev = ws_f / (ws_ev * 1e-3) samplerE = Sampler1D(ws_flux_per_ev, ws_ev) sampled_energies, h, h_center = samplerE.get_n_sampled_points_and_histogram( NRAYS) ############################################### gamma = syned_electron_beam.gamma() m2ev = codata.c * codata.h / codata.e TOANGS = m2ev * 1e10 ##################################################### RAD_MIN = 1.0 / numpy.abs(self.__result_cdf["curv"]).max() critical_energy = TOANGS * 3.0 * numpy.power( gamma, 3) / 4.0 / numpy.pi / 1.0e10 * (1.0 / RAD_MIN) if psi_interval_in_units_one_over_gamma is None: c = numpy.array([-0.3600382, 0.11188709]) # see file fit_psi_interval.py # x = numpy.log10(self._EMIN / critical_energy) x = numpy.log10( wiggler._EMIN / (4 * critical_energy)) # the wiggler that does not have an unique # Ec. To be safe, I use 4 times the # Ec vale to make the interval wider than for the BM y_fit = c[1] + c[0] * x psi_interval_in_units_one_over_gamma = 10**y_fit # this is the semi interval psi_interval_in_units_one_over_gamma *= 4 # doubled interval if psi_interval_in_units_one_over_gamma < 2: psi_interval_in_units_one_over_gamma = 2 if verbose: print(">>> psi_interval_in_units_one_over_gamma: ", psi_interval_in_units_one_over_gamma) angle_array_mrad = numpy.linspace( -0.5 * psi_interval_in_units_one_over_gamma * 1e3 / gamma, 0.5 * psi_interval_in_units_one_over_gamma * 1e3 / gamma, psi_interval_number_of_points) # a = numpy.linspace(-0.6,0.6,150) a = angle_array_mrad ##################################################################### a8 = 1.0 hdiv_mrad = 1.0 # i_a = self.syned_electron_beam._current # # fm = sync_f(a*self.syned_electron_beam.gamma()/1e3,eene,polarization=0) * \ # numpy.power(eene,2)*a8*i_a*hdiv_mrad*numpy.power(self.syned_electron_beam._energy_in_GeV,2) # # plot(a,fm,title="sync_f") # # samplerAng = Sampler1D(fm,a) # # sampled_theta,hx,h = samplerAng.get_n_sampled_points_and_histogram(10*NRAYS) # plot(h,hx) for itik in range(NRAYS): # ARG_Y = GRID(2,ITIK) # CALL SPL_INT (SEED_Y, NP_SY, ARG_Y, Y_TRAJ, IER) arg_y = numpy.random.random() # ARG_Y[itik] Y_TRAJ = SEED_Y(arg_y) # ! [email protected] 2014-05-19 # ! in wiggler some problems arise because spl_int # ! does not return a Y value in the correct range. # ! In those cases, we make a linear interpolation instead. # if ((y_traj.le.y_temp(1)).or.(y_traj.gt.y_temp(NP_SY))) then # y_traj_old = y_traj # CALL LIN_INT (SEED_Y, NP_SY, ARG_Y, Y_TRAJ, IER) # print*,'SOURCESYNC: bad y_traj from SPL_INT, corrected with LIN_SPL: ',y_traj_old,'=>',y_traj # endif # # CALL SPL_INT (Y_X, NP_TRAJ, Y_TRAJ, X_TRAJ, IER) # CALL SPL_INT (Y_XPRI, NP_TRAJ, Y_TRAJ, ANGLE, IER) # CALL SPL_INT (Y_CURV, NP_TRAJ, Y_TRAJ, CURV, IER) # CALL SPL_INT (Y_PATH, NP_TRAJ, Y_TRAJ, EPSI_PATH, IER) # END IF X_TRAJ = Y_X(Y_TRAJ) ANGLE = Y_XPRI(Y_TRAJ) CURV = Y_CURV(Y_TRAJ) EPSI_PATH = Y_PATH(Y_TRAJ) # print("\n>>><<<",arg_y,Y_TRAJ,X_TRAJ,ANGLE,CURV,EPSI_PATH) # EPSI_PATH = EPSI_PATH - PATH0 ! now refer to wiggler's origin # IF (CURV.LT.0) THEN # POL_ANGLE = 90.0D0 ! instant orbit is CW # ELSE # POL_ANGLE = -90.0D0 ! CCW # END IF # IF (CURV.EQ.0) THEN # R_MAGNET = 1.0D+20 # ELSE # R_MAGNET = ABS(1.0D0/CURV) # END IF # POL_ANGLE = TORAD*POL_ANGLE EPSI_PATH = EPSI_PATH - PATH0 # now refer to wiggler's origin if CURV < 0: POL_ANGLE = 90.0 # instant orbit is CW else: POL_ANGLE = -90.0 # CCW if CURV == 0.0: R_MAGNET = 1.0e20 else: R_MAGNET = numpy.abs(1.0 / CURV) POL_ANGLE = POL_ANGLE * numpy.pi / 180.0 # ! C # ! C Compute the actual distance (EPSI_W*) from the orbital focus # ! C EPSI_WX = EPSI_DX + EPSI_PATH EPSI_WZ = EPSI_DZ + EPSI_PATH # ! BUG [email protected] found that these routine does not make the # ! calculation correctly. Changed to new one BINORMAL # !CALL GAUSS (SIGMAX, EPSI_X, EPSI_WX, XXX, E_BEAM(1), istar1) # !CALL GAUSS (SIGMAZ, EPSI_Z, EPSI_WZ, ZZZ, E_BEAM(3), istar1) # ! # ! calculation of the electrom beam moments at the current position # ! (sX,sZ) = (epsi_wx,epsi_ez): # ! <x2> = sX^2 + sigmaX^2 # ! <x x'> = sX sigmaXp^2 # ! <x'2> = sigmaXp^2 (same for Z) # # ! then calculate the new recalculated sigmas (rSigmas) and correlation rho of the # ! normal bivariate distribution at the point in the electron trajectory # ! rsigmaX = sqrt(<x2>) # ! rsigmaXp = sqrt(<x'2>) # ! rhoX = <x x'>/ (rsigmaX rsigmaXp) (same for Z) # # if (abs(sigmaX) .lt. 1e-15) then !no emittance # sigmaXp = 0.0d0 # XXX = 0.0 # E_BEAM(1) = 0.0 # else # sigmaXp = epsi_Xold/sigmaX ! true only at waist, use epsi_xOld as it has been redefined :( # rSigmaX = sqrt( (epsi_wX**2) * (sigmaXp**2) + sigmaX**2 ) # rSigmaXp = sigmaXp # if (abs(rSigmaX*rSigmaXp) .lt. 1e-15) then !no emittance # rhoX = 0.0 # else # rhoX = epsi_wx * sigmaXp**2 / (rSigmaX * rSigmaXp) # endif # # CALL BINORMAL (rSigmaX, rSigmaXp, rhoX, XXX, E_BEAM(1), istar1) # endif # if wiggler._FLAG_EMITTANCE: # CALL BINORMAL (rSigmaX, rSigmaXp, rhoX, XXX, E_BEAM(1), istar1) # [ c11 c12 ] [ sigma1^2 rho*sigma1*sigma2 ] # [ c21 c22 ] = [ rho*sigma1*sigma2 sigma2^2 ] sigmaX, sigmaXp, sigmaZ, sigmaZp = syned_electron_beam.get_sigmas_all( ) epsi_wX = sigmaX * sigmaXp rSigmaX = numpy.sqrt((epsi_wX**2) * (sigmaXp**2) + sigmaX**2) rSigmaXp = sigmaXp rhoX = epsi_wX * sigmaXp**2 / (rSigmaX * rSigmaXp) mean = [0, 0] cov = [[sigmaX**2, rhoX * sigmaX * sigmaXp], [rhoX * sigmaX * sigmaXp, sigmaXp**2]] # diagonal covariance sampled_x, sampled_xp = numpy.random.multivariate_normal( mean, cov, 1).T # plot_scatter(sampled_x,sampled_xp) XXX = sampled_x E_BEAM1 = sampled_xp epsi_wZ = sigmaZ * sigmaZp rSigmaZ = numpy.sqrt((epsi_wZ**2) * (sigmaZp**2) + sigmaZ**2) rSigmaZp = sigmaZp rhoZ = epsi_wZ * sigmaZp**2 / (rSigmaZ * rSigmaZp) mean = [0, 0] cov = [[sigmaZ**2, rhoZ * sigmaZ * sigmaZp], [rhoZ * sigmaZ * sigmaZp, sigmaZp**2]] # diagonal covariance sampled_z, sampled_zp = numpy.random.multivariate_normal( mean, cov, 1).T ZZZ = sampled_z E_BEAM3 = sampled_zp else: sigmaXp = 0.0 XXX = 0.0 E_BEAM1 = 0.0 rhoX = 0.0 sigmaZp = 0.0 ZZZ = 0.0 E_BEAM3 = 0.0 # # ! C # ! C For normal wiggler, XXX is perpendicular to the electron trajectory at # ! C the point defined by (X_TRAJ,Y_TRAJ,0). # ! C # IF (F_WIGGLER.EQ.1) THEN ! normal wiggler # YYY = Y_TRAJ - XXX*SIN(ANGLE) # XXX = X_TRAJ + XXX*COS(ANGLE) YYY = Y_TRAJ - XXX * numpy.sin(ANGLE) XXX = X_TRAJ + XXX * numpy.cos(ANGLE) rays[itik, 0] = XXX rays[itik, 1] = YYY rays[itik, 2] = ZZZ # # directions # # ! C # ! C Synchrotron source # ! C Note. The angle of emission IN PLANE is the same as the one used # ! C before. This will give rise to a source curved along the orbit. # ! C The elevation angle is instead characteristic of the SR distribution. # ! C The electron beam emittance is included at this stage. Note that if # ! C EPSI = 0, we'll have E_BEAM = 0.0, with no changes. # ! C # IF (F_WIGGLER.EQ.3) ANGLE=0 ! Elliptical Wiggler. # ANGLEX = ANGLE + E_BEAM(1) # DIREC(1) = TAN(ANGLEX) # IF (R_ALADDIN.LT.0.0D0) DIREC(1) = - DIREC(1) # DIREC(2) = 1.0D0 # ARG_ANG = GRID(6,ITIK) ANGLEX = ANGLE + E_BEAM1 DIREC1 = numpy.tan(ANGLEX) DIREC2 = 1.0 # ! C # ! C In the case of SR, we take into account the fact that the electron # ! C trajectory is not orthogonal to the field. This will give a correction # ! C to the photon energy. We can write it as a correction to the # ! C magnetic field strength; this will linearly shift the critical energy # ! C and, with it, the energy of the emitted photon. # ! C # E_TEMP(3) = TAN(E_BEAM(3))/COS(E_BEAM(1)) # E_TEMP(2) = 1.0D0 # E_TEMP(1) = TAN(E_BEAM(1)) # CALL NORM (E_TEMP,E_TEMP) # CORREC = SQRT(1.0D0-E_TEMP(3)**2) # 4400 CONTINUE E_TEMP3 = numpy.tan(E_BEAM3) / numpy.cos(E_BEAM1) E_TEMP2 = 1.0 E_TEMP1 = numpy.tan(E_BEAM1) e_temp_norm = numpy.sqrt(E_TEMP1**2 + E_TEMP2**2 + E_TEMP3**2) E_TEMP3 /= e_temp_norm E_TEMP2 /= e_temp_norm E_TEMP1 /= e_temp_norm CORREC = numpy.sqrt(1.0 - E_TEMP3**2) # IF (FDISTR.EQ.6) THEN # CALL ALADDIN1 (ARG_ANG,ANGLEV,F_POL,IER) # Q_WAVE = TWOPI*PHOTON(1)/TOCM*CORREC # POL_DEG = ARG_ANG # ELSE IF (FDISTR.EQ.4) THEN # ARG_ENER = WRAN (ISTAR1) # RAD_MIN = ABS(R_MAGNET) # # i1 = 1 # CALL WHITE & # (RAD_MIN,CORREC,ARG_ENER,ARG_ANG,Q_WAVE,ANGLEV,POL_DEG,i1) # END IF RAD_MIN = numpy.abs(R_MAGNET) # CALL WHITE (RAD_MIN,CORREC,ARG_ENER,ARG_ANG,Q_WAVE,ANGLEV,POL_DEG,i1) ARG_ANG = numpy.random.random() ARG_ENER = numpy.random.random() # print(" >> R_MAGNET, DIREC",R_MAGNET,DIREC1,DIREC2) # print(" >> RAD_MIN,CORREC,ARG_ENER,ARG_ANG,",RAD_MIN,CORREC,ARG_ENER,ARG_ANG) ####################################################################### # gamma = self.syned_electron_beam.gamma() # m2ev = codata.c * codata.h / codata.e # TOANGS = m2ev * 1e10 # critical_energy = TOANGS*3.0*numpy.power(gamma,3)/4.0/numpy.pi/1.0e10*(1.0/RAD_MIN) # sampled_photon_energy = sampled_energies[itik] # wavelength = codata.h * codata.c / codata.e /sampled_photon_energy # Q_WAVE = 2 * numpy.pi / (wavelength*1e2) # print(" >> PHOTON ENERGY, Ec, lambda, Q: ",sampled_photon_energy,critical_energy,wavelength*1e10,Q_WAVE) ################################################################################### sampled_photon_energy = sampled_energies[itik] # wavelength = codata.h * codata.c / codata.e /sampled_photon_energy critical_energy = TOANGS * 3.0 * numpy.power( gamma, 3) / 4.0 / numpy.pi / 1.0e10 * (1.0 / RAD_MIN) eene = sampled_photon_energy / critical_energy # TODO: remove old after testing... method = "new" if method == "old": # fm = sync_f(a*1e-3*self.syned_electron_beam.gamma(),eene,polarization=0) * \ # numpy.power(eene,2)*a8*self.syned_electron_beam._current*hdiv_mrad * \ # numpy.power(self.syned_electron_beam._energy_in_GeV,2) fm_s = sync_f(a*1e-3*self.syned_electron_beam.gamma(),eene,polarization=1) * \ numpy.power(eene,2)*a8*self.syned_electron_beam._current*hdiv_mrad * \ numpy.power(self.syned_electron_beam._energy_in_GeV,2) fm_p = sync_f(a*1e-3*self.syned_electron_beam.gamma(),eene,polarization=2) * \ numpy.power(eene,2)*a8*self.syned_electron_beam._current*hdiv_mrad * \ numpy.power(self.syned_electron_beam._energy_in_GeV,2) else: fm_s, fm_p = sync_f_sigma_and_pi( a * 1e-3 * syned_electron_beam.gamma(), eene) cte = eene**2 * a8 * syned_electron_beam._current * hdiv_mrad * syned_electron_beam._energy_in_GeV**2 fm_s *= cte fm_p *= cte fm = fm_s + fm_p fm_pol = numpy.zeros_like(fm) for i in range(fm_pol.size): if fm[i] == 0.0: fm_pol[i] = 0 else: fm_pol[i] = fm_s[i] / fm[i] fm.shape = -1 fm_s.shape = -1 fm_pol.shape = -1 pol_deg_interpolator = interp1d(a * 1e-3, fm_pol) samplerAng = Sampler1D(fm, a * 1e-3) # samplerPol = Sampler1D(fm_s/fm,a*1e-3) # plot(a*1e-3,fm_s/fm) if fm.min() == fm.max(): print("Warning: cannot compute divergence for ray index %d" % itik) sampled_theta = 0.0 else: sampled_theta = samplerAng.get_sampled(ARG_ENER) sampled_pol_deg = pol_deg_interpolator(sampled_theta) # print("sampled_theta: ",sampled_theta, "sampled_energy: ",sampled_photon_energy, "sampled pol ",sampled_pol_deg) ANGLEV = sampled_theta ANGLEV += E_BEAM3 # IF (ANGLEV.LT.0.0) I_CHANGE = -1 # ANGLEV = ANGLEV + E_BEAM(3) # ! C # ! C Test if the ray is within the specified limits # ! C # IF (FGRID.EQ.0.OR.FGRID.EQ.2) THEN # IF (ANGLEV.GT.VDIV1.OR.ANGLEV.LT.-VDIV2) THEN # ARG_ANG = WRAN(ISTAR1) # ! C # ! C If it is outside the range, then generate another ray. # ! C # GO TO 4400 # END IF # END IF # DIREC(3) = TAN(ANGLEV)/COS(ANGLEX) DIREC3 = numpy.tan(ANGLEV) / numpy.cos(ANGLEX) # IF (F_WIGGLER.EQ.3) THEN # CALL ROTATE (DIREC, ANGLE3,ANGLE2,ANGLE1,DIREC) # END IF # CALL NORM (DIREC,DIREC) direc_norm = numpy.sqrt(DIREC1**2 + DIREC2**2 + DIREC3**2) DIREC1 /= direc_norm DIREC2 /= direc_norm DIREC3 /= direc_norm rays[itik, 3] = DIREC1 # VX rays[itik, 4] = DIREC2 # VY rays[itik, 5] = DIREC3 # VZ if user_unit_to_m != 1.0: rays[:, 0] /= user_unit_to_m rays[:, 1] /= user_unit_to_m rays[:, 2] /= user_unit_to_m # # sample divergences (cols 4-6): the Shadow way # # # electric field vectors (cols 7-9, 16-18) and phases (cols 14-15) # # ! C # ! C --------------------------------------------------------------------- # ! C POLARIZATION # ! C # ! C Generates the polarization of the ray. This is defined on the # ! C source plane, so that A_VEC is along the X-axis and AP_VEC is along Z-axis. # ! C Then care must be taken so that A will be perpendicular to the ray # ! C direction. # ! C # ! C # A_VEC(1) = 1.0D0 # A_VEC(2) = 0.0D0 # A_VEC(3) = 0.0D0 DIREC = rays[:, 3:6].copy() A_VEC = numpy.zeros_like(DIREC) A_VEC[:, 0] = 1.0 # ! C # ! C Rotate A_VEC so that it will be perpendicular to DIREC and with the # ! C right components on the plane. # ! C # CALL CROSS (A_VEC,DIREC,A_TEMP) A_TEMP = self._cross(A_VEC, DIREC) # CALL CROSS (DIREC,A_TEMP,A_VEC) A_VEC = self._cross(DIREC, A_TEMP) # CALL NORM (A_VEC,A_VEC) A_VEC = self._norm(A_VEC) # CALL CROSS (A_VEC,DIREC,AP_VEC) AP_VEC = self._cross(A_VEC, DIREC) # CALL NORM (AP_VEC,AP_VEC) AP_VEC = self._norm(AP_VEC) # # obtain polarization for each ray (interpolation) # POL_DEG = sampled_pol_deg DENOM = numpy.sqrt(1.0 - 2.0 * POL_DEG + 2.0 * POL_DEG**2) AX = POL_DEG / DENOM for i in range(3): A_VEC[:, i] *= AX AZ = (1.0 - POL_DEG) / DENOM for i in range(3): AP_VEC[:, i] *= AZ rays[:, 6:9] = A_VEC rays[:, 15:18] = AP_VEC # # ! C # ! C Now the phases of A_VEC and AP_VEC. # ! C # POL_ANGLE = 0.5 * numpy.pi if F_COHER == 1: PHASEX = 0.0 else: PHASEX = numpy.random.random(NRAYS) * 2 * numpy.pi # PHASEZ = PHASEX + POL_ANGLE * numpy.sign(ANGLEV) rays[:, 13] = 0.0 # PHASEX rays[:, 14] = 0.0 # PHASEZ # set flag (col 10) rays[:, 9] = 1.0 # # photon energy (col 11) # # A2EV = 2.0*numpy.pi/(codata.h*codata.c/codata.e*1e2) sampled_photon_energy = sampled_energies wavelength = codata.h * codata.c / codata.e / sampled_photon_energy Q_WAVE = 2 * numpy.pi / (wavelength * 1e2) rays[:, 10] = Q_WAVE # sampled_photon_energy * A2EV # col 12 (ray index) rays[:, 11] = 1 + numpy.arange(NRAYS) # col 13 (optical path) rays[:, 11] = 0.0 return rays
# # flux # calculate_spectrum = True enerMin = 100.0 # 100.0, enerMax = 15000.0 # 10000.0, enerN = 500 ENERGIES = numpy.linspace(enerMin, enerMax, enerN) e, f, w = srfunc.wiggler_spectrum(traj, enerMin=enerMin, enerMax=enerMax, nPoints=enerN, electronCurrent=current, outFile="spectrum.dat", elliptical=False) if False: FLUX = numpy.zeros_like(ENERGIES) POWER = numpy.zeros_like(ENERGIES) for i, energy in enumerate(ENERGIES): #TODO: chech this funny numbers.... flux_vs_theta = 27.45 * 2.457e17 * ener_gev * current * sync_g1( energy / Ec) flux = numpy.trapz(flux_vs_theta, XP) # flux_vs_theta.sum() * (XP[1]-XP[0]) # FLUX[i] = flux
def calculate_spectrum(emin, emax, npoints=500, do_plot=False): # # script to run the wiggler preprocessor (created by ShadowOui:Wiggler) # (traj, pars) = srfunc.wiggler_trajectory(b_from=1, inData="Bz_Alba_rev3.dat", nPer=1, nTrajPoints=501, ener_gev=2.5, per=0.755, kValue=211.0, trajFile="tmp.traj", shift_x_flag=4, shift_x_value=0.0, shift_betax_flag=4, shift_betax_value=0.0) # # calculate cdf and write file for Shadow/Source # srfunc.wiggler_cdf(traj, enerMin=emin, enerMax=emax, enerPoints=1001, outFile=b'xshwig.sha', elliptical=False) calculate_spectrum = True if calculate_spectrum: e, f, w = srfunc.wiggler_spectrum(traj, enerMin=emin, enerMax=emax, nPoints=npoints, electronCurrent=400 * 1e-3, outFile="spectrum.dat", elliptical=False) if do_plot: from srxraylib.plot.gol import plot plot(e, f, xlog=False, ylog=False, show=False, xtitle="Photon energy [eV]", ytitle="Flux [Photons/s/0.1%bw]", title="Flux") plot(e, w, xlog=False, ylog=False, show=False, xtitle="Photon energy [eV]", ytitle="Spectral Power [W/eV]", title="Spectral Power") # # end script # return e, w