08 external undulator flux table

This example shows how to use an external undulator flux table. The top-level recap file DetectorAtFocus_RawRaysOutgoing.csv contains the geometric results together with the harmonic-resolved flux columns such as PhotonFlux1 and FluxPerMilPerBwAbs1. That recap file is the main result to inspect and plot after the simulation. Outside the tabulated energy window of a harmonic, the harmonic-derived recap columns are written as NaN so the plot can ignore them naturally.

The simulation script:

from raypyng import Simulate
import numpy as np
import os
import pandas as pd


if __name__ == '__main__':
    this_file_dir = os.path.dirname(os.path.realpath(__file__))
    rml_file = os.path.join(this_file_dir, '..', 'rml', 'simple_undulator_beamline.rml')

    sim = Simulate(rml_file, hide=True)
    sim.path = this_file_dir  # write output inside this example's own folder

    rml = sim.rml
    beamline = sim.rml.beamline

    # define the values of the parameters to scan
    energy = np.arange(200, 1800.1, 50)
    SlitSize = np.array([0.1])
    cff = np.array([2.25])
    nrays = 1e5

    params = [
        {beamline.SU.photonEnergy: energy},
        {beamline.ExitSlit.totalHeight: SlitSize},
        {beamline.PG.cFactor: cff},
        {beamline.SU.numberRays: nrays},
    ]

    sim.params = params
    sim.simulation_name = 'external_undulator_flux_table'
    sim.repeat = 4
    sim.analyze = False
    sim.raypyng_analysis = True

    sim.exports = [
        {beamline.SU: ['RawRaysOutgoing']},
        {beamline.DetectorAtFocus: ['RawRaysOutgoing']},
    ]

    undulator_file_path = os.path.join(
        this_file_dir, '..', 'undulator', 'undulator_harmonics_energy_photons.csv'
    )
    sim.undulator_table = pd.read_csv(undulator_file_path)

    sim.run(multiprocessing="auto", force=True)

The eval script:

import os

import matplotlib

matplotlib.use("Agg")

import matplotlib.pyplot as plt  # noqa: E402
import pandas as pd  # noqa: E402


if __name__ == "__main__":
    this_file_dir = os.path.dirname(os.path.realpath(__file__))

    undulator = pd.read_csv(
        os.path.join(
            this_file_dir,
            "..",
            "undulator",
            "undulator_harmonics_energy_photons.csv",
        )
    )
    detector = pd.read_csv(
        os.path.join(
            this_file_dir,
            "RAYPy_Simulation_external_undulator_flux_table",
            "DetectorAtFocus_RawRaysOutgoing.csv",
        )
    ).sort_values("PhotonEnergy")

    fig, axs = plt.subplots(2, 1, figsize=(10, 9), sharex=True)
    xmin = detector["PhotonEnergy"].min()
    xmax = detector["PhotonEnergy"].max()

    axs[0].plot(undulator["Energy1[eV]"], undulator["Photons1"], label="H1")
    axs[0].plot(undulator["Energy3[eV]"], undulator["Photons3"], label="H3")
    axs[0].set(
        ylabel="Photons at source [ph/s/0.1%BW]",
        title="Undulator harmonics from the supplied table",
    )
    axs[0].set_xlim(xmin, xmax)
    axs[0].grid(True, alpha=0.3)
    axs[0].legend()

    axs[1].plot(
        detector["PhotonEnergy"],
        detector["FluxPerMilPerBwAbs1"],
        marker="o",
        label="H1 at DetectorAtFocus",
    )
    axs[1].plot(
        detector["PhotonEnergy"],
        detector["FluxPerMilPerBwAbs3"],
        marker="o",
        label="H3 at DetectorAtFocus",
    )
    axs[1].set(
        xlabel="Photon energy [eV]",
        ylabel="Flux at DetectorAtFocus [ph/s/0.1%BW]",
        title="Beamline result read directly from the recap CSV",
    )
    axs[1].set_xlim(xmin, xmax)
    axs[1].grid(True, alpha=0.3)
    axs[1].legend()

    fig.tight_layout()
    out_png = os.path.join(this_file_dir, "eval_external_undulator_flux_table.png")
    fig.savefig(out_png, dpi=150)
    print("[eval] saved:", out_png)

Result:

external undulator flux table example plot