Skip to content
Snippets Groups Projects
Commit 971893a8 authored by Laurent Mercadier's avatar Laurent Mercadier
Browse files

Simplifies selectSASEinXGM() by using mask based on bunch pattern

parent 3c42d1db
No related branches found
No related tags found
1 merge request!53Tim
...@@ -183,7 +183,8 @@ def cleanXGMdata(data, npulses=None, sase3First=True): ...@@ -183,7 +183,8 @@ def cleanXGMdata(data, npulses=None, sase3First=True):
def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses=None): def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses=None):
''' Extract SASE1- or SASE3-only XGM data. ''' Given an array containing both SASE1 and SASE3 data, extracts SASE1-
or SASE3-only XGM data.
There are various cases depending on i) the mode of operation (10 Hz There are various cases depending on i) the mode of operation (10 Hz
with fresh bunch, dedicated trains to one SASE, pulse on demand), with fresh bunch, dedicated trains to one SASE, pulse on demand),
ii) the potential change of number of pulses per train in each SASE ii) the potential change of number of pulses per train in each SASE
...@@ -192,7 +193,7 @@ def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses= ...@@ -192,7 +193,7 @@ def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses=
Inputs: Inputs:
data: xarray Dataset containing xgm data data: xarray Dataset containing xgm data
sase: key of sase to select: {'sase1', 'sase3'} sase: key of sase to select: {'sase1', 'sase3'}
xgm: key of xgm to select: {'SA3_XGM', 'SCS_XGM'} xgm: key of xgm to select: {'XTD10_XGM', 'SCS_XGM'}
sase3First: bool, optional. Used in case no bunch pattern was recorded sase3First: bool, optional. Used in case no bunch pattern was recorded
npulses: int, optional. Required in case no bunch pattern was recorded. npulses: int, optional. Required in case no bunch pattern was recorded.
...@@ -202,6 +203,7 @@ def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses= ...@@ -202,6 +203,7 @@ def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses=
that sase in the run. The missing values, in case of change of number of pulses, that sase in the run. The missing values, in case of change of number of pulses,
are filled with NaNs. are filled with NaNs.
''' '''
#1. case where bunch pattern is missing:
if sase not in data: if sase not in data:
print('Missing bunch pattern info!') print('Missing bunch pattern info!')
if npulses is None: if npulses is None:
...@@ -221,108 +223,27 @@ def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses= ...@@ -221,108 +223,27 @@ def selectSASEinXGM(data, sase='sase3', xgm='SCS_XGM', sase3First=True, npulses=
else: else:
start=xgmData.shape[1]-npulses start=xgmData.shape[1]-npulses
return xgmData[:,start:start+npulses] return xgmData[:,start:start+npulses]
result = None
npulses_sa3 = data['npulses_sase3'] #2. case where bunch pattern is provided
npulses_sa1 = data['npulses_sase1'] xgm_arr = data[xgm].where(data[xgm] != 1., drop=True)
dedicated = 0 sa3 = data['sase3'].where(data['sase3'] > 1, drop=True)
if np.all(npulses_sa1.where(npulses_sa3 !=0, drop=True) == 0): sa3_val=np.unique(sa3)
dedicated += 1 sa3_val = sa3_val[~np.isnan(sa3_val)]
print('No SASE 1 pulses during SASE 3 operation') sa1 = data['sase1'].where(data['sase1'] > 1, drop=True)
if np.all(npulses_sa3.where(npulses_sa1 !=0, drop=True) == 0): sa1_val=np.unique(sa1)
dedicated += 1 sa1_val = sa1_val[~np.isnan(sa1_val)]
print('No SASE 3 pulses during SASE 1 operation') sa_all = xr.concat([sa1, sa3], dim='bunchId').rename('sa_all')
#Alternating pattern with dedicated pulses in SASE1 and SASE3: sa_all = xr.DataArray(np.sort(sa_all)[:,:xgm_arr['XGMbunchId'].shape[0]],
if dedicated==2: dims=['trainId', 'bunchId'],
if sase=='sase1': coords={'trainId':data.trainId},
result = data[xgm].where(npulses_sa1>0, drop=True)[:,:npulses_sa1.max().values] name='sase_all')
else: mask_sa1 = sa_all.sel(trainId=sa1.trainId).isin(sa1_val).rename({'bunchId':'XGMbunchId'})
result = data[xgm].where(npulses_sa3>0, drop=True)[:,:npulses_sa3.max().values] mask_sa3 = sa_all.sel(trainId=sa3.trainId).isin(sa3_val).rename({'bunchId':'XGMbunchId'})
result = result.where(result != 1.0)
return result
# SASE1 and SASE3 bunches in a same train: find minimum indices of first and
# maximum indices of last pulse per train
else:
pulseIdmin_sa1 = data['sase1'].where(npulses_sa1 != 0).where(data['sase1']>1).min().values
pulseIdmax_sa1 = data['sase1'].where(npulses_sa1 != 0).where(data['sase1']>1).max().values
pulseIdmin_sa3 = data['sase3'].where(npulses_sa3 != 0).where(data['sase3']>1).min().values
pulseIdmax_sa3 = data['sase3'].where(npulses_sa3 != 0).where(data['sase3']>1).max().values
if pulseIdmin_sa1 > pulseIdmax_sa3:
sa3First = True
elif pulseIdmin_sa3 > pulseIdmax_sa1:
sa3First = False
else:
print('Interleaved mode, but no sase-dedicated XGM data loaded.')
saseStr = 'SA{}'.format(sase[4])
xgmStr = xgm.split('_')[0]
print('Loading {}_{} data...'.format(xgmStr, saseStr))
try:
if npulses == None:
npulses = data['npulses_sase{}'.format(sase[4])].max().values
if xgmStr == 'XTD10':
source = 'SA3_XTD10_XGM/XGM/DOOCS:output'
if xgmStr == 'SCS':
source = 'SCS_BLU_XGM/XGM/DOOCS:output'
key = 'data.intensitySa{}TD'.format(sase[4])
result = data.attrs['run'].get_array(source, key, extra_dims=['XGMbunchId'])
result = result.isel(XGMbunchId=slice(0, npulses))
return result
except:
print('Could not load {}_{} data. '.format(xgmStr, saseStr) +
'Interleaved mode and no sase-dedicated data is not yet supported.')
#take the derivative along the trainId to track changes in pulse number:
diff = npulses_sa3.diff(dim='trainId')
#only keep trainIds where a change occured:
diff = diff.where(diff != 0, drop=True)
#get a list of indices where a change occured:
idx_change_sa3 = np.argwhere(np.isin(npulses_sa3.trainId.values,
diff.trainId.values, assume_unique=True))[:,0]
#Same for SASE 1:
diff = npulses_sa1.diff(dim='trainId')
diff = diff.where(diff !=0, drop=True)
idx_change_sa1 = np.argwhere(np.isin(npulses_sa1.trainId.values,
diff.trainId.values, assume_unique=True))[:,0]
#create index that locates all changes of pulse number in both SASE1 and 3:
#add index 0 to get the initial pulse number per train:
idx_change = np.unique(np.concatenate(([0], idx_change_sa3, idx_change_sa1))).astype(int)
if sase=='sase1': if sase=='sase1':
npulses = npulses_sa1 return xgm_arr.where(mask_sa1, drop=True).rename('{}_SA1'.format(xgm.split('_')[0]))
maxpulses = int(npulses_sa1.max().values)
else: else:
npulses = npulses_sa3 return xgm_arr.where(mask_sa3, drop=True).rename('{}_SA3'.format(xgm.split('_')[0]))
maxpulses = int(npulses_sa3.max().values)
for i,k in enumerate(idx_change):
#skip if no pulses after the change:
if npulses[idx_change[i]]==0:
continue
#calculate indices
if sa3First:
a = 0
b = int(npulses_sa3[k].values)
c = b
d = int(c + npulses_sa1[k].values)
else:
a = int(npulses_sa1[k].values)
b = int(a + npulses_sa3[k].values)
c = 0
d = a
if sase=='sase1':
a = c
b = d
if i==len(idx_change)-1:
l = None
else:
l = idx_change[i+1]
temp = data[xgm][k:l,a:a+maxpulses].copy()
temp[:,b:] = np.NaN
if result is None:
result = temp
else:
result = xr.concat([result, temp], dim='trainId')
return result
def saseContribution(data, sase='sase1', xgm='XTD10_XGM'): def saseContribution(data, sase='sase1', xgm='XTD10_XGM'):
''' Calculate the relative contribution of SASE 1 or SASE 3 pulses ''' Calculate the relative contribution of SASE 1 or SASE 3 pulses
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment