diff --git a/doc/source/api/force_bdss.kpi.rst b/doc/source/api/force_bdss.kpi.rst
deleted file mode 100644
index a18dcbd30d10a44c7343be5c30fb9052805103c8..0000000000000000000000000000000000000000
--- a/doc/source/api/force_bdss.kpi.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-force\_bdss\.kpi package
-========================
-
-Subpackages
------------
-
-.. toctree::
-
-    force_bdss.kpi.tests
-
-Submodules
-----------
-
-force\_bdss\.kpi\.base\_kpi\_calculator module
-----------------------------------------------
-
-.. automodule:: force_bdss.kpi.base_kpi_calculator
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-force\_bdss\.kpi\.base\_kpi\_calculator\_factory module
--------------------------------------------------------
-
-.. automodule:: force_bdss.kpi.base_kpi_calculator_factory
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-force\_bdss\.kpi\.base\_kpi\_calculator\_model module
------------------------------------------------------
-
-.. automodule:: force_bdss.kpi.base_kpi_calculator_model
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-force\_bdss\.kpi\.i\_kpi\_calculator\_factory module
-----------------------------------------------------
-
-.. automodule:: force_bdss.kpi.i_kpi_calculator_factory
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: force_bdss.kpi
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/source/api/force_bdss.kpi.tests.rst b/doc/source/api/force_bdss.kpi.tests.rst
deleted file mode 100644
index d45f2935e2ef89e1651ddf070aeb38942241bda2..0000000000000000000000000000000000000000
--- a/doc/source/api/force_bdss.kpi.tests.rst
+++ /dev/null
@@ -1,38 +0,0 @@
-force\_bdss\.kpi\.tests package
-===============================
-
-Submodules
-----------
-
-force\_bdss\.kpi\.tests\.test\_base\_kpi\_calculator module
------------------------------------------------------------
-
-.. automodule:: force_bdss.kpi.tests.test_base_kpi_calculator
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-force\_bdss\.kpi\.tests\.test\_base\_kpi\_calculator\_factory module
---------------------------------------------------------------------
-
-.. automodule:: force_bdss.kpi.tests.test_base_kpi_calculator_factory
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-force\_bdss\.kpi\.tests\.test\_base\_kpi\_calculator\_model module
-------------------------------------------------------------------
-
-.. automodule:: force_bdss.kpi.tests.test_base_kpi_calculator_model
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: force_bdss.kpi.tests
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/source/api/force_bdss.rst b/doc/source/api/force_bdss.rst
index fbf2323722188e50bd866ffa999adafbe307f675..8fda5b9d3a4200c08df182dc04e4b498b4949e3f 100644
--- a/doc/source/api/force_bdss.rst
+++ b/doc/source/api/force_bdss.rst
@@ -11,7 +11,6 @@ Subpackages
     force_bdss.core_plugins
     force_bdss.data_sources
     force_bdss.io
-    force_bdss.kpi
     force_bdss.mco
     force_bdss.notification_listeners
     force_bdss.tests
diff --git a/doc/source/api/force_bdss.tests.probe_classes.rst b/doc/source/api/force_bdss.tests.probe_classes.rst
index acdf96347ff91d3908ea8bb7aa35aef3dc5d6683..7650c03d2d5f56057b8d7504ff6950cd65d46538 100644
--- a/doc/source/api/force_bdss.tests.probe_classes.rst
+++ b/doc/source/api/force_bdss.tests.probe_classes.rst
@@ -28,14 +28,6 @@ force\_bdss\.tests\.probe\_classes\.factory\_registry\_plugin module
     :undoc-members:
     :show-inheritance:
 
-force\_bdss\.tests\.probe\_classes\.kpi\_calculator module
-----------------------------------------------------------
-
-.. automodule:: force_bdss.tests.probe_classes.kpi_calculator
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
 force\_bdss\.tests\.probe\_classes\.mco module
 ----------------------------------------------
 
diff --git a/force_bdss/api.py b/force_bdss/api.py
index f9afd7c2e5c4f9c4bb06348a9c3834994c71c760..e38740304a3ef4666c6886d0df0f2573f7b541a6 100644
--- a/force_bdss/api.py
+++ b/force_bdss/api.py
@@ -10,11 +10,6 @@ from .data_sources.base_data_source import BaseDataSource  # noqa
 from .data_sources.base_data_source_factory import BaseDataSourceFactory  # noqa
 from .data_sources.i_data_source_factory import IDataSourceFactory  # noqa
 
-from .kpi.base_kpi_calculator import BaseKPICalculator  # noqa
-from .kpi.base_kpi_calculator_model import BaseKPICalculatorModel  # noqa
-from .kpi.base_kpi_calculator_factory import BaseKPICalculatorFactory  # noqa
-from .kpi.i_kpi_calculator_factory import IKPICalculatorFactory  # noqa
-
 from .mco.base_mco_model import BaseMCOModel  # noqa
 from .mco.base_mco_communicator import BaseMCOCommunicator  # noqa
 from .mco.base_mco import BaseMCO  # noqa
diff --git a/force_bdss/base_extension_plugin.py b/force_bdss/base_extension_plugin.py
index c94b622a6ac546a32610da49f70e600b13e99f04..baaeb4261bd326003d7ce0cd176fd4b51c82abce 100644
--- a/force_bdss/base_extension_plugin.py
+++ b/force_bdss/base_extension_plugin.py
@@ -5,7 +5,6 @@ from .notification_listeners.i_notification_listener_factory import \
     INotificationListenerFactory
 from .ids import ExtensionPointID
 from .data_sources.i_data_source_factory import IDataSourceFactory
