This page contains some guidelines for middle layer servers that provide information for multiple locations along the accelerator (everything that should be plotted against the z axis). Examples are beam positions (x/y vs. z/BPM location), beam energies (beam energy vs. z/module location), magnet "energies" (nominal momentum vs. z/magnet location) and so on. A completely standardized interface for such diverse subsystems is neither practical nor desirable, but observing a few rules can make life much easier for people that have to read data from these servers.
The caller wants arrays
Make sure that the caller can easily access the information in array form without much post-processing. It does not matter whether the array is the result of a star operation or whether it comes directly from an array property. So, as long as they return the same information, both of the following approaches are fine:
array = read("XFEL/SERVER.ML/DEVICE.*/Z_POS") array = read("XFEL/SERVER.ML/GROUP.ALL/Z_POSITIONS")
The "star operation" approach is discouraged where different location types coexist that cannot easily be separated. The "array approach" has problems where arrays of location names are needed, which are badly supported by current control systems. Alternatives might be single strings with names separated by whitespace.
The caller needs z positions
Make sure that the caller can easily access the z position of any device/location, and that it is accurate. You can retrieve component lists with the HLC SQL library if you are so inclined.
Bunch train calculations
If your server analyzes bunch-resolved data, you should calculate a few standard values and provide them as properties with standard suffixes. Typically, the subtrain name should show up inside the property name (replace "QUANTITY" by something like "CHARGE" or "X" and "SA1" by the subtrain name):
QUANTITY.SA1 value of the first bunch of subtrain SA1 QUANTITY.SA1.TRAIN.MEAN mean value over all bunches QUANTITY.SA1.TRAIN.MIN minimum value over all bunches QUANTITY.SA1.TRAIN.MAX maximum value over all bunches QUANTITY.SA1.TRAIN.PKPK peak-to-peak fluctuation over all bunches (==MAX-MIN) QUANTITY.SA1.TRAIN.STD standard deviation over all bunches [calculated as sqrt(1/(N-1) * sum_1^N( (x_i - x_mean)^2 ))] QUANTITY.SA1.TRAIN.SUM sum over all bunches
A few combined quantities should be prepared as XYZS structures to support jddd plots:
QUANTITY.SA1.TRAIN.MEAN_STD mean value and standard deviation over all bunches of subtrain SA1 QUANTITY.SA1.TRAIN.MIN_MAX minimum and maximum value over all bunches QUANTITY.SA1.TRAIN.MEAN_PKPK mean value and peak-to-peak amplitude over all bunches
Statistics across macropulses (sliding window)
Your server can also offer statistical calculations over a sliding window of the last N macropulses. These calculations always focus on the first bunch of the train, and the first bunch only.
QUANTITY.SA1.PULSE.MEAN mean value over the last N pulses of subtrain SA1 QUANTITY.SA1.PULSE.MIN minimum value over the last N pulses QUANTITY.SA1.PULSE.MAX maximum value over the last N pulses QUANTITY.SA1.PULSE.PKPK peak-to-peak fluctuation over the last N pulses (==MAX-MIN) QUANTITY.SA1.PULSE.STD standard deviation over the last N pulses [calculated as sqrt(1/(N-1) * sum_1^N( (x_i - x_mean)^2 ))]
Like for intra-bunchtrain statistics, a few combined quantities can be prepared as XYZS structures to support jddd plots:
QUANTITY.SA1.PULSE.MEAN_STD mean value and standard deviation over the last N pulses of subtrain SA1 QUANTITY.SA1.PULSE.MIN_MAX minimum and maximum value over the last N pulses QUANTITY.SA1.PULSE.MEAN_PKPK mean value and peak-to-peak amplitude over the last N pulses
In some cases it can make sense to use the subtrain identifier as a separate hierarchy in control system name:
A display tool needs to be able to disentangle values for the various branches of the accelerator. If your server presents information separately for each subtrain, the problem is already solved - we know where SA2 bunches are going. If you have no subtrain information, you may need to define groups or sections in an easy-to-access manner. For example:
XFEL/MAGNET.ML/GROUP.BRANCH_LINAC/... XFEL/MAGNET.ML/GROUP.BRANCH_SA1_SA3/... XFEL/MAGNET.ML/GROUP.BRANCH_SA2/...
You can define flags in the component database to help you with this job. See HLC SQL library.
Finding bunches in time domain spectrums
Many servers use DOOCS time domain spectrums as their main data structure, often as properties with the ".TD" suffix. For clients it can be difficult to find out
- at which samples of this spectrum there are actual electron bunches present,
- at which samples of this spectrum there should be bunches according to the timing system,
- to which subtrain (SA1, SA2, ...) these bunches belong.
To simplify this task, it is recommended to implement an additional time domain spectrum with the same sampling rate (indexing) as the spectrums that contain the actual data. This makes it easy to determine for data sample whether it belongs to a bunch or not:
A time domain spectrum (D_spectrum or D_DAQspectrum) that contains markers for each bunch that should be present at a specific sample position. Each entry is a bitmask whose bits have the following meaning:
- 1 (bit 0): A bunch from subtrain 1 (e.g. SA1, FLASH1) is present according to the timing system.
- 2 (bit 1): A bunch from subtrain 2 (e.g. SA2, FLASH2) is present according to the timing system.
- 4 (bit 2): A bunch from subtrain 3 (e.g. SA3) is present according to the timing system.
- 32768 (bit 15): A bunch has been detected by a nearby BPM or toroid (implementation specific).
All other bits are reserved. An entry is zero when the timing system does not indicate any bunches at the corresponding position.