Skip to main content

cellular_raza_building_blocks/cell_models/
modular_cell.rs

1use cellular_raza_concepts::reactions_old::*;
2use cellular_raza_concepts::*;
3
4use serde::{Deserialize, Serialize};
5
6use num::Zero;
7
8/// Superseded by the [CellAgent] derive macro.
9///
10/// The [ModularCell] is a struct with fields that implement the various
11/// [concepts](cellular_raza_concepts). The concepts are afterwards derived automatically for the
12/// [ModularCell] struct.
13
14#[derive(Clone, Debug, Serialize, Deserialize)]
15pub struct ModularCell<Mec, Int, Cyc, React, IntExtracellular> {
16    /// Physical mechanics of the cell
17    pub mechanics: Mec,
18    /// Physical interactions with other cells
19    pub interaction: Int,
20    /// Interaction with extracellular gradient
21    pub interaction_extracellular: IntExtracellular,
22    /// Cell cycle
23    pub cycle: Cyc,
24    /// Intracellular reactions
25    pub cellular_reactions: React,
26    /// Volume of the cell
27    pub volume: f64,
28}
29
30/// Do not model intracellular reactions at all.
31#[derive(Clone, Debug, Serialize, Deserialize)]
32pub struct NoCellularReactions;
33
34impl CellularReactions<Nothing, Nothing> for NoCellularReactions
35where
36    Nothing: num::Zero,
37    Nothing: num::Zero,
38{
39    fn calculate_intra_and_extracellular_reaction_increment(
40        &self,
41        _internal_concentration_vector: &Nothing,
42        _external_concentration_vector: &Nothing,
43    ) -> Result<(Nothing, Nothing), CalcError> {
44        Ok((<Nothing>::zero(), <Nothing>::zero()))
45    }
46
47    fn get_intracellular(&self) -> Nothing {
48        <Nothing>::zero()
49    }
50
51    fn set_intracellular(&mut self, _concentration_vector: Nothing) {}
52}
53
54/// Type alias used when not wanting to simulate any cellular reactions for example.
55pub type Nothing = nalgebra::SVector<f64, 0>;
56
57impl<Pos, Vel, For, Float, Mec, Int, Cyc, React, IntExtracellular> Mechanics<Pos, Vel, For, Float>
58    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
59where
60    Mec: Mechanics<Pos, Vel, For, Float>,
61{
62    fn get_random_contribution(
63        &self,
64        rng: &mut rand_chacha::ChaCha8Rng,
65        dt: Float,
66    ) -> Result<(Pos, Vel), RngError> {
67        self.mechanics.get_random_contribution(rng, dt)
68    }
69
70    fn calculate_increment(&self, force: For) -> Result<(Pos, Vel), CalcError> {
71        self.mechanics.calculate_increment(force)
72    }
73}
74
75impl<Pos, Mec, Int, Cyc, React, InteractionExtracellular> cellular_raza_concepts::Position<Pos>
76    for ModularCell<Mec, Int, Cyc, React, InteractionExtracellular>
77where
78    Mec: Position<Pos>,
79{
80    fn set_pos(&mut self, pos: &Pos) {
81        self.mechanics.set_pos(pos)
82    }
83
84    fn pos(&self) -> Pos {
85        self.mechanics.pos()
86    }
87}
88
89impl<Vel, Mec, Int, Cyc, React, InteractionExtracellular> Velocity<Vel>
90    for ModularCell<Mec, Int, Cyc, React, InteractionExtracellular>
91where
92    Mec: Velocity<Vel>,
93{
94    fn set_velocity(&mut self, velocity: &Vel) {
95        self.mechanics.set_velocity(velocity);
96    }
97
98    fn velocity(&self) -> Vel {
99        self.mechanics.velocity()
100    }
101}
102
103impl<Inf, Mec, Int, Cyc, React, IntExtracellular> InteractionInformation<Inf>
104    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
105where
106    Int: InteractionInformation<Inf>,
107{
108    fn get_interaction_information(&self) -> Inf {
109        self.interaction.get_interaction_information()
110    }
111}
112
113impl<Pos, Vel, For, Inf, Mec, Int, Cyc, React, IntExtracellular> Interaction<Pos, Vel, For, Inf>
114    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
115where
116    Int: Interaction<Pos, Vel, For, Inf>,
117{
118    fn calculate_force_between(
119        &self,
120        own_pos: &Pos,
121        own_vel: &Vel,
122        ext_pos: &Pos,
123        ext_vel: &Vel,
124        ext_information: &Inf,
125    ) -> Result<(For, For), CalcError> {
126        self.interaction.calculate_force_between(
127            own_pos,
128            own_vel,
129            ext_pos,
130            ext_vel,
131            ext_information,
132        )
133    }
134}
135
136impl<Mec, Int, Cyc, React, IntExtracellular> Volume
137    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
138{
139    fn get_volume(&self) -> f64 {
140        self.volume
141    }
142}
143
144impl<Mec, Int, Cyc, Float, React, IntExtracellular> Cycle<Self, Float>
145    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
146where
147    Cyc: Cycle<Self, Float>,
148{
149    fn update_cycle(
150        rng: &mut rand_chacha::ChaCha8Rng,
151        dt: &Float,
152        cell: &mut Self,
153    ) -> Option<CycleEvent> {
154        Cyc::update_cycle(rng, dt, cell)
155    }
156
157    fn divide(rng: &mut rand_chacha::ChaCha8Rng, cell: &mut Self) -> Result<Self, DivisionError> {
158        Cyc::divide(rng, cell)
159    }
160
161    fn update_conditional_phased_death(
162        rng: &mut rand_chacha::ChaCha8Rng,
163        dt: &Float,
164        cell: &mut Self,
165    ) -> Result<bool, DeathError> {
166        Cyc::update_conditional_phased_death(rng, dt, cell)
167    }
168}
169
170impl<ConcVecIntracellular, ConcVecExtracellular, Mec, Int, Cyc, React, IntExtracellular>
171    CellularReactions<ConcVecIntracellular, ConcVecExtracellular>
172    for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
173where
174    React: CellularReactions<ConcVecIntracellular, ConcVecExtracellular>,
175{
176    fn calculate_intra_and_extracellular_reaction_increment(
177        &self,
178        internal_concentration_vector: &ConcVecIntracellular,
179        external_concentration_vector: &ConcVecExtracellular,
180    ) -> Result<(ConcVecIntracellular, ConcVecExtracellular), CalcError> {
181        self.cellular_reactions
182            .calculate_intra_and_extracellular_reaction_increment(
183                internal_concentration_vector,
184                external_concentration_vector,
185            )
186    }
187
188    fn get_intracellular(&self) -> ConcVecIntracellular {
189        self.cellular_reactions.get_intracellular()
190    }
191
192    fn set_intracellular(&mut self, concentration_vector: ConcVecIntracellular) {
193        self.cellular_reactions
194            .set_intracellular(concentration_vector)
195    }
196}
197
198/// Type which allows to simply not model gradients.
199#[derive(Clone, Debug, Serialize, Deserialize)]
200pub struct NoExtracellularGradientSensing;
201
202impl<C, ConcGradientExtracellular> InteractionExtracellularGradient<C, ConcGradientExtracellular>
203    for NoExtracellularGradientSensing
204{
205    fn sense_gradient(
206        _cell: &mut C,
207        _extracellular_gradient: &ConcGradientExtracellular,
208    ) -> Result<(), CalcError> {
209        Ok(())
210    }
211}
212
213impl<Mec, Int, Cyc, React, IntExtracellular, ConcGradientExtracellular>
214    InteractionExtracellularGradient<
215        ModularCell<Mec, Int, Cyc, React, IntExtracellular>,
216        ConcGradientExtracellular,
217    > for ModularCell<Mec, Int, Cyc, React, IntExtracellular>
218where
219    IntExtracellular: InteractionExtracellularGradient<Self, ConcGradientExtracellular>,
220{
221    fn sense_gradient(
222        cell: &mut Self,
223        extracellular_gradient: &ConcGradientExtracellular,
224    ) -> Result<(), CalcError> {
225        IntExtracellular::sense_gradient(cell, extracellular_gradient)
226    }
227}