SRW Simulations#
This section is based on the TES and ARI beamline examples.
Hint: See the List of predefined simulations in Sirepo for examples of identifiers for different beamlines.
Run “Beamline” SRW simulations#
In this example, we scan the horizontal size of the aperture and collect the resulting averaged intensities and corresponding 2D intensity distributions from the “Watchpoint” report on the “Beamline” page of the Sirepo/SRW app.
Start ipython
and run the following where sim_id
is the UID for the simulation we are working with:
[1]:
from sirepo_bluesky import prepare_re_env
%run -i $prepare_re_env.__file__
from sirepo_bluesky.sirepo_bluesky import SirepoBluesky
from sirepo_bluesky.sirepo_ophyd import create_classes
connection = SirepoBluesky("http://localhost:8000")
data, schema = connection.auth("srw", sim_id="00000002")
classes, objects = create_classes(connection=connection)
globals().update(**objects)
aperture.horizontalSize.kind = "hinted"
w9.duration.kind = "hinted"
(uid,) = RE(bp.scan([w9], aperture.horizontalSize, 0, 2, 6))
hdr = db[uid]
tbl = hdr.table(fill=True)
print(tbl)
w9_image = np.array(list(hdr.data("w9_image")))
Transient Scan ID: 1 Time: 2023-08-19 16:57:34
Persistent Unique Scan ID: '6126f53f-40fc-49e4-9fa7-c3621d03e520'
New stream: 'primary'
+-----------+------------+-------------------------+-------------+------------+
| seq_num | time | aperture_horizontalSize | w9_duration | w9_flux |
+-----------+------------+-------------------------+-------------+------------+
| 1 | 16:58:03.0 | 0.000 | 28.225 | 0.000 |
| 2 | 16:58:30.5 | 0.400 | 27.304 | 18526369890570088.000 |
| 3 | 16:58:58.0 | 0.800 | 27.310 | 875180761407870848.000 |
| 4 | 16:59:25.5 | 1.200 | 27.312 | 2835215383578687488.000 |
| 5 | 16:59:53.1 | 1.600 | 27.319 | 6790620360429310976.000 |
| 6 | 17:00:20.6 | 2.000 | 27.397 | 13986015521742526464.000 |
+-----------+------------+-------------------------+-------------+------------+
generator scan ['6126f53f'] (scan num: 1)
time aperture_horizontalSize \
seq_num
1 2023-08-19 16:58:03.096503496 0.0
2 2023-08-19 16:58:30.599914789 0.4
3 2023-08-19 16:58:58.099466085 0.8
4 2023-08-19 16:59:25.595795631 1.2
5 2023-08-19 16:59:53.104821920 1.6
6 2023-08-19 17:00:20.696308136 2.0
w9_sirepo_data_json \
seq_num
1 {"models": {"arbitraryMagField": {"interpolati...
2 {"models": {"arbitraryMagField": {"interpolati...
3 {"models": {"arbitraryMagField": {"interpolati...
4 {"models": {"arbitraryMagField": {"interpolati...
5 {"models": {"arbitraryMagField": {"interpolati...
6 {"models": {"arbitraryMagField": {"interpolati...
w9_sirepo_data_hash w9_duration \
seq_num
1 047eb85878c27c3165864c4e7fc180d5b399dbbd0e8801... 28.224578
2 89764dace87dcc26f52d9089cd083808d4ce01101cdd2e... 27.304115
3 1256afb97668467b0ff356a3135da3a54769bc0722bf06... 27.309898
4 27a64c6a971fa63b9d8225532d332e9f5dc81fc98b5492... 27.312175
5 5c33991278d7a36bc54609343da1932d9b68ac08fbcb2d... 27.319178
6 180a2a6153d01ecbb4d9d805a86a02d2fa5b0c1ca5df82... 27.396652
w9_image w9_shape \
seq_num
1 [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... [42, 960]
2 [[88.9896469116211, 90.30567169189453, 89.9160... [42, 960]
3 [[259953.59375, 261614.125, 263485.9375, 26631... [42, 960]
4 [[9238843.0, 9838710.0, 9552324.0, 9303515.0, ... [42, 960]
5 [[68400960.0, 68992840.0, 69654168.0, 70279808... [42, 960]
6 [[980697920.0, 1007002496.0, 1032909120.0, 103... [42, 960]
w9_flux w9_mean w9_x w9_y w9_fwhm_x \
seq_num
1 0.000000e+00 0.000000e+00 NaN NaN NaN
2 1.852637e+16 4.594834e+11 -9.046412e-07 2.967016e-07 0.000001
3 8.751808e+17 2.170587e+13 -2.024554e-07 2.583469e-07 0.000001
4 2.835215e+18 7.031784e+13 1.189526e-08 2.134382e-07 0.000002
5 6.790620e+18 1.684182e+14 2.282297e-08 1.655073e-07 0.000002
6 1.398602e+19 3.468754e+14 1.569344e-08 1.041249e-07 0.000002
w9_fwhm_y w9_photon_energy \
seq_num
1 NaN 2500.0
2 0.000010 2500.0
3 0.000010 2500.0
4 0.000009 2500.0
5 0.000008 2500.0
6 0.000008 2500.0
w9_horizontal_extent \
seq_num
1 [-2.1254114436366436e-06, -9.098470371627117e-07]
2 [-0.0003455044933673651, 0.00034048111593430996]
3 [-9.497909538938273e-05, 9.223270409422599e-05]
4 [-4.719082396641057e-05, 4.4254846231433526e-05]
5 [-2.815987725485224e-05, 2.514591016781304e-05]
6 [-1.880166558286725e-05, 1.5761422775379623e-05]
w9_vertical_extent w9_id w9_title \
seq_num
1 [-6.735306985152392e-07, 6.90416995865796e-07] 15.0 W9
2 [-1.7898270041274756e-05, 1.7460512118472577e-05] 15.0 W9
3 [-1.788263286486139e-05, 1.744525739789714e-05] 15.0 W9
4 [-1.737099036964788e-05, 1.6946128712979616e-05] 15.0 W9
5 [-1.6659548548370817e-05, 1.6252087416622406e-05] 15.0 W9
6 [-1.556055992165305e-05, 1.517997797863667e-05] 15.0 W9
w9_type w9_element_position
seq_num
1 watch 57.142
2 watch 57.142
3 watch 57.142
4 watch 57.142
5 watch 57.142
6 watch 57.142
[2]:
from mpl_toolkits.axes_grid1 import ImageGrid
print(f"Data shape: {w9_image.shape}")
num_frames = w9_image.shape[0]
ncols = 2
nrows = int(np.ceil(num_frames / ncols))
fig = plt.figure()
grid = ImageGrid(
fig,
(1, 2, ncols, nrows),
nrows_ncols=(nrows, ncols),
axes_pad=0.5,
aspect=False,
)
for ax, im in zip(grid, w9_image[:, ...]):
ax.imshow(im, aspect="auto")
Data shape: (6, 42, 960)
SRW Propagation as Ophyd Objects#
This example repeats the above simulation in “Optical Elements as Ophyd Objects”, but instead scans the horizontal and vertical resolution modification factors of the “Final Post Propagation” on the “Beamline” page of the Sirepo/SRW app.
Hint: See the “SRW Propagation Parameters” wiki page for a list of available propagation parameters.
[3]:
from sirepo_bluesky import prepare_re_env
%run -i $prepare_re_env.__file__
from sirepo_bluesky.sirepo_bluesky import SirepoBluesky
from sirepo_bluesky.sirepo_ophyd import create_classes
connection = SirepoBluesky("http://localhost:8000")
data, schema = connection.auth("srw", sim_id="00000002")
classes, objects = create_classes(connection=connection)
globals().update(**objects)
post_propagation.hres_mod.kind = "hinted"
post_propagation.vres_mod.kind = "hinted"
w9.duration.kind = "hinted"
(uid,) = RE(
bp.list_scan(
[w9],
post_propagation.hres_mod,
[0.1, 0.25, 0.5, 1, 2, 5],
post_propagation.vres_mod,
[0.1, 0.25, 0.5, 1, 2, 5],
)
)
hdr = db[uid]
tbl = hdr.table(fill=True)
print(tbl)
w9_image = []
for im in list(hdr.data("w9_image")):
w9_image.append(im)
Transient Scan ID: 1 Time: 2023-08-19 17:00:23
Persistent Unique Scan ID: 'eea68bd8-ccfa-4974-be88-8662e0ff8a94'
New stream: 'primary'
+-----------+------------+---------------------------+---------------------------+-------------+------------+
| seq_num | time | post_propagation_hres_mod | post_propagation_vres_mod | w9_duration | w9_flux |
+-----------+------------+---------------------------+---------------------------+-------------+------------+
| 1 | 17:00:50.1 | 0.100 | 0.100 | 26.304 | 1073586585333243904.000 |
| 2 | 17:01:17.5 | 0.250 | 0.250 | 27.308 | 9175272414847424512.000 |
| 3 | 17:01:44.0 | 0.500 | 0.500 | 26.324 | 34882168960161890304.000 |
| 4 | 17:02:11.6 | 1.000 | 1.000 | 27.366 | 135695489249894498304.000 |
| 5 | 17:02:39.6 | 2.000 | 2.000 | 27.651 | 548121885006057046016.000 |
| 6 | 17:03:12.8 | 5.000 | 5.000 | 31.660 | 3411478534323461160960.000 |
+-----------+------------+---------------------------+---------------------------+-------------+------------+
generator list_scan ['eea68bd8'] (scan num: 1)
time \
seq_num
1 2023-08-19 17:00:50.134056330
2 2023-08-19 17:01:17.594286442
3 2023-08-19 17:01:44.090910196
4 2023-08-19 17:02:11.650974751
5 2023-08-19 17:02:39.667309046
6 2023-08-19 17:03:12.854381323
w9_sirepo_data_json \
seq_num
1 {"models": {"arbitraryMagField": {"interpolati...
2 {"models": {"arbitraryMagField": {"interpolati...
3 {"models": {"arbitraryMagField": {"interpolati...
4 {"models": {"arbitraryMagField": {"interpolati...
5 {"models": {"arbitraryMagField": {"interpolati...
6 {"models": {"arbitraryMagField": {"interpolati...
w9_sirepo_data_hash w9_duration \
seq_num
1 444ff37a841f1eae5e760102e175dc700123f10466d9ab... 26.304120
2 ea9b1201ec7bfbd1b4b2e9bd5f9f6c3631ad953c85aebf... 27.307690
3 0fb266f27def0adc59d1ad4610be25219edb661bb6823e... 26.323790
4 5f0866aa47391d345216aa6c4506ebe7de5b1fec2c1a3a... 27.365714
5 f796c332c8b40b67dcd40751ed332ad7ec6499b3f78055... 27.651106
6 ec7b6a8487eabe1007b13f10d6bafe21a5b4a5a42b4db4... 31.659634
w9_image w9_shape \
seq_num
1 [[1721896192.0, 2558392064.0, 4199006208.0, 76... [4, 96]
2 [[1721896192.0, 2017554816.0, 2349399808.0, 28... [12, 240]
3 [[1721896192.0, 1859565440.0, 2017218560.0, 21... [22, 480]
4 [[1729820288.0, 1829252736.0, 1847327872.0, 19... [42, 960]
5 [[1721896192.0, 1753946112.0, 1798868992.0, 18... [84, 1920]
6 [[1721896192.0, 1734087168.0, 1747285888.0, 17... [210, 4752]
w9_flux w9_mean w9_x w9_y ... \
seq_num ...
1 1.073587e+18 2.795798e+15 1.000970e-08 1.216330e-06 ...
2 9.175272e+18 3.185858e+15 3.416623e-08 9.122925e-07 ...
3 3.488217e+19 3.303236e+15 3.608676e-08 8.955650e-07 ...
4 1.356955e+20 3.365464e+15 3.642247e-08 8.798182e-07 ...
5 5.481219e+20 3.398573e+15 3.638440e-08 8.797063e-07 ...
6 3.411479e+21 3.418589e+15 3.638517e-08 8.763118e-07 ...
w9_fwhm_y w9_photon_energy \
seq_num
1 0.000002 2500.0
2 0.000003 2500.0
3 0.000002 2500.0
4 0.000002 2500.0
5 0.000002 2500.0
6 0.000002 2500.0
w9_horizontal_extent \
seq_num
1 [-1.539735979953162e-05, 1.2266423752247285e-05]
2 [-1.539735979953162e-05, 1.2266423752247285e-05]
3 [-1.539735979953162e-05, 1.2266423752247285e-05]
4 [-1.552692914676393e-05, 1.2395993099479593e-05]
5 [-1.539735979953162e-05, 1.2266423752247285e-05]
6 [-1.539735979953162e-05, 1.2266423752247285e-05]
w9_vertical_extent w9_id w9_title \
seq_num
1 [-3.1233386249489396e-06, 3.200689687176562e-06] 15.0 W9
2 [-3.1233386249489396e-06, 3.200689687176561e-06] 15.0 W9
3 [-3.1233386249489396e-06, 3.200689687176562e-06] 15.0 W9
4 [-3.0852420688517978e-06, 3.16259313107942e-06] 15.0 W9
5 [-3.1233386249489396e-06, 3.200689687176562e-06] 15.0 W9
6 [-3.1233386249489396e-06, 3.200689687176562e-06] 15.0 W9
w9_type w9_element_position post_propagation_hres_mod \
seq_num
1 watch 57.142 0.10
2 watch 57.142 0.25
3 watch 57.142 0.50
4 watch 57.142 1.00
5 watch 57.142 2.00
6 watch 57.142 5.00
post_propagation_vres_mod
seq_num
1 0.10
2 0.25
3 0.50
4 1.00
5 2.00
6 5.00
[6 rows x 21 columns]
[4]:
from mpl_toolkits.axes_grid1 import ImageGrid
num_frames = len(w9_image)
ncols = 2
nrows = int(np.ceil(num_frames / ncols))
fig = plt.figure()
grid = ImageGrid(
fig,
(1, 2, ncols, nrows),
nrows_ncols=(nrows, ncols),
axes_pad=0.5,
aspect=False,
)
for ax, im in zip(grid, w9_image):
h_dims = 1e6 * w9.horizontal_extent.get()
v_dims = 1e6 * w9.vertical_extent.get()
ax.imshow(
im, interpolation="nearest", aspect="auto", extent=(*h_dims[:], *v_dims[:])
)
Using Run Engine to Generate Spectrum Reports#
In this example, we scan the vertical amplitude of the undulator’s magnetic field and collect the “Single Electron Spectrum” report from the “Beamline” page of the Sirepo/SRW app. Afterwards, we plot the peaks of the spectra. This section is based on the ARI beamline example.
Hint: See the List of predefined simulations in Sirepo for examples of identifiers for different beamlines.
[5]:
from sirepo_bluesky import prepare_re_env
%run -i $prepare_re_env.__file__
from sirepo_bluesky.sirepo_bluesky import SirepoBluesky
from sirepo_bluesky.sirepo_ophyd import create_classes
connection = SirepoBluesky("http://localhost:8000")
data, schema = connection.auth("srw", sim_id="00000003")
classes, objects = create_classes(
connection=connection, extra_model_fields=["undulator", "intensityReport"]
)
globals().update(**objects)
undulator.verticalAmplitude.kind = "hinted"
single_electron_spectrum.duration.kind = "hinted"
single_electron_spectrum.flux.kind = "hinted"
single_electron_spectrum.initialEnergy.get()
single_electron_spectrum.initialEnergy.put(20)
single_electron_spectrum.finalEnergy.put(1100)
num_steps = 6
(uid,) = RE(
bp.scan(
[single_electron_spectrum],
undulator.verticalAmplitude,
0.2,
1.2,
num_steps,
)
)
hdr = db[uid]
tbl = hdr.table()
print(tbl)
ses_data = np.array(list(hdr.data("single_electron_spectrum_image")))
ampl_data = np.array(list(hdr.data("undulator_verticalAmplitude")))
Transient Scan ID: 1 Time: 2023-08-19 17:03:17
Persistent Unique Scan ID: 'f74655bf-9b14-4de9-9c1d-403fc690ed44'
New stream: 'primary'
+-----------+------------+-----------------------------+-----------------------------------+-------------------------------+
| seq_num | time | undulator_verticalAmplitude | single_electron_spectrum_duration | single_electron_spectrum_flux |
+-----------+------------+-----------------------------+-----------------------------------+-------------------------------+
| 1 | 17:03:22.2 | 0.200 | 4.071 | 11582410813310422.000 |
| 2 | 17:03:26.4 | 0.400 | 4.064 | 7511914020931007.000 |
| 3 | 17:03:30.6 | 0.600 | 4.062 | 6133644985399308.000 |
| 4 | 17:03:34.8 | 0.800 | 4.066 | 5528586337089524.000 |
| 5 | 17:03:39.0 | 1.000 | 4.064 | 4389188523218694.000 |
| 6 | 17:03:43.2 | 1.200 | 4.069 | 3839228997372156.500 |
+-----------+------------+-----------------------------+-----------------------------------+-------------------------------+
generator scan ['f74655bf'] (scan num: 1)
time \
seq_num
1 2023-08-19 17:03:22.213392973
2 2023-08-19 17:03:26.425994635
3 2023-08-19 17:03:30.637144804
4 2023-08-19 17:03:34.842891932
5 2023-08-19 17:03:39.060551643
6 2023-08-19 17:03:43.279510736
single_electron_spectrum_sirepo_data_json \
seq_num
1
2
3
4
5
6
single_electron_spectrum_sirepo_data_hash \
seq_num
1
2
3
4
5
6
single_electron_spectrum_duration \
seq_num
1 4.070882
2 4.064391
3 4.062473
4 4.065910
5 4.063592
6 4.068893
single_electron_spectrum_image \
seq_num
1 5fc1661d-78a2-4498-b84f-585d2981c0e3/0
2 19b5a36a-6f35-4587-80a8-44bb085aded4/0
3 d4e2da0a-b428-4c7e-a74e-15dc78661724/0
4 1ef5f3d1-e060-435b-a46f-5fd31065f8ad/0
5 e994ebd9-8ea0-4eff-9ef4-cb6351b775c8/0
6 02208608-2269-4da4-a88d-6e5af0d41f02/0
single_electron_spectrum_shape single_electron_spectrum_flux \
seq_num
1 [2000] 1.158241e+16
2 [2000] 7.511914e+15
3 [2000] 6.133645e+15
4 [2000] 5.528586e+15
5 [2000] 4.389189e+15
6 [2000] 3.839229e+15
single_electron_spectrum_mean single_electron_spectrum_x \
seq_num
1 5.791205e+12 NaN
2 3.755957e+12 NaN
3 3.066822e+12 NaN
4 2.764293e+12 NaN
5 2.194594e+12 NaN
6 1.919614e+12 NaN
single_electron_spectrum_y ... single_electron_spectrum_method \
seq_num ...
1 NaN ... 1
2 NaN ... 1
3 NaN ... 1
4 NaN ... 1
5 NaN ... 1
6 NaN ... 1
single_electron_spectrum_notes \
seq_num
1
2
3
4
5
6
single_electron_spectrum_photonEnergyPointCount \
seq_num
1 2000.0
2 2000.0
3 2000.0
4 2000.0
5 2000.0
6 2000.0
single_electron_spectrum_plotScale \
seq_num
1 linear
2 linear
3 linear
4 linear
5 linear
6 linear
single_electron_spectrum_polarization \
seq_num
1 6.0
2 6.0
3 6.0
4 6.0
5 6.0
6 6.0
single_electron_spectrum_precision \
seq_num
1 0.01
2 0.01
3 0.01
4 0.01
5 0.01
6 0.01
single_electron_spectrum_verticalPosition \
seq_num
1 0.0
2 0.0
3 0.0
4 0.0
5 0.0
6 0.0
single_electron_spectrum_title single_electron_spectrum_type \
seq_num
1 SingleElectronSpectrum intensityReport
2 SingleElectronSpectrum intensityReport
3 SingleElectronSpectrum intensityReport
4 SingleElectronSpectrum intensityReport
5 SingleElectronSpectrum intensityReport
6 SingleElectronSpectrum intensityReport
undulator_verticalAmplitude
seq_num
1 0.2
2 0.4
3 0.6
4 0.8
5 1.0
6 1.2
[6 rows x 31 columns]
[6]:
import peakutils
from mpl_toolkits.axes_grid1 import ImageGrid
ncols = 2
nrows = int(np.ceil((num_steps) / ncols))
fig = plt.figure()
grid = ImageGrid(
fig,
(1, 2, ncols, nrows),
nrows_ncols=(nrows, ncols),
axes_pad=0.5,
aspect=False,
)
for i in range(num_steps):
ax = grid[i]
ax.grid(True)
ax.plot(ses_data[i, :])
peak = peakutils.indexes(ses_data[i, :], thres=0.07)
ax.scatter(peak, ses_data[i, peak], c="orange")
ax.set_xlabel("Photon energy [eV]")
ax.set_ylabel("Intensity [Sirepo units]")
ax.set_title(
f"Single-Electron Spectrum at Vertical Magnetic Field = {ampl_data[i]:.1f}T"
)
plt.figure()
plt.xlabel("Photon energy [eV]")
plt.ylabel("Frame number")
plt.imshow(ses_data, aspect="auto")
[6]:
<matplotlib.image.AxesImage at 0x7fad67f8b160>