Pulse patterns
Analog to European XFEL's timing structure, its data is also organized in trains identifed by a unique and global train ID. Some data however, in particular many of the primary detectors in an experiment like AGIPD, DSSC, LPD or fast digitizers, also resolves every or at least some of the underlying pulses a train is composed of.

The PulsePattern family of components allows access to pulse patterns recorded
by various sources. For example, in order to obtain the FEL pulses for a particular
SASE:
There are different types available depending on the source that should be used for
the pulse pattern information, but they all offer the same interface as
PulsePattern for access. Furthermore,
many other components like AdqRawChannel can be
given a PulsePattern component to customize
how pulse-resolved data is interpreted.
The primary source of pulse pattern information is the bunch pattern table from the machine side, which is recorded either through a so called timeserver or a pulse pattern decoder source. There are three different components available to access different parts of this data:
XrayPulsesfor FEL pulses.OpticalLaserPulsesfor optical laser or PPL pulses.MachinePulsesfor machine-related pulses or any other data in the bunch pattern table.
There is a special component available for pump-probe experiments, which can combine FEL and PPL pulses into a single pattern with corresponding labels which of these two is present in a given pulse:
PumpProbePulsesfor combined FEL/PPL pulse patterns.
All of the components above offer the interface of
TimeserverPulses in addition to the
general interface of PulsePattern.
Apart from that, there are components to access other sources of pulse pattern
information via the same PulsePattern
interface:
-
ManualPulsesfor manually created pulse pattern or modifications of existing patterns viaselect_pulses(),deselect_pulses()orunion(). -
DldPulsesfor pulse informations generated as part of processed DLD (delay line detector) data.
As opposed to trains, there is no single global mechanism how to record pulses and some sources use their own identification scheme. Therefore, these components aim to refer to the location of pulses in the machine bunch pattern table wherever possible as a shared and universal identification called pulse ID. An enumeration of pulses for a single SASE, instrument or device is called pulse index. If desired, the pulse time uses the relative time to the beginning of a subtrain.
extra.components.pulses.PulsePattern ¤
Abstract interface to pulse patterns.
This class should not be instantiated directly, but one of its
implementations such as XrayPulses or OpticalLaserPulses. It
provides the shared interface accessible from all oher pulse pattern
implementations, however.
bunch_clock_divider
property
¤
Divider to generate repetition rate from master clock.
bunch_repetition_rate
property
¤
European XFEL fundamental bunch repetition rate in Hz.
Generated from the master clock using a divider of 288, resulting in 4.5 MHz.
select_trains ¤
Select a subset of trains.
The argument can be any object accepted by DataCollection.select_trains().
select_pulses ¤
Select a subset of pulses.
The possible options for pulse selection are:
-
By pulse index using
extra_data.by_indexwith a slice, list or ndarray:Slices with negative indices are supported, but may be significantly slower than non-negative indices.by_index[5:] # All pulses after the first five. by_index[[0, 1, 2]] # Explicitly the first three pulses.by_indexmay be omitted and a regular slice, list or ndarray used directly instead. -
By pulse ID using
extra_data.by_idwith a slice, list or ndarray: -
By a boolean ndarray acting as a mask, must contain at least as many elements as the highest number of pulses per train,
The train selection may be any object accepted by DataCollection.select_trains(). If specified, the pulse selection is only applied for the selected trains. This will not change the trains described by the resulting pulse pattern, but only which trains actually contain any pulses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pulse_sel
|
by_index or by_id or slice or list or ndarray
|
Pulse selection, may be a slice by pulse index or pulse ID or boolean mask. |
required |
train_sel
|
by_index or by_id or slice or list or ndarray
|
Train selection to which the pulse selection is applied. |
None
|
reset_index
|
bool
|
Whether to re-enumerate the pulseIndex index level, True by default. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pulses |
ManualPulses
|
New manual pulse patterns containing only the selected pulses. |
deselect_pulses ¤
Deselect a subset of pulses.
This method accepts the same option as PulsePattern.select_pulses() for its arguments, but removes the selected pulses and removes a pattern that remains.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pulse_sel
|
by_index or by_id or slice or list or ndarray
|
Pulse selection, may be a slice by pulse index or pulse ID or boolean mask. |
required |
train_sel
|
by_index or by_id or slice or list or ndarray
|
Train selection to which the pulse selection is applied. |
None
|
reset_index
|
bool
|
Whether to re-enumerate the pulseIndex index level, True by default. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pulses |
ManualPulses
|
New manual pulse patterns not containing the deselected pulses. |
union ¤
Join the pulses in this pattern with one or more others.
Any additional pulse index columns, e.g. flags for FEL/PPL
pulses as used by PumpProbePulses
are currently removed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*others
|
PulsePattern
|
Pulse patterns to join with. |
()
|
Returns:
| Name | Type | Description |
|---|---|---|
pulses |
ManualPulses
|
New manual pulse pattern containing the union of all pulses. |
pulse_ids ¤
Get pulse IDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled pandas Series (default) or unlabelled numpy array is returned. |
True
|
copy
|
bool
|
Whether a copy is returned (default) or potentially a reference to an internal object. In the latter case, modifying the returned value will likely break other methods. |
True
|
Returns:
| Type | Description |
|---|---|
Series or ndarray
|
Pulse ID indexed by train ID and pulse index if labelled is True. |
peek_pulse_ids ¤
Get pulse IDs for the first train.
This method may be significantly faster than to
pulse_ids() by only reading data for the very first train
of data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled pandas Series (default) or unlabelled numpy array is returned. |
True
|
Returns:
| Type | Description |
|---|---|
Series or ndarray
|
Pulse ID in the first train of this data. |
pulse_mask ¤
Get boolean pulse mask.
The returned mask has the same shape as the full bunch pattern table but only contains boolean flags whether a given pulse was present in this pattern.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled xarray DataArray (default) or unlabelled numpy array is returned. |
True
|
Returns:
| Type | Description |
|---|---|
DataArray or ndarray
|
|
is_constant_pattern ¤
Whether pulse IDs are constant in this data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
include_empty_trains
|
bool
|
Whether trains without any pulses cause a pulse pattern to not be considered constant, False by default. |
False
|
Returns:
| Type | Description |
|---|---|
bool
|
Whether pulse IDs are identical in every train. |
is_interleaved_with ¤
Check whether pulses are interleaved with other pattern.
This method returns True if and only if it can safely determine that the pulse pattern described by this component and the passed component are interleaved, and False if and only if it is clear they are not interleaved. In all other cases, the pulses may or may not be interleaved and None is returned.
Returns:
| Type | Description |
|---|---|
Optional[bool]
|
(bool or None) Whether pulses are interleaved or None if the pulse patterns do not allow the determination. |
pulse_counts ¤
pulse_periods ¤
Get pulse periods per train.
The pulse period is expressed in units of the fundamental bunch repetition rate of 4.5 MHz. Its exact value can be accessed via PulsePattern.bunch_repetition_rate.
In each train, the smallest period between consecutive pulses is considered if the pulses do not have equal distances. For trains with a single pulse, the value can be specified or is filled by the largest value encountered across other trains with more pulses.
The resulting series is cast to integers unless it contains non-finite values as a result of fill values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled pandas Series (default) or unlabelled numpy array is returned. |
True
|
single_pulse_value
|
number
|
Fill value for trains with a single pulse. If omitted the largest period encountered in the data is used or an exception raised if there are no trains with more than one pulse. |
None
|
no_pulse_value
|
number
|
Fill value for trains without any pulse, 0 if omitted. |
None
|
Returns:
| Type | Description |
|---|---|
Series or ndarray
|
Pulse period per train train, indexed by train ID if labelled is True. |
pulse_repetition_rates ¤
Get pulse repetition rate per train in Hz.
In each train, the highest repetition rate is used if the pulses do not have equal distances.
For trains with a single pulse, 0.0 is returned while trains without any pulse return NaN. If different fill values are desired, PulsePattern.bunch_repetition_rate can be divided manually by the result from PulsePattern.pulse_periods().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled pandas Series (default) or unlabelled numpy array is returned. |
True
|
Returns:
| Type | Description |
|---|---|
Series or ndarray
|
Pulse repetition rate per train, indexed by train ID if labelled is True. |
train_durations ¤
Get durations of each train in seconds.
The duration is the time difference between the first and last pulse in each train. For trains with no pulses, NaN is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled pandas Series (default) or unlabelled numpy array is returned. |
True
|
Returns:
| Type | Description |
|---|---|
Series or ndarray
|
Train duration in seconds per train, indexed by train ID if labelled is True. |
build_pulse_index ¤
Get a multi-level index for pulse-resolved data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pulse_dim
|
{pulseId, pulseIndex, pulseTime}
|
Label for pulse dimension, pulse ID by default. |
'pulseId'
|
include_extra_dims
|
bool
|
Whether to include any additional dimensions of this particular implementation beyond train ID and pulse dimension. |
True
|
pulse_dtype
|
dtype
|
If specified, force casts the pulse dimension to the specified dtype. |
None
|
Returns:
| Type | Description |
|---|---|
MultiIndex
|
Multi-level index covering train ID, pulse ID or pulse index and potentially any additonal extra index dimensions. |
search_pulse_patterns ¤
Search identical pulse patterns in this data.
Reads the bunch pattern table and gathers contiguous train regions of constant pulse pattern. It returns a list of train slices and corresponding pulse IDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled pandas Series (default) or unlabelled numpy array is returned. |
True
|
Returns:
| Type | Description |
|---|---|
list of (slice, pandas.Series or ndarray) tuples
|
List of train regions identified by index slices with identical pulse IDs. |
extra.components.pulses.TimeserverPulses ¤
Bases: PulsePattern
Abstract interface to timeserver-based based pulse patterns.
This class should not be instantiated directly, but one of its
implementations such as XrayPulses
or OpticalLaserPulses. It
provides the shared interface to access pulse patterns encoded in
the timeserver or pulse pattern decoder data.
machine_pulses ¤
Get MachinePulses component for the same data.
Any additional keyword arguments are passed to the MachinePulses initializer.
Returns:
| Type | Description |
|---|---|
MachinePulses
|
(MachinePulses) Corresponding component using the same data as this component. |
is_sa1_interleaved_with_sa3
cached
¤
Check whether SASE1 and SASE3 pulses are interleaved.
Due to their unique geometry, the pulses of the SASE1 and SASE3 beamlines can either occur after each other on the pulse train or be interleaved. Here, each beamline generally receives their first pulse directly after each other, with their relative pulse patterns following afterwards in a back-and-forth fashion.
This method returns True if and only if it can be safely determined the SA1 and SA3 pulses are intereavled, and False if and only if it is clear they are not interleaved. In all other cases, the pulses may or may not be interleaved and None is returned.
Returns:
| Name | Type | Description |
|---|---|---|
is_interleaved |
bool or None
|
Whether SA1 and SA3 are interleaved or None if the pulse patterns do not allow the determination. |
plot_xray_patterns ¤
Visualize X-ray pulse patterns.
Plots the X-ray pulse pattterns in this data on a common time scale. Variable patterns are represented by levels of transparency weighted by their rate of occurence. The right Y axis includes statistics about pulse count (Σ) and period (Δ).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sase
|
Sequence of int
|
SASE beamlines to include and in which order, [2, 1, 3] by default. |
[2, 1, 3]
|
figsize
|
2-tuple of float
|
Figure size in inches passed to matplotlib, ignored if ax is passed. |
(9, 4)
|
ax
|
Axes
|
Axes object to plot into, created automatically if omitted. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
ax |
Axes
|
Axes object the plot was generated in. |
extra.components.XrayPulses ¤
Bases: TimeserverPulses
An interface to X-ray free electron laser pulses.
The pulse structure of each train at European XFEL is described by the bunch pattern table and accesssible in recorded data through the timeserver device or in decoded form through pulse pattern decoders.
This component aids in locating and reading the bunch pattern table, as well as providing utility methods to apply the pulse patterns to other recorded data. It only considers the X-ray laser pulses generated by one of the SASE beamlines and is thus a good choice for exclusive use of X-rays or pump-probe experiments with congruent optical laser pulses.
This class only deals with X-ray pulses of a particular SASE beamline. Please see OpticalLaserPulses to access pulses of the optical laser sources or PumpProbePulses to combine both into a single pattern.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataCollection
|
Data to access bunch pattern data from. |
required |
source
|
str
|
Source name of a timeserver or pulse pattern decoder, only needed if the data includes more than one such device or none could not be detected automatically. |
None
|
sase
|
int
|
SASE beamline to interpret pulses of, only needed if the data includes sources from more than one beamline or it could not be detected automatically. |
None
|
extra.components.OpticalLaserPulses ¤
Bases: TimeserverPulses
An interface to optical laser pulses.
The pump-probe lasers (LAS or PPL) are optical lasers commonly used in conjunction with X-ray pulses for pump-probe experiments. There are multiple laser sources called seeds distributed across the SASE beamlines and instruments with their pulse patterns also contained in the bunch pattern table.
However, an important difference to the FEL pulses is that only the number of pulses and their spacing can be inferred from the bunch pattern table. Optical laser pulses always starts at offset 0 for technical reasons, even if they temporally overlap with FEL pulses by means of optical delay.
For experiments where all FEL and PPL laser pulses overlap, it is recommended to just use the XrayPulses component. In the case of more complex or non-overlapping patterns, the PumpProbePulses allows to combine both into a single pulse pattern.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataCollection
|
Data to access bunch pattern data from. |
required |
source
|
str
|
Source name of a timeserver or pulse pattern decoder, only needed if the data includes more than one such device or none could not be detected automatically. |
None
|
ppl_seed
|
PPL_BITS or str
|
PPL seed to interpret pulses of, only needed if the data includes sources from more than one instrument or it could not be detected automatically. May either be an explicit seed value or an instrument as a string. |
None
|
extra.components.PumpProbePulses ¤
PumpProbePulses(data, source=None, instrument=None, *, bunch_table_position=None, bunch_table_offset=None, pulse_offset=None, extrapolate=True)
Bases: XrayPulses, OpticalLaserPulses
An interface to combined FEL and PPL pulses.
This component offers support for arbitrary pulse relations between X-ray FEL and optical laser pulses (PPL) in pump-probe experiments. As the PPL pulse information in the bunch pattern table always starts at offset 0 for technical reasons irrespective of its actual temporal relation, it is corrected during initialization by exactly one of three methods:
- Offset all PPL pulses to a fixed bunch table position.
- Offset all PPL pulses relative to the first FEL pulse in units of the bunch pattern table.
- Offset all PPL pulses relative to the first FEL pulse in units of FEL pulses.
In cases where there are no FEL pulses (for method 2) or too few (for method 3) to determine this offset, it may be extrapolated from a previous train if enabled. If extrapolation is disabled, an exception is raised.
Unlike XrayPulses and OpticalLaserPulses, this component adds additional levels to the pulse index indicated whether an FEL or PPL pulse is present in any particular position. It will only consider a pattern equal if it is equal for both FEL and PPL.
For experiments where all FEL and PPL laser pulses overlap, it is recommended to just use the XrayPulses component.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataCollection
|
Data to access bunch pattern data from. |
required |
source
|
str
|
Source name of a timeserver or pulse pattern decoder, only needed if the data includes more than one such device or none could not be detected automatically. |
None
|
instrument
|
src or tuple
|
Instrument to interpret FEL and PPL pulses of, only needed if the data includes sources from more than one instrument or it could not be detected automatically. May also be a tuple of (sase, ppl_seed) corresponding to arguments for XrayPulses and OpticalLaserPulses. |
None
|
bunch_table_position
|
int
|
Absolute bunch table position or pulse ID for the PPL pulse. |
None
|
bunch_table_offset
|
int
|
Offset to the first FEL pulse in bunch table positions or pulse IDs. |
None
|
pulse_offset
|
number
|
Offset to the first FEL pulse in units of the spacing between the first two FEL pulses, i.e. in units of FEL pulses. |
None
|
extrapolate
|
bool
|
Whether FEL pulse IDs may be extrapolated from past trains if missing, true by default. An exception is raised if disabled and the PPL anchoring method is missing the minimum number of required FEL pulses. |
True
|
pulse_mask ¤
Get boolean pulse mask.
The returned mask has the same shape as the full bunch pattern table but only contains boolean flags whether a given pulse was present in this pattern.
For instance, to see whether each FEL pulse has a corresponding pump laser pulse in a consistent pulse pattern:
ppl_on = ppp.select_trains(0).pulse_mask(field='ppl').squeeze()
fel_on = ppp.select_trains(0).pulse_mask(field='fel').squeeze()
fel_pulse_is_pumped = ppl_on[fel_on]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labelled
|
bool
|
Whether a labelled xarray DataArray (default) or unlabelled numpy array is returned. |
True
|
field
|
str
|
'fel'/'ppl' to mark only FEL or only pump laser pulses in the returned array. By default, pulses are True whether either an FEL pulse or a PPL pulse occured. |
None
|
Returns:
| Type | Description |
|---|---|
DataArray or ndarray
|
|
pumped_pulses_ratios ¤
Determine ratio of pumped pulses per train.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ppl_only_value
|
float
|
Value for trains only containing PPL pulses, same value as for pulses without any pulses (np.nan) by default. |
nan
|
labelled
|
bool
|
Whether a labelled pandas Series (default) or unlabelled numpy array is returned. |
True
|
Returns:
| Type | Description |
|---|---|
Series or ndarray
|
Number of pulses per train, indexed by train ID if labelled is True. |
extra.components.MachinePulses ¤
Bases: TimeserverPulses
An interface to machine pulses and other bunch pattern data.
The bunch pattern table contains much more information than just the pulses of each SASE beamline or the optical laser systems, in particular about the upstream electron systems.
This component is configurable to extract any information from the bunch pattern table beyond the X-ray or optical laser pulses. By default, it considers all generated electron bunches by combining the various electron dumps along the accelerator. Please consult the XFEL Timing System Specification for the various mask bits used.
Note that the full range of bunch pattern table information is only available when used with timeserver data. The pulse pattern decoder data only contains information about those pulses in the main dump and SASE dumps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataCollection
|
Data to access bunch pattern data from. |
required |
source
|
str
|
Source name of a timeserver or pulse pattern decoder, only needed if the data includes more than one such device or none could not be detected automatically. |
None
|
mask
|
int
|
Custom mask into the bunch pattern table, by default all electron dumps are used. When initialized with ppdecoder data, only the main and SASE dumps are supported. |
_all_dumps
|
require_all_bits
|
bool
|
Whether to consider entries having any or all of the bits specified by mask, False by default. Only supported when initialized with timeserver data. |
False
|
extra.components.ManualPulses ¤
Bases: PulsePattern
Manual pulse patterns.
The pattern described by this component is directly loaded from data,
but either generated manually or modified from another
PulsePattern-based
component through
select_pulses(),
deselect_pulses()
or union().
from_constant_pulses
classmethod
¤
Generate a pulse pattern from constant pulse IDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
train_ids
|
ArrayLike or DataCollection or SourceData or KeyData
|
Train IDs or data to take train IDs from. |
required |
pulse_ids
|
ArrayLike
|
Pulse IDs of a single train to be repeated in every train. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
pulses |
ManualPulses
|
Manual pulse pattern with specified pulse IDs in every train. |
from_constant_pattern
classmethod
¤
from_constant_pattern(train_ids, pulses_per_train, repetition_rate=None, pulse_period=None, pulse_id_offset=0)
Generate a uniform pulse pattern.
Requires either repetition_rate or pulse_period to be passed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
train_ids
|
ArrayLike or DataCollection or SourceData or KeyData
|
Train IDs or data to take train IDs from. |
required |
pulses_per_train
|
int
|
Number of pulses per train. |
required |
repetition_rate
|
float
|
Repetition rate in Hz, mutually exclusive with pulse_period. |
None
|
pulse_period
|
int
|
Period between pulses in units of 4.5 MHz, mutually exclusive with repetition_rate. |
None
|
pulse_id_offset
|
int
|
Pulse ID for the first generated pulse in each train, 0 by default. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
pulses |
ManualPulses
|
Manual pulse pattern with uniform pulses in every train. |
extra.components.DldPulses ¤
Bases: PulsePattern
An interface to pulses from DLD reconstruction.
The facility-provided event reconstruction for delay line detectors
records its own pulse pattern information as part of its output in
the raw.triggers key. This class exposes the same pulse pattern
interface based on this information, and is primarily meant to be
used alongside such data. Note that it is influenced by parameters
set at the time of reconstruction, and hence may (incorrectly!)
differ from timeserver data.
For data processed before October 2022, this data may not contain flags for FEL/PPL pulses and may also be based on analog trigger signals. It is also lacking the true pulse IDs, which are in this case estimated by this component based on trigger positions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
detector
|
SourceData
|
Instrument source of reconstructed event data to retrieve trigger information from. |
required |
clock_ratio
|
int
|
Ratio between bunch repetition rate and digitizer sampling rate, only used in case of missing pulse ID information in data and 196 by default (non-interleaved ADQ412-3G). |
None
|
first_pulse_id
|
int
|
Pulse ID for the first pulse, only used in case of missing pulse ID information in data and 0 by default. |
None
|
negative_ppl_indices
|
bool
|
Whether to enumerate PPL-only pulses with negative indices (while keeping non-negative indices for FEL-only or pumped pulses) or interleave all pulses with positive indices (default). |
False
|