From c2661a08bd251815ee4915ef3eb8602956650b36 Mon Sep 17 00:00:00 2001 From: Tanguy Damart Date: Tue, 23 Feb 2021 15:32:47 +0100 Subject: [PATCH 1/2] Add feature computation functions to CellEvaluator, ObjectivesCalculator and Objectives --- bluepyopt/ephys/evaluators.py | 26 ++++++++++++++++-------- bluepyopt/ephys/objectives.py | 14 +++++++++++++ bluepyopt/ephys/objectivescalculators.py | 6 ++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/bluepyopt/ephys/evaluators.py b/bluepyopt/ephys/evaluators.py index 7db58279..fd7ecc1e 100644 --- a/bluepyopt/ephys/evaluators.py +++ b/bluepyopt/ephys/evaluators.py @@ -182,34 +182,44 @@ def run_protocols(self, protocols, param_values): return responses - def evaluate_with_dicts(self, param_dict=None): + def evaluate_with_dicts(self, param_dict=None, target='scores'): """Run evaluation with dict as input and output""" - + + if target not in ['scores', 'values']: + raise Exception( + 'CellEvaluator: target has to be "scores" or "values".') + if self.fitness_calculator is None: raise Exception( 'CellEvaluator: need fitness_calculator to evaluate') logger.debug('Evaluating %s', self.cell_model.name) - + responses = self.run_protocols( self.fitness_protocols.values(), param_dict) - return self.fitness_calculator.calculate_scores(responses) + if target == 'scores': + return self.fitness_calculator.calculate_scores(responses) + + elif target == 'values': + return self.fitness_calculator.calculate_values(responses) - def evaluate_with_lists(self, param_list=None): + def evaluate_with_lists(self, param_list=None, target='scores'): """Run evaluation with lists as input and outputs""" param_dict = self.param_dict(param_list) - obj_dict = self.evaluate_with_dicts(param_dict=param_dict) + obj_dict = self.evaluate_with_dicts( + param_dict=param_dict, target=target + ) return self.objective_list(obj_dict) - def evaluate(self, param_list=None): + def evaluate(self, param_list=None, target='scores'): """Run evaluation with lists as input and outputs""" - return self.evaluate_with_lists(param_list) + return self.evaluate_with_lists(param_list, target=target) def __str__(self): diff --git a/bluepyopt/ephys/objectives.py b/bluepyopt/ephys/objectives.py index eb1833a6..ae8deb34 100644 --- a/bluepyopt/ephys/objectives.py +++ b/bluepyopt/ephys/objectives.py @@ -47,6 +47,15 @@ def calculate_feature_scores(self, responses): return scores + def calculate_feature_values(self, responses): + """Calculate the value of an individual features""" + + values = [] + for feature in self.features: + values.append(feature.calculate_feature(responses)) + + return values + class SingletonObjective(EFeatureObjective): @@ -66,6 +75,11 @@ def calculate_score(self, responses): """Objective score""" return self.calculate_feature_scores(responses)[0] + + def calculate_value(self, responses): + """Objective value""" + + return self.calculate_feature_values(responses)[0] def __str__(self): """String representation""" diff --git a/bluepyopt/ephys/objectivescalculators.py b/bluepyopt/ephys/objectivescalculators.py index 177d092d..0465e32d 100644 --- a/bluepyopt/ephys/objectivescalculators.py +++ b/bluepyopt/ephys/objectivescalculators.py @@ -41,6 +41,12 @@ def calculate_scores(self, responses): return {objective.name: objective.calculate_score(responses) for objective in self.objectives} + def calculate_values(self, responses): + """Calculator the value of each objective""" + + return {objective.name: objective.calculate_value(responses) + for objective in self.objectives} + def __str__(self): return 'objectives:\n %s' % '\n '.join( [str(obj) for obj in self.objectives]) \ From 42dd6bb9465243c7b0d3b23edc88493dbc536052 Mon Sep 17 00:00:00 2001 From: Tanguy Damart Date: Tue, 23 Feb 2021 17:48:35 +0100 Subject: [PATCH 2/2] Add tests --- bluepyopt/ephys/evaluators.py | 6 +++--- bluepyopt/ephys/objectives.py | 2 +- bluepyopt/tests/test_ephys/test_evaluators.py | 7 +++++++ bluepyopt/tests/test_ephys/test_objectives.py | 2 ++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/bluepyopt/ephys/evaluators.py b/bluepyopt/ephys/evaluators.py index fd7ecc1e..51b7f101 100644 --- a/bluepyopt/ephys/evaluators.py +++ b/bluepyopt/ephys/evaluators.py @@ -184,17 +184,17 @@ def run_protocols(self, protocols, param_values): def evaluate_with_dicts(self, param_dict=None, target='scores'): """Run evaluation with dict as input and output""" - + if target not in ['scores', 'values']: raise Exception( 'CellEvaluator: target has to be "scores" or "values".') - + if self.fitness_calculator is None: raise Exception( 'CellEvaluator: need fitness_calculator to evaluate') logger.debug('Evaluating %s', self.cell_model.name) - + responses = self.run_protocols( self.fitness_protocols.values(), param_dict) diff --git a/bluepyopt/ephys/objectives.py b/bluepyopt/ephys/objectives.py index ae8deb34..5031c223 100644 --- a/bluepyopt/ephys/objectives.py +++ b/bluepyopt/ephys/objectives.py @@ -75,7 +75,7 @@ def calculate_score(self, responses): """Objective score""" return self.calculate_feature_scores(responses)[0] - + def calculate_value(self, responses): """Objective value""" diff --git a/bluepyopt/tests/test_ephys/test_evaluators.py b/bluepyopt/tests/test_ephys/test_evaluators.py index a3f64408..16338777 100644 --- a/bluepyopt/tests/test_ephys/test_evaluators.py +++ b/bluepyopt/tests/test_ephys/test_evaluators.py @@ -110,7 +110,11 @@ def test_CellEvaluator_evaluate(): sim=sim) responses = protocol.run(cell_model, {'cm': 1.0}, sim=sim) + feature_value = efeature.calculate_feature(responses) + feature_value_eva = evaluator.evaluate_with_dicts( + {'cm': 1.0}, target='values' + ) score = evaluator.evaluate([1.0]) expected_score = abs(mean - feature_value) @@ -120,3 +124,6 @@ def test_CellEvaluator_evaluate(): score_dict = evaluator.objective_dict(score) nt.assert_almost_equal(score_dict['singleton'], expected_score) + nt.assert_almost_equal( + feature_value, feature_value_eva['singleton'] + ) diff --git a/bluepyopt/tests/test_ephys/test_objectives.py b/bluepyopt/tests/test_ephys/test_objectives.py index 7b236705..57e2dc9b 100644 --- a/bluepyopt/tests/test_ephys/test_objectives.py +++ b/bluepyopt/tests/test_ephys/test_objectives.py @@ -79,10 +79,12 @@ def test_SingletonObjective(): responses = {'square_pulse_step1.soma.v': response, } efeature_value = efeature.calculate_feature(responses) + efeature_value_obj = s_obj.calculate_value(responses) nt.assert_almost_equal( s_obj.calculate_score(responses), abs(efeature_value - mean)) + nt.assert_almost_equal(efeature_value_obj, efeature_value) @attr('unit')