Basic analysis of PES spectra¶
[1]:
import matplotlib.pyplot as plt
import toolbox_scs as tb
First, we load the raw traces of PES (W and E channels), the pressure and the XGM pulse energy. In this run, 100 pulses per train were recorded.
[2]:
proposal = 2927
runNB = 100
fields = ['PES_W_raw', 'PES_E_raw', 'PES_pressure', 'XTD10_SA3']
run, ds = tb.load(proposal, runNB, fields)
ds
[2]:
<xarray.Dataset> Dimensions: (PESsampleId: 600000, pulse_slot: 2700, sa3_pId: 100, trainId: 4044) Coordinates: * trainId (trainId) uint64 1044495172 1044495174 ... 1044501582 * sa3_pId (sa3_pId) int64 1032 1036 1040 1044 ... 1420 1424 1428 Dimensions without coordinates: PESsampleId, pulse_slot Data variables: bunchPatternTable (trainId, pulse_slot) uint32 2113321 0 2097193 ... 0 0 0 PES_W_raw (trainId, PESsampleId) int16 1 5 -1 2 3 3 ... 4 -1 4 1 4 PES_E_raw (trainId, PESsampleId) int16 -5 -8 -5 -5 ... -5 -3 -7 -3 PES_pressure (trainId) float32 6.28733e-07 ... 6.7894194e-07 XTD10_SA3 (trainId, sa3_pId) float64 2.661e+03 ... 2.11e+03 Attributes: runFolder: /gpfs/exfel/exp/SCS/202121/p002927/raw/r0100
- PESsampleId: 600000
- pulse_slot: 2700
- sa3_pId: 100
- trainId: 4044
- trainId(trainId)uint641044495172 ... 1044501582
array([1044495172, 1044495174, 1044495175, ..., 1044501578, 1044501580, 1044501582], dtype=uint64)
- sa3_pId(sa3_pId)int641032 1036 1040 ... 1420 1424 1428
array([1032, 1036, 1040, 1044, 1048, 1052, 1056, 1060, 1064, 1068, 1072, 1076, 1080, 1084, 1088, 1092, 1096, 1100, 1104, 1108, 1112, 1116, 1120, 1124, 1128, 1132, 1136, 1140, 1144, 1148, 1152, 1156, 1160, 1164, 1168, 1172, 1176, 1180, 1184, 1188, 1192, 1196, 1200, 1204, 1208, 1212, 1216, 1220, 1224, 1228, 1232, 1236, 1240, 1244, 1248, 1252, 1256, 1260, 1264, 1268, 1272, 1276, 1280, 1284, 1288, 1292, 1296, 1300, 1304, 1308, 1312, 1316, 1320, 1324, 1328, 1332, 1336, 1340, 1344, 1348, 1352, 1356, 1360, 1364, 1368, 1372, 1376, 1380, 1384, 1388, 1392, 1396, 1400, 1404, 1408, 1412, 1416, 1420, 1424, 1428])
- bunchPatternTable(trainId, pulse_slot)uint322113321 0 2097193 0 ... 0 0 0 0
array([[2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0], ..., [2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0]], dtype=uint32)
- PES_W_raw(trainId, PESsampleId)int161 5 -1 2 3 3 3 4 ... 4 1 4 -1 4 1 4
array([[ 1, 5, -1, ..., 4, 3, 5], [ 4, 2, 2, ..., 3, 1, 5], [ 1, 2, 2, ..., 2, 1, 3], ..., [ 1, 5, 0, ..., 2, 4, 1], [ 1, 5, -1, ..., 2, 1, 2], [ 2, 3, 1, ..., 4, 1, 4]], dtype=int16)
- PES_E_raw(trainId, PESsampleId)int16-5 -8 -5 -5 -6 ... -3 -5 -3 -7 -3
array([[-5, -8, -5, ..., -3, -2, -6], [-2, -6, -7, ..., -5, -6, -4], [-2, -5, -6, ..., -4, -4, 0], ..., [-4, -6, -8, ..., -5, -6, -4], [-6, -7, -7, ..., -3, -3, -4], [-5, -5, -7, ..., -3, -7, -3]], dtype=int16)
- PES_pressure(trainId)float326.28733e-07 ... 6.7894194e-07
array([6.2873301e-07, 6.2873301e-07, 6.2873301e-07, ..., 6.4182740e-07, 6.7894194e-07, 6.7894194e-07], dtype=float32)
- XTD10_SA3(trainId, sa3_pId)float642.661e+03 2.445e+03 ... 2.11e+03
array([[2661.23291016, 2444.58691406, 2480.74072266, ..., 2380.93359375, 2479.30371094, 2232.07226562], [2404.85668945, 2658.734375 , 2217.1796875 , ..., 2488.41577148, 2629.03076172, 2302.22460938], [2401.78662109, 2247.9284668 , 2280.03271484, ..., 2320.97119141, 2199.11914062, 2297.96264648], ..., [2248.18920898, 2398.20703125, 2354.68212891, ..., 2307.03833008, 2568.10595703, 2465.97509766], [2123.55004883, 2414.68261719, 2608.14404297, ..., 2427.31542969, 2626.33886719, 2505.59179688], [1932.66723633, 1922.01318359, 2103.00415039, ..., 2199.97802734, 2235.63769531, 2109.60400391]])
- runFolder :
- /gpfs/exfel/exp/SCS/202121/p002927/raw/r0100
We can now plot the raw trace for one train:
[3]:
ds.PES_W_raw.isel(trainId=5).plot()
[3]:
[<matplotlib.lines.Line2D at 0x2b786f4696a0>]

Extracting PES spectra from raw traces¶
The function get_pes_tof()
selects the sample intervals containing the spectra, subtracts a baseline, aligns the spectra to the SASE 3 pulse Id and assigns time-of-flight coordinates, based on the digitizer sampling rate. The default parameters start
and width
are usually correct but they may need to be adjusted depending on the signal.
[5]:
pes = tb.get_pes_tof(run, merge_with=ds)
# this is to make sure that the train Ids are well sorted
pes = pes.sortby(pes.trainId)
pes
[5]:
<xarray.Dataset> Dimensions: (pulse_slot: 2700, sa3_pId: 100, time_ns: 300, trainId: 4044) Coordinates: * trainId (trainId) uint64 1044495172 1044495174 ... 1044501582 * sa3_pId (sa3_pId) int64 1032 1036 1040 1044 ... 1420 1424 1428 * time_ns (time_ns) float64 0.0 0.5 1.0 1.5 ... 148.5 149.0 149.5 Dimensions without coordinates: pulse_slot Data variables: bunchPatternTable (trainId, pulse_slot) uint32 2113321 0 2097193 ... 0 0 0 PES_pressure (trainId) float32 6.28733e-07 ... 6.7894194e-07 XTD10_SA3 (trainId, sa3_pId) float64 2.661e+03 ... 2.11e+03 PES_E_tof (sa3_pId, trainId, time_ns) float64 -3.6 -0.6 ... 0.4125 PES_W_tof (sa3_pId, trainId, time_ns) float64 -1.337 ... 0.0375 Attributes: runFolder: /gpfs/exfel/exp/SCS/202121/p002927/raw/r0100
- pulse_slot: 2700
- sa3_pId: 100
- time_ns: 300
- trainId: 4044
- trainId(trainId)uint641044495172 ... 1044501582
array([1044495172, 1044495174, 1044495175, ..., 1044501578, 1044501580, 1044501582], dtype=uint64)
- sa3_pId(sa3_pId)int641032 1036 1040 ... 1420 1424 1428
array([1032, 1036, 1040, 1044, 1048, 1052, 1056, 1060, 1064, 1068, 1072, 1076, 1080, 1084, 1088, 1092, 1096, 1100, 1104, 1108, 1112, 1116, 1120, 1124, 1128, 1132, 1136, 1140, 1144, 1148, 1152, 1156, 1160, 1164, 1168, 1172, 1176, 1180, 1184, 1188, 1192, 1196, 1200, 1204, 1208, 1212, 1216, 1220, 1224, 1228, 1232, 1236, 1240, 1244, 1248, 1252, 1256, 1260, 1264, 1268, 1272, 1276, 1280, 1284, 1288, 1292, 1296, 1300, 1304, 1308, 1312, 1316, 1320, 1324, 1328, 1332, 1336, 1340, 1344, 1348, 1352, 1356, 1360, 1364, 1368, 1372, 1376, 1380, 1384, 1388, 1392, 1396, 1400, 1404, 1408, 1412, 1416, 1420, 1424, 1428])
- time_ns(time_ns)float640.0 0.5 1.0 ... 148.5 149.0 149.5
array([ 0. , 0.5, 1. , ..., 148.5, 149. , 149.5])
- bunchPatternTable(trainId, pulse_slot)uint322113321 0 2097193 0 ... 0 0 0 0
array([[2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0], ..., [2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0], [2113321, 0, 2097193, ..., 0, 0, 0]], dtype=uint32)
- PES_pressure(trainId)float326.28733e-07 ... 6.7894194e-07
array([6.2873301e-07, 6.2873301e-07, 6.2873301e-07, ..., 6.4182740e-07, 6.7894194e-07, 6.7894194e-07], dtype=float32)
- XTD10_SA3(trainId, sa3_pId)float642.661e+03 2.445e+03 ... 2.11e+03
array([[2661.23291016, 2444.58691406, 2480.74072266, ..., 2380.93359375, 2479.30371094, 2232.07226562], [2404.85668945, 2658.734375 , 2217.1796875 , ..., 2488.41577148, 2629.03076172, 2302.22460938], [2401.78662109, 2247.9284668 , 2280.03271484, ..., 2320.97119141, 2199.11914062, 2297.96264648], ..., [2248.18920898, 2398.20703125, 2354.68212891, ..., 2307.03833008, 2568.10595703, 2465.97509766], [2123.55004883, 2414.68261719, 2608.14404297, ..., 2427.31542969, 2626.33886719, 2505.59179688], [1932.66723633, 1922.01318359, 2103.00415039, ..., 2199.97802734, 2235.63769531, 2109.60400391]])
- PES_E_tof(sa3_pId, trainId, time_ns)float64-3.6 -0.6 -1.6 ... -2.588 0.4125
array([[[-3.6 , -0.6 , -1.6 , ..., 0.4 , -1.6 , 1.4 ], [ 0.45 , 0.45 , -0.55 , ..., 0.45 , -2.55 , 1.45 ], [-0.5875, -0.5875, 0.4125, ..., 0.4125, 0.4125, 1.4125], ..., [ 0.65 , 1.65 , -3.35 , ..., 0.65 , -0.35 , 1.65 ], [ 0.85 , 0.85 , 2.85 , ..., 0.85 , -1.15 , -0.15 ], [ 0.1625, 2.1625, -1.8375, ..., 4.1625, 1.1625, 0.1625]], [[ 0.3125, -1.6875, -3.6875, ..., 1.3125, -5.6875, 0.3125], [-1.25 , 0.75 , 1.75 , ..., 1.75 , -1.25 , 1.75 ], [-0.475 , -0.475 , -0.475 , ..., 2.525 , -1.475 , -0.475 ], ..., [ 0.4625, 2.4625, -2.5375, ..., 1.4625, 0.4625, 1.4625], [ 0.95 , 0.95 , -3.05 , ..., 2.95 , 0.95 , -1.05 ], [-0.325 , 1.675 , -1.325 , ..., -0.325 , -2.325 , -1.325 ]], [[-1.875 , 0.125 , -2.875 , ..., 2.125 , -0.875 , -0.875 ], [-0.7 , 1.3 , -0.7 , ..., 3.3 , -0.7 , 3.3 ], [-1.4625, -0.4625, 0.5375, ..., 2.5375, -2.4625, -0.4625], ..., ... ..., [-1.7125, 1.2875, -2.7125, ..., -0.7125, -0.7125, 4.2875], [-2.925 , 2.075 , -3.925 , ..., 3.075 , -2.925 , 2.075 ], [-0.65 , 0.35 , -0.65 , ..., -0.65 , 1.35 , 0.35 ]], [[ 1.5125, 0.5125, -1.4875, ..., 0.5125, 1.5125, -0.4875], [ 0.375 , -0.625 , -1.625 , ..., 1.375 , -1.625 , -0.625 ], [ 0.5625, 1.5625, -1.4375, ..., 4.5625, 0.5625, 2.5625], ..., [-3.5375, 1.4625, -1.5375, ..., 2.4625, -1.5375, 2.4625], [-1.7125, -1.7125, -1.7125, ..., 2.2875, -1.7125, 2.2875], [ 0.6375, 3.6375, -1.3625, ..., 2.6375, 1.6375, 1.6375]], [[-2.2375, 1.7625, -0.2375, ..., 1.7625, 1.7625, -0.2375], [-1.575 , 2.425 , -2.575 , ..., 3.425 , 0.425 , 2.425 ], [ 2.55 , 2.55 , 2.55 , ..., 2.55 , -0.45 , -3.45 ], ..., [-1.75 , 0.25 , -2.75 , ..., 3.25 , -1.75 , 1.25 ], [-2.475 , 4.525 , -2.475 , ..., -0.475 , -1.475 , 3.525 ], [ 0.4125, 0.4125, 0.4125, ..., 2.4125, -2.5875, 0.4125]]])
- PES_W_tof(sa3_pId, trainId, time_ns)float64-1.337 2.663 1.663 ... 1.038 0.0375
array([[[ -1.3375, 2.6625, 1.6625, ..., 1.6625, 0.6625, 1.6625], [ -0.55 , -1.55 , 0.45 , ..., 1.45 , -1.55 , -0.55 ], [ -0.9 , 1.1 , 1.1 , ..., 1.1 , 2.1 , 1.1 ], ..., [ -0.45 , -3.45 , -0.45 , ..., -0.45 , 0.55 , 0.55 ], [ 0.05 , 2.05 , -0.95 , ..., 0.05 , 0.05 , 1.05 ], [ -0.825 , 0.175 , -1.825 , ..., 1.175 , 3.175 , 0.175 ]], [[ -2.65 , 1.35 , -3.65 , ..., -0.65 , -0.65 , 2.35 ], [ -3.4875, 1.5125, 1.5125, ..., -0.4875, 3.5125, 1.5125], [ -2.025 , 0.975 , -2.025 , ..., -1.025 , -3.025 , 0.975 ], ... [ -1.05 , 0.95 , 0.95 , ..., 0.95 , -0.05 , -0.05 ], [ -3.025 , 2.975 , 0.975 , ..., -0.025 , -2.025 , -1.025 ], [ -1.5125, 1.4875, 0.4875, ..., 3.4875, 2.4875, -1.5125]], [[ 0.7625, 1.7625, -1.2375, ..., -2.2375, -10.2375, -0.2375], [ -1.5 , -0.5 , -1.5 , ..., 1.5 , -2.5 , 0.5 ], [ -5.3375, 1.6625, -1.3375, ..., 0.6625, -12.3375, -11.3375], ..., [ -1.35 , -0.35 , 0.65 , ..., 1.65 , -1.35 , 3.65 ], [ -1.7875, 2.2125, 0.2125, ..., 0.2125, -10.7875, -0.7875], [ -3.9625, 2.0375, -2.9625, ..., 4.0375, 1.0375, 0.0375]]])
- runFolder :
- /gpfs/exfel/exp/SCS/202121/p002927/raw/r0100
In the dataset above, PES_W_raw
and PES_E_raw
are replaced by PES_W_tof
and PES_E_tof
, which have dimensions trainId
, sa3_pId
, time_ns
. We can plot for instance the mean spectrum over all pulses for each train:
[6]:
plt.figure()
pes.PES_W_tof.mean(dim='sa3_pId').plot()
[6]:
<matplotlib.collections.QuadMesh at 0x2b786fcbc780>

Signal normalization¶
The intensity is slowly varying as a function of train Id. The main reason is the oscillating pressure in the PES, but it can also be related to pulse energy variations. We can plot the pressure and pulse energy as a function of train:
[7]:
plt.figure()
pes.PES_pressure.plot()
plt.tight_layout()
plt.figure()
pes.XTD10_SA3.plot()
[7]:
<matplotlib.collections.QuadMesh at 0x2b78728e34a8>


Normalization can be performed as follows:
[8]:
pes['PES_W_norm'] = pes['PES_W_tof'] / (pes['PES_pressure'] * pes['XTD10_SA3'])
pes['PES_E_norm'] = pes['PES_E_tof'] / (pes['PES_pressure'] * pes['XTD10_SA3'])
[9]:
plt.figure()
pes.PES_W_norm.mean(dim='sa3_pId').plot()
# first 10 spectra of first train
plt.figure()
plt.plot(pes.time_ns, pes.PES_W_norm.isel(trainId=0, sa3_pId=slice(10)).T)
plt.xlabel('time_ns');

