diff --git a/src/toolbox_scs/detectors/digitizers.py b/src/toolbox_scs/detectors/digitizers.py
index 4d28e6947a21e64df57d6887128faf7387dbd2cf..0bb2662665eebc2dc511120886a14e6a7fa97776 100644
--- a/src/toolbox_scs/detectors/digitizers.py
+++ b/src/toolbox_scs/detectors/digitizers.py
@@ -92,8 +92,7 @@ def peaks_from_raw_trace(traces,
     return results
         
 
-def get_peaks(proposal,
-              runNB,
+def get_peaks(run,
               data=None,
               source=None,
               key=None,
@@ -110,10 +109,8 @@ def get_peaks(proposal,
 
     Parameters
     ----------
-    proposal: int or str
-        proposal number
-    runNB: int or str
-        run number
+    run: extra_data.DataCollection
+        DataCollection containing the digitizer data
     data: xarray DataArray or str
         array containing the raw traces or peak-integrated values from the
         digitizer. If str, must be one of the ToolBox mnemonics. If None, 
@@ -145,7 +142,8 @@ def get_peaks(proposal,
         pattern can be provided, e.g. {'source':'SCS_RR_UTC/TSYS/TIMESERVER',
         'key':'bunchPatternTable.value', 'pattern':'sase3'}
     extra_dim: str
-        Name given to the dimension along the peaks.
+        Name given to the dimension along the peaks. If None, the name is given
+        according to the bunchPattern.
     indices: array, slice
         indices from the peak-integrated data to retrieve. Only required
         when bunch pattern is missing and useRaw is False.
@@ -158,7 +156,6 @@ def get_peaks(proposal,
         raise ValueError('At least data or source + key arguments ' +
                          'are required.')
     # load data
-    run = ed.open_run(proposal, runNB)
     if data is None:
         arr = run.get_array(source, key)
     elif type(data) is str:
@@ -273,7 +270,7 @@ def get_peaks(proposal,
     if autoFind:
         integParams = find_integ_params(arr.mean(dim='trainId'),
                                         min_distance=min_distance)
-        log.debug('Auto find peaks result:', integParams)
+        log.debug(f'Auto find peaks result: {integParams}')
 
     # 2.1. No bunch pattern provided
     if bpt is None:
@@ -361,7 +358,7 @@ def find_integ_params(trace, min_distance=1, height=None, width=1):
     intstop = np.round(peaks['right_ips'][0]
                        + 0.5*np.mean(peaks['widths'])).astype(int)
     bkgstop = intstart - int(0.5*np.mean(peaks['widths']))
-    bkgstart = bkgstop - 100
+    bkgstart = np.max([bkgstop - min_distance, 0])
     result = {'intstart':intstart, 'intstop':intstop,
               'bkgstart':bkgstart, 'bkgstop':bkgstop,
               'period':period, 'npulses':npulses}
@@ -380,7 +377,8 @@ def get_tim_peaks(data, bunchPattern='sase3',
     data: xarray Dataset containing TIM data
     bunchPattern: str
         'sase1' or 'sase3' or 'scs_ppl', bunch pattern
-        used to extract peaks.
+        used to extract peaks. The pulse ID dimension will be named
+        'sa1_pId', 'sa3_pId' or 'ol_pId', respectively.
     integParams: dict
         dictionnary for raw trace integration, e.g.
         {'intstart':100, 'intstop':200, 'bkgstart':50, 
@@ -401,6 +399,7 @@ def get_tim_peaks(data, bunchPattern='sase3',
     
     proposal = data.attrs['runFolder'].split('/')[-3]
     runNB = data.attrs['runFolder'].split('/')[-1]
+    run = ed.open_run(proposal, runNB)
     peakDict = {}
     toRemove = []
     autoFind=True
@@ -416,7 +415,7 @@ def get_tim_peaks(data, bunchPattern='sase3',
             continue
         log.debug(f'Retrieving TIM peaks from {key}...')
         mnemonic = _mnemonics[key]
-        peaks = get_peaks(proposal, runNB, data[key],
+        peaks = get_peaks(run, data[key],
                           source=mnemonic['source'],
                           key=mnemonic['key'],
                           digitizer='ADQ412',
@@ -467,6 +466,7 @@ def get_fast_adc_peaks(data, bunchPattern='scs_ppl',
 
     proposal = data.attrs['runFolder'].split('/')[-3]
     runNB = data.attrs['runFolder'].split('/')[-1]
+    run = ed.open_run(proposal, runNB)
     peakDict = {}
     toRemove = []
     autoFind=True
@@ -482,7 +482,7 @@ def get_fast_adc_peaks(data, bunchPattern='scs_ppl',
             continue
         log.debug('Retrieving Fast ADC peaks from {key}...')
         mnemonic = _mnemonics[key]
-        peaks = get_peaks(proposal, runNB, data[key],
+        peaks = get_peaks(run, data[key],
                           source=mnemonic['source'],
                           key=mnemonic['key'],
                           digitizer='FastADC',
diff --git a/src/toolbox_scs/detectors/xgm.py b/src/toolbox_scs/detectors/xgm.py
index 76e02153d9e453f4431b35a9fa0370924804b1c1..c0869d62a83e9c3897ace2f9d54bf3b89c145bdc 100644
--- a/src/toolbox_scs/detectors/xgm.py
+++ b/src/toolbox_scs/detectors/xgm.py
@@ -23,11 +23,11 @@ log = logging.getLogger(__name__)
 
 def load_xgm(run, xgm_mnemonic='SCS_SA3'):
     """
-    Loads XGM data from karabo_data.DataCollection
+    Loads XGM data from extra_data.DataCollection
 
     Parameters
     ----------
-    run: karabo_data.DataCollection
+    run: extra_data.DataCollection
 
     Returns
     -------
@@ -71,24 +71,35 @@ def cleanXGMdata(data, npulses=None, sase3First=True, keepAllSase=False):
                 dimension names 'sa1_pId' and 'sa3_pId'                
     '''
     if 'XGMbunchId' not in data.dims:
-        log.debug('Dataset does not contain XGMbunchId dimension. Aborting.')
+        log.info('Dataset does not contain XGMbunchId '+
+                 'dimension. Aborting.')
         return data
     proposal = data.attrs['runFolder'].split('/')[-3]
     runNB = data.attrs['runFolder'].split('/')[-1]
     run = ed.open_run(proposal, runNB)
     load_sa1 = True
+    load_sa3 = True
     #check bunch pattern table
     if _mnemonics['bunchPatternTable']['source'] in run.all_sources:
-        bpt = run.get_array(*_mnemonics['bunchPatternTable'].values())
+        if 'bunchPatternTable' in data:
+            bpt = data['bunchPatternTable']
+        else:
+            bpt = run.get_array(*_mnemonics['bunchPatternTable'].values())
         mask_sa1 = is_sase_1(bpt).sel(trainId=data.trainId)
         mask_sa3 = is_sase_3(bpt).sel(trainId=data.trainId)
-        valid_tid_sa1 = mask_sa1.where(mask_sa1.sum(dim='pulse_slot')>0,
+        tid_sa1 = mask_sa1.where(mask_sa1.sum(dim='pulse_slot')>0,
                                        drop=True).trainId
-        valid_tid_sa3 = mask_sa3.where(mask_sa3.sum(dim='pulse_slot')>0,
+        tid_sa3 = mask_sa3.where(mask_sa3.sum(dim='pulse_slot')>0,
                                        drop=True).trainId
-        if valid_tid_sa1.size==0:
-            load_sa1 = False
-        if np.intersect1d(valid_tid_sa1, valid_tid_sa3, 
+        if tid_sa1.size==0 or tid_sa3.size==0:
+            keepAllSase = False
+            if tid_sa1.size==0:
+                log.info('No SASE 1 pulses in the data.')
+                load_sa1 = False
+            if tid_sa3.size==0:
+                log.info('No SASE 3 pulses in the data.')
+                load_sa3 = False
+        elif np.intersect1d(tid_sa1, tid_sa3, 
                       assume_unique=True).size==0:
             load_sa1 = keepAllSase
             if keepAllSase:
@@ -98,7 +109,7 @@ def cleanXGMdata(data, npulses=None, sase3First=True, keepAllSase=False):
                 log.info('Dedicated trains, only loading SASE 3.')
         isBunchPattern = True
     else:
-        print('Missing bunch pattern info!')
+        log.info('Missing bunch pattern info!')
         bpt = None
         isBunchPattern = False
     dropList = []
@@ -117,7 +128,7 @@ def cleanXGMdata(data, npulses=None, sase3First=True, keepAllSase=False):
     for key in keys_all_sase:
         if isBunchPattern is False:
             if npulses is None:
-                raise TypeError('npulses argument is required '
+                raise TypeError('npulses argument is required '+
                     'when retrieving non-dedicated XGM arrays '+
                     'without bunch pattern info. Consider using '+
                     'SASE 1 or SASE 3 dedicated data arrays.')
@@ -137,23 +148,27 @@ def cleanXGMdata(data, npulses=None, sase3First=True, keepAllSase=False):
                                   {'XGMbunchId':'sa1_pId'})
             sa1 = sa1.rename(key.replace('XGM', 'SA1'))
             mergeList.append(sa1)
-        sa3 = selectSASEinXGM(data, xgm=key, sase='sase3', 
+        if load_sa3:
+            sa3 = selectSASEinXGM(data, xgm=key, sase='sase3', 
                               bpt=bpt, npulses=npulses,
                               sase3First=sase3First).rename(
                               {'XGMbunchId':'sa3_pId'})
-        sa3 = sa3.rename(key.replace('XGM', 'SA3'))
-        mergeList.append(sa3)
+            sa3 = sa3.rename(key.replace('XGM', 'SA3'))
+            mergeList.append(sa3)
         dropList.append(key)
     
     #dedicated sase data        
     for key in keys_dedicated:
         if "sa3" in key.lower():
+            if load_sa3 is False:
+                dropList.append(key)
+                continue
             sase = 'sa3_'
         else:
-            sase = 'sa1_'
             if load_sa1 is False:
                 dropList.append(key)
                 continue
+            sase = 'sa1_'
         res = data[key].where(data[key] != 1.0, drop=True).rename(
                 {'XGMbunchId':'{}pId'.format(sase)}).rename(key)        
         dropList.append(key)
@@ -179,7 +194,7 @@ def cleanXGMdata(data, npulses=None, sase3First=True, keepAllSase=False):
                                      2700-ds[key].sizes[sase])))).flatten()
                 xgm_flat_arg = np.argwhere(xgm_flat!=1.0)
                 if(xgm_flat_arg.shape != mask_flat_arg.shape):
-                    log.warning('The XGM data does not match the 
+                    log.warning('The XGM data does not match the '+
                                 'bunch pattern! Cannot assign pulse '+
                                 'id coordinates.')
                     break