{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 20. Lateral Inhibition: Spontaneous symmetry breaking to form a spatial pattern of cells\n", "\n", "
\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"
\\n\"+\n", " \"\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"
\\n\"+\n",
" \"\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"
\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"
\\n\"+\n \"Sliders are inactive. To get active sliders, re-run notebook with\\n fully_interactive_plots = True\\n in the first code cell.
\\n \",\"width\":250},\"id\":\"1218\",\"type\":\"Div\"},{\"attributes\":{},\"id\":\"1078\",\"type\":\"LogScale\"},{\"attributes\":{\"line_color\":\"blue\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Ni\"}},\"id\":\"1103\",\"type\":\"Line\"},{\"attributes\":{\"ticker\":null},\"id\":\"1148\",\"type\":\"LogTickFormatter\"},{\"attributes\":{\"children\":[{\"id\":\"1217\"},{\"id\":\"1218\"}]},\"id\":\"1219\",\"type\":\"Column\"},{\"attributes\":{},\"id\":\"1029\",\"type\":\"SaveTool\"},{\"attributes\":{\"children\":[{\"id\":\"1003\"},{\"id\":\"1004\"},{\"id\":\"1005\"},{\"id\":\"1006\"}],\"width\":150},\"id\":\"1217\",\"type\":\"Column\"},{\"attributes\":{},\"id\":\"1030\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"1149\",\"type\":\"AllLabels\"},{\"attributes\":{\"disabled\":true,\"end\":3,\"start\":-3,\"step\":0.1,\"title\":\"Log Initial Dj\",\"value\":-2.9},\"id\":\"1006\",\"type\":\"Slider\"},{\"attributes\":{},\"id\":\"1027\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"1026\",\"type\":\"PanTool\"},{\"attributes\":{\"overlay\":{\"id\":\"1032\"}},\"id\":\"1028\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"disabled\":true,\"end\":3,\"start\":-3,\"step\":0.1,\"title\":\"Log Initial Di\",\"value\":-3},\"id\":\"1004\",\"type\":\"Slider\"},{\"attributes\":{\"ticker\":null},\"id\":\"1111\",\"type\":\"LogTickFormatter\"},{\"attributes\":{},\"id\":\"1112\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"1115\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"1114\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1010\",\"type\":\"DataRange1d\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"1194\"},{\"id\":\"1212\"}]},\"id\":\"1193\",\"type\":\"Legend\"},{\"attributes\":{\"source\":{\"id\":\"1008\"}},\"id\":\"1181\",\"type\":\"CDSView\"},{\"attributes\":{\"label\":{\"value\":\"Cell i\"},\"renderers\":[{\"id\":\"1180\"}]},\"id\":\"1194\",\"type\":\"LegendItem\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"1182\",\"type\":\"Title\"},{\"attributes\":{\"line_color\":\"orange\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Dj\"}},\"id\":\"1159\",\"type\":\"Line\"},{\"attributes\":{\"label\":{\"value\":\"Cell j\"},\"renderers\":[{\"id\":\"1125\"}]},\"id\":\"1138\",\"type\":\"LegendItem\"},{\"attributes\":{\"source\":{\"id\":\"1008\"}},\"id\":\"1126\",\"type\":\"CDSView\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"orange\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Nj\"}},\"id\":\"1123\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1151\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"ticker\":null},\"id\":\"1185\",\"type\":\"LogTickFormatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"1008\"},\"glyph\":{\"id\":\"1122\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"1124\"},\"nonselection_glyph\":{\"id\":\"1123\"},\"view\":{\"id\":\"1126\"}},\"id\":\"1125\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"line_color\":\"blue\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Di\"}},\"id\":\"1140\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1186\",\"type\":\"AllLabels\"},{\"attributes\":{\"line_alpha\":0.2,\"line_color\":\"orange\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Nj\"}},\"id\":\"1124\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1188\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1189\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"1016\",\"type\":\"LogScale\"},{\"attributes\":{\"line_color\":\"orange\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Nj\"}},\"id\":\"1122\",\"type\":\"Line\"},{\"attributes\":{\"line_alpha\":0.2,\"line_color\":\"orange\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Dj\"}},\"id\":\"1161\",\"type\":\"Line\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"1094\",\"type\":\"BoxAnnotation\"},{\"attributes\":{},\"id\":\"1014\",\"type\":\"LinearScale\"},{\"attributes\":{\"line_color\":\"blue\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Ri\"}},\"id\":\"1177\",\"type\":\"Line\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"1008\"},\"glyph\":{\"id\":\"1159\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"1161\"},\"nonselection_glyph\":{\"id\":\"1160\"},\"view\":{\"id\":\"1163\"}},\"id\":\"1162\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"orange\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Dj\"}},\"id\":\"1160\",\"type\":\"Line\"},{\"attributes\":{\"axis_label\":\"dimensionless time\",\"coordinates\":null,\"formatter\":{\"id\":\"1114\"},\"group\":null,\"major_label_policy\":{\"id\":\"1115\"},\"ticker\":{\"id\":\"1019\"}},\"id\":\"1018\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"1008\"}},\"id\":\"1163\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1019\",\"type\":\"BasicTicker\"},{\"attributes\":{\"line_alpha\":0.2,\"line_color\":\"blue\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Ri\"}},\"id\":\"1179\",\"type\":\"Line\"},{\"attributes\":{\"axis\":{\"id\":\"1018\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"1021\",\"type\":\"Grid\"},{\"attributes\":{\"label\":{\"value\":\"Cell j\"},\"renderers\":[{\"id\":\"1162\"}]},\"id\":\"1175\",\"type\":\"LegendItem\"},{\"attributes\":{\"label\":{\"value\":\"Cell i\"},\"renderers\":[{\"id\":\"1106\"}]},\"id\":\"1120\",\"type\":\"LegendItem\"},{\"attributes\":{\"axis_label\":\"dimensionless\\nNotch concentration\",\"coordinates\":null,\"formatter\":{\"id\":\"1111\"},\"group\":null,\"major_label_policy\":{\"id\":\"1112\"},\"ticker\":{\"id\":\"1023\"}},\"id\":\"1022\",\"type\":\"LogAxis\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"1008\"},\"glyph\":{\"id\":\"1103\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"1105\"},\"nonselection_glyph\":{\"id\":\"1104\"},\"view\":{\"id\":\"1107\"}},\"id\":\"1106\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"num_minor_ticks\":10},\"id\":\"1023\",\"type\":\"LogTicker\"},{\"attributes\":{},\"id\":\"1041\",\"type\":\"DataRange1d\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"blue\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Ni\"}},\"id\":\"1104\",\"type\":\"Line\"},{\"attributes\":{\"axis\":{\"id\":\"1022\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"1025\",\"type\":\"Grid\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"1008\"},\"glyph\":{\"id\":\"1177\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"1179\"},\"nonselection_glyph\":{\"id\":\"1178\"},\"view\":{\"id\":\"1181\"}},\"id\":\"1180\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"tools\":[{\"id\":\"1088\"},{\"id\":\"1089\"},{\"id\":\"1090\"},{\"id\":\"1091\"},{\"id\":\"1092\"},{\"id\":\"1093\"}]},\"id\":\"1095\",\"type\":\"Toolbar\"},{\"attributes\":{\"source\":{\"id\":\"1008\"}},\"id\":\"1107\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1050\",\"type\":\"BasicTicker\"},{\"attributes\":{\"line_alpha\":0.2,\"line_color\":\"blue\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Ni\"}},\"id\":\"1105\",\"type\":\"Line\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"blue\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Ri\"}},\"id\":\"1178\",\"type\":\"Line\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"1108\",\"type\":\"Title\"},{\"attributes\":{\"axis_label\":\"dimensionless time\",\"coordinates\":null,\"formatter\":{\"id\":\"1151\"},\"group\":null,\"major_label_policy\":{\"id\":\"1152\"},\"ticker\":{\"id\":\"1050\"}},\"id\":\"1049\",\"type\":\"LinearAxis\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"1120\"},{\"id\":\"1138\"}]},\"id\":\"1119\",\"type\":\"Legend\"},{\"attributes\":{},\"id\":\"1045\",\"type\":\"LinearScale\"},{\"attributes\":{\"line_color\":\"orange\",\"line_width\":3,\"x\":{\"field\":\"t\"},\"y\":{\"field\":\"Rj\"}},\"id\":\"1196\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1043\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1072\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1047\",\"type\":\"LogScale\"}],\"root_ids\":[\"1220\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.2\"}};\n", " const render_items = [{\"docid\":\"992c601b-7069-4604-b9db-fc958a9ffc18\",\"root_ids\":[\"1220\"],\"roots\":{\"1220\":\"9ee79ead-4f91-44cf-bacf-d965fa3f3a10\"}}];\n", " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", "\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " let attempts = 0;\n", " const timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " clearInterval(timer);\n", " embed_document(root);\n", " } else {\n", " attempts++;\n", " if (attempts > 100) {\n", " clearInterval(timer);\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " }\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "1220" } }, "output_type": "display_data" } ], "source": [ "def LI_2cell_rhs(x, t, betaN, betaD, betaR, nD, nR, kRS, tau):\n", " Ni, Di, Ri, Nj, Dj, Rj = x\n", " \n", " return np.array(\n", " [\n", " (betaN - Ni - Ni*Dj)/tau,\n", " (betaD/(1+Ri**nD) - Di - Nj*Di)/tau,\n", " betaR*(Ni*Dj)**nR / (kRS**nR + (Ni*Dj)**nR) - Ri,\n", " (betaN - Nj - Nj*Di)/tau,\n", " (betaD/(1+Rj**nD) - Dj - Ni*Dj)/tau,\n", " betaR*(Nj*Di)**nR / (kRS**nR + (Nj*Di)**nR) - Rj,\n", " ]\n", " )\n", "\n", "# Parameters (from Sprinzak et al)\n", "betaN = 10 \n", "betaD = 100 \n", "betaR = 1e6\n", "nD = 1\n", "nR = 3\n", "kRS = 3e5 ** (1/nR) \n", "tau = 1\n", "\n", "# initial conditions\n", "Ni0_slider = bokeh.models.Slider(title=\"Log Initial Ni\", start=-3, end=3, step=0.1, value=1)\n", "Di0_slider = bokeh.models.Slider(title=\"Log Initial Di\", start=-3, end=3, step=0.1, value=-3)\n", "Nj0_slider = bokeh.models.Slider(title=\"Log Initial Nj\", start=-3, end=3, step=0.1, value=1)\n", "Dj0_slider = bokeh.models.Slider(title=\"Log Initial Dj\", start=-3, end=3, step=0.1, value=-2.9)\n", "nR_slider = bokeh.models.Slider(title=\"Cooperativity (nR)\", start=0.1, end=10, step=0.1, value=3)\n", "\n", "x0 = [10**Ni0_slider.value,\n", " 10**Di0_slider.value,\n", " 0,\n", " 10**Nj0_slider.value,\n", " 10**Dj0_slider.value,\n", " 0]\n", "\n", "# Solve ODEs\n", "t = np.linspace(0, 20, 1000)\n", "args = (betaN, betaD, betaR, nD, nR_slider.value, kRS, tau)\n", "x = scipy.integrate.odeint(LI_2cell_rhs, x0, t, args=args)\n", "x = x.transpose()\n", "\n", "cds = bokeh.models.ColumnDataSource(data=dict(t=t, Ni=x[0,:], Di=x[1,:], Ri=x[2,:],\n", " Nj=x[3,:], Dj=x[4,:], Rj=x[5,:]))\n", "\n", "# Set up the plots\n", "pN = bokeh.plotting.figure(\n", " frame_width=275, frame_height=150,\n", " x_axis_label=\"dimensionless time\", \n", " y_axis_label=\"dimensionless\\nNotch concentration\", y_axis_type=\"log\",\n", ")\n", "pD = bokeh.plotting.figure(\n", " frame_width=275, frame_height=150,\n", " x_axis_label=\"dimensionless time\", \n", " y_axis_label=\"dimensionless\\nDelta concentration\", y_axis_type=\"log\",\n", ")\n", "pR = bokeh.plotting.figure(\n", " frame_width=275, frame_height=150,\n", " x_axis_label=\"dimensionless time\", \n", " y_axis_label=\"dimensionless\\nReporter concentration\", y_axis_type=\"log\",\n", ")\n", "\n", "pN.line(source=cds, x=\"t\", y=\"Ni\", color=\"blue\", width=3, legend_label=\"Cell i\")\n", "pN.line(source=cds, x=\"t\", y=\"Nj\", color=\"orange\", width=3, legend_label=\"Cell j\")\n", "pD.line(source=cds, x=\"t\", y=\"Di\", color=\"blue\", width=3, legend_label=\"Cell i\")\n", "pD.line(source=cds, x=\"t\", y=\"Dj\", color=\"orange\", width=3, legend_label=\"Cell j\")\n", "pR.line(source=cds, x=\"t\", y=\"Ri\", color=\"blue\", width=3, legend_label=\"Cell i\")\n", "pR.line(source=cds, x=\"t\", y=\"Rj\", color=\"orange\", width=3, legend_label=\"Cell j\")\n", "\n", "LI_2cell_layout = bokeh.layouts.row(\n", " bokeh.layouts.column(\n", " pN,\n", " pD,\n", " pR,\n", " ),\n", " bokeh.layouts.column(\n", " Ni0_slider,\n", " Di0_slider,\n", " Nj0_slider,\n", " Dj0_slider,\n", " nR_slider,\n", " width=150,\n", " )\n", ")\n", "\n", "# Display\n", "if interactive_python_plots:\n", " # Set up callbacks\n", " def _callback(attr, old, new):\n", " x0 = [10**Ni0_slider.value,\n", " 10**Di0_slider.value,\n", " 0,\n", " 10**Nj0_slider.value,\n", " 10**Dj0_slider.value,\n", " 0]\n", " args = (betaN, betaD, betaR, nD, nR_slider.value, kRS, tau)\n", " x = scipy.integrate.odeint(LI_2cell_rhs, x0, t, args=args)\n", " x = x.transpose()\n", " cds.data = dict(t=t, Ni=x[0,:], Di=x[1,:], Ri=x[2,:], Nj=x[3,:], Dj=x[4,:], Rj=x[5,:])\n", "\n", " Ni0_slider.on_change(\"value\", _callback)\n", " Di0_slider.on_change(\"value\", _callback)\n", " Nj0_slider.on_change(\"value\", _callback)\n", " Dj0_slider.on_change(\"value\", _callback)\n", " nR_slider.on_change(\"value\", _callback)\n", " \n", " # Build the app\n", " def LI_2cell_app(doc):\n", " doc.add_root(LI_2cell_layout)\n", " \n", " bokeh.io.show(LI_2cell_app, notebook_url=notebook_url)\n", "else:\n", " Ni0_slider.disabled = True\n", " Di0_slider.disabled = True\n", " Nj0_slider.disabled = True\n", " Dj0_slider.disabled = True\n", " nR_slider.disabled = True\n", "\n", " # Build layout\n", " LI_2cell_layout = bokeh.layouts.row(\n", " bokeh.layouts.column(\n", " pN,\n", " pD,\n", " pR,\n", " ),\n", " bokeh.layouts.column(\n", " bokeh.layouts.column(\n", " Ni0_slider,\n", " Di0_slider,\n", " Nj0_slider,\n", " Dj0_slider,\n", " width=150\n", " ),\n", " bokeh.models.Div(\n", " text=\"\"\"\n", "Sliders are inactive. To get active sliders, re-run notebook with\n", " fully_interactive_plots = True\n", " in the first code cell.
\n", " \"\"\",\n", " width=250,\n", " ),\n", " )\n", " )\n", "\n", " \n", " bokeh.io.show(LI_2cell_layout)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we can see, in a two-cell system these dynamics (in this particular parameter regime) lead to a divergence in the states of the two cells. When the initial Notch concentrations of the two cells are equal, this divergence follows a \"winner-takes-all\" process where the cell that starts with a higher Delta concentration ends up in the high-Delta state. But by using the sliders to alter the intial values of the Notch concentration as well, you can see that the full relationship is a bit more subtle.\n", "\n", "Is it always guaranteed that the two cells will end up in divergent cell states? No— try moving around the slider for the $n_R$ parameter to see how the system behaves both in regions of low cooperativity _and_ in regimes of high cooperativity. We can see that having the cells the cells go to diverging states, which is a prerequisite for patterning, is not necessarily a guarantee in our system. " ] }, { "cell_type": "markdown", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Expanding beyond a two-cell system\n", "\n", "Although the two-cell model is a good demonstration that our dynamics can, in principle, lead to diverging cell fates, we are fundamentally interested in cellular patterns that can expand over a spatial area that involves more than just two cells. In order to expand our model to accomdate larger systems, we need to incorporate the possibility of a given cell having more than one neighbor. A given Notch receptor $N_i$ will have the ability to interact with *multiple* possible Delta ligands $D_j$ to form a variety of distinct $T_{ij}$ complexes, all of which will contribute to the formation of $S_i$ within the receiver cell. We therefore need to update our steady-state expression for $S_i$ to\n", "\n", "\\begin{align}\n", "S_i = \\frac{k_S}{\\gamma_S} \\sum_{j=]i[ } T_{ij} = \\frac{1}{\\gamma_S}\\frac{k_S k_D^+}{k_D^- + k_S}\\sum_{j=]i[ } N_iD_j.\n", "\\end{align}\n", "\n", "Here, the notation $\\sum_{j = ]i[}$ means the index $j$ is iterated over all cells that are adjacent to cell $i$ (but not including $i$ itself), and the resulting set is summed together. \n", "\n", "Carrying this through the simplifcations and nondimensionalizations given above, we obtain the following nondimensionalized ODE system to accomodate arbitray spatial arrangements of cells:\n", "\n", "\\begin{align}\n", "\\tau \\frac{\\mathrm{d}N_i}{\\mathrm{d}t} &= \\beta_N - N_i - \\sum_{j = ]i[} N_i D_j \\\\\n", "\\tau \\frac{\\mathrm{d}D_i}{\\mathrm{d}t} &= \\beta_D \\frac{1}{1 + R_i^{n_D}} - D_i - \\sum_{j = ]i[} N_j D_i \\\\\n", "\\frac{\\mathrm{d}R_i}{\\mathrm{d}t} &= \\beta_R \\frac{\\left(\\sum_{j = ]i[} N_i D_j / k_{RS}\\right)^{n_R}}{1 +\\left(\\sum_{j = ]i[} N_i D_j / k_{RS}\\right)^{n_R} } - R_i\n", "\\end{align}\n", "\n", "Note the way that the summations affect the $T_{ij}$ formation terms in the $N_i$ and $D_i$ ODEs. Although the expressions now look quite a bit more complicated with all these sums, we did not add any new parameters our system— visually comparing the above ODE system with the previous ODE system for the two-cell system should reveal how the addition of additional neighbors did not change the fundamental nature of a given species' dynamics.\n", "\n", "\n", "\n", "We now note two features of this model:\n", "* First, it can represent the behavior any number of cells by expanding the size of the ODE system— a system of $i$ cells can be modeled by $3i$ equations following the above formula. While such a system would be impractical to solve by hand, using numerical approaches we can solve large ODE systems without much additional difficulty. \n", "* Second, the model can represent arbitrary geometric arrangements of cells because the assignment of neighbors to each cell is left arbitrary. Thus we could easily switch between, for example, a square or hexagonal lattice, or even the dimensionality of the space, by changing the neighbor-assignment rule for a given cell. However, the fact that the ODEs do not natively encode the neighbor-assignment rule means that we will have to write an additional function to go inside our ODE solver that identifies the apporpriate neighbors for a given cell." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Specifying the neighbor-assignment rules\n", "\n", "Let's first expand our two-cell system to a one-dimensional line of cells, where each cell would have just neighbors. In this arrangement we can easily write down a rule for determining the neighbors of a given cell $i$. Since a single index fully determines the location of a cell, we can know right away that the neighbors of cell $i$ are cell $i-1$ and $i+1$. But remember that we are only simulating a finite number of cells, say $N$ of them. What happens to this rule when we are looking at the leftmost or rightmost cell? Cell $0$ has no leftward neighbor, as Cell $-1$ does not exist— similarly, cell $N-1$ has no rightward neighbor, as cell $N$ does not exist (this is because our first cell is indexed as cell $0$, so the highest index for a group of $N$ cells is $N-1$). So what is the right way to handle these situations?\n", "\n", "There actually isn't a single right answer that will apply to every situation— different choices of how to handle the boundaries could be equally valid depending on the situation being modeled. A few different choices are schematized in the figure below.\n", "\n", "\n", "\n", "