cellular_raza-building-blocks 0.0.5

cellular_raza Building Blocks
Documentation
use cellular_raza_concepts::cycle::{Cycle, CycleEvent};
use cellular_raza_concepts::errors::{CalcError, RngError};
use cellular_raza_concepts::interaction::{
    CellularReactions, Interaction, InteractionExtracellularGradient, Volume,
};
use cellular_raza_concepts::mechanics::{Force, Mechanics, Position, Velocity};

use serde::{Deserialize, Serialize};

use num::Zero;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ModularCell<Mec, Int, Cyc, React, IntExtracellular> {
    pub mechanics: Mec,
    pub interaction: Int,
    pub interaction_extracellular: IntExtracellular,
    pub cycle: Cyc,
    pub cellular_reactions: React,
    pub volume: f64,
}

macro_rules! define_no_cellular_reactions {
    ($conc_vec_intracellular:ty, $conc_vec_extracellular:ty) => {
        #[derive(Clone, Debug, Serialize, Deserialize)]
        pub struct NoCellularreactions;

        impl<Mec, Int, Cyc, IntExtracellular>
            CellularReactions<$conc_vec_intracellular, $conc_vec_extracellular>
            for ModularCell<Mec, Int, Cyc, NoCellularreactions, IntExtracellular>
        where
            $conc_vec_intracellular: num::Zero,
            $conc_vec_extracellular: num::Zero,
        {
            fn calculate_intra_and_extracellular_reaction_increment(
                &self,
                _internal_concentration_vector: &$conc_vec_intracellular,
                _external_concentration_vector: &$conc_vec_extracellular,
            ) -> Result<
                ($conc_vec_intracellular, $conc_vec_extracellular),
                cellular_raza_concepts::errors::CalcError,
            > {
                Ok((
                    <$conc_vec_intracellular>::zero(),
                    <$conc_vec_extracellular>::zero(),
                ))
            }

            fn get_intracellular(&self) -> $conc_vec_intracellular {
                <$conc_vec_intracellular>::zero()
            }

            fn set_intracellular(&mut self, _concentration_vector: $conc_vec_intracellular) {}
        }
    };
}

// #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub type Nothing = nalgebra::SVector<f64, 0>;

define_no_cellular_reactions! {Nothing, Nothing}

impl<Pos, Vel, For, Mec, Int, Cyc, React, IntExtracellular> Mechanics<Pos, Vel, For>
    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
where
    Mec: Mechanics<Pos, Vel, For>,
    Pos: Position,
    For: Force,
    Vel: Velocity,
{
    fn set_pos(&mut self, pos: &Pos) {
        self.mechanics.set_pos(pos)
    }

    fn pos(&self) -> Pos {
        self.mechanics.pos()
    }

    fn set_velocity(&mut self, velocity: &Vel) {
        self.mechanics.set_velocity(velocity);
    }

    fn velocity(&self) -> Vel {
        self.mechanics.velocity()
    }

    fn set_random_variable(
        &mut self,
        rng: &mut rand_chacha::ChaCha8Rng,
        dt: f64,
    ) -> Result<Option<f64>, RngError> {
        self.mechanics.set_random_variable(rng, dt)
    }

    fn calculate_increment(&self, force: For) -> Result<(Pos, Vel), CalcError> {
        self.mechanics.calculate_increment(force)
    }
}

impl<Pos, Vel, For, Inf, Mec, Int, Cyc, React, IntExtracellular> Interaction<Pos, Vel, For, Inf>
    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
where
    Pos: Position,
    For: Force,
    Int: Interaction<Pos, Vel, For, Inf>,
{
    fn get_interaction_information(&self) -> Inf {
        self.interaction.get_interaction_information()
    }

    fn calculate_force_between(
        &self,
        own_pos: &Pos,
        own_vel: &Vel,
        ext_pos: &Pos,
        ext_vel: &Vel,
        ext_information: &Inf,
    ) -> Option<Result<For, CalcError>> {
        self.interaction.calculate_force_between(
            own_pos,
            own_vel,
            ext_pos,
            ext_vel,
            ext_information,
        )
    }

    fn is_neighbour(&self, own_pos: &Pos, ext_pos: &Pos, ext_inf: &Inf) -> Result<bool, CalcError> {
        self.interaction.is_neighbour(own_pos, ext_pos, ext_inf)
    }

    fn react_to_neighbours(&mut self, neighbours: usize) -> Result<(), CalcError> {
        self.interaction.react_to_neighbours(neighbours)
    }
}

impl<Mec, Int, Cyc, React, IntExtracellular> Volume
    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
{
    fn get_volume(&self) -> f64 {
        self.volume
    }
}

impl<Mec, Int, Cyc, React, IntExtracellular> Cycle<Self>
    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
where
    Cyc: Cycle<Self>,
{
    fn update_cycle(
        rng: &mut rand_chacha::ChaCha8Rng,
        dt: &f64,
        cell: &mut Self,
    ) -> Option<CycleEvent> {
        Cyc::update_cycle(rng, dt, cell)
    }

    fn divide(
        rng: &mut rand_chacha::ChaCha8Rng,
        cell: &mut Self,
    ) -> Result<Self, cellular_raza_concepts::errors::DivisionError> {
        Cyc::divide(rng, cell)
    }
}

impl<ConcVecIntracellular, ConcVecExtracellular, Mec, Int, Cyc, React, IntExtracellular>
    CellularReactions<ConcVecIntracellular, ConcVecExtracellular>
    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
where
    React: CellularReactions<ConcVecIntracellular, ConcVecExtracellular>,
{
    fn calculate_intra_and_extracellular_reaction_increment(
        &self,
        internal_concentration_vector: &ConcVecIntracellular,
        external_concentration_vector: &ConcVecExtracellular,
    ) -> Result<(ConcVecIntracellular, ConcVecExtracellular), CalcError> {
        self.cellular_reactions
            .calculate_intra_and_extracellular_reaction_increment(
                internal_concentration_vector,
                external_concentration_vector,
            )
    }

    fn get_intracellular(&self) -> ConcVecIntracellular {
        self.cellular_reactions.get_intracellular()
    }

    fn set_intracellular(&mut self, concentration_vector: ConcVecIntracellular) {
        self.cellular_reactions
            .set_intracellular(concentration_vector)
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NoExtracellularGradientSensing;

impl<C, ConcGradientExtracellular> InteractionExtracellularGradient<C, ConcGradientExtracellular>
    for NoExtracellularGradientSensing
{
    fn sense_gradient(
        _cell: &mut C,
        _extracellular_gradient: &ConcGradientExtracellular,
    ) -> Result<(), cellular_raza_concepts::errors::CalcError> {
        Ok(())
    }
}

impl<Mec, Int, Cyc, React, IntExtracellular, ConcGradientExtracellular>
    InteractionExtracellularGradient<
        ModularCell<Mec, Int, Cyc, React, IntExtracellular>,
        ConcGradientExtracellular,
    > for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
where
    IntExtracellular: InteractionExtracellularGradient<Self, ConcGradientExtracellular>,
{
    fn sense_gradient(
        cell: &mut Self,
        extracellular_gradient: &ConcGradientExtracellular,
    ) -> Result<(), cellular_raza_concepts::errors::CalcError> {
        IntExtracellular::sense_gradient(cell, extracellular_gradient)
    }
}