Source code for neuron_morphology.feature_extractor.feature_extractor
from typing import (
Sequence, Set, AbstractSet, List, Optional, Type, Union, Iterable,
Mapping, Any)
import logging
import collections
from neuron_morphology.feature_extractor.mark import Mark
from neuron_morphology.feature_extractor.marked_feature import (
MarkedFeature, Feature
)
from neuron_morphology.feature_extractor.feature_extraction_run import \
FeatureExtractionRun
from neuron_morphology.feature_extractor.data import Data
# The register_features method on FeatureExtractor supports one level of
# nesting in its inputs
RegistrableFeature = Union[
Feature, Mapping[Any, Feature], Iterable[Feature]
]
[docs]class FeatureExtractor:
def __init__(self, features: Sequence[Feature] = tuple()):
""" Extracts morphological features from data
Parameters
----------
features : a sequence of marked (ideally) callables, each of which
defines some feature calculation. These define the set of features
eligible to be calculated on any specific run
"""
self.marks: Set[Type[Mark]] = set()
self.features: List[MarkedFeature] = []
if features:
self.register_features(features)
[docs] def register_features(self, features: Sequence[RegistrableFeature]):
""" Add a new feature to the list of options
Parameters
----------
features : the features to be registered. If it is not already marked,
it will be registered with no marks
"""
for feature in features:
to_register: List[Feature] = []
if isinstance(feature, collections.abc.Mapping):
to_register.extend(feature.values())
elif isinstance(feature, collections.abc.Iterable):
to_register.extend(feature)
else:
to_register.append(feature)
for feature_to_register in to_register:
feature_to_register = MarkedFeature.ensure(feature_to_register)
self.marks |= feature_to_register.marks
self.features.append(feature_to_register)
return self
[docs] def extract(
self,
data: Data,
only_marks: Optional[AbstractSet[Type[Mark]]] = None,
required_marks: AbstractSet[Type[Mark]] = frozenset()
) -> FeatureExtractionRun:
""" Run the feature extractor for a single dataset
Parameters
----------
data : the dataset from which features will be calculated
only_marks : if provided, reject marks not in this set
required_marks : if provided, raise an exception if any of these marks
do not validate successfully
Returns
-------
The calculated features, along with a record of the marks and features
selected.
"""
return (
FeatureExtractionRun(data)
.select_marks(
self.marks,
required_marks=required_marks
)
.select_features(
self.features,
only_marks=only_marks
)
.extract()
)