diff --git a/setup.py b/setup.py
index b2b0f3f66bb9affb38b67d59df92fc50adf06143..320b5926c3bf775fba9ce6b6c6a6567fa9fcdf5e 100644
--- a/setup.py
+++ b/setup.py
@@ -101,7 +101,7 @@ install_requires = [
         "tabulate==0.8.6",
         "traitlets==4.3.3",
         "xarray==2022.3.0",
-        "EXtra-redu==0.0.7",
+        "EXtra-redu==0.0.8",
         "rich==12.6.0",
         "httpx==0.23.0",
 ]
diff --git a/src/cal_tools/agipdlib.py b/src/cal_tools/agipdlib.py
index 2f4046a6c88193319545e9102b7d704a57cae8fc..011905554fbdc24453ccfb552ec845c517ff8ad4 100644
--- a/src/cal_tools/agipdlib.py
+++ b/src/cal_tools/agipdlib.py
@@ -316,17 +316,21 @@ class CellSelection:
         raise NotImplementedError
 
     def get_cells_on_trains(
-        self, train_sel: np.ndarray, nfrm: np.ndarray, cm: int = 0
+        self, train_sel: np.ndarray, nfrm: np.ndarray,
+        cellid: np.ndarray, cm: int = 0
     ) -> np.array:
         """Returns mask of cells selected for processing
 
         :param train_sel: list of a train ids selected for processing
         :param nfrm: the number of frames expected for every train in
             the list `train_sel`
+        :param cellid: array of cell IDs in the same sequence as images to
+            filter
         :param cm: flag indicates the final selection or interim selection
             for common-mode correction
-
-        :return: boolean array with flags indicating images for processing
+        :returns:
+            - boolean array with flags indicating images for processing
+            - integer array with number of selected frames in trains
         """
         raise NotImplementedError
 
@@ -337,17 +341,6 @@ class CellSelection:
         """
         raise NotImplementedError
 
-    @staticmethod
-    def _sel_for_cm(flag, flag_cm, cm):
-        if cm == CellSelection.CM_NONE:
-            return flag
-        elif cm == CellSelection.CM_PRESEL:
-            return flag_cm
-        elif cm == CellSelection.CM_FINSEL:
-            return flag[flag_cm]
-        else:
-            raise ValueError("param 'cm' takes only 0,1,2")
-
 
 class AgipdCorrections:
 
@@ -535,7 +528,6 @@ class AgipdCorrections:
         n_valid_trains = len(valid_train_ids)
         data_dict["n_valid_trains"][0] = n_valid_trains
         data_dict["valid_trains"][:n_valid_trains] = valid_train_ids
-        data_dict["nimg_in_trains"][:n_valid_trains] = nimg_in_trains
 
         if "AGIPD500K" in agipd_base:
             agipd_comp = components.AGIPD500K(im_dc)
@@ -550,8 +542,11 @@ class AgipdCorrections:
         cm = (self.cell_sel.CM_NONE if apply_sel_pulses
               else self.cell_sel.CM_PRESEL)
 
-        img_selected = self.cell_sel.get_cells_on_trains(
-            np.array(valid_train_ids), nimg_in_trains, cm=cm)
+        cellid = np.squeeze(im_dc[agipd_base, "image.cellId"].ndarray())
+
+        img_selected, nimg_in_trains = self.cell_sel.get_cells_on_trains(
+            np.array(valid_train_ids), nimg_in_trains, cellid, cm=cm)
+        data_dict["nimg_in_trains"][:n_valid_trains] = nimg_in_trains
 
         frm_ix = np.flatnonzero(img_selected)
         data_dict["cm_presel"][0] = (cm == self.cell_sel.CM_PRESEL)
@@ -1022,11 +1017,13 @@ class AgipdCorrections:
         ntrains = data_dict["n_valid_trains"][0]
         train_ids = data_dict["valid_trains"][:ntrains]
         nimg_in_trains = data_dict["nimg_in_trains"][:ntrains]
+        cellid = data_dict["cellId"][:n_img]
 
         # Initializing can_calibrate array
-        can_calibrate = self.cell_sel.get_cells_on_trains(
-            train_ids, nimg_in_trains, cm=self.cell_sel.CM_FINSEL
+        can_calibrate, nimg_in_trains = self.cell_sel.get_cells_on_trains(
+            train_ids, nimg_in_trains, cellid, cm=self.cell_sel.CM_FINSEL
         )
+        data_dict["nimg_in_trains"][:ntrains] = nimg_in_trains
         if np.all(can_calibrate):
             return n_img
 
@@ -1624,6 +1621,7 @@ class CellRange(CellSelection):
         self.flag_cm[:self.max_cells] = self.flag
         self.flag_cm = (self.flag_cm.reshape(-1, self.row_size).any(1)
                         .repeat(self.row_size)[:self.max_cells])
+        self.sel_type = [self.flag, self.flag_cm, self.flag]
 
     def msg(self):
         return (
@@ -1633,10 +1631,24 @@ class CellRange(CellSelection):
         )
 
     def get_cells_on_trains(
-        self, train_sel: np.ndarray, nfrm: np.ndarray, cm: int = 0
+        self, train_sel: np.ndarray, nfrm: np.ndarray,
+        cellid: np.ndarray, cm: int = 0
     ) -> np.array:
-        return np.tile(self._sel_for_cm(self.flag, self.flag_cm, cm),
-                       len(train_sel))
+        if cm < 0 or cm > 2:
+            raise ValueError("param 'cm' takes only 0,1,2")
+
+        flag = self.sel_type[cm]
+        sel = np.zeros(np.sum(nfrm), bool)
+        counts = np.zeros(len(nfrm), int)
+        i0 = 0
+        for i, nfrm_i in enumerate(nfrm):
+            iN = i0 + nfrm_i
+            f = flag[cellid[i0:iN]]
+            sel[i0:iN] = f
+            counts[i] = np.sum(f)
+            i0 = iN
+
+        return sel, counts
 
     def filter_trains(self, train_sel: np.ndarray):
         return train_sel
@@ -1670,14 +1682,11 @@ class LitFrameSelection(CellSelection):
         self.use_super_selection = use_super_selection
 
         if use_super_selection == 'off':
-            self.cm_sel_type = SelType.ROW
-            self.final_sel_type = SelType.CELL
+            self.sel_type = [SelType.CELL, SelType.ROW, SelType.CELL]
         elif use_super_selection == 'cm':
-            self.cm_sel_type = SelType.SUPER_ROW
-            self.final_sel_type = SelType.CELL
+            self.sel_type = [SelType.CELL, SelType.SUPER_ROW, SelType.CELL]
         elif use_super_selection == 'final':
-            self.cm_sel_type = SelType.SUPER_ROW
-            self.final_sel_type = SelType.SUPER_CELL
+            self.sel_type = [SelType.SUPER_CELL, SelType.SUPER_ROW, SelType.SUPER_CELL]
         else:
             raise ValueError("param 'use_super_selection' takes only "
                              "'off', 'cm' or 'final'")
@@ -1713,12 +1722,16 @@ class LitFrameSelection(CellSelection):
         )
 
     def get_cells_on_trains(
-        self, train_sel: np.ndarray, nfrm: np.ndarray, cm: int = 0
+        self, train_sel: np.ndarray, nfrm: np.ndarray,
+        cellid: np.ndarray, cm: int = 0
     ) -> np.array:
+        if cm < 0 or cm > 2:
+            raise ValueError("param 'cm' takes only 0,1,2")
+
+        (sel, counts), = self._sel.litframes_on_trains(
+            train_sel, nfrm, cellid, [self.sel_type[cm]])
 
-        cell_flags, cm_flags = self._sel.litframes_on_trains(
-            train_sel, nfrm, [self.final_sel_type, self.cm_sel_type])
-        return self._sel_for_cm(cell_flags, cm_flags, cm)
+        return sel, counts
 
     def filter_trains(self, train_sel: np.ndarray):
         return self._sel.filter_trains(train_sel, drop_empty=True)