Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • SCS/ToolBox
  • kluyvert/ToolBox
2 results
Show changes
Commits on Source (2)
source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -30,6 +30,11 @@ Detectors that produce one point per pulse, or 0D detectors, are all handled in
* :doc:`extract data from point detectors <point_detectors/point_detectors>`.
Photo-Electron Spectrometer (PES)
+++++++++++++++++++++++++++++++++
* :doc:`Basic analysis of PES spectra <PES_spectra_extraction>`.
routines
--------
......
......@@ -73,6 +73,75 @@ mnemonics = {
"UND": ({'source': 'SA3_XTD10_UND/DOOCS/PHOTON_ENERGY',
'key': 'actualPosition.value',
'dim': None},),
# PES
"PES_N_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_4_A.raw.samples',
'dim': ['PESsampleId']},),
"PES_NNE_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_4_B.raw.samples',
'dim': ['PESsampleId']},),
"PES_NE_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_4_C.raw.samples',
'dim': ['PESsampleId']},),
"PES_ENE_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_4_D.raw.samples',
'dim': ['PESsampleId']},),
"PES_E_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_3_A.raw.samples',
'dim': ['PESsampleId']},),
"PES_ESE_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_3_B.raw.samples',
'dim': ['PESsampleId']},),
"PES_SE_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_3_C.raw.samples',
'dim': ['PESsampleId']},),
"PES_SSE_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_3_D.raw.samples',
'dim': ['PESsampleId']},),
"PES_S_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_1_A.raw.samples',
'dim': ['PESsampleId']},),
"PES_SSW_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_1_B.raw.samples',
'dim': ['PESsampleId']},),
"PES_SW_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_1_C.raw.samples',
'dim': ['PESsampleId']},),
"PES_WSW_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_1_D.raw.samples',
'dim': ['PESsampleId']},),
"PES_W_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_2_A.raw.samples',
'dim': ['PESsampleId']},),
"PES_WNW_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_2_B.raw.samples',
'dim': ['PESsampleId']},),
"PES_NW_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_2_C.raw.samples',
'dim': ['PESsampleId']},),
"PES_NNW_raw": ({'source': 'SA3_XTD10_PES/ADC/1:network',
'key': 'digitizers.channel_2_D.raw.samples',
'dim': ['PESsampleId']},),
"PES_pressure": ({'source': 'SA3_XTD10_PES/GAUGE/G30310F',
'key': 'value.value',
'dim': None},),
"PES_RV": ({'source': 'SA3_XTD10_PES/MDL/DAQ_MPOD',
'key': 'u215.value',
'dim': None},),
"PES_N2": ({'source': 'SA3_XTD10_PES/DCTRL/V30300S_NITROGEN',
'key': 'interlock.AActionState.value',
'dim': None},),
"PES_Ne": ({'source': 'SA3_XTD10_PES/DCTRL/V30310S_NEON',
'key': 'interlock.AActionState.value',
'dim': None},),
"PES_Kr": ({'source': 'SA3_XTD10_PES/DCTRL/V30320S_KRYPTON',
'key': 'interlock.AActionState.value',
'dim': None},),
"PES_Xe": ({'source': 'SA3_XTD10_PES/DCTRL/V30330S_XENON',
'key': 'interlock.AActionState.value',
'dim': None},),
# DPS imagers
"DPS1CAM2": ({'source': 'SCS_BLU_DPS-1/CAM/IMAGER2CAMERA:daqOutput',
'key': 'data.image.pixels',
......@@ -80,6 +149,7 @@ mnemonics = {
"DPS2CAM2": ({'source': 'SCS_BLU_DPS-2/CAM/IMAGER2CAMERA:daqOutput',
'key': 'data.image.pixels',
'dim': ['dps2cam2_y', 'dps2cam2_x']},),
# XTD10 XGM
# keithley
"XTD10_photonFlux": ({'source': 'SA3_XTD10_XGM/XGM/DOOCS',
......
......@@ -4,6 +4,7 @@ from .digitizers import (
get_peaks, get_tim_peaks, get_laser_peaks, get_digitizer_peaks,
check_peak_params)
from .bam_detectors import get_bam
from .pes import get_pes_tof, get_pes_params
from .dssc_data import (
save_xarray, load_xarray, get_data_formatted, save_attributes_h5)
from .dssc_misc import (
......@@ -26,6 +27,8 @@ __all__ = (
"get_digitizer_peaks",
"check_peak_params",
"get_bam",
"get_pes_tof",
"get_pes_params",
"save_xarray",
"load_xarray",
"get_data_formatted",
......@@ -66,7 +69,8 @@ clean_ns = [
'FastCCD',
'xgm',
'digitizers',
'bam_detectors'
'bam_detectors',
'pes'
]
......
""" Beam Arrival Monitor related sub-routines
Copyright (2021) SCS Team.
(contributions preferrably comply with pep8 code structure
guidelines.)
"""
import logging
import numpy as np
import xarray as xr
import extra_data as ed
from ..misc.bunch_pattern_external import is_sase_3
from ..mnemonics_machinery import (mnemonics_to_process,
mnemonics_for_run)
log = logging.getLogger(__name__)
def get_pes_tof(run, mnemonics=None, merge_with=None,
start=31390, width=300, origin=None, width_ns=None,
baseStart=None, baseWidth=80,
sample_rate=2e9):
"""
Extracts time-of-flight spectra from raw digitizer traces. The
tracesvare either loaded via ToolBox mnemonics or those in the
optionally provided merge_with dataset. The spectra are aligned
by pulse Id using the SASE 3 bunch pattern, and have time coordinates
in nanoseconds.
Parameters
----------
run: extra_data.DataCollection
DataCollection containing the digitizer data
mnemonics: str or list of str
mnemonics for PES, e.g. "PES_W_raw" or ["PES_W_raw", "PES_ENE_raw"].
If None and no merge_with dataset is provided, defaults to "PES_W_raw".
merge_with: xarray Dataset
If provided, the resulting Dataset will be merged with this
one. The PES variables of merge_with (if any) will also be
computed and merged.
start: int
starting sample of the first spectrum in the raw trace.
width: int
number of samples per spectra.
origin: int
sample of the raw trace that corresponds to time-of-flight origin.
If None, origin is equal to start.
width_ns: float
time window for one spectrum. If None, the time window is defined by
width / sample rate.
baseStart: int
starting sample of the baseline.
baseWidth: int
number of samples to average (starting from baseStart) for baseline
calculation.
sample_rate: float
sample rate of the digitizer.
Returns
-------
pes: xarray Dataset
Dataset containing the PES time-of-flight spectra (e.g. "PES_W_tof"),
merged with optionally provided merg_with dataset.
Example
-------
>>> import toolbox_scs as tb
>>> import toolbox_scs.detectors as tbdet
>>> run, ds = tb.load(2927, 100, "PES_W_raw")
>>> pes = tbdet.get_pes_tof(run, merge_with=ds)
"""
def to_processed_name(name):
return name.replace('raw', 'tof')
to_process = mnemonics_to_process(mnemonics, merge_with,
'PES', to_processed_name)
run_mnemonics = mnemonics_for_run(run)
# check if bunch pattern table exists
if bool(merge_with) and 'bunchPatternTable' in merge_with:
bpt = merge_with['bunchPatternTable']
elif 'bunchPatternTable' in run_mnemonics:
bpt = run.get_array(*run_mnemonics['bunchPatternTable'].values())
elif 'bunchPatternTable_SA3' in run_mnemonics:
bpt = run.get_array(*mnemonics['bunchPatternTable_SA3'].values())
else:
bpt = None
mask = is_sase_3(bpt).assign_coords({'pulse_slot': np.arange(2700)})
mask_on = mask.where(mask, drop=True)
npulses = mask.sum(dim='pulse_slot')[0].values
if npulses > 1:
period = mask_on['pulse_slot'].diff(dim='pulse_slot')[0].values
else:
period = 0
if origin is None:
origin = start
if baseStart is None:
baseStart = start
if width_ns is not None:
width = int(sample_rate * width_ns * 1e-9)
time_ns = 1e9 * (np.arange(start, start + width) - origin) / sample_rate
ds = xr.Dataset()
for m in to_process:
if bool(merge_with) and m in merge_with:
arr = merge_with[m]
else:
arr = run.get_array(*run_mnemonics[m].values(), name=m)
spectra = []
for p in range(npulses):
begin = p*period*440 + start
end = begin + width
baseBegin = p*period*440 + baseStart
baseEnd = baseBegin + baseWidth
pes = arr.isel(PESsampleId=slice(begin, end))
bl = arr.isel(
PESsampleId=slice(baseBegin, baseEnd)).mean(dim='PESsampleId')
spectra.append(pes - bl)
spectra = xr.concat(spectra,
dim='sa3_pId').rename(m.replace('raw', 'tof'))
ds = ds.merge(spectra)
if len(ds.variables) > 0:
ds = ds.assign_coords({'sa3_pId': mask_on['pulse_slot'].values})
ds = ds.rename({'PESsampleId': 'time_ns'})
ds = ds.assign_coords({'time_ns': time_ns})
if bool(merge_with):
ds = merge_with.drop(to_process,
errors='ignore').merge(ds, join='inner')
return ds
def get_pes_params(run):
"""
Extract PES parameters for a given extra_data DataCollection.
Parameters are gas, retardation voltage.
Parameters
----------
run: extra_data.DataCollection
DataCollection containing the digitizer data
Returns
-------
params: dict
dictionnary of PES parameters
"""
params = {}
sel = run.select_trains(ed.by_index[:20])
mnemonics = mnemonics_for_run(run)
for gas in ['N2', 'Ne', 'Kr', 'Xe']:
arr = sel.get_array(*mnemonics[f'PES_{gas}'].values())
if arr[0] == 0:
params['gas'] = gas
break
if 'gas' not in params:
params['gas'] = 'unknown'
log.warning('Could not find which PES gas was used.')
arr = sel.get_array(*mnemonics['PES_RV'].values())
params['ret_voltage'] = float(arr[0].values)
return params
......@@ -117,6 +117,10 @@ def mnemonics_to_process(mnemo_list, merge_with, detector, func=None):
det_mnemos = [m for m in _mnemonics if 'FastADC' in m]
default_mnemo = 'FastADC5raw'
default_processed = 'FastADC5peaks'
if detector == 'PES':
det_mnemos = [m for m in _mnemonics if 'PES' in m and 'raw' in m]
default_mnemo = 'PES_W_raw'
default_processed = 'PES_W_tof'
dig_dims = list(set([_mnemonics[m][0]['dim'][0] for m in det_mnemos]))
processed_mnemos = list(set([func(m) for m in det_mnemos]))
......