Skip to content
Snippets Groups Projects
Commit a22d9456 authored by Stefano Borini's avatar Stefano Borini
Browse files

Added basic infrastructure for KPI calculators

parent 2493cfe2
No related branches found
No related tags found
1 merge request!11Kpi calculators
Showing
with 194 additions and 5 deletions
...@@ -12,6 +12,24 @@ ...@@ -12,6 +12,24 @@
"column": 5, "column": 5,
"cuba_type": "PRESSURE" "cuba_type": "PRESSURE"
} }
},
{
"name": "csv_extractor",
"model_data": {
"filename": "foo.csv",
"row": 3,
"column": 5,
"cuba_type": "PRESSURE"
}
}
],
"kpi_calculators": [
{
"name": "kpi_adder",
"model_data": {
"cuba_type_in": "PRESSURE",
"cuba_type_out": "TOTAL_PRESSURE"
}
} }
] ]
} }
......
...@@ -5,6 +5,7 @@ from traits.trait_types import List ...@@ -5,6 +5,7 @@ from traits.trait_types import List
from force_bdss.data_sources.i_data_source_bundle import ( from force_bdss.data_sources.i_data_source_bundle import (
IDataSourceBundle) IDataSourceBundle)
from force_bdss.kpi.i_kpi_calculator_bundle import IKPICalculatorBundle
from force_bdss.mco.i_multi_criteria_optimizer_bundle import ( from force_bdss.mco.i_multi_criteria_optimizer_bundle import (
IMultiCriteriaOptimizerBundle) IMultiCriteriaOptimizerBundle)
...@@ -25,12 +26,18 @@ class CoreMCODriver(Plugin): ...@@ -25,12 +26,18 @@ class CoreMCODriver(Plugin):
List(IMultiCriteriaOptimizerBundle), List(IMultiCriteriaOptimizerBundle),
id='force.bdss.mco.bundles') id='force.bdss.mco.bundles')
#: A list of the available Key Performance Indicator calculators. #: A list of the available Data Sources.
#: It will be populated by plugins. #: It will be populated by plugins.
data_source_bundles = ExtensionPoint( data_source_bundles = ExtensionPoint(
List(IDataSourceBundle), List(IDataSourceBundle),
id='force.bdss.data_sources.bundles') id='force.bdss.data_sources.bundles')
#: A list of the available Key Performance Indicator calculators.
#: It will be populated by plugins.
kpi_calculator_bundles = ExtensionPoint(
List(IKPICalculatorBundle),
id='force.bdss.kpi_calculators.bundles')
@on_trait_change("application:started") @on_trait_change("application:started")
def application_started(self): def application_started(self):
workflow = self.application.workflow workflow = self.application.workflow
...@@ -47,6 +54,27 @@ class CoreMCODriver(Plugin): ...@@ -47,6 +54,27 @@ class CoreMCODriver(Plugin):
else: else:
raise Exception("Requested data source {} but don't know " raise Exception("Requested data source {} but don't know "
"to find it.".format(requested_ds.name)) "to find it.".format(requested_ds.name))
kpi_results = []
for requested_kpic in workflow.kpi_calculators:
kpic_bundle = self._find_kpi_calculator_bundle_by_name(
requested_kpic.name)
if kpic_bundle:
ds_model = kpic_bundle.create_model(
requested_kpic.model_data)
kpi_calculator = kpic_bundle.create_data_source(
self.application, ds_model)
kpi_results.append(kpi_calculator.run(ds_results))
else:
raise Exception(
"Requested kpi calculator {} but don't know "
"to find it.".format(requested_kpic.name))
print(
kpi_results[0].value_types,
kpi_results[0].values
)
else: else:
mco_data = workflow.multi_criteria_optimizer mco_data = workflow.multi_criteria_optimizer
mco_bundle = self._find_mco_bundle_by_name(mco_data.name) mco_bundle = self._find_mco_bundle_by_name(mco_data.name)
...@@ -65,6 +93,13 @@ class CoreMCODriver(Plugin): ...@@ -65,6 +93,13 @@ class CoreMCODriver(Plugin):
return None return None
def _find_kpi_calculator_bundle_by_name(self, name):
for kpic in self.kpi_calculator_bundles:
if kpic.name == name:
return kpic
return None
def _find_mco_bundle_by_name(self, name): def _find_mco_bundle_by_name(self, name):
for mco in self.mco_bundles: for mco in self.mco_bundles:
if mco.name == name: if mco.name == name:
......
...@@ -16,7 +16,8 @@ class CSVExtractorDataSource(BaseDataSource): ...@@ -16,7 +16,8 @@ class CSVExtractorDataSource(BaseDataSource):
return DataSourceResult( return DataSourceResult(
originator=self, originator=self,
value_types = [self.model.cuba_type], value_types = [self.model.cuba_type],
values=numpy.array(row[self.model.column]).reshape(1,1) values=numpy.array(
float(row[self.model.column])).reshape(1,1)
) )
return None return None
......
from traits.api import provides, HasStrictTraits
from traits.trait_types import String
from force_bdss.kpi.i_kpi_calculator_bundle import IKPICalculatorBundle
from .kpi_adder_model import KPIAdderModel
from .kpi_adder_calculator import KPIAdderCalculator
@provides(IKPICalculatorBundle)
class KPIAdderBundle(HasStrictTraits):
name = String("kpi_adder")
def create_model(self, model_data):
return KPIAdderModel.from_json(model_data)
def create_data_source(self, application, model):
return KPIAdderCalculator(self, application, model)
import numpy
from force_bdss.kpi.base_kpi_calculator import BaseKPICalculator
from force_bdss.kpi.kpi_calculator_result import KPICalculatorResult
class KPIAdderCalculator(BaseKPICalculator):
def run(self, data_source_results):
sum = 0.0
for res in data_source_results:
try:
value_idx = res.value_types.index(self.model.cuba_type_in)
except ValueError:
continue
sum += res.values[value_idx].sum()
return KPICalculatorResult(
originator=self,
value_types = [self.model.cuba_type_out],
values=numpy.array([sum])
)
from traits.api import HasStrictTraits, Int, String
class KPIAdderModel(HasStrictTraits):
cuba_type_in = String()
cuba_type_out = String()
@classmethod
def from_json(cls, json_data):
return cls(
cuba_type_in=json_data["cuba_type_in"],
cuba_type_out=json_data["cuba_type_out"]
)
from envisage.plugin import Plugin
from traits.api import List
from force_bdss.kpi.i_kpi_calculator_bundle import (
IKPICalculatorBundle)
from .kpi_adder.kpi_adder_bundle import KPIAdderBundle
class TestKPICalculatorPlugin(Plugin):
id = "force.bdss.kpi_calculators.test_kpi_calculator_plugin"
kpi_calculators = List(
IKPICalculatorBundle,
contributes_to='force.bdss.kpi_calculators.bundles'
)
def _kpi_calculators_default(self):
return [KPIAdderBundle()]
import abc
import six
class BaseKPICalculator(six.with_metaclass(abc.ABCMeta)):
def __init__(self, bundle, application, model):
self.bundle = bundle
self.application = application
self.model = model
@property
def name(self):
return self.bundle.name
@abc.abstractmethod
def run(self, data_source_results):
"""Executes the KPI evaluation and returns the list of results."""
pass
from traits.api import Interface, String
class IKPICalculatorBundle(Interface):
name = String()
def create_kpi_calculator(self, application, model):
pass
def create_model(self, model_data):
pass
from traits.api import HasTraits, List, Array, ArrayOrNone, String, Instance
from .base_kpi_calculator import BaseKPICalculator
class KPICalculatorResult(HasTraits):
originator = Instance(BaseKPICalculator)
value_types = List(String)
values = Array(shape=(None, ))
accuracy = ArrayOrNone(shape=(None, ))
quality = ArrayOrNone(shape=(None, ))
from traits.has_traits import HasStrictTraits
from traits.trait_types import String, Dict
class KPICalculator(HasStrictTraits):
name = String()
model_data = Dict()
@classmethod
def from_json(cls, json_data):
self = cls(
name=json_data["name"],
model_data=json_data["model_data"]
)
return self
from traits.api import HasStrictTraits, Instance, String, List from traits.api import HasStrictTraits, Instance, String, List
from force_bdss.workspecs.data_source import DataSource from force_bdss.workspecs.data_source import DataSource
from force_bdss.workspecs.kpi_calculator import KPICalculator
from .multi_criteria_optimizer import MultiCriteriaOptimizer from .multi_criteria_optimizer import MultiCriteriaOptimizer
...@@ -8,17 +9,20 @@ class Workflow(HasStrictTraits): ...@@ -8,17 +9,20 @@ class Workflow(HasStrictTraits):
name = String() name = String()
multi_criteria_optimizer = Instance(MultiCriteriaOptimizer) multi_criteria_optimizer = Instance(MultiCriteriaOptimizer)
data_sources = List(DataSource) data_sources = List(DataSource)
kpi_calculators = List(KPICalculator)
@classmethod @classmethod
def from_json(cls, json_data): def from_json(cls, json_data):
self = cls( self = cls(
multi_criteria_optimizer=MultiCriteriaOptimizer.from_json( multi_criteria_optimizer=MultiCriteriaOptimizer.from_json(
json_data["multi_criteria_optimizer"] json_data["multi_criteria_optimizer"]
), ),
data_sources=[ data_sources=[
DataSource.from_json(data_source_data) DataSource.from_json(data_source_data)
for data_source_data in json_data["data_sources"]] for data_source_data in json_data["data_sources"]],
) kpi_calculators=[
KPICalculator.from_json(kpi_calculator_data)
for kpi_calculator_data in json_data["kpi_calculators"]]
)
return self return self
...@@ -14,6 +14,8 @@ setup( ...@@ -14,6 +14,8 @@ setup(
"multi_criteria_optimizers_plugin:MultiCriteriaOptimizersPlugin", "multi_criteria_optimizers_plugin:MultiCriteriaOptimizersPlugin",
"csv_extractor = force_bdss.core_plugins.csv_extractor" "csv_extractor = force_bdss.core_plugins.csv_extractor"
".csv_extractor_plugin:CSVExtractorPlugin", ".csv_extractor_plugin:CSVExtractorPlugin",
"kpi_adder = force_bdss.core_plugins.test_kpi"
".test_kpi_calculator_plugin:TestKPICalculatorPlugin",
] ]
}, },
packages=find_packages(), packages=find_packages(),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment