diff --git a/src/cal_tools/agipdlib.py b/src/cal_tools/agipdlib.py
index 88c3413cc623efda893852293865abc2b90db701..3a9da4e2283e9d784def6537b8bda7e8e0163023 100644
--- a/src/cal_tools/agipdlib.py
+++ b/src/cal_tools/agipdlib.py
@@ -53,12 +53,19 @@ class AgipdCtrl:
         self.ctrl_src = ctrl_src
         self.raise_error = raise_error
 
-    def get_num_cells(self) -> Optional[int]:
-        """Read number of memory cells from fast data.
+    def _get_num_cells_ctrl(self) -> Optional[int]:
+        """Get number of cells from CONTROL source."""
+        # Attempt to look for number of cells in slow data
+        ncell_src = (
+            self.ctrl_src, "bunchStructure.nPulses.value")
+        if (
+            ncell_src[0] in self.run_dc.all_sources and
+            ncell_src[1] in self.run_dc.keys_for_source(ncell_src[0])
+        ):
+            return int(self.run_dc[ncell_src].as_single_value(reduce_by='max'))
 
-        :return mem_cells: Number of memory cells
-        return None, if no data available.
-        """
+    def _get_num_cells_instr(self) -> Optional[int]:
+        """Get number of cells from INSTRUMENT source."""
         cells = np.squeeze(
             self.run_dc[
                 self.image_src, "image.cellId"].drop_empty_trains().ndarray()
@@ -70,6 +77,19 @@ class AgipdCtrl:
         dists = [abs(o - maxcell) for o in options]
         return options[np.argmin(dists)]
 
+    def get_num_cells(self) -> Optional[int]:
+        """Read number of memory cells from fast data.
+
+        :return mem_cells: Number of memory cells
+        return None, if no data available.
+        """
+        ncell = self._get_num_cells_ctrl()
+        if ncell is not None:
+            return ncell
+        # In case of data filtering at DAQ, this function produces
+        # wrong value.
+        return self._get_num_cells_instr()
+
     def _get_acq_rate_ctrl(self) -> Optional[float]:
         """Get acquisition (repetition) rate from CONTROL source."""
         # Attempt to look for acquisition rate in slow data
@@ -83,9 +103,6 @@ class AgipdCtrl:
             # about bucketing the rate for managing meta-data.
             return round(float(self.run_dc[rep_rate_src].as_single_value()), 1)
 
-    def _get_acq_rate_instr(self) -> Optional[float]:
-        """Get acquisition (repetition rate) from INSTRUMENT source."""
-
     def _get_acq_rate_instr(self) -> Optional[float]:
         """Get acquisition (repetition rate) from INSTRUMENT source."""
 
@@ -298,7 +315,8 @@ 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
 
@@ -309,6 +327,8 @@ class CellSelection:
             for common-mode correction
 
         :return: boolean array with flags indicating images for processing
+        :return: integer array with number of frames to use in the second
+            step in two step selection procedure
         """
         raise NotImplementedError
 
@@ -517,7 +537,7 @@ 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
+        #data_dict["nimg_in_trains"][:n_valid_trains] = nimg_in_trains
 
         if "AGIPD500K" in agipd_base:
             agipd_comp = components.AGIPD500K(im_dc)
@@ -532,8 +552,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)
@@ -1004,10 +1027,11 @@ 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, _ = self.cell_sel.get_cells_on_trains(
+            train_ids, nimg_in_trains, cellid, cm=self.cell_sel.CM_FINSEL
         )
         if np.all(can_calibrate):
             return n_img
@@ -1606,6 +1630,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 (
@@ -1615,10 +1640,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
@@ -1695,12 +1734,14 @@ 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:
 
         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)
+        sel = self._sel_for_cm(cell_flags, cm_flags, cm)
+        return sel, nfrm
 
     def filter_trains(self, train_sel: np.ndarray):
         return self._sel.filter_trains(train_sel, drop_empty=True)