Example #1
0
    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)
Example #2
0
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
Example #3
0
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
Example #4
0
 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")
Example #5
0
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)
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
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
Example #9
0
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
Example #10
0
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
Example #11
0
    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
Example #12
0
#
# 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
Example #13
0
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