-from .kpi.i_kpi_calculator_factory import IKPICalculatorFactory
 from .mco.i_mco_factory import IMCOFactory
 from .ui_hooks.i_ui_hooks_factory import IUIHooksFactory
 
@@ -37,12 +36,6 @@ class BaseExtensionPlugin(Plugin):
         contributes_to=ExtensionPointID.DATA_SOURCE_FACTORIES
     )
 
-    #: A list of the available KPI calculators this plugin exports.
-    kpi_calculator_factories = List(
-        IKPICalculatorFactory,
-        contributes_to=ExtensionPointID.KPI_CALCULATOR_FACTORIES
-    )
-
     notification_listener_factories = List(
         INotificationListenerFactory,
         contributes_to=ExtensionPointID.NOTIFICATION_LISTENER_FACTORIES
diff --git a/force_bdss/core/workflow.py b/force_bdss/core/workflow.py
index c0750a25c72354392a8150c4b5d2db8ee81d56e0..d7d29231b9883a4493a91f8bc35290159b8c313f 100644
--- a/force_bdss/core/workflow.py
+++ b/force_bdss/core/workflow.py
@@ -1,7 +1,6 @@
 from traits.api import HasStrictTraits, Instance, List
 
 from force_bdss.data_sources.base_data_source_model import BaseDataSourceModel
-from force_bdss.kpi.base_kpi_calculator_model import BaseKPICalculatorModel
 from force_bdss.mco.base_mco_model import BaseMCOModel
 from force_bdss.notification_listeners.base_notification_listener_model \
     import BaseNotificationListenerModel
@@ -20,9 +19,5 @@ class Workflow(HasStrictTraits):
     #: will go away when we remove the KPI calculators.
     execution_layers = List(List(BaseDataSourceModel))
 
-    #: Contains the factory-specific KPI Calculator Model objects.
-    #: The list can be empty
-    kpi_calculators = List(BaseKPICalculatorModel)
-
     #: Contains information about the listeners to be setup
     notification_listeners = List(BaseNotificationListenerModel)
diff --git a/force_bdss/core_evaluation_driver.py b/force_bdss/core_evaluation_driver.py
index 6ff50dd4df6067e461723929d146169034ef0db6..274e04c037c06fefbfbac4da48ae87ee2894f44c 100644
--- a/force_bdss/core_evaluation_driver.py
+++ b/force_bdss/core_evaluation_driver.py
@@ -57,23 +57,17 @@ def execute_workflow(workflow, data_values):
         ds_results = _compute_layer_results(
             available_data_values,
             layer,
-            "create_data_source"
         )
         available_data_values += ds_results
 
     log.info("Computing KPI layer")
-    kpi_results = _compute_layer_results(
-        available_data_values,
-        workflow.kpi_calculators,
-        "create_kpi_calculator"
-    )
+    kpi_results = [dv for dv in available_data_values if dv.is_kpi]
 
     return kpi_results
 
 
 def _compute_layer_results(environment_data_values,
                            evaluator_models,
-                           creator_method_name
                            ):
     """Helper routine.
     Performs the evaluation of a single layer.
@@ -86,12 +80,7 @@ def _compute_layer_results(environment_data_values,
         A list of data values to submit to the evaluators.
 
     evaluator_models: list
-        A list of the models for all the evaluators (data source
-        or kpi calculator)
-
-    creator_method_name: str
-        A string of the creator method for the evaluator on the
-        factory (e.g. create_kpi_calculator)
+        A list of the models for all the data sources
 
     NOTE: The above parameter is going to go away as soon as we move
     to unlimited layers and remove the distinction between data sources
@@ -101,12 +90,12 @@ def _compute_layer_results(environment_data_values,
 
     for model in evaluator_models:
         factory = model.factory
-        evaluator = getattr(factory, creator_method_name)()
+        data_source = factory.create_data_source()
 
         # Get the slots for this data source. These must be matched to
         # the appropriate values in the environment data values.
         # Matching is by position.
-        in_slots, out_slots = evaluator.slots(model)
+        in_slots, out_slots = data_source.slots(model)
 
         # Binding performs the extraction of the specified data values
         # satisfying the above input slots from the environment data values
@@ -125,7 +114,7 @@ def _compute_layer_results(environment_data_values,
             factory.name))
 
         try:
-            res = evaluator.run(model, passed_data_values)
+            res = data_source.run(model, passed_data_values)
         except Exception:
             log.error("Evaluation could not be performed. Run method raised"
                       "exception", exc_info=True)
@@ -162,6 +151,7 @@ def _compute_layer_results(environment_data_values,
         # Add the names as specified by the user.
         for dv, output_slot_info in zip(res, model.output_slot_info):
             dv.name = output_slot_info.name
+            dv.is_kpi = output_slot_info.is_kpi
 
         # If the name was not specified, simply discard the value,
         # because apparently the user is not interested in it.
diff --git a/force_bdss/core_mco_driver.py b/force_bdss/core_mco_driver.py
index 79c6844c2e1e625caeb9a1c98d34add8f7889e02..b7dfda63a0022798bf607871d456dec6e45afc6b 100644
--- a/force_bdss/core_mco_driver.py
+++ b/force_bdss/core_mco_driver.py
@@ -56,8 +56,12 @@ class CoreMCODriver(BaseCoreDriver):
     @on_trait_change("mco:started")
     def _deliver_start_event(self):
         output_names = []
-        for kpi in self.workflow.kpi_calculators:
-            output_names.extend(kpi.output_slot_info)
+        for layer in self.workflow.execution_layers:
+            for data_source in layer:
+                output_names.extend(info.name
+                                    for info in data_source.output_slot_info
+                                    if info.is_kpi
+                                    )
 
         self._deliver_event(MCOStartEvent(
             input_names=tuple(p.name for p in self.workflow.mco.parameters),
diff --git a/force_bdss/factory_registry_plugin.py b/force_bdss/factory_registry_plugin.py
index e588792e65ca752a1048f5544b032dacf23e86c5..cb6680b48b9b6af29cc0a79d2ce403a698fd1047 100644
--- a/force_bdss/factory_registry_plugin.py
+++ b/force_bdss/factory_registry_plugin.py
@@ -7,7 +7,6 @@ from force_bdss.notification_listeners.i_notification_listener_factory import \
     INotificationListenerFactory
 from .data_sources.i_data_source_factory import (
     IDataSourceFactory)
-from .kpi.i_kpi_calculator_factory import IKPICalculatorFactory
 from .mco.i_mco_factory import IMCOFactory
 from .ui_hooks.i_ui_hooks_factory import IUIHooksFactory
 
@@ -56,12 +55,6 @@ class FactoryRegistryPlugin(Plugin):
         List(IDataSourceFactory),
         id=ExtensionPointID.DATA_SOURCE_FACTORIES)
 
-    #: A list of the available Key Performance Indicator calculators.
-    #: It will be populated by plugins.
-    kpi_calculator_factories = ExtensionPoint(
-        List(IKPICalculatorFactory),
-        id=ExtensionPointID.KPI_CALCULATOR_FACTORIES)
-
     #: Notification listeners are pluggable entities that will listen
     #: to MCO events and act accordingly.
     notification_listener_factories = ExtensionPoint(
@@ -97,26 +90,6 @@ class FactoryRegistryPlugin(Plugin):
 
         raise KeyError(id)
 
-    def kpi_calculator_factory_by_id(self, id):
-        """Finds a given kpi factory by means of its id.
-        The ID is as obtained by the function factory_id() in the
-        plugin api.
-
-        Parameters
-        ----------
-        id: str
-            The identifier returned by the factory_id() function.
-
-        Raises
-        ------
-        KeyError: if the entry is not found.
-        """
-        for kpic in self.kpi_calculator_factories:
-            if kpic.id == id:
-                return kpic
-
-        raise KeyError(id)
-
     def mco_factory_by_id(self, id):
         """Finds a given Multi Criteria Optimizer (MCO) factory by means of
         its id. The ID is as obtained by the function factory_id() in the
diff --git a/force_bdss/io/tests/test_workflow_writer.py b/force_bdss/io/tests/test_workflow_writer.py
index fc197c306921d8ff7fe6de1ecd6340249398b7c6..db58071091bc91e32c9b7b7168a7517bcf98fcc5 100644
--- a/force_bdss/io/tests/test_workflow_writer.py
+++ b/force_bdss/io/tests/test_workflow_writer.py
@@ -57,7 +57,6 @@ class TestWorkflowWriter(unittest.TestCase):
         self.assertIn("workflow", result)
         self.assertIn("mco", result["workflow"])
         self.assertIn("execution_layers", result["workflow"])
-        self.assertIn("kpi_calculators", result["workflow"])
 
     def test_write_and_read(self):
         wfwriter = WorkflowWriter()
diff --git a/force_bdss/io/workflow_reader.py b/force_bdss/io/workflow_reader.py
index d28c05de645d1138f8effd76f58cd92fe523ff07..a63925c666a83385436e6f790bf21163f19bc63b 100644
--- a/force_bdss/io/workflow_reader.py
+++ b/force_bdss/io/workflow_reader.py
@@ -91,7 +91,6 @@ class WorkflowReader(HasStrictTraits):
             wf_data = json_data["workflow"]
             wf.mco = self._extract_mco(wf_data)
             wf.execution_layers[:] = self._extract_execution_layers(wf_data)
-            wf.kpi_calculators[:] = self._extract_kpi_calculators(wf_data)
             wf.notification_listeners[:] = \
                 self._extract_notification_listeners(wf_data)
         except KeyError as e:
@@ -167,37 +166,6 @@ class WorkflowReader(HasStrictTraits):
 
         return layers
 
-    def _extract_kpi_calculators(self, wf_data):
-        """Extracts the KPI calculators from the workflow dictionary data.
-
-        Parameters
-        ----------
-        wf_data: dict
-            the content of the workflow key in the top level dictionary data.
-
-        Returns
-        -------
-        list of BaseKPICalculatorModel instances. Each BaseKPICalculatorModel
-        is an instance of the specific model class. The list can be
-        empty.
-        """
-        registry = self.factory_registry
-
-        kpi_calculators = []
-        for kpic_entry in wf_data["kpi_calculators"]:
-            kpic_id = kpic_entry["id"]
-            kpic_factory = registry.kpi_calculator_factory_by_id(kpic_id)
-            model_data = kpic_entry["model_data"]
-            model_data["input_slot_info"] = self._extract_input_slot_info(
-                model_data["input_slot_info"]
-            )
-
-            kpi_calculators.append(
-                kpic_factory.create_model(model_data)
-            )
-
-        return kpi_calculators
-
     def _extract_mco_parameters(self, mco_id, parameters_data):
         """Extracts the MCO parameters from the data as dictionary.
 
diff --git a/force_bdss/io/workflow_writer.py b/force_bdss/io/workflow_writer.py
index 22a7f185040f75afffe1b066c1c3111608a72459..f47981f7a77609adc6a472c9eb223e9265fad3aa 100644
--- a/force_bdss/io/workflow_writer.py
+++ b/force_bdss/io/workflow_writer.py
@@ -25,9 +25,6 @@ class WorkflowWriter(HasStrictTraits):
     def _workflow_data(self, workflow):
         workflow_data = {
             "mco": self._mco_data(workflow.mco),
-            "kpi_calculators": [
-                self._model_data(kpic)
-                for kpic in workflow.kpi_calculators],
             "execution_layers": [
                 self._execution_layer_data(el)
                 for el in workflow.execution_layers],
diff --git a/force_bdss/kpi/__init__.py b/force_bdss/kpi/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/force_bdss/kpi/base_kpi_calculator.py b/force_bdss/kpi/base_kpi_calculator.py
deleted file mode 100644
index 0ba7607dc029a26a97b472d3df4f919cf417baad..0000000000000000000000000000000000000000
--- a/force_bdss/kpi/base_kpi_calculator.py
+++ /dev/null
@@ -1,69 +0,0 @@
-import abc
-
-from traits.api import ABCHasStrictTraits, Instance
-
-from .i_kpi_calculator_factory import IKPICalculatorFactory
-
-
-class BaseKPICalculator(ABCHasStrictTraits):
-    """Base class for the KPICalculators.
-
-    Inherit this class for your KPI calculator.
-    """
-    #: A reference to the factory
-    factory = Instance(IKPICalculatorFactory)
-
-    def __init__(self, factory, *args, **kwargs):
-        self.factory = factory
-        super(BaseKPICalculator, self).__init__(*args, **kwargs)
-
-    @abc.abstractmethod
-    def run(self, model, data_values):
-        """
-        Executes the KPI evaluation and returns the results it computes.
-        Reimplement this method in your specific KPI calculator.
-
-        Parameters
-        ----------
-        model: BaseKPICalculatorModel
-            The model of the KPI Calculator, instantiated through
-            create_model()
-
-        data_values:
-            a list of DataValue instances containing data from the
-            MCO and DataSources.
-
-        Returns
-        -------
-        List[DataValue]:
-            The result of this KPI evaluation, as a list of DataValues.
-        """
-
-    @abc.abstractmethod
-    def slots(self, model):
-        """Returns the input (and output) slots of the KPI Calculator.
-        Slots are the entities that are needed (and produced) by this
-        KPI Calculator.
-
-        The slots may depend on the configuration options, and thus the model.
-        This allows, for example, to change the slots depending if an option
-        is enabled or not.
-
-        Parameters
-        ----------
-        model: BaseKPICalculatorModel
-            The model of the KPICalculator, instantiated through create_model()
-
-        Returns
-        -------
-        (input_slots, output_slots): tuple[tuple, tuple]
-            A tuple containing two tuples.
-            The first element is the input slots, the second element is
-            the output slots. Each slot must be an instance of the Slot class.
-            It is possible for each of the two inside tuples to be empty.
-            The case of an empty input slot is common: the KPICalculator does
-            not need any information from the MCO to operate.
-            The case of an empty output slot is uncommon, but supported:
-            the KPICalculator does not produce any output and is therefore
-            useless.
-        """
diff --git a/force_bdss/kpi/base_kpi_calculator_factory.py b/force_bdss/kpi/base_kpi_calculator_factory.py
deleted file mode 100644
index de210b58c5adb6b5f99d7a9d1e56d521c99d741b..0000000000000000000000000000000000000000
--- a/force_bdss/kpi/base_kpi_calculator_factory.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import logging
-from envisage.plugin import Plugin
-from traits.api import ABCHasStrictTraits, provides, String, Instance, Type
-
-from force_bdss.kpi.base_kpi_calculator import BaseKPICalculator
-from force_bdss.kpi.base_kpi_calculator_model import BaseKPICalculatorModel
-from .i_kpi_calculator_factory import IKPICalculatorFactory
-
-
-log = logging.getLogger(__name__)
-
-
-@provides(IKPICalculatorFactory)
-class BaseKPICalculatorFactory(ABCHasStrictTraits):
-    """Base class for the Key Performance Indicator calculator factories.
-    Inherit from this class to create a factory, and reimplement the abstract
-    methods.
-    """
-    # NOTE: any changes in this interface must be ported to
-    # IKPICalculatorFactory
-
-    #: A unique ID generated with factory_id() routine
-    id = String()
-
-    #: A UI friendly name for the factory. Can contain spaces.
-    name = String()
-
-    #: The KPI calculator to be instantiated. Define this to your KPICalculator
-    kpi_calculator_class = Type(BaseKPICalculator)
-
-    #: The model associated to the KPI calculator.
-    #: Define this to your KPICalculatorModel
-    model_class = Type(BaseKPICalculatorModel)
-
-    #: A reference to the plugin that holds this factory.
-    plugin = Instance(Plugin)
-
-    def __init__(self, plugin, *args, **kwargs):
-        """Initializes the instance.
-
-        Parameters
-        ----------
-        plugin: Plugin
-            The plugin that holds this factory.
-        """
-        self.plugin = plugin
-        super(BaseKPICalculatorFactory, self).__init__(*args, **kwargs)
-
-    def create_kpi_calculator(self):
-        """Factory method.
-        Creates and returns an instance of a KPI Calculator, associated
-        to the given application and model.
-
-        Returns
-        -------
-        BaseKPICalculator
-            The specific instance of the generated KPICalculator
-        """
-        if self.kpi_calculator_class is None:
-            msg = ("kpi_calculator_class cannot be None in {}. Either define "
-                   "kpi_calculator_class or reimplement create_kpi_calculator "
-                   "on your factory class.".format(self.__class__.__name__))
-            log.error(msg)
-            raise RuntimeError(msg)
-
-        return self.kpi_calculator_class(self)
-
-    def create_model(self, model_data=None):
-        """Factory method.
-        Creates the model object (or network of model objects) of the KPI
-        calculator. The model can provide a traits UI View according to
-        traitsui specifications, so that a UI can be provided automatically.
-
-        Parameters
-        ----------
-        model_data: dict or None
-            A dictionary containing the information to recreate the model.
-            If None, an empty (with defaults) model will be returned.
-
-        Returns
-        -------
-        BaseKPICalculatorModel
-            The model
-        """
-        if model_data is None:
-            model_data = {}
-
-        if self.model_class is None:
-            msg = ("model_class cannot be None in {}. Either define "
-                   "model_class or reimplement create_model on your "
-                   "factory class.".format(self.__class__.__name__))
-            log.error(msg)
-            raise RuntimeError(msg)
-
-        return self.model_class(self, **model_data)
diff --git a/force_bdss/kpi/base_kpi_calculator_model.py b/force_bdss/kpi/base_kpi_calculator_model.py
deleted file mode 100644
index 425af9e8cbcddaae589a53645e8194f61040ebe6..0000000000000000000000000000000000000000
--- a/force_bdss/kpi/base_kpi_calculator_model.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from traits.api import ABCHasStrictTraits, Instance, List, Event
-
-from force_bdss.core.output_slot_info import OutputSlotInfo
-from ..core.input_slot_info import InputSlotInfo
-from .i_kpi_calculator_factory import IKPICalculatorFactory
-
-
-class BaseKPICalculatorModel(ABCHasStrictTraits):
-    """Base class for the factory specific KPI calculator models.
-    This model will also provide, through traits/traitsui magic the View
-    that will appear in the workflow manager UI.
-
-    In your factory definition, your factory-specific model must reimplement
-    this class.
-    """
-    #: A reference to the creating factory, so that we can
-    #: retrieve it as the originating factory.
-    factory = Instance(IKPICalculatorFactory, visible=False, transient=True)
-
-    #: Specifies binding between input slots and source for that value.
-    #: Each InputSlotMap instance specifies this information for each of the
-    #: slots.
-    input_slot_info = List(Instance(InputSlotInfo), visible=False)
-
-    #: Allows to assign names to the output slots, so that they can be
-    #: referenced somewhere else (e.g. the KPICalculators).
-    #: If the name is the empty string, it means that the user is not
-    #: interested in preserving the information, and should therefore be
-    #: discarded and not propagated further.
-    output_slot_info = List(Instance(OutputSlotInfo), visible=False)
-
-    #: This event claims that a change in the model influences the slots
-    #: (either input or output). It must be triggered every time a specific
-    #: option in your model implies a change in the slots. The UI will detect
-    #: this and adapt the visual entries.
-    changes_slots = Event()
-
-    def __init__(self, factory, *args, **kwargs):
-        self.factory = factory
-        super(BaseKPICalculatorModel, self).__init__(*args, **kwargs)
-
-    def __getstate__(self):
-        state = super(BaseKPICalculatorModel, self).__getstate__()
-        state["input_slot_info"] = [
-            x.__getstate__() for x in self.input_slot_info
-            ]
-        state["output_slot_info"] = [
-            x.__getstate__() for x in self.output_slot_info
-        ]
-        return state
diff --git a/force_bdss/kpi/i_kpi_calculator_factory.py b/force_bdss/kpi/i_kpi_calculator_factory.py
deleted file mode 100644
index 2877217a97d71be232cdd883dc9b2561482e7369..0000000000000000000000000000000000000000
--- a/force_bdss/kpi/i_kpi_calculator_factory.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from traits.api import Interface, String, Instance, Type
-from envisage.plugin import Plugin
-
-
-class IKPICalculatorFactory(Interface):
-    """Envisage required interface for the BaseKPICalculatorFactory.
-    You should not need to use this directly.
-
-    Refer to the BaseKPICalculatorFactory for documentation.
-    """
-    id = String()
-
-    name = String()
-
-    kpi_calculator_class = Type(
-        "force_bdss.kpi.base_kpi_calculator.BaseKPICalculator"
-    )
-
-    model_class = Type(
-        "force_bdss.kpi.base_kpi_calculator_model.BaseKPICalculatorModel"
-    )
-
-    plugin = Instance(Plugin)
-
-    def create_kpi_calculator(self):
-        """"""
-
-    def create_model(self, model_data=None):
-        """"""
diff --git a/force_bdss/kpi/tests/__init__.py b/force_bdss/kpi/tests/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/force_bdss/kpi/tests/test_base_kpi_calculator.py b/force_bdss/kpi/tests/test_base_kpi_calculator.py
deleted file mode 100644
index 945a49a1ba72b49c586fa06735a17361b4e5b85d..0000000000000000000000000000000000000000
--- a/force_bdss/kpi/tests/test_base_kpi_calculator.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import unittest
-try:
-    import mock
-except ImportError:
-    from unittest import mock
-
-from force_bdss.kpi.base_kpi_calculator import BaseKPICalculator
-from force_bdss.kpi.i_kpi_calculator_factory import IKPICalculatorFactory
-
-
-class DummyKPICalculator(BaseKPICalculator):
-    def run(self, *args, **kwargs):
-        pass
-
-    def slots(self, model):
-        return (), ()
-
-
-class TestBaseKPICalculator(unittest.TestCase):
-    def test_initialization(self):
-        factory = mock.Mock(spec=IKPICalculatorFactory)
-        kpic = DummyKPICalculator(factory)
-
-        self.assertEqual(kpic.factory, factory)
diff --git a/force_bdss/kpi/tests/test_base_kpi_calculator_factory.py b/force_bdss/kpi/tests/test_base_kpi_calculator_factory.py
deleted file mode 100644
index 91a81a3ce2bd93bc22be9f320c27c878abccae70..0000000000000000000000000000000000000000
--- a/force_bdss/kpi/tests/test_base_kpi_calculator_factory.py
+++ /dev/null
@@ -1,64 +0,0 @@
-import unittest
-import testfixtures
-from envisage.plugin import Plugin
-
-from force_bdss.kpi.tests.test_base_kpi_calculator import DummyKPICalculator
-from force_bdss.kpi.tests.test_base_kpi_calculator_model import \
-    DummyKPICalculatorModel
-
-try:
-    import mock
-except ImportError:
-    from unittest import mock
-
-from force_bdss.kpi.base_kpi_calculator_factory import \
-    BaseKPICalculatorFactory
-
-
-class DummyKPICalculatorFactory(BaseKPICalculatorFactory):
-    id = "foo"
-
-    name = "bar"
-
-    def create_kpi_calculator(self):
-        pass
-
-    def create_model(self, model_data=None):
-        pass
-
-
-class DummyKPICalculatorFactoryFast(BaseKPICalculatorFactory):
-    id = "foo"
-
-    name = "bar"
-
-    kpi_calculator_class = DummyKPICalculator
-
-    model_class = DummyKPICalculatorModel
-
-
-class TestBaseKPICalculatorFactory(unittest.TestCase):
-    def test_initialization(self):
-        factory = DummyKPICalculatorFactory(mock.Mock(spec=Plugin))
-        self.assertEqual(factory.id, 'foo')
-        self.assertEqual(factory.name, 'bar')
-
-    def test_fast_definition(self):
-        factory = DummyKPICalculatorFactoryFast(mock.Mock(spec=Plugin))
-        self.assertIsInstance(factory.create_kpi_calculator(),
-                              DummyKPICalculator)
-
-        self.assertIsInstance(factory.create_model(),
-                              DummyKPICalculatorModel)
-
-    def test_fast_definition_errors(self):
-        factory = DummyKPICalculatorFactoryFast(mock.Mock(spec=Plugin))
-        factory.kpi_calculator_class = None
-        factory.model_class = None
-
-        with testfixtures.LogCapture():
-            with self.assertRaises(RuntimeError):
-                factory.create_kpi_calculator()
-
-            with self.assertRaises(RuntimeError):
-                factory.create_model()
diff --git a/force_bdss/kpi/tests/test_base_kpi_calculator_model.py b/force_bdss/kpi/tests/test_base_kpi_calculator_model.py
deleted file mode 100644
index c8f36d330875eb3822b18a5d28a2580673641e93..0000000000000000000000000000000000000000
--- a/force_bdss/kpi/tests/test_base_kpi_calculator_model.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import unittest
-
-from force_bdss.core.input_slot_info import InputSlotInfo
-from force_bdss.core.output_slot_info import OutputSlotInfo
-from force_bdss.kpi.base_kpi_calculator_factory import BaseKPICalculatorFactory
-from force_bdss.kpi.base_kpi_calculator_model import BaseKPICalculatorModel
-
-try:
-    import mock
-except ImportError:
-    from unittest import mock
-
-
-class DummyKPICalculatorModel(BaseKPICalculatorModel):
-    pass
-
-
-class TestBaseKPICalculatorModel(unittest.TestCase):
-    def test_getstate(self):
-        model = DummyKPICalculatorModel(
-            mock.Mock(spec=BaseKPICalculatorFactory))
-        self.assertEqual(
-            model.__getstate__(),
-            {
-                "__traits_version__": "4.6.0",
-                "input_slot_info": [],
-                "output_slot_info": []
-            })
-
-        model.input_slot_info = [
-            InputSlotInfo(name="foo"),
-            InputSlotInfo(name="bar")
-        ]
-        model.output_slot_info = [
-            OutputSlotInfo(name="baz"),
-            OutputSlotInfo(name="quux")
-        ]
-
-        self.assertEqual(
-            model.__getstate__(),
-            {
-                "__traits_version__": "4.6.0",
-                "input_slot_info": [
-                    {
-                        "__traits_version__": "4.6.0",
-                        "source": "Environment",
-                        "name": "foo"
-                    },
-                    {
-                        "__traits_version__": "4.6.0",
-                        "source": "Environment",
-                        "name": "bar"
-                    }
-                ],
-                "output_slot_info": [
-                    {
-                        "__traits_version__": "4.6.0",
-                        "name": "baz",
-                        "is_kpi": False,
-                    },
-                    {
-                        "__traits_version__": "4.6.0",
-                        "name": "quux",
-                        "is_kpi": False,
-                    }
-                ]
-            })
diff --git a/force_bdss/tests/probe_classes/factory_registry_plugin.py b/force_bdss/tests/probe_classes/factory_registry_plugin.py
index b5d1dfea47504ae86811d6c4c5bb7be3d37d25ef..28115d26817a24880937b08e1ab4f2de3b3c6527 100644
--- a/force_bdss/tests/probe_classes/factory_registry_plugin.py
+++ b/force_bdss/tests/probe_classes/factory_registry_plugin.py
@@ -3,7 +3,6 @@ from traits.api import List, HasStrictTraits, provides
 from force_bdss.factory_registry_plugin import IFactoryRegistryPlugin
 
 from .mco import ProbeMCOFactory
-from .kpi_calculator import ProbeKPICalculatorFactory
 from .data_source import ProbeDataSourceFactory
 from .notification_listener import ProbeNotificationListenerFactory
 from .ui_hooks import ProbeUIHooksFactory
@@ -20,9 +19,6 @@ class ProbeFactoryRegistryPlugin(HasStrictTraits):
     def _mco_factories_default(self):
         return [ProbeMCOFactory(None)]
 
-    def _kpi_calculator_factories_default(self):
-        return [ProbeKPICalculatorFactory(None)]
-
     def _data_source_factories_default(self):
         return [ProbeDataSourceFactory(None)]
 
diff --git a/force_bdss/tests/probe_classes/kpi_calculator.py b/force_bdss/tests/probe_classes/kpi_calculator.py
deleted file mode 100644
index befdfb1366b869a600a94780356445dbcc6dabb1..0000000000000000000000000000000000000000
--- a/force_bdss/tests/probe_classes/kpi_calculator.py
+++ /dev/null
@@ -1,73 +0,0 @@
-from traits.api import Bool, Function, Str, Int, on_trait_change, Type
-
-from force_bdss.ids import factory_id
-from force_bdss.api import (
-    BaseKPICalculatorFactory, BaseKPICalculatorModel, BaseKPICalculator,
-    Slot
-)
-
-from .evaluator_factory import ProbeEvaluatorFactory
-
-
-def run_func(*args, **kwargs):
-    return []
-
-
-class ProbeKPICalculator(BaseKPICalculator):
-    run_function = Function(default_value=run_func)
-
-    run_called = Bool(False)
-    slots_called = Bool(False)
-
-    def run(self, model, parameters):
-        self.run_called = True
-        return self.run_function(model, parameters)
-
-    def slots(self, model):
-        self.slots_called = True
-        return (
-            tuple(Slot(type=model.input_slots_type)
-                  for _ in range(model.input_slots_size))
-        ), (
-            tuple(Slot(type=model.output_slots_type)
-                  for _ in range(model.output_slots_size))
-        )
-
-
-class ProbeKPICalculatorModel(BaseKPICalculatorModel):
-    input_slots_type = Str('PRESSURE')
-    output_slots_type = Str('PRESSURE')
-
-    input_slots_size = Int(0)
-    output_slots_size = Int(0)
-
-    @on_trait_change('input_slots_type,output_slots_type,'
-                     'input_slots_size,output_slots_size')
-    def update_slots(self):
-        self.changes_slots = True
-
-
-class ProbeKPICalculatorFactory(BaseKPICalculatorFactory,
-                                ProbeEvaluatorFactory):
-    id = Str(factory_id("enthought", "test_kpic"))
-    name = Str('test_kpi_calculator')
-
-    model_class = Type(ProbeKPICalculatorModel)
-
-    def create_model(self, model_data=None):
-        if model_data is None:
-            model_data = {}
-        return self.model_class(
-            factory=self,
-            input_slots_type=self.input_slots_type,
-            output_slots_type=self.output_slots_type,
-            input_slots_size=self.input_slots_size,
-            output_slots_size=self.output_slots_size,
-            **model_data
-        )
-
-    def create_kpi_calculator(self):
-        return ProbeKPICalculator(
-            factory=self,
-            run_function=self.run_function,
-        )
diff --git a/force_bdss/tests/test_core_evaluation_driver.py b/force_bdss/tests/test_core_evaluation_driver.py
index c10fed256608334c8502962c3bd3328c3be6ca4c..ffbbf86b32c1e23e9b49ad89758eaf9a11c11460 100644
--- a/force_bdss/tests/test_core_evaluation_driver.py
+++ b/force_bdss/tests/test_core_evaluation_driver.py
@@ -9,8 +9,6 @@ from force_bdss.tests.probe_classes.factory_registry_plugin import \
     ProbeFactoryRegistryPlugin
 from force_bdss.tests.probe_classes.mco import ProbeMCOFactory
 from force_bdss.tests.probe_classes.data_source import ProbeDataSourceFactory
-from force_bdss.tests.probe_classes.kpi_calculator import (
-    ProbeKPICalculatorFactory)
 
 from force_bdss.core.input_slot_info import InputSlotInfo
 from force_bdss.core.data_value import DataValue
@@ -104,51 +102,6 @@ class TestCoreEvaluationDriver(unittest.TestCase):
                     " the number of user-defined names"):
                 driver.application_started()
 
-    def test_error_for_incorrect_kpic_output_slots(self):
-        kpi_calculator_factories = \
-            self.factory_registry_plugin.kpi_calculator_factories
-
-        def run(self, *args, **kwargs):
-            return [DataValue()]
-        kpi_calculator_factories[0] = ProbeKPICalculatorFactory(
-            None,
-            run_function=run)
-        driver = CoreEvaluationDriver(
-            application=self.mock_application,
-        )
-        with testfixtures.LogCapture():
-            with six.assertRaisesRegex(
-                    self,
-                    RuntimeError,
-                    "The number of data values \(1 values\)"
-                    " returned by 'test_kpi_calculator' does not match"
-                    " the number of output slots"):
-
-                driver.application_started()
-
-    def test_error_for_missing_kpic_output_names(self):
-        kpi_calculator_factories = \
-            self.factory_registry_plugin.kpi_calculator_factories
-
-        def run(self, *args, **kwargs):
-            return [DataValue()]
-        kpi_calculator_factories[0] = ProbeKPICalculatorFactory(
-            None,
-            run_function=run,
-            output_slots_size=1)
-        driver = CoreEvaluationDriver(
-            application=self.mock_application,
-        )
-
-        with testfixtures.LogCapture():
-            with six.assertRaisesRegex(
-                    self,
-                    RuntimeError,
-                    "The number of data values \(1 values\)"
-                    " returned by 'test_kpi_calculator' does not match"
-                    " the number of user-defined names"):
-                driver.application_started()
-
     def test_bind_data_values(self):
         data_values = [
             DataValue(name="foo"),
@@ -227,7 +180,6 @@ class TestCoreEvaluationDriver(unittest.TestCase):
         res = _compute_layer_results(
             data_values,
             [evaluator_model],
-            "create_data_source"
         )
         self.assertEqual(len(res), 2)
         self.assertEqual(res[0].name, "one")
@@ -243,10 +195,10 @@ class TestCoreEvaluationDriver(unittest.TestCase):
         #                    res3
         # layer 2:        res3 * res1
         #                     res4
-        # kpi layer:      res4 * res2
-        #
+        # layer 3:        res4 * res2
+        #                     out1
         # Final result should be
-        # ((in1 + in2 + in3 + in4) * (in1 + in2) * (in3 + in4)
+        # out1 = ((in1 + in2 + in3 + in4) * (in1 + in2) * (in3 + in4)
 
         data_values = [
             DataValue(value=10, name="in1"),
@@ -278,14 +230,9 @@ class TestCoreEvaluationDriver(unittest.TestCase):
             output_slots_size=1,
             run_function=multiplier)
 
-        multiplier_kpi_factory = ProbeKPICalculatorFactory(
-            None,
-            input_slots_size=2,
-            output_slots_size=1,
-            run_function=multiplier)
-
         wf = Workflow(
             execution_layers=[
+                [],
                 [],
                 [],
                 []
@@ -334,16 +281,16 @@ class TestCoreEvaluationDriver(unittest.TestCase):
         ]
         wf.execution_layers[2].append(model)
 
-        # KPI layer
-        model = multiplier_kpi_factory.create_model()
+        # layer 3
+        model = multiplier_factory.create_model()
         model.input_slot_info = [
             InputSlotInfo(name="res4"),
             InputSlotInfo(name="res2")
         ]
         model.output_slot_info = [
-            OutputSlotInfo(name="out1")
+            OutputSlotInfo(name="out1", is_kpi=True)
         ]
-        wf.kpi_calculators.append(model)
+        wf.execution_layers[3].append(model)
 
         kpi_results = execute_workflow(wf, data_values)
         self.assertEqual(len(kpi_results), 1)
diff --git a/force_bdss/tests/test_factory_registry_plugin.py b/force_bdss/tests/test_factory_registry_plugin.py
index fccc89aa42d3c019c0b619989d5fb4e421d8fcea..459050fa11b802a5977cde2436fa314493422946 100644
--- a/force_bdss/tests/test_factory_registry_plugin.py
+++ b/force_bdss/tests/test_factory_registry_plugin.py
@@ -18,9 +18,7 @@ from envisage.application import Application
 
 from force_bdss.factory_registry_plugin import FactoryRegistryPlugin
 from force_bdss.data_sources.i_data_source_factory import IDataSourceFactory
-from force_bdss.kpi.i_kpi_calculator_factory import IKPICalculatorFactory
-from force_bdss.mco.i_mco_factory import \
-    IMCOFactory
+from force_bdss.mco.i_mco_factory import IMCOFactory
 
 
 class TestFactoryRegistry(unittest.TestCase):
@@ -33,7 +31,6 @@ class TestFactoryRegistry(unittest.TestCase):
     def test_initialization(self):
         self.assertEqual(self.plugin.mco_factories, [])
         self.assertEqual(self.plugin.data_source_factories, [])
-        self.assertEqual(self.plugin.kpi_calculator_factories, [])
 
 
 class MySuperPlugin(BaseExtensionPlugin):
@@ -56,14 +53,6 @@ class MySuperPlugin(BaseExtensionPlugin):
                 mock.Mock(spec=IDataSourceFactory,
                           id=factory_id("enthought", "ds2"))]
 
-    def _kpi_calculator_factories_default(self):
-        return [mock.Mock(spec=IKPICalculatorFactory,
-                          id=factory_id("enthought", "kpi1")),
-                mock.Mock(spec=IKPICalculatorFactory,
-                          id=factory_id("enthought", "kpi2")),
-                mock.Mock(spec=IKPICalculatorFactory,
-                          id=factory_id("enthought", "kpi3"))]
-
     def _notification_listener_factories_default(self):
         return [mock.Mock(spec=INotificationListenerFactory,
                           id=factory_id("enthought", "nl1"))]
@@ -81,7 +70,6 @@ class TestFactoryRegistryWithContent(unittest.TestCase):
     def test_initialization(self):
         self.assertEqual(len(self.plugin.mco_factories), 1)
         self.assertEqual(len(self.plugin.data_source_factories), 2)
-        self.assertEqual(len(self.plugin.kpi_calculator_factories), 3)
 
     def test_lookup(self):
         mco_id = factory_id("enthought", "mco1")
@@ -93,11 +81,6 @@ class TestFactoryRegistryWithContent(unittest.TestCase):
             id = factory_id("enthought", entry)
             self.assertEqual(self.plugin.data_source_factory_by_id(id).id, id)
 
-        for entry in ["kpi1", "kpi2", "kpi3"]:
-            id = factory_id("enthought", entry)
-            self.assertEqual(self.plugin.kpi_calculator_factory_by_id(id).id,
-                             id)
-
         for entry in ["nl1"]:
             id = factory_id("enthought", entry)
             self.assertEqual(
@@ -124,11 +107,6 @@ class TestFactoryRegistryWithContent(unittest.TestCase):
                 factory_id("enthought", "foo")
             )
 
-        with self.assertRaises(KeyError):
-            self.plugin.kpi_calculator_factory_by_id(
-                factory_id("enthought", "foo")
-            )
-
         with self.assertRaises(KeyError):
             self.plugin.notification_listener_factory_by_id(
                 factory_id("enthought", "foo")