Exemplo n.º 1
0
    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
Exemplo n.º 2
0
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))
Exemplo n.º 3
0
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
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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
Exemplo n.º 6
0
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")
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
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
Exemplo n.º 10
0
    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":
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
    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)
Exemplo n.º 13
0
    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)
Exemplo n.º 14
0
    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)