Source code for neurorosettes.neurons
"""This module deals with the neuron structure and functions"""
from dataclasses import dataclass
import numpy as np
from neurorosettes.subcellular import Neurite, ObjectFactory
from neurorosettes.clocks import CellClocks, ClocksFactory
from neurorosettes.physics import normalize_vector
[docs]class Neuron:
"""
Class to represent a neuron as a combination of a cell body and neurites.
Parameters
----------
position
The center position of the neuron's cell body.
outgrowth_axis
The direction of growth of the neuron's neurites.
factory
The factory object to be used to create new neuron components.
clocks
The rates of the neuron's biological processes.
max_number_of_neurites
The total number of neurites a neuron can have before
proliferation is blocked.
differentiation_grade
The starting differentiation stage of the neurite, represented
by the initial number of neurites.
"""
def __init__(
self,
position: np.ndarray,
outgrowth_axis: np.ndarray,
factory: ObjectFactory,
clocks: CellClocks,
max_number_of_neurites: int = 4,
differentiation_grade: int = 0,
) -> None:
self.cell = factory.get_cell_body(position)
self.outgrowth_axis = outgrowth_axis
self.clocks = clocks
self.max_number_of_neurites = max_number_of_neurites
self.neurites = []
if differentiation_grade != 0:
self.create_first_neurite(factory)
for _ in range(1, differentiation_grade):
self.create_secondary_neurite(factory)
@property
def cell_radius(self):
"""The radius of the neuron's cell body."""
return self.cell.mechanics.radius
@property
def ready_for_division(self):
"""If the neuron is ready to proliferate."""
return self.clocks.cycle_clock.signal
@property
def ready_for_differentiation(self):
"""If the neuron is ready to differentiate."""
return self.clocks.differentiation_clock.signal
@property
def ready_to_die(self):
"""If the neuron is ready to die."""
return self.clocks.death_clock.signal
[docs] def set_outgrowth_axis(self, coordinates: np.ndarray) -> None:
"""
Sets the axis that neurites will follow when new neurites are created.
Prameters
----------
outgrowth_axis
The direction of growth of the neuron's neurites.
"""
if np.linalg.norm(coordinates) > 1.0:
coordinates = normalize_vector(coordinates)
self.outgrowth_axis[0] = coordinates[0]
self.outgrowth_axis[1] = coordinates[1]
self.outgrowth_axis[2] = coordinates[2]
[docs] def get_neurite_position_on_cell_surface(self) -> np.ndarray:
"""Returns the coordinates on the cell surface where the first neurite should be placed"""
connector = self.neurites[0].distal_point - self.cell.position
unit_connector = connector / np.linalg.norm(connector)
new_point = self.cell.position + unit_connector * self.cell.mechanics.radius
return new_point
[docs] def place_neurite_on_cell_surface(self, neurite: Neurite) -> None:
"""
Places the neurite base on the cell surface according to the cell-distal vector.
Parameters
----------
neurite
The neurite to be placed on the cell body's surface.
"""
neurite_attachment_coordinates = self.get_neurite_position_on_cell_surface()
neurite.move_proximal_point(neurite_attachment_coordinates)
[docs] def create_first_neurite(self, factory: ObjectFactory) -> None:
"""
Creates a neurite attached to the soma cell
Parameters
----------
factory
The factory object to be used to create new neuron components.
"""
proximal_point = (
self.cell.position + self.outgrowth_axis * self.cell.mechanics.radius
)
neurite = factory.get_neurite(proximal_point, self.outgrowth_axis)
self.neurites.append(neurite)
self.clocks.cycle_clock.cycle_block = True
[docs] def create_secondary_neurite(self, factory: ObjectFactory) -> None:
"""
Creates a neurite attached to the most recent neurite.
Parameters
----------
factory
The factory object to be used to create new neuron components.
"""
if len(self.neurites) >= self.max_number_of_neurites:
return
proximal_point = self.neurites[-1].distal_point
neurite = factory.get_neurite(proximal_point, self.outgrowth_axis)
self.neurites.append(neurite)
[docs]@dataclass
class NeuronFactory:
"""
Helper class to create instances of neurons based on defined properties.
"""
max_number_of_neurites: int
"""The maximum number of neurites that a neuron can have."""
objects_factory: ObjectFactory
"""The ObjectFactory used to create new object instances."""
clocks_factory: ClocksFactory
"""The ClocksFactory used to create new clock instances."""
[docs] def create_neuron(
self, coordinates: np.ndarray, outgrowth_axis: np.ndarray
) -> Neuron:
"""Returns a Neuron object placed in the given coordinates."""
clocks = self.clocks_factory.get_clocks()
return Neuron(
coordinates,
outgrowth_axis,
self.objects_factory,
clocks,
self.max_number_of_neurites,
)