Source code for dendrotweaks.biophys.groups
# SPDX-FileCopyrightText: 2025 Poirazi Lab <dendrotweaks@dendrites.gr>
# SPDX-License-Identifier: MPL-2.0
from typing import List, Callable, Dict
from dendrotweaks.utils import timeit
from dataclasses import dataclass, field, asdict
from typing import List, Tuple, Dict, Optional
[docs]
@dataclass
class SegmentGroup:
"""
A group of segments that share a common property.
Parameters
----------
name : str
The name of the segment group.
domains : List[str]
The domains the segments belong to.
select_by : Optional[str]
The property to select the segments by. Can be:
- 'diam': the diameter of the segment.
- 'section_diam': the diameter of the section the segment belongs to.
- 'distance': the distance of the segment from the root.
- 'domain_distance': the distance of the segment from the root within the domain.
min_value : Optional[float]
The minimum value of the property.
max_value : Optional[float]
The maximum value of the property.
Examples
--------
Create a segment group that selects segments by diameter:
>>> group = SegmentGroup('group1', domains=['dend'], select_by='diam', min_value=1, max_value=2)
>>> group
SegmentGroup("group1", domains=['dend'], diam(1, 2))
Check if a segment is in the group:
>>> segment in group
True
"""
name: str
domains: List[str]
select_by: Optional[str] = None
min_value: Optional[float] = None
max_value: Optional[float] = None
def _get_segment_value(self, segment) -> Optional[float]:
if self.select_by == 'diam':
return segment.diam
elif self.select_by == 'section_diam':
return segment._section._ref.diam
elif self.select_by == 'distance':
return segment.path_distance()
elif self.select_by == 'domain_distance':
return segment.path_distance(within_domain=True)
return None
def __contains__(self, segment) -> bool:
if segment.domain_name not in self.domains:
return False
if self.select_by is None:
return True
segment_value = self._get_segment_value(segment)
return (
(self.min_value is None or segment_value > self.min_value) and
(self.max_value is None or segment_value <= self.max_value)
)
def __repr__(self):
filters = (
f"{self.select_by}({self.min_value}, {self.max_value})"
if self.select_by is not None and (self.min_value is not None or self.max_value is not None) else ""
)
return f'SegmentGroup("{self.name}", domains={self.domains}' + (f", {filters}" if filters else "") + ')'
[docs]
def to_dict(self) -> Dict:
"""
Convert the SegmentGroup to a dictionary.
"""
result = {
'name': self.name,
'domains': self.domains,
'select_by': self.select_by,
'min_value': self.min_value,
'max_value': self.max_value,
}
return {k: v for k, v in result.items() if v is not None}
[docs]
@staticmethod
def from_dict(data: Dict) -> 'SegmentGroup':
"""
Create a SegmentGroup from a dictionary.
"""
return SegmentGroup(**data)