def get_fwhm(self): sig_x, sig_y = calculate_fwhm(self)['fwhm_x'], calculate_fwhm( self)['fwhm_y'] self.custom_fields['fwhm'] = sig_x, sig_y return sig_x, sig_y
def simpleProp(wfr): print(calculate_fwhm(wfr)) bl = Beamline() #bl.append(Aperture('c','a', 500e-06),propagation_parameters(1,1,1,1,mode = 'normal')) bl.append(Drift(100), propagation_parameters(1,1,1,1,mode = 'quadratic')) #bl.append(Drift(100), propagation_parameters(1,1,1,1,mode = 'quadratic')) bl.propagate(wfr) plotIntensity(wfr) print(calculate_fwhm(wfr))
def storeWavefrontInfo(wfr): sz0 = get_axial_power_density(wfr, spectrum = False) sz1 = get_axial_power_density(wfr, spectrum = True) fwhm = calculate_fwhm(wfr) srwlib.srwl.SetRepresElecField(wfr._srwl_wf, 't') pulseEn, photons_per_pulse = calc_pulse_energy(wfr) srwlib.srwl.SetRepresElecField(wfr._srwl_wf, 'f') divergence = wfr.get_divergence() wfr.custom_fields['/source/t_spectrum'] = sz0 wfr.custom_fields['/source/f_spectrum'] = sz1 wfr.custom_fields['/source/xFWHM'] = fwhm['fwhm_x'] wfr.custom_fields['/source/yFWHM'] = fwhm['fwhm_y'] wfr.custom_fields['/source/divX'] = divergence[0] wfr.custom_fields['/source/divX'] = divergence[1] wfr.custom_fields['/source/pulseEn'] = pulseEn wfr.custom_fields['/source/nPhotons'] = photons_per_pulse
def get_divergence(self): """ calculate the full-angle divergence of the beam :param wfr: WPG wavefront structure """ self.set_electric_field_representation('a') sig_x, sig_y = calculate_fwhm(self)['fwhm_x'], calculate_fwhm( self)['fwhm_y'] self.set_electric_field_representation('c') self.custom_fields['divergence'] = sig_x, sig_y return sig_x, sig_y
def get_divergence(self): """ calculate the full-angle divergence of the beam :param wfr: WPG wavefront structure """ wDomain = self.params.wDomain self.set_electric_field_representation('a') sig_x, sig_y = calculate_fwhm(self)['fwhm_x'], calculate_fwhm( self)['fwhm_y'] self.set_electric_field_representation(wDomain) return sig_x, sig_y
def comparePulses(wfr, cwfr, savedir): print("Intial Incoherent Integrated Intensity: {} W/mm^2".format(wfr.initial_intensity)) print("Coherent Integrated Intensity: {} W/mm^2".format(cwfr.initial_intensity)) print("Final Incoherent Integrated Intensity: {} W/mm^2".format(wfr.final_intensity)) print("Final Coherent Integrated Intensity: {} W/mm^2".format(cwfr.final_intensity)) print("Incoherent System Efficiency: {}".format((wfr.final_intensity)/wfr.initial_intensity)) print("Coherent System Efficiency: {}".format((cwfr.final_intensity)/cwfr.initial_intensity)) fwhm_x, fwhm_y = calculate_fwhm(wfr)['fwhm_x'], calculate_fwhm(wfr)['fwhm_y'] cfwhm_x, cfwhm_y = calculate_fwhm(cwfr)['fwhm_x'], calculate_fwhm(cwfr)['fwhm_y'] print("Incoherent Focal FWHM-x: {} um".format(fwhm_x*1e6)) print("Incoherent Focal FWHM-y: {} um".format(fwhm_y*1e6)) print("Coherent Focal FWHM-x: {} um".format(cfwhm_x*1e6)) print("coherent Focal FWHM-y: {} um".format(cfwhm_y*1e6)) ### store pulses wfr.store_hdf5(savedir + "pulse.hdf5") cwfr.store_hdf5(savedir + "gaussian.hdf5")
def test_coherent_pulse_fwhm(E, sdir=None): """ Test that the FWHM of the source matches the analytical prediction :param E: list/array of energies [keV] :param sdir: output directory [str] """ print("Testing Source Size vs. Energy and Resolution") sns.set() fig = plt.figure(figsize=[12, 8]) ax = fig.add_subplot(111) ax.set_title("Source Size Radiation Dependence", fontsize=22) ax.set_ylabel("FWHM [$\mu$m]", fontsize=22) ax.set_xlabel("Radiation Energy [keV]", fontsize=22) ax.set_xlim([2.5, 17.5]) ax.set_ylim([0, 55]) E analytical_data = np.array([analytical_pulse_width(a) * 1e6 for a in E]) fwhms = [] for energy in E: wfr = construct_SA1_wavefront(nx=1024, ny=1024, ekev=energy, q=0.25) fwhms.append(calculate_fwhm(wfr)['fwhm_x'] * 1e6) simulation, = ax.plot(E, fwhms, 'r') analytical, = ax.plot(E, analytical_data, '--b') leg1 = ax.legend([simulation, analytical], ["Simulated Data", "Analytical Model"], loc='lower left', fontsize=22) ax.add_artist(leg1) ax.tick_params(axis='both', which='major', labelsize=18) ax.tick_params(axis='both', which='minor', labelsize=14) if sdir is not None: fig.savefig(sdir + "coherent_source_test_fwhm.eps") plt.show() return wfr
def main(wpg_out): # Backup backup = wpg_out + ".backup" shutil.copy2(wpg_out, backup) print("Processing %s." % (wpg_out)) # Load wavefront. wavefront = Wavefront() wavefront.load_hdf5(wpg_out) # Get width from intensity profile. fwhm = wpg_uti_wf.calculate_fwhm(wavefront) # Carefully insert new datasets. try: with h5py.File(wpg_out, 'a') as h5_handle: if not 'misc' in h5_handle.keys(): misc = h5_handle.create_group("misc") else: misc = h5_handle['misc'] if not "xFWHM" in misc.keys(): misc.create_dataset("xFWHM", data=fwhm["fwhm_x"]) if not "yFWHM" in misc.keys(): misc.create_dataset("yFWHM", data=fwhm["fwhm_y"]) # If anything went wrong, restore the original file and raise. except: shutil.move(backup, wpg_out) raise # We only reach this point if everything went well, so can safely remove the backup." os.remove(backup)
def propToBeamParameters(prop_output_path): """ Utility to setup a PhotonBeamParameters instance from propagation output. """ # Check prop out exists. if not os.path.isfile(prop_output_path): raise IOError("File not found: %s." % (prop_output_path)) # Construct the wavefront. wavefront = Wavefront() wavefront.load_hdf5(prop_output_path) pulse_energy = wpg_uti_wf.calc_pulse_energy(wavefront) mesh = wavefront.params.Mesh dx = (mesh.xMax - mesh.xMin) / (mesh.nx - 1) dy = (mesh.yMax - mesh.yMin) / (mesh.ny - 1) int0 = wavefront.get_intensity().sum(axis=0).sum(axis=0) # I(slice_num) total_intensity = int0 * dx * dy # [J] times = numpy.linspace(mesh.sliceMin, mesh.sliceMax, mesh.nSlices) t = times[:-1] dt = times[1:] - times[:-1] It = total_intensity[:-1] m0 = numpy.sum(It * dt) m1 = numpy.sum(It * t * dt) / m0 m2 = numpy.sum(It * t**2 * dt) / m0 rms = math.sqrt(m2 - m1**2) spike_fwhm_J = constants.hbar / rms spike_fwhm_eV = spike_fwhm_J / constants.e # Switch to energy domain srwl.SetRepresElecField(wavefront._srwl_wf, 'f') mesh = wavefront.params.Mesh spectrum = wavefront.get_intensity().sum(axis=0).sum( axis=0) # I(slice_num) energies = numpy.linspace(mesh.sliceMin, mesh.sliceMax, mesh.nSlices) w = energies[:-1] dw = energies[1:] - energies[:-1] Iw = spectrum[:-1] m0 = numpy.sum(Iw * dw) m1 = numpy.sum(Iw * w * dw) / m0 m2 = numpy.sum(Iw * w**2 * dw) / m0 rms = math.sqrt(m2 - m1**2) photon_energy = m1 #spec_fwhm_eV = rms # Extract beam diameter fwhm xy_fwhm = wpg_uti_wf.calculate_fwhm(wavefront) # Extract divergence # Switch to reciprocal space srwl.SetRepresElecField(wavefront._srwl_wf, 'a') qxqy_fwhm = wpg_uti_wf.calculate_fwhm(wavefront) del wavefront beam_parameters = PhotonBeamParameters( photon_energy=photon_energy * electronvolt, photon_energy_relative_bandwidth=spike_fwhm_eV / photon_energy, pulse_energy=pulse_energy * joule, divergence=max([qxqy_fwhm['fwhm_x'], qxqy_fwhm['fwhm_y']]) / 2. * radian, beam_diameter_fwhm=max([xy_fwhm['fwhm_x'], xy_fwhm['fwhm_y']]) * meter, photon_energy_spectrum_type="SASE", ) return beam_parameters
spb = Instrument(overwrite_mirrors = True) spb.setupHOMs(ekev, 2.2e-03) spb.setupKBs(ekev, 3.5e-03) spb.build_elements(focus = focus) <<<<<<< HEAD spb.build_beamline(focus = focus) ======= spb.buildBeamline(focus = focus) >>>>>>> 108cfb9b6fc97d3841ee1db54862523eee5b184e bl = spb.get_beamline() bl.propagate(wfr) meas = calculate_fwhm(wfr) fwhm_x = meas['fwhm_x'] fwhm_y = meas['fwhm_y'] return fwhm_x, fwhm_y def plot(energyrange, data, estr, qstr, focus, outdir = "../../tmp/"): fig = plt.figure() ax = fig.add_subplot(111) if focus == "micron": focstr = "Micron-KB " elif focus == "nano":
def testGaussianReference(self, debug=False): """ Check that propagation of a Gaussian pulse (in t,x,y) through vacuum reproduces reference data. """ # Central photon energy. ekev = 8.4 # Energy [keV] # Pulse parameters. qnC = 0.5 # e-bunch charge, [nC] pulse_duration = 9.0e-15 # [s] pulseEnergy = 1.5e-3 # total pulse energy, J # Coherence time coh_time = 0.25e-15 # [s] # Distance in free space. z0 = 10. # (m), position where to build the wavefront. z1 = 10. # (m), distance to travel in free space. # Beam divergence. theta_fwhm = 2.5e-6 # rad wlambda = 12.4*1e-10/ekev # wavelength, m w0 = wlambda/(numpy.pi*theta_fwhm) # beam waist, m zR = (math.pi*w0**2)/wlambda #Rayleigh range, m fwhm_at_zR = theta_fwhm*zR #FWHM at Rayleigh range, m sigmaAmp = w0/(2.0*math.sqrt(math.log(2.0))) #sigma of amplitude, m if debug: print (" *** Pulse properties ***") print (" lambda = %4.3e m" % (wlambda) ) print (" w0 = %4.3e m" % (w0) ) print (" zR = %4.3e m" % (zR) ) print (" fwhm at zR = %4.3e m" % (fwhm_at_zR) ) print (" sigma = %4.3e m" % (sigmaAmp) ) # expected beam radius after free space drift. expected_beam_radius = w0*math.sqrt(1.0+(z0/zR)**2) # Number of points in each x and y dimension. np=400 # Sampling window = 6 sigma of initial beam. range_xy = 6.*expected_beam_radius dx = range_xy / (np-1) nslices = 20 if debug: print (" Expected beam waist at z=%4.3f m : %4.3e m." % (z0, expected_beam_radius) ) print ("Setting up mesh of %d points per dimension on a %4.3e x %4.3e m^2 grid with grid spacing %4.3e m." % (np, range_xy, range_xy, dx) ) # Construct srw wavefront. srwl_wf = build_gauss_wavefront(np, np, nslices, ekev, -range_xy/2., range_xy/2., -range_xy/2., range_xy/2., coh_time/math.sqrt(2.), sigmaAmp, sigmaAmp, z0, pulseEn=pulseEnergy, pulseRange=8.) # Convert to wpg. wf = Wavefront(srwl_wf) if debug: print('*** z=%4.3e m ***' % (z0)) fwhm = calculate_fwhm(wf) print('fwhm_x = %4.3e\nfwhm_y = %4.3e' % (fwhm['fwhm_x'], fwhm['fwhm_y']) ) plot_t_wf(wf) look_at_q_space(wf) # Construct the beamline. beamline = Beamline() # Add free space drift. drift = Drift(z1) beamline.append( drift, Use_PP(semi_analytical_treatment=1)) # Propagate srwl.SetRepresElecField(wf._srwl_wf, 'f') # <---- switch to frequency domain beamline.propagate(wf) srwl.SetRepresElecField(wf._srwl_wf, 't') if debug: print('*** z=%4.3e m ***' % (z0+z1)) fwhm = calculate_fwhm(wf) print('fwhm_x = %4.3e\nfwhm_y = %4.3e' % (fwhm['fwhm_x'], fwhm['fwhm_y']) ) plot_t_wf(wf) look_at_q_space(wf) # Get propagated wavefront data. wf_intensity = wf.get_intensity() # Project on t axis. wf_onaxis = wf_intensity.sum(axis=(0,1)) # Get hash of the data. wf_hash = hash( wf_intensity.tostring() ) # Load reference hash. with open(TestUtilities.generateTestFilePath("reference_wf_gauss_10m.hash.txt"), 'r') as hashfile: ref_hash = hashfile.readline() hashfile.close() ref_onaxis = numpy.loadtxt(TestUtilities.generateTestFilePath("reference_wf_gauss_onaxis_10m.txt")) # Weak test. for x,y in zip(wf_onaxis, ref_onaxis): self.assertAlmostEqual( x, y, 14 ) # Strong test. self.assertEqual( str(wf_hash), ref_hash)
def testGaussianVsAnalytic(self, debug=False): """ Check that propagation of a Gaussian pulse (in t,x,y) through vacuum gives the correct result, compare to analytic solution. """ # Central photon energy. ekev = 8.4 # Energy [keV] # Pulse parameters. qnC = 0.5 # e-bunch charge, [nC] pulse_duration = 9.0e-15 # [s] pulseEnergy = 1.5e-3 # total pulse energy, J # Coherence time coh_time = 0.25e-15 # [s] # Distance in free space. z0 = 10. # (m), position where to build the wavefront. z1 = 20. # (m), distance to travel in free space. z2 = z0 + z1 # distance where to build the reference wavefront. # Beam divergence. theta_fwhm = 2.5e-6 # rad wlambda = 12.4*1e-10/ekev # wavelength, m w0 = wlambda/(numpy.pi*theta_fwhm) # beam waist, m zR = (math.pi*w0**2)/wlambda #Rayleigh range, m fwhm_at_zR = theta_fwhm*zR #FWHM at Rayleigh range, m sigmaAmp = w0/(2.0*math.sqrt(math.log(2.0))) #sigma of amplitude, m if debug: print (" *** Pulse properties ***") print (" lambda = %4.3e m" % (wlambda) ) print (" w0 = %4.3e m" % (w0) ) print (" zR = %4.3e m" % (zR) ) print (" fwhm at zR = %4.3e m" % (fwhm_at_zR) ) print (" sigma = %4.3e m" % (sigmaAmp) ) # expected beam radius after free space drift. expected_beam_radius = w0*math.sqrt(1.0+(z0/zR)**2) # Number of points in each x and y dimension. np=600 # Sampling window = 6 sigma of initial beam. range_xy = 6.*expected_beam_radius dx = range_xy / (np-1) nslices = 20 #if debug: #print (" Expected beam waist at z=%4.3f m : %4.3e m." % (z0, expected_beam_radius) ) #print ("Setting up mesh of %d points per dimension on a %4.3e x %4.3e m^2 grid with grid spacing %4.3e m." % (np, range_xy, range_xy, dx) ) # Construct srw wavefront. srwl_wf = build_gauss_wavefront(np, np, nslices, ekev, -range_xy/2., range_xy/2., -range_xy/2., range_xy/2., coh_time/math.sqrt(2.), sigmaAmp, sigmaAmp, z0, pulseEn=pulseEnergy, pulseRange=8.) # Convert to wpg. wf = Wavefront(srwl_wf) # Construct reference srw wavefront. reference_srwl_wf = build_gauss_wavefront(np, np, nslices, ekev, -1.5*range_xy/2., 1.5*range_xy/2., -1.5*range_xy/2., 1.5*range_xy/2., coh_time/math.sqrt(2.), sigmaAmp, sigmaAmp, z2, pulseEn=pulseEnergy, pulseRange=8.) reference_wf = Wavefront(reference_srwl_wf) if debug: print('*** z=%4.3e m ***' % (z0)) fwhm = calculate_fwhm(wf) print('wf:\nfwhm_x = %4.3e\nfwhm_y = %4.3e' % (fwhm['fwhm_x'], fwhm['fwhm_y']) ) plot_t_wf(wf) #look_at_q_space(wf) # Construct the beamline. beamline = Beamline() # Add free space drift. drift = Drift(z1) beamline.append( drift, Use_PP(semi_analytical_treatment=0, zoom=2.0, sampling=0.5)) # Propagate srwl.SetRepresElecField(wf._srwl_wf, 'f') beamline.propagate(wf) srwl.SetRepresElecField(wf._srwl_wf, 't') fwhm = calculate_fwhm(wf) reference_fwhm = calculate_fwhm(reference_wf) if debug: print('*** z=%4.3e m ***' % (z0+z1)) print('wf :\nfwhm_x = %4.3e\nfwhm_y = %4.3e' % (fwhm['fwhm_x'], fwhm['fwhm_y']) ) plot_t_wf(wf) print('ref:\nfwhm_x = %4.3e\nfwhm_y = %4.3e' % (reference_fwhm['fwhm_x'], reference_fwhm['fwhm_y']) ) plot_t_wf(reference_wf) #look_at_q_space(wf) # Calculate difference reference_norm = numpy.linalg.norm(numpy.array([reference_fwhm['fwhm_x'], reference_fwhm['fwhm_y']])) difference_norm = numpy.linalg.norm(numpy.array([fwhm['fwhm_x'], fwhm['fwhm_y']]) - numpy.array([reference_fwhm['fwhm_x'], reference_fwhm['fwhm_y']])) if debug: print ("|ref_fwhm_xy| = %4.3e" % (reference_norm) ) print ("|ref_fwhm_xy - fhwm_xy| = %4.3e" % (difference_norm) ) self.assertLess(difference_norm / reference_norm, 0.01)