diff --git a/Load.py b/Load.py index d539553c5606c979143a0025ae32ccc0b486c2f6..d05679c50cd3b914174b5e870500e1e30f0e3427 100644 --- a/Load.py +++ b/Load.py @@ -116,6 +116,14 @@ mnemonics = { "VFM_BENDERF": {'source':'SCS_KBS_VFM/MOTOR/BENDERF', 'key':'encoderPosition.value', 'dim':None}, + + # LASER TIMING + "AFS_PhaseShifter": {'source':'SCS_ILH_LAS/PHASESHIFTER/DOOCS', + 'key':'actualPosition.value', + 'dim':None}, + "AFS_DelayLine": {'source':'SCS_ILH_LAS/MOTOR/LT3', + 'key':'AActualPosition.value', + 'dim':None}, # FFT "scannerX": {'source':'SCS_CDIFFT_SAM/LMOTOR/SCANNERX', @@ -192,6 +200,68 @@ mnemonics = { 'key':'digitizers.channel_1_A.raw.samples', 'dim': ['samplesId']}, + # FastADC + "FastADC0peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_0.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC0raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_0.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC1peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_1.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC1raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_1.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC2peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_2.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC2raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_2.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC3peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_3.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC3raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_3.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC4peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_4.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC4raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_4.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC5peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_5.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC5raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_5.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC6peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_6.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC6raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_6.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC7peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_7.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC7raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_7.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC8peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_8.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC8raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_8.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + "FastADC9peaks": {'source':'SCS_UTC1_MCP/ADC/1:channel_9.output', + 'key':'data.peaks', + 'dim':['peakId']}, + "FastADC9raw": {'source':'SCS_UTC1_MCP/ADC/1:channel_9.output', + 'key':'data.rawData', + 'dim':['samplesId']}, + # KARABACON "KARABACON": {'source':'SCS_DAQ_SCAN/MDL/KARABACON', 'key': 'actualStep.value', diff --git a/xgm.py b/xgm.py index 5b292f64a1a03c9d5f861cf6c53fd5f12729b74c..9b62b14a332b21be5e3a4daf3388657f7c0fd935 100644 --- a/xgm.py +++ b/xgm.py @@ -10,6 +10,7 @@ import numpy as np import xarray as xr +# Machine def pulsePatternInfo(data, plot=False): ''' display general information on the pulse patterns operated by SASE1 and SASE3. This is useful to track changes of number of pulses or mode of operation of @@ -114,6 +115,7 @@ def repRate(data, sase='sase3'): return f +# XGM def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses=None): ''' Extract SASE1- or SASE3-only XGM data. There are various cases depending on i) the mode of operation (10 Hz @@ -385,6 +387,7 @@ def calibrateXGMs(data, rollingWindow=200, plot=False): return np.array([sa3_calib_factor, scs_calib_factor]) +# TIM def mcpPeaks(data, intstart, intstop, bkgstart, bkgstop, mcp=1, t_offset=None, npulses=None): ''' Computes peak integration from raw MCP traces. @@ -844,4 +847,93 @@ def matchXgmTimPulseId(data, use_apd=True, intstart=None, intstop=None, dropList.append('MCP{}apd'.format(mcp)) mergeList.append(data.drop(dropList)) subset = xr.merge(mergeList, join='inner') + subset.attrs['run'] = data.attrs['run'] return subset + +# Fast ADC +def fastAdcPeaks(data, channel, intstart, intstop, bkgstart, bkgstop, period=None, npulses=None): + ''' Computes peak integration from raw FastADC traces. + + Inputs: + data: xarray Dataset containing FastADC raw traces (e.g. 'FastADC1raw') + channel: FastADC channel number + intstart: trace index of integration start + intstop: trace index of integration stop + bkgstart: trace index of background start + bkgstop: trace index of background stop + period: number of samples between two pulses. Needed if bunch + pattern info is not available. If None, checks the pulse + pattern and determine the period assuming a resolution of + 9.23 ns per sample which leads to 24 samples between + two bunches @ 4.5 MHz. + npulses: number of pulses. If None, takes the maximum number of + pulses according to the bunch patter (field 'npulses_sase3') + + Output: + results: DataArray with dims trainId x max(sase3 pulses) + + ''' + keyraw = 'FastADC{}raw'.format(channel) + if keyraw not in data: + raise ValueError("Source not found: {}!".format(keyraw)) + if npulses is None: + npulses = int(data['npulses_sase3'].max().values) + if period is None: + sa3 = data['sase3'].where(data['sase3']>1) + if npulses > 1: + #Calculate the number of pulses between two lasing pulses (step) + step = sa3.where(data['npulses_sase3']>1, drop=True)[0,:2].values + step = int(step[1] - step[0]) + #multiply by elementary pulse length (221.5 ns / 9.23 ns = 24 samples) + period = 24 * step + else: + period = 1 + results = xr.DataArray(np.empty((data.trainId.shape[0], npulses)), coords=data[keyraw].coords, + dims=['trainId', 'peakId'.format(channel)]) + for i in range(npulses): + a = intstart + period*i + b = intstop + period*i + bkga = bkgstart + period*i + bkgb = bkgstop + period*i + bg = np.outer(np.median(data[keyraw][:,bkga:bkgb], axis=1), np.ones(b-a)) + integ = np.trapz(data[keyraw][:,a:b] - bg, axis=1) + results[:,i] = integ + return results + + +def mergeFastAdcPeaks(data, channel, intstart, intstop, bkgstart, bkgstop, + period=None, npulses=None, dim='lasPulseId'): + ''' Calculates the peaks from Fast ADC raw traces with fastAdcPeaks() + and merges the results in Dataset. + Inputs: + data: xr Dataset with 'FastADC[channel]raw' traces + channel: Fast ADC channel + intstart: trace index of integration start + intstop: trace index of integration stop + bkgstart: trace index of background start + bkgstop: trace index of background stop + period: Number of samples separation between two pulses. Needed + if bunch pattern info is not available. If None, checks the + pulse pattern and determine the period assuming a resolution + of 9.23 ns per sample which leads to 24 samples between + two bunches @ 4.5 MHz. + npulses: number of pulses. If None, takes the maximum number of + pulses according to the bunch patter (field 'npulses_sase3') + dim: name of the xr dataset dimension along the peaks + + ''' + peaks = fastAdcPeaks(data, channel=channel, intstart=intstart, intstop=intstop, + bkgstart=bkgstart, bkgstop=bkgstop, period=period, + npulses=npulses) + + key = 'FastADC{}peaks'.format(channel) + if key in data: + s = data.drop(key) + else: + s = data + peaks = peaks.rename(key).rename({'peakId':dim}) + subset = xr.merge([s, peaks], join='inner') + subset.attrs['run'] = data.attrs['run'] + return subset + +