Group Abstract Group Abstract

Message Boards Message Boards

How do I model stem cell growth using loops?

Posted 11 years ago
POSTED BY: c bro
19 Replies
POSTED BY: Sam Carrettie
Posted 11 years ago
POSTED BY: David Keith
Posted 11 years ago

When using Manipuate, I simplified the equation by removing the occupancy function from the mix and allowing the v[t] and p1[t] be constants rather than functions. Is there a way to reintroduce these easily? I originally thought I could use the code you constructed and then a replace command that would replace v->v[t] and p1->p1[t] but I can't seem to find something that will substitute just portions of an equation. Even after this replacement, I am concerned the code wouldn't work in Manipulate since based off what you have shown me, it seems to be very sensitive to the type of problem I am working on.

EDIT: Using /. (thanks for teaching me about that) I was able to replace what I needed so that the equations read how I want them to (i.e. include the functions p1[t] and v[t] as you define in your earlier code. The issue with using Manipulate to graph them persists however.

POSTED BY: c bro
Posted 11 years ago

And here is one more version which I think is better. Rather than build functions with all the parameters exposed as arguments, we build functions of t, which still have undefined variables internally. We expose these to manipulate not as explicit arguments, but rather we use dummy parameters in manipulate, so manipulate can see them, but then we use a Replace with a Rule in the expression being plotted. This replace causes the "hidden" parameters in the expression to be replaced by the numerical values generated for the dummy parameters by manipulate. I think this is better because the functions are not so cluttered up with a long argument list. They can always be used with specific values for the undefined variable by using a similar Replace in other applications. (Note that I did remove a lot of unused parameters from manipulate.)

Attachments:
POSTED BY: David Keith
Posted 11 years ago

Hi Carolyn,

There was an additional problem, and it's somewhat advanced. It has to do with how Plot and Manipulate localize variables. The short solution is that all of the parameters being manipulated should appear explicitly within the Plot expression. I attach this as a notebook.

You should also study the way the result of DSolve is being used to define the functions we want from its output. DSolve outputs rules, and we use these to generate expressions, which are themselves used as the templates for function definitions. And so these templates allow us to define the functions as having their parameters as arguments, as well as the independent variable t.

I'm not usually this helpful ;-). But it is 95 degrees heading for 100 here in the state of Washington. We prefer 65-75. So I'm indoors amusing myself with Mathematica.

Best, David

Attachments:
POSTED BY: David Keith
Posted 11 years ago
Attachments:
POSTED BY: c bro
Posted 11 years ago

I should add that an expression intended for manipulate will have one or more variables undefined, so manipulate can make the substitutions. These also need numerical values during Plotting, but they will be provided by Manipulate. So for such an expression the Replace test indicates success if you evaluate the expression with a numerical independent variable and the only undefined symbols remaining are those which will be parameters in Manipulate.

POSTED BY: David Keith
Posted 11 years ago
POSTED BY: David Keith
Posted 11 years ago

I thought it would be a good idea to use the command Manipulate so that I could observe the changes in the graph that correspond to changing the values of the constants. To do this, I need the symbolic solution to the system, which I found as follows:

equations = {c'[t] == c[t] (p1*v - (1 - p1) v - dr), 
  p'[t] == c[t] (1 - p1) v + p[t] (p1*v - (1 - p1) v - dr), 
  d'[t] == p[t] (1 - p1) v + d[t] (1 - dr)}


 DSolve[{equations, c[0] == 1, p[0] == 0, d[0] == 0}, {c[t], d[t], 
      p[t]}, {t}]
    ffc[t_] == E^(t (-dr + (-1 + 2 p1) v))
    ffp[t_] == 
     1/(-1 - v + 2 p1 v)^2 (-1 + p1)^2 v^2 (E^((1 - dr) t) - E^(
        t (-dr + (-1 + 2 p1) v)) - E^(t (-dr + (-1 + 2 p1) v)) t - 
        E^(t (-dr + (-1 + 2 p1) v)) t v + 
        2 E^(t (-dr + (-1 + 2 p1) v)) p1 t v)
    ffd[t_] == -E^(t (-dr + (-1 + 2 p1) v)) (-1 + p1) t v

  total[t_] == ffc[t] + ffp[t] + ffd[t]

 Manipulate[
     Plot[{ffc[t], ffp[t], ffd[t],total[t]}, {t, 0, 10}, 
      PlotLegends -> {"c[t]", "p[t]", "d[t]", "total cells"}], {{x1, 1, 
       "Occupany Level at which Division Speed Increases"}, 1, 
      10}, {{y1, 1, "Division Speed Increase Factor"}, 0, 
      10}, {{x2, 1, 
       "Occupancy Level at which Prop. Symmetric Division Increases"}, 1, 
      10}, {{y2, 1, "Division Proportion Increase Factor"}, 0, 
      10}, {{v0, 1, "Cell Divisions Per Unit Time"}, 0, 
      10}, {{p10, .5, 
       "Proportion of Cells Undergoing Symmetric Division"}, 0, 
      1}, {{dr, .2, "Cell Death Rate"}, 0, 
      1}, {{f1, 1, "CSC DLL4 Production"}, 0, 
      10}, {{f2, 1, "PC DLL4 Production"}, 0, 
      10}, {{f3, 1, "TDC DLL4 Production"}, 0, 
      10}, {{r, 1, "Receptors Per Cell"}, 0, 10}, {k, 0, 10}]

This is a very rough attempt and I know that I should include v[t] and p1[t] in the plot too, in addition to several other things, but I can't seem to make the plot show any thing currently. Once I can get it to work I plan on tinkering with it. Anyexplanation as to why nothing shows up?

Attachments:
POSTED BY: c bro
Posted 11 years ago

I thought it would be a good idea to use the command Manipulate so that I could observe the changes in the graph that correspond to changing the values of the constants. To do this, I need the symbolic solution to the system, which I found as follows:

equations = {c'[t] == c[t] (p1*v - (1 - p1) v - dr), 
  p'[t] == c[t] (1 - p1) v + p[t] (p1*v - (1 - p1) v - dr), 
  d'[t] == p[t] (1 - p1) v + d[t] (1 - dr)}


 DSolve[{equations, c[0] == 1, p[0] == 0, d[0] == 0}, {c[t], d[t], 
      p[t]}, {t}]
    ffc[t_] == E^(t (-dr + (-1 + 2 p1) v))
    ffp[t_] == 
     1/(-1 - v + 2 p1 v)^2 (-1 + p1)^2 v^2 (E^((1 - dr) t) - E^(
        t (-dr + (-1 + 2 p1) v)) - E^(t (-dr + (-1 + 2 p1) v)) t - 
        E^(t (-dr + (-1 + 2 p1) v)) t v + 
        2 E^(t (-dr + (-1 + 2 p1) v)) p1 t v)
    ffd[t_] == -E^(t (-dr + (-1 + 2 p1) v)) (-1 + p1) t v

  total[t_] == ffc[t] + ffp[t] + ffd[t]

 Manipulate[
     Plot[{ffc[t], ffp[t], ffd[t],total[t]}, {t, 0, 10}, 
      PlotLegends -> {"c[t]", "p[t]", "d[t]", "total cells"}], {{x1, 1, 
       "Occupany Level at which Division Speed Increases"}, 1, 
      10}, {{y1, 1, "Division Speed Increase Factor"}, 0, 
      10}, {{x2, 1, 
       "Occupancy Level at which Prop. Symmetric Division Increases"}, 1, 
      10}, {{y2, 1, "Division Proportion Increase Factor"}, 0, 
      10}, {{v0, 1, "Cell Divisions Per Unit Time"}, 0, 
      10}, {{p10, .5, 
       "Proportion of Cells Undergoing Symmetric Division"}, 0, 
      1}, {{dr, .2, "Cell Death Rate"}, 0, 
      1}, {{f1, 1, "CSC DLL4 Production"}, 0, 
      10}, {{f2, 1, "PC DLL4 Production"}, 0, 
      10}, {{f3, 1, "TDC DLL4 Production"}, 0, 
      10}, {{r, 1, "Receptors Per Cell"}, 0, 10}, {k, 0, 10}]

This is a very rough attempt and I know that I should include v[t] and p1[t] in the plot too, in addition to several other things, but I can't seem to make the plot show any thing currently. Once I can get it to work I plan on tinkering with it. Anyexplanation as to why nothing shows up?

Attachments:
POSTED BY: c bro
Posted 11 years ago
POSTED BY: David Keith
Posted 11 years ago

.

POSTED BY: c bro
Posted 11 years ago
POSTED BY: c bro
Posted 11 years ago

Here's what I had in mind. It includes the discontinuous algebraics, although for my choice of parameter values they never switch. I suggest you provide some "reasonable" parameter values, most of which are fixed, but a few for which you would like to see results for a range of values. (My values likely make no sense.)

In[1]:= (* function for occupancy *)
occupancy[c_, p_, d_] := r (c f1 + p f2 + d f3)/k

In[2]:= (* equations *)
eqs = {c'[t] == c[t] (p1[t]*v[t] - (1 - p1[t]) v[t] - dr), 
   p'[t] == 
    c[t] (1 - p1[t]) v[t] + p[t] (p1v - (1 - p1[t]) v[t] - dr), 
   d'[t] == p[t] (1 - p1[t]) v[t] + d[t] (1 - dr)};

In[3]:= (* initial conditions *)
initial = {c[0] == 1, p[0] == 0, d[0] == 0};

In[4]:= (* algebraic equations *)
(* values that vary with the independent parameter must be functions \
of it *)
algebraics = {v[t] == If[occupancy[c[t], p[t], d[t]] < x1, vy1, v0], 
   p1[t] == If[occupancy[c[t], p[t], d[t]] < x2, p1y2, p10]};

In[5]:= (* real numbers *)
values = {x1 -> .5, vy1 -> .5, v0 -> .3, x2 -> .6, p10 -> .3, 
   p1y2 -> .7, p10 -> .2, dr -> .5, p1v -> .4, f1 -> .5, f2 -> .3, 
   f3 -> .7, r -> .7, k -> 10};

In[6]:= (* check to make sure no undefined symbols *)
{eqs, initial, algebraics} /. values

Out[6]= {{Derivative[1][c][t] == 
   c[t] (-0.5 - (1 - p1[t]) v[t] + p1[t] v[t]), 
  Derivative[1][p][t] == 
   c[t] (1 - p1[t]) v[t] + p[t] (-0.1 - (1 - p1[t]) v[t]), 
  Derivative[1][d][t] == 0.5 d[t] + p[t] (1 - p1[t]) v[t]}, {c[0] == 
   1, p[0] == 0, 
  d[0] == 0}, {v[t] == 
   If[0.07 (0.5 c[t] + 0.7 d[t] + 0.3 p[t]) < 0.5, 0.5, 0.3], 
  p1[t] == If[0.07 (0.5 c[t] + 0.7 d[t] + 0.3 p[t]) < 0.6, 0.7, 0.3]}}

In[7]:= (* solve to f[t] set *)
{fc, fp, fd, fv, fp1} = NDSolveValue[
   {eqs, initial, algebraics} /. values,
   {c[t], p[t], d[t], v[t], p1[t]},
   {t, 0, 10}
   ];

In[8]:= Plot[{fc, fp, fd, fv, fp1}, {t, 0, 10}, 
 PlotLegends -> {"c[t]", "p[t]", "d[t]", "v[t]", "p1[t]"}]

enter image description here

Attachments:
POSTED BY: David Keith
Posted 11 years ago
POSTED BY: c bro
Posted 11 years ago

These equations look like finite difference approximations to differential equations. That being the case, I think that writing them as such and using NDSolve or related functions is the way to do this. For example, ParametricNDSolve can generate a solutions set based on stated parameters, which can be investigated graphically. The last relationship you mention says that v and p1 are functions of the dependent variables. That can be included in the equations provided NDSolve. Discontinuity is OK.

I attach a fun example. It's not parametric, but does include discontinuous algebraic functions of the dependent variables. A rocket is launched. The thrust occurs between tOn and Toff. At chuteTime a parachute is deployed, which significantly increases drag.

How about if we reformulate these as diffeq's?

In[1]:= SetOptions[ParametricPlot, PlotTheme -> "Scientific"];

In[2]:= SetOptions[Plot, PlotTheme -> "Scientific"];

In[3]:= tImpact = 
  100; (* initialize - without this WhenEvent can't access it *)

In[4]:= (* rocket thrust *)
thrust[t_] := If[tOn <= t < tOff, f, 0]

In[5]:= (* drag coefficients without / with parachute *)
dragC[t_] := If[t < chuteTime, c1, c2]

In[6]:= (* values for simulation *)
values = {v0 -> 0.0001, theta -> 70 Degree, tOn -> 0, tOff -> 5, 
   f -> 150, chuteTime -> 40, c1 -> 0.0001, c2 -> 0.002, g -> 9.8};

In[7]:= equations = {
   {x''[t], y''[t]} == 
    thrust[t] Normalize[{x'[t], y'[t]}] - {0, g} - 
     dragC[t] Normalize[{x'[t], y'[t]}] Norm[{x'[t], y'[t]}]^2,
   {x'[0], y'[0]} == v0 {Cos[theta], Sin[theta]},
   {x[0], y[0]} == {0, 0},
   WhenEvent[y[t] < 0, {"StopIntegration", tImpact = t}]
   };

In[8]:= sol = 
  NDSolveValue[equations /. values, {x[t], y[t]}, {t, 0, 500}];

In[9]:= sol = 
  NDSolveValue[
   equations /. values, {x[t], y[t], x'[t], y'[t], x''[t], 
    y''[t]}, {t, 0, 500}];

In[10]:= tImpact

Out[10]= 90.9562

In[11]:= ParametricPlot[sol[[{1, 2}]], {t, 0, tImpact}, 
 AspectRatio -> Automatic, PlotRange -> All]

enter image description here

Attachments:
POSTED BY: David Keith
Posted 11 years ago

The t[i] is a type and should instead be d[i]. I changed this in the original question. Thanks for catching that. David, your code is much more eloquent than mine; thanks for the lesson recursive functions! I feel like I have a good handle on them but remain confused as to how I should incorporate the second rule, explained at the bottom of my post. Ideally at the end, I would like to be able to input different values for the variables and observe the behavior of the graphs as i changes.

POSTED BY: c bro
Posted 11 years ago

Sam, thanks for your advice. Based on David's advice on another post, I meant to remove all subscripts as they often cause problems, but must have missed that one. It is now corrected!

Yes, by "symbolically" that is what I mean. is there a more precise way of saying that?

There is no reference for these materials as it is a new proposed model for cell growth, one that I am hoping to investigate.

POSTED BY: c bro
Posted 11 years ago

Hi Carolyn,

Below is an example of how a recursive system of definitions can be used for such a calculation. It makes use of the basic principle of the evaluation loop in Mathematica: When you evaluate an expression Mathematica continues to evaluate subsequent output until no built-in or user defined rule applies.

Using this, the intertwined recursive definitions provide a result for any index of any of the defined functions. In symbolic form it will of course use a lot of memory to get to high-index values. The earlier numerical values are substituted, the less memory required.

** Note that there is an issue in evaluation, because t[i] appears in the definition of d[i], but is not defined, it appears unevaluated in the results. **

In[1]:= (* Mathematica's evaluation engine handles recursion *)
(* Specific cases take precedence *)
(* Here is how we define and use c *)

In[2]:= c[0] = 1; c[1] = 1;

In[3]:= (* The = stores the value, so we don't have to calculate it \
again *)
c[i_] := c[i] = c[i - 1]*(1 + p1*v - (1 - p1) v - dr)

In[4]:= (* example *)
c[5]

Out[4]= (1 - dr - (1 - p1) v + p1 v)^4

In[5]:= (* and likewise for p *)

In[6]:= p[0] = 0;

In[7]:= p[i_] := 
 p[i] = c[i - 1] (1 - p1) v + p[i - 1] (1 + p2*v - (1 - p2) v - d)

In[8]:= (* example *)
p[5]

Out[8]= (1 - p1) v (1 - dr - (1 - p1) v + p1 v)^3 + (1 - 
    d - (1 - p2) v + 
    p2 v) ((1 - p1) v (1 - dr - (1 - p1) v + p1 v)^2 + (1 - 
       d - (1 - p2) v + 
       p2 v) ((1 - p1) v (1 - dr - (1 - p1) v + p1 v) + (1 - 
          d - (1 - p2) v + 
          p2 v) ((1 - p1) v + (1 - p1) v (1 - d - (1 - p2) v + p2 v))))

In[9]:= (* and for d *)

In[10]:= d[0] = 0;

In[11]:= (* I deleted the subscript typo *)
d[i_] := p[i - 1] (1 - p2) v + t[i - 1] (1 - dr)

In[12]:= (* example *)
d[11] // Simplify

Out[12]= (-1 + p1) (1 - 
    p2) v^2 (-(-1 + dr + v - 2 p1 v)^8 + (1 - 
       d + (-1 + 2 p2) v) ((-1 + dr + v - 
         2 p1 v)^7 + (1 - 
          d + (-1 + 2 p2) v) (-(-1 + dr + v - 2 p1 v)^6 + (1 - 
             d + (-1 + 2 p2) v) ((-1 + dr + v - 
               2 p1 v)^5 + (1 - 
                d + (-1 + 2 p2) v) (-(-1 + dr + v - 2 p1 v)^4 + (1 - 
                   d + (-1 + 2 p2) v) ((-1 + dr + v - 
                    2 p1 v)^3 + (1 - 
                    d + (-1 + 2 p2) v) (-(-1 + dr + v - 
                    2 p1 v)^2 + (-1 + d + v - 2 p2 v) (3 + d^2 - dr - 
                    4 v + 2 p1 v + 6 p2 v + v^2 - 4 p2 v^2 + 
                    4 p2^2 v^2 + d (-3 + (2 - 4 p2) v))))))))) - (-1 +
     dr) t[10]
Attachments:
POSTED BY: David Keith
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard