diff --git a/src/toolbox_scs/detectors/bam_detectors.py b/src/toolbox_scs/detectors/bam_detectors.py
index 72614ea77595439b764281261b154dcd65682073..7cd6fb21e4509609e873ce2cc5b5d5d664f2edec 100644
--- a/src/toolbox_scs/detectors/bam_detectors.py
+++ b/src/toolbox_scs/detectors/bam_detectors.py
@@ -12,7 +12,9 @@ import xarray as xr
 from ..misc.bunch_pattern_external import is_pulse_at
 from ..mnemonics_machinery import mnemonics_for_run
 from ..constants import mnemonics as _mnemonics
-from toolbox_scs.load import (get_array, load_bpt, get_sase_pId)
+from ..misc.bunch_pattern import (npulses_has_changed,
+                                  get_unique_sase_pId, load_bpt)
+from toolbox_scs.load import get_array
 
 __all__ = [
     'get_bam',
@@ -22,7 +24,8 @@ __all__ = [
 log = logging.getLogger(__name__)
 
 
-def get_bam(run, mnemonics=None, merge_with=None, bunchPattern='sase3'):
+def get_bam(run, mnemonics=None, merge_with=None, bunchPattern='sase3',
+            pulseIds=None):
     """
     Load beam arrival monitor (BAM) data and align their pulse ID
     according to the bunch pattern. Sources can be loaded on the fly
@@ -45,6 +48,8 @@ def get_bam(run, mnemonics=None, merge_with=None, bunchPattern='sase3'):
         'sase1' or 'sase3' or 'scs_ppl', bunch pattern
         used to extract peaks. The pulse ID dimension will be named
         'sa1_pId', 'sa3_pId' or 'ol_pId', respectively.
+    pulseIds:  list, 1D array
+        Pulse Ids. If None, they are automatically loaded.
     Returns
     -------
     xarray Dataset with pulse-resolved BAM variables aligned,
@@ -82,17 +87,25 @@ def get_bam(run, mnemonics=None, merge_with=None, bunchPattern='sase3'):
         ds_mw = xr.Dataset()
 
     ds = xr.Dataset()
-    sase3, sase3_changed = get_sase_pId(run)
+    dim_names = {'sase3': 'sa3_pId', 'sase1': 'sa1_pId',
+                 'scs_ppl': 'ol_pId'}
     run_mnemonics = mnemonics_for_run(run)
+    if pulseIds is None:
+        npulses_changed = npulses_has_changed(run, bunchPattern,
+                                              run_mnemonics)
+        if npulses_changed is False:
+            pulseIds = get_unique_sase_pId(run, bunchPattern,
+                                           run_mnemonics)
     for m in mnemonics:
         if merge_with is not None and m in merge_with:
             da_bam = merge_with[m]
         else:
             da_bam = get_array(run, m)
         da_bam = da_bam.sel(BAMbunchId=slice(0, 5400, 2))
-        if sase3_changed is False:
-            da_bam = da_bam.isel(BAMbunchId=sase3).rename(BAMbunchId='sa3_pId')
-            da_bam = da_bam.assign_coords(sa3_pId=sase3)
+        if npulses_changed is False:
+            da_bam = da_bam.isel(BAMbunchId=pulseIds)
+            da_bam = da_bam.assign_coords(BAMbunchId=pulseIds)
+            da_bam = da_bam.rename(BAMbunchId=dim_names[bunchPattern])
         else:
             # align the pulse Id
             bpt = load_bpt(run, ds_mw)
@@ -101,8 +114,6 @@ def get_bam(run, mnemonics=None, merge_with=None, bunchPattern='sase3'):
                     log.warning('Number of pulses changed during '
                                 'the run. Loading bunch pattern table.')
                     ds_mw = ds_mw.merge(bpt, join='inner')
-                dim_names = {'sase3': 'sa3_pId', 'sase1': 'sa1_pId',
-                             'scs_ppl': 'ol_pId'}
                 mask = is_pulse_at(bpt, bunchPattern)
                 mask = mask.rename({'pulse_slot': dim_names[bunchPattern]})
                 da_bam = da_bam.rename(BAMbunchId=dim_names[bunchPattern])
diff --git a/src/toolbox_scs/detectors/xgm.py b/src/toolbox_scs/detectors/xgm.py
index 9c604d5525c43a48fce60e156a13bea84fa93b8d..cb85e276881c0489ec54eadf3b89149b46b169df 100644
--- a/src/toolbox_scs/detectors/xgm.py
+++ b/src/toolbox_scs/detectors/xgm.py
@@ -13,8 +13,10 @@ import xarray as xr
 import matplotlib.pyplot as plt
 
 from ..misc.bunch_pattern_external import is_sase_1, is_sase_3
+from ..misc.bunch_pattern import (npulses_has_changed,
+                                  get_unique_sase_pId, load_bpt)
 from ..mnemonics_machinery import mnemonics_for_run
-from toolbox_scs.load import (get_array, load_bpt, get_sase_pId)
+from toolbox_scs.load import get_array
 
 __all__ = [
     'calibrate_xgm',
@@ -26,7 +28,7 @@ log = logging.getLogger(__name__)
 
 
 def get_xgm(run, mnemonics=None, merge_with=None,
-            indices=slice(0, None)):
+            indices=slice(0, None), sase3=None):
     """
     Load and/or computes XGM data. Sources can be loaded on the
     fly via the mnemonics argument, or processed from an existing dataset
@@ -47,6 +49,8 @@ def get_xgm(run, mnemonics=None, merge_with=None,
         computed and merged.
     indices: slice, list, 1D array
         Pulse indices of the XGM array in case bunch pattern is missing.
+    sase3:  list, 1D array
+        Pulse Ids of sase3. If None, they are automatically loaded.
     Returns
     -------
     xarray Dataset with pulse-resolved XGM variables aligned,
@@ -82,8 +86,9 @@ def get_xgm(run, mnemonics=None, merge_with=None,
     else:
         ds_mw = xr.Dataset()
 
-    sase1 = sase3 = None
+    sase1 = None
     sase1_changed = sase3_changed = False
+    run_mnemonics = mnemonics_for_run(run)
     ds = xr.Dataset()
     for m in mnemonics:
         if merge_with is not None and m in merge_with:
@@ -91,10 +96,14 @@ def get_xgm(run, mnemonics=None, merge_with=None,
         else:
             da_xgm = get_array(run, m)
         if sase1 is None and ('XGM' in m or 'SA1' in m):
-            sase1, sase1_changed = get_sase_pId(run, 'sase1')
+            sase1_changed = npulses_has_changed(run, 'sase1',
+                                                run_mnemonics)
         if sase3 is None and ('XGM' in m or 'SA3' in m):
-            sase3, sase3_changed = get_sase_pId(run, 'sase3')
+            sase3_changed = npulses_has_changed(run, 'sase3',
+                                                run_mnemonics)
         if sase3_changed is False and sase1_changed is False:
+            sase1 = get_unique_sase_pId(run, 'sase1', run_mnemonics)
+            sase3 = get_unique_sase_pId(run, 'sase3', run_mnemonics)
             ds_xgm = load_xgm_array(run, da_xgm, m, sase1, sase3)
         else:
             bpt = load_bpt(run, merge_with)