diff --git a/bluepyemodel/efeatures_extraction/efeatures_extraction.py b/bluepyemodel/efeatures_extraction/efeatures_extraction.py index 2e3d6f50..36e53c7b 100644 --- a/bluepyemodel/efeatures_extraction/efeatures_extraction.py +++ b/bluepyemodel/efeatures_extraction/efeatures_extraction.py @@ -219,6 +219,24 @@ def extract_save_features_protocols(access_point, mapper=map): targets_configuration.protocols_mapping, ) + # correct for any weight present in features + for target in targets_configuration.targets: + if target.weight != 1.0: + try: + feat = next( + feat + for feat in fitness_calculator_config.efeatures + if feat.efel_feature_name == target.efeature + and feat.protocol_name == f"{target.protocol}_{target.amplitude}" + ) + feat.weight = target.weight + except StopIteration: + logger.debug( + "Could not find efeature with name %s and protocol %s", + target.efeature, + target.protocol, + ) + if access_point.pipeline_settings.bound_max_std: threshold_efeatures_std( fitness_calculator_config, access_point.pipeline_settings.default_std_value diff --git a/bluepyemodel/efeatures_extraction/target.py b/bluepyemodel/efeatures_extraction/target.py index 5df5020a..34a3e0a6 100644 --- a/bluepyemodel/efeatures_extraction/target.py +++ b/bluepyemodel/efeatures_extraction/target.py @@ -32,6 +32,7 @@ def __init__( tolerance, efeature_name=None, efel_settings=None, + weight=1.0, ): """Constructor @@ -50,6 +51,8 @@ def __init__( efeature_name (str): given name for this specific target. Can be different from the efel efeature name. efel_settings (dict): target specific efel settings. + weight (float): weight of the efeature. + Basically multiplies the score of the efeature by this value. """ self.efeature = efeature @@ -60,6 +63,8 @@ def __init__( self.efeature_name = efeature_name + self.weight = weight + if efel_settings is None: self.efel_settings = {"strict_stiminterval": True} else: diff --git a/bluepyemodel/efeatures_extraction/targets_configuration.py b/bluepyemodel/efeatures_extraction/targets_configuration.py index 5b8e4f62..ef072bcc 100644 --- a/bluepyemodel/efeatures_extraction/targets_configuration.py +++ b/bluepyemodel/efeatures_extraction/targets_configuration.py @@ -75,6 +75,7 @@ def __init__( "protocol": "IDRest", "amplitude": 150., "tolerance": 10., + "weight": 1.0, # optional "efel_settings": { 'stim_start': 200., 'stim_end': 500., diff --git a/bluepyemodel/evaluation/efeature_configuration.py b/bluepyemodel/evaluation/efeature_configuration.py index 2d96b6ee..67a9f541 100644 --- a/bluepyemodel/evaluation/efeature_configuration.py +++ b/bluepyemodel/evaluation/efeature_configuration.py @@ -33,6 +33,7 @@ def __init__( std=None, sample_size=None, default_std_value=1e-3, + weight=1.0, ): """Init. @@ -57,6 +58,8 @@ def __init__( the mean of the features value (optional). sample_size (float): number of data point that were used to compute the present average and standard deviation. + weight (float): weight of the efeature. + Basically multiplies the score of the efeature by this value. """ self.efel_feature_name = efel_feature_name @@ -70,6 +73,7 @@ def __init__( self.sample_size = sample_size self.efeature_name = efeature_name + self.weight = weight if efel_settings is None: self.efel_settings = {"strict_stiminterval": True} diff --git a/bluepyemodel/evaluation/efel_feature_bpem.py b/bluepyemodel/evaluation/efel_feature_bpem.py index 951e6c0c..1aab9e51 100644 --- a/bluepyemodel/evaluation/efel_feature_bpem.py +++ b/bluepyemodel/evaluation/efel_feature_bpem.py @@ -44,6 +44,7 @@ class eFELFeatureBPEM(eFELFeature): "threshold", "comment", ) + # pylint: disable=too-many-arguments def __init__( self, @@ -61,6 +62,7 @@ def __init__( double_settings=None, int_settings=None, string_settings=None, + weight=1.0, ): """Constructor @@ -76,6 +78,8 @@ def __init__( exp_std(float): experimental standard deviation of this eFeature threshold(float): spike detection threshold (mV) comment (str): comment + weight (float): weight of the efeature. + Basically multiplies the score of the efeature by this value. """ super().__init__( @@ -95,6 +99,7 @@ def __init__( string_settings, max_score=250.0, ) + self.weight = weight # used in objective def calculate_bpo_feature(self, responses): """Return internal feature which is directly passed as a response""" @@ -270,6 +275,7 @@ def __init__( string_settings=None, decay=None, linear=None, + weight=1.0, ): """Constructor""" # pylint: disable=too-many-arguments @@ -288,6 +294,7 @@ def __init__( double_settings, int_settings, string_settings, + weight, ) self.decay = decay self.linear = linear diff --git a/bluepyemodel/evaluation/evaluator.py b/bluepyemodel/evaluation/evaluator.py index fecc1dc7..00b6de6b 100644 --- a/bluepyemodel/evaluation/evaluator.py +++ b/bluepyemodel/evaluation/evaluator.py @@ -25,7 +25,7 @@ from bluepyopt.ephys.locations import NrnSeclistCompLocation from bluepyopt.ephys.locations import NrnSomaDistanceCompLocation from bluepyopt.ephys.locations import NrnTrunkSomaDistanceCompLocation -from bluepyopt.ephys.objectives import SingletonObjective +from bluepyopt.ephys.objectives import SingletonWeightObjective from bluepyopt.ephys.objectivescalculators import ObjectivesCalculator from bluepyopt.ephys.simulators import NrnSimulator @@ -269,6 +269,7 @@ def define_efeature(feature_config, protocol=None, global_efel_settings=None): string_settings=string_settings, decay=decay, linear=linear, + weight=feature_config.weight, ) # protocol name contains list of location, e.g. 'apic[050,100,150]' elif "[" in feature_config.recording_name_for_instantiation[""]: @@ -290,6 +291,7 @@ def define_efeature(feature_config, protocol=None, global_efel_settings=None): string_settings=string_settings, decay=decay, linear=linear, + weight=feature_config.weight, ) else: efeature = eFELFeatureBPEM( @@ -306,6 +308,7 @@ def define_efeature(feature_config, protocol=None, global_efel_settings=None): double_settings=double_settings, int_settings=int_settings, string_settings=string_settings, + weight=feature_config.weight, ) return efeature @@ -854,7 +857,7 @@ def define_fitness_calculator(features): ObjectivesCalculator """ - objectives = [SingletonObjective(feat.name, feat) for feat in features] + objectives = [SingletonWeightObjective(feat.name, feat, feat.weight) for feat in features] return ObjectivesCalculator(objectives) diff --git a/bluepyemodel/evaluation/fitness_calculator_configuration.py b/bluepyemodel/evaluation/fitness_calculator_configuration.py index d3ff0ea1..3159bca3 100644 --- a/bluepyemodel/evaluation/fitness_calculator_configuration.py +++ b/bluepyemodel/evaluation/fitness_calculator_configuration.py @@ -114,6 +114,7 @@ def __init__( "mean": 6.026, "original_std": 4.016, "efeature_name": "Spikecount", + "weight": 1.0, # optional "efel_settings": { "strict_stiminterval": true, "Threshold": -30.0, diff --git a/setup.py b/setup.py index b8b0bcd3..6f7e34e9 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,7 @@ "tqdm", "pyyaml", "gitpython", - "bluepyopt>=1.14.8", + "bluepyopt>=1.14.10", "bluepyefe>=2.2.0", "neurom>=3.0,<4.0", "efel>=3.1",