From 07971741c94e1e336ea4dc7dac8ff820b3e6ecfd Mon Sep 17 00:00:00 2001 From: compucell3d Date: Sat, 24 Aug 2024 17:53:52 -0600 Subject: [PATCH 01/11] added elongated cell tutorial - w.i.p --- ...compartmental_elongated_cells_tutorial.rst | 168 ++++++++++++++++++ .../elongated_cells_tutorial/img001.png | Bin 0 -> 832 bytes .../elongated_cells_tutorial/img002.png | Bin 0 -> 896 bytes docs/index.rst | 7 + 4 files changed, 175 insertions(+) create mode 100644 docs/example_compartmental_elongated_cells_tutorial.rst create mode 100644 docs/images/elongated_cells_tutorial/img001.png create mode 100644 docs/images/elongated_cells_tutorial/img002.png diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst new file mode 100644 index 0000000..e1cc7f1 --- /dev/null +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -0,0 +1,168 @@ +Building Simulation of Elongated Cells. Case Study in using Compartments, FPP Links, Curvature energy terms. +------------------------------------------------------------------------------------------------------------ + +The goal of this tutorial is to build a simulation of multiple elongated cells where each sell is composed of compartments. +We want the cells to stay elongated throughout the course of the simulation. In this tutorial we want to show you how +starting from a simulation involving a single cell you can scale up and build more sophisticated models + + +Understanding Contact Energies - how to get non-pixelated cell shape +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now that we know about compartments and how they are handled by CC3D, let's see how we can translate our knowledge +into building a simple simulation that involves contact energies. In particular, we want to show you a common pitfall +that you may encounter in your work and how to diagnose it. + +In fact this tutorial is an intro to a more sophisticated simulation where we will leverage Focal Point Plasticity Plugin +and Curvature plugin. + +.. note:: + + Our intention is to teach you how you can start building complex simulation from grounds up + by starting with a single ce,, understand the behavior of the single cell under different set of parameters + and gradually adding complexity to your simulation. We strongly believe that in order to build robust and complex + simulations you firs must master simple cases and build confidence needed to bring your modeling skills + to the "next level". It is very much like playing the piano, in general it is advised to learn how to play + "Chopsticks" https://www.youtube.com/watch?v=JM5fjgiFrxg before attempting to play the "Flight of the Bumblebee" https://www.youtube.com/watch?v=M93qXQWaBdE + +Let's start. Our first simulation will involve single cell of type "Top" and two plugins - Volume and Contact. +The goal is to make the cell look non-pixelized and do not disappear. + +The code for this simulation can be found in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01`` + +Here is the XML + +.. code-block:: xml + + + + + 10000 + 10 + 1 + 2 + + + + + 25 + 2.0 + + + + + + + + + + + 0 + 0 + 0 + 4 + + + + + +Note that while we are using Contact Energy all the coefficients there are set to 0. As you can expect + +Main Python script is simple + +.. code-block:: python + + from cc3d import CompuCellSetup + + from ElongatedCellsSteppables import ElongatedCellsSteppable + + CompuCellSetup.register_steppable(steppable=ElongatedCellsSteppable(frequency=1)) + + CompuCellSetup.run() + + +and Python file with steppables is also not too complex: + +.. code-block:: Python + + from cc3d.core.PySteppables import * + + + class ElongatedCellsSteppable(SteppableBasePy): + def __init__(self, frequency=1): + + SteppableBasePy.__init__(self, frequency) + + def start(self): + """ + any code in the start function runs before MCS=0 + """ + top = self.new_cell(cell_type=1) + self.cell_field[45:50, 25:30, 0] = top + +In the steppable class ``ElongatedCellsSteppable`` we create a cell of type 1 (this is cell of type ``Top`` - see XML above). + +The XML is also very simple. We defined 3 cell types there and set ``TargetVolume`` and ``LambdaVolume`` to ``25`` and 2.0 +All contact energy coefficients are 0 - effectively stating that contact energy included in the actual simulation is always 0. + +If we run this simulation we will get the following: + +|img001| + +A partially pixelated cell is not particularly interesting but we should expect this. We created a square cell - see Steppable code above +and after few MCS it disintegrated into few pieces. Because we have only volume energy there is nothing to prevent cell pixelization +and any cell shape as long as the total number of pixel in the single cell is roughly 25 is perfectly fine. + +Let's try using contact energy to see if we can make the cell non-pixelized - ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01`` +The rationale is as follows: Volume energy will asure the number of pixel in the cell is roughly 25 and the +contact energy's task will be to keep cell from pixelizing by +penalizing cell-Medium interface. As you recall CC3D minimizes energy so if we use positive contact coefficient +between cell and the Medium the simulation the pixelized cell will have quite a high energy - because many single +pixels are surrounded by Medium and each such pixel will bring up total energy by multiples of contact energy coefficient. + +The actual number of interfaces between single pixel and Medium is control by ```` input in Contact PLugin. +In our case we are including interfaces up to 4th nearest neighbor - ``4`` . + +Let's look at the new specification of Contact energy: + +.. code-block:: XML + + + 0 + 0 + 15 + 4 + + +By changing contact energy coefficient between ``Top`` cells and ``Medium`` to a positive number CC3D will work to +minimize Top-Medium interfaces while maintaining total number of pixels of the cell (due to Volume energy term). + +It turns out that the cell disappears. Why? This is because Volume energy term was not "strong enough" to +overcome minimization of energy coming from Contact energy. Simply put when we get to one-pixel cell and we +try to overwrite this pixel by Medium the Volume energy plugin will contribute positive term to change of energy and Contact energy +will contribute negative term (because loosing cell medium interfaces leads to a negative change energy). + +Let's try fixing it by "strengthening" Volume energy term + + +.. code-block:: XML + + + 25 + 4.0 + + + +|img002| + + +This time we get the desired result. + +Let's add few more cells (including of type ``Center``). + + +.. |img001| image:: images/elongated_cells_tutorial/img001.png + :scale: 50% + +.. |img002| image:: images/elongated_cells_tutorial/img002.png + :scale: 50% \ No newline at end of file diff --git a/docs/images/elongated_cells_tutorial/img001.png b/docs/images/elongated_cells_tutorial/img001.png new file mode 100644 index 0000000000000000000000000000000000000000..50dbaa681d67de6d00ae986a61f03b2c48baa6f8 GIT binary patch literal 832 zcmeAS@N?(olHy`uVBq!ia0y~yU=#$hmvgWINwb0spa3(wr;B4qMcmt4hJM-U60U)4 z(3=t{}I>SV`z_R}T*W0T<=O1Vn(tBQMQ}_RKf4!v84Aq!E!A5=09dounKU2N@ zY&CDi)PhX?eAVY26~T?Oh4jvL9ME|vbnf!gqo*VG@Em*jM{WU-dvM3`iUYBn{BN&C zAFs}rf4}wf?}oPavTU1k+xw#D8>u^wsIkZ>N zQj%|n_Cui_j+)sm-aAZ{p1*w5(#Wq0loGVG=e{$wfYXg-pYNg6J+|RJ9DnjTrzg8S z@D|cL-oN65DkO>y9WGpVpx>*)qRygKe(Hw;pt2P$?H|6?SpJ{+#yI_KB~$G)$sItU zg1+M~7d!6w`p5nJK~`0pme0J8=6$}|KhNHtTYP!}=lSFZZ<+SF9#WMM{9(p9y&&6V zj;?|Cj+ScWBC`kUTD%REKI97NJ$!q!sPDwf%8+x<8^bwm?$!k}DmAJrGc~jP`+RRF hv&&#iFh91`Gwd>H5Nh)aR|4h?22WQ%mvv4FO#o>^BUJzZ literal 0 HcmV?d00001 diff --git a/docs/images/elongated_cells_tutorial/img002.png b/docs/images/elongated_cells_tutorial/img002.png new file mode 100644 index 0000000000000000000000000000000000000000..fa8e382532cb096ba38fa0c711e5255ea4ac7f48 GIT binary patch literal 896 zcmeAS@N?(olHy`uVBq!ia0y~yVB`T}4h}Y;$ST=Wtqcsz?w&4=Ar*0NuN!(Tag=bq z70+3vs0KNhkys4^yaGDHY5OdDm6 z%y6g>SYQ9Y=Jm^`mgWV^S>%o!*U)+Yet!M~KTaEt=7X$47B|B0_Z?06zzt;mcRQ5u z;k1y&jDru7IAzWx6l`SSOEcIJ!NhJX5u?-CEXkuc?Z81EHgWF<1@E0d1kcZZ=*P+6 n&2(TA!v+-wouR<2dC7bHp=tZkgd;A%oWgTe~DWM4fWU}oQ literal 0 HcmV?d00001 diff --git a/docs/index.rst b/docs/index.rst index 84b3d47..4475663 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -73,6 +73,13 @@ or watch the `CompuCell3D Workshop Python tutorial videos Date: Sat, 24 Aug 2024 20:11:40 -0600 Subject: [PATCH 02/11] added elongated cell tutorial - w.i.p --- ...compartmental_elongated_cells_tutorial.rst | 100 +++++++++++++++++- .../elongated_cells_tutorial/img003.png | Bin 0 -> 2731 bytes .../elongated_cells_tutorial/img004.png | Bin 0 -> 2854 bytes .../elongated_cells_tutorial/img005.png | Bin 0 -> 3318 bytes .../elongated_cells_tutorial/img006.png | Bin 0 -> 3364 bytes 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 docs/images/elongated_cells_tutorial/img003.png create mode 100644 docs/images/elongated_cells_tutorial/img004.png create mode 100644 docs/images/elongated_cells_tutorial/img005.png create mode 100644 docs/images/elongated_cells_tutorial/img006.png diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst index e1cc7f1..fdec979 100644 --- a/docs/example_compartmental_elongated_cells_tutorial.rst +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -160,9 +160,107 @@ This time we get the desired result. Let's add few more cells (including of type ``Center``). +.. code-block:: python + + class ElongatedCellsSteppable(SteppableBasePy): + def __init__(self, frequency=1): + + SteppableBasePy.__init__(self, frequency) + + def start(self): + """ + any code in the start function runs before MCS=0 + """ + top = self.new_cell(cell_type=1) + self.cell_field[45:50, 25:30, 0] = top + + center_1 = self.new_cell(cell_type=2) + self.cell_field[45:50, 30:35, 0] = center_1 + + top_1 = self.new_cell(cell_type=1) + self.cell_field[45:50, 35:40, 0] = top_1 + + + +and let's create a situation where cells "prefer" to be surrounded by Medium and not touch each other. This means +contact energy coefficient between cell and Medium is lower than contact energy between two cells: + +.. code-block:: XML + + + 0 + 30 + 15 + 15 + 30 + 30 + 4 + + +When we run this new simulation (``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01``) we get the following: + +|img003| + +|img004| + +Cells that initially stick to each other after few steps are separated but each cell is i a non-pixelized form. + +Writing Convenience function to create elongated cell ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +When we look at the Python code above where we created 3 cells we can see that it would be nice to have a function that +would create entire cell for us. Here is a prototype of such function: + +The entire code can be found here: ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01`` + +.. code-block:: python + + class ElongatedCellsSteppable(SteppableBasePy): + def __init__(self, frequency=1): + + SteppableBasePy.__init__(self, frequency) + + def start(self): + self.create_arranged_cells(x_s=25, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + + def create_arranged_cells(self, x_s, y_s, size, cell_type_ids=None): + """ + this function creates vertically arranged cells. + + x_s, ys - coordinates of bottom_left corner of the cell arrangement + size - size of the cell arrangement + cell_type_ids - list of cell type ids + + """ + for i, cell_type_id in enumerate(cell_type_ids): + cell = self.new_cell(cell_type=cell_type_id) + self.cell_field[x_s : x_s + size, y_s + i * size : y_s + (i + 1) * size, 0] = cell + + +This function iterates over a list of ``cell_type_ids`` and for each new cell type listed it creates a new cell of this +type that is placed 5 pixel above previous cell. This way after we run it we will see the following initial configuration (after first MCS and after several MCS): + +|img005| + + +|img006| + + .. |img001| image:: images/elongated_cells_tutorial/img001.png :scale: 50% .. |img002| image:: images/elongated_cells_tutorial/img002.png - :scale: 50% \ No newline at end of file + :scale: 50% + +.. |img003| image:: images/elongated_cells_tutorial/img003.png + :scale: 50% + +.. |img004| image:: images/elongated_cells_tutorial/img004.png + :scale: 50% + +.. |img005| image:: images/elongated_cells_tutorial/img005.png + :scale: 50% +.. |img006| image:: images/elongated_cells_tutorial/img006.png + :scale: 50% + diff --git a/docs/images/elongated_cells_tutorial/img003.png b/docs/images/elongated_cells_tutorial/img003.png new file mode 100644 index 0000000000000000000000000000000000000000..db628e8cfcf1255f43e5e1ff2d9cdc01759926d1 GIT binary patch literal 2731 zcmeAS@N?(olHy`uVBq!ia0y~yUl6*MvXZXLcaolI$A7lB0Rl#b4{4kX3^}8CGz>=5 zz-Ss6O#=g+2K@Ke*Y4f%*q-s757U9nCpG^+Rv5a8eBe}JkO*XmW@->*-JpuhjHz+4 zwcdBFx^NHc12Ch?P5jbQn!*@K-=~5t2I} zXeqy%^H`U`T#NC+Bjr~z%3M2?IT_qU4oqW6aA5@2@<_}|!*bu_(F}PZObozuHHt^W efV4DlSUyUqXp@_|P%y9&%HZkh=d#Wzp$P!)1Gkj` literal 0 HcmV?d00001 diff --git a/docs/images/elongated_cells_tutorial/img004.png b/docs/images/elongated_cells_tutorial/img004.png new file mode 100644 index 0000000000000000000000000000000000000000..a443435cfd7eaf714b6b2dc412ad710f000a0eee GIT binary patch literal 2854 zcmeAS@N?(olHy`uVBq!ia0y~yVDblI9}YI4$m3wA0}KpYZ#`WcLn`9l-nQ<08p7au zah{N+Psy|{Y5>Z!PcUfZ5jtGcW2yuYvZ_cwC}hV|1J7!Hi$ z(J&ZI1EXnRG!0NA4Scu~U;pn<+HqrseJfZRmd72tuzvslZ&}BL3lupS{3ZPl^r|x0 zq}ni=Ph60R7?cwBCZ?5ESTVu(2a45XS>k82ss zCo#kvIDO#f%jx!h$qt}UiD~%AQZS3<0Ta-3msJ?V6Kojgs4?zfc+C00g!2Hagg?V_ zPX@gM6-*YsOa+X`gb!p2HE;vN#&0r3S`VDw@l*e};1{Xm#`}OFP$0~CpmlGlgQO?J zM246dA6Y&m0tF=f8RUU3MC0E0c=S%T%=riR`~IJFYB-xCV^< zPL_sf<9QA0LJWClE12eaFzhgW%vk|U3}SujAJmn|*vvm!0ah$_PR_IYBTIZ7(*a!x z{{z;l40oD7vg`@QO(|>IDsKTs(laqlV iXB3Zy0hwul=RZRk+se1j?^lA_zYLzPelF{r5}E+V;bsB= literal 0 HcmV?d00001 diff --git a/docs/images/elongated_cells_tutorial/img005.png b/docs/images/elongated_cells_tutorial/img005.png new file mode 100644 index 0000000000000000000000000000000000000000..833a0c81f3615d32dd54ce2f4bad320cba78f73e GIT binary patch literal 3318 zcmeAS@N?(olHy`uVBq!ia0y~yVDbavU=B8*$UniE8yFaP_IkQFhE&A8y}i3v*E7lW zVp*rv%M&k>A4oW4ueiu5q-t_u$8Q^hS&{SGrM)9gu^Aa3X=ZuUZ~yPd<9Y@Li%AR& z2d0hU(J&ZI1EXmGYZ`F>_j~`pzutT6_!;V$ISZa7-}&=6{{J7NW5Nvk7qVC+Suhsh zqCUwU&aAX$XQ)}sV)5zf;g{h(>I`)OOfrUZ7%@19#96V%hzF)16p2@%=w|?AtuRS$ri$&G`W_+G+q|EDT3h97FcAYa{nc|FiGe-_{mZhTQeuG}ZX zgt|koEg2q2s~(uxFZlVF`3qx7Pli8jLJvS8*ouQXQO>hGzS5SPp=L5P>Ve@*y{IQX z0sUO_@XN<}`(J<6Vff%H^x#A~-}39_%m?zd82f-B8l!=O+H@7r(T>yw`wOG4u7(^ck|;RED%5<*GB!2T&Lh>kZ@{+0eB zON65<_rCnL{QAPrHz8_mK3#o$5}4VD2qfR{N3~r5gb=yCWzMvtJs(Jp8ZkI^&o6%G!VH-a2fUAI+CdLteQCGrFGO;6&)ea<1Zf7eK7!G;{Ze_H^x0v`t%*2R4O!)Er_|Ese z?|I($eV*s!)Fwz{93A#LAcPzxvEoF8a2c$`o%Zm=F#8dK(5`ujIQ)%*wEGhWvZjCP zh|&jp&pZ^j7n2@jjA5wJSS|WKqGIe<>6>4Uyio6-JYZiauk`I$*7D2EOgcgy%?MH3 zYr6;A9N6Z-lQ|Gaww?Dw1uZDp zO@@qtSk}Q#L?6ee{WU80>YJ*=eXG|P5i(VA)asb(o89|ALqdgJ;Efub)Ch=d$T04$ zsCx-w0@vQySAcLCFRFxBp;>M9J zXUxv_VLa`y&g-5`8-ksPC0mvYgq})eQw|e30Wj|=4bL`epfnJNb5ugoU&QLB|iQYY^uLJ0u6g|T1Lc-d= z#`XulmFc$vw2v@a%t7eK4U0ah?S4@5$x{?dKwX=(A7ZwDW))s>tBe~5~ zzvZ%1-n(IsnMa7Ki=*#kIksn9$*TrP!631Ty+U2?{BG#IT%f4a93n2xjk*K+saTww z{|+5G{8fle8TEiP^ZIxW?jPDaN2yg-wXU12qFk4wkIh}b zt7&|B)~{%JB?edl8dJ~dWy`ZmAA((&BG|-mSJ$k5hJRX&87n#Tr5^o*FAT;)Ac;+P z@o$SU;w`rEWq{(_yfs_7*G&0gWyf8URj16yDR~1@E$BT@zla%OV#7A(zKWL|S!W>` z4^BkjY~vghBHf3HCYYx+>tqjlvU_gw>q1qUZ7zGx@C_m`cIvldrj^yOHO2*+$Zevc zz>|!g?9}%`H~fY_Z`tlwFRk7dR+at0jPsROcOa=i(OCF%a#7Q|M-vC3WhLkAq~C$~ z;_ImaTe9alLN`#KC<^z5#!{ch(x;#>lMB23JiJ5ooT3p7i+)|OA-LDEHAUGqljN?m z+_Di!A|RY}9y09`Mo)9pJ8e0EHv1tsa>KU9kd({M3*{qe;HF*WpE%I=-Oao8|EE{C Z*N{SVf1)fcMGAjEND?I#Uye9&_BR%SZSDX7 literal 0 HcmV?d00001 From 12930d7365b1d24152f8d2e19d57eb44547c0b1f Mon Sep 17 00:00:00 2001 From: compucell3d Date: Sat, 31 Aug 2024 11:49:53 -0600 Subject: [PATCH 03/11] added new content --- ...compartmental_elongated_cells_tutorial.rst | 180 +++++++++++++++++- .../elongated_cells_tutorial/img007.png | Bin 0 -> 3399 bytes .../elongated_cells_tutorial/img008.png | Bin 0 -> 3362 bytes .../elongated_cells_tutorial/img009.png | Bin 0 -> 3198 bytes 4 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 docs/images/elongated_cells_tutorial/img007.png create mode 100644 docs/images/elongated_cells_tutorial/img008.png create mode 100644 docs/images/elongated_cells_tutorial/img009.png diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst index fdec979..0064405 100644 --- a/docs/example_compartmental_elongated_cells_tutorial.rst +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -6,8 +6,8 @@ We want the cells to stay elongated throughout the course of the simulation. In starting from a simulation involving a single cell you can scale up and build more sophisticated models -Understanding Contact Energies - how to get non-pixelated cell shape -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Understanding Contact Energies - how to avoid pixelated cells +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Now that we know about compartments and how they are handled by CC3D, let's see how we can translate our knowledge into building a simple simulation that involves contact energies. In particular, we want to show you a common pitfall @@ -113,7 +113,7 @@ A partially pixelated cell is not particularly interesting but we should expect and after few MCS it disintegrated into few pieces. Because we have only volume energy there is nothing to prevent cell pixelization and any cell shape as long as the total number of pixel in the single cell is roughly 25 is perfectly fine. -Let's try using contact energy to see if we can make the cell non-pixelized - ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01`` +Let's try using contact energy to see if we can make the cell non-pixelized - ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_02`` The rationale is as follows: Volume energy will asure the number of pixel in the cell is roughly 25 and the contact energy's task will be to keep cell from pixelizing by penalizing cell-Medium interface. As you recall CC3D minimizes energy so if we use positive contact coefficient @@ -197,7 +197,7 @@ contact energy coefficient between cell and Medium is lower than contact energy 4 -When we run this new simulation (``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01``) we get the following: +When we run this new simulation (``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_03``) we get the following: |img003| @@ -211,7 +211,7 @@ Writing Convenience function to create elongated cell When we look at the Python code above where we created 3 cells we can see that it would be nice to have a function that would create entire cell for us. Here is a prototype of such function: -The entire code can be found here: ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01`` +The entire code can be found here: ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_04`` .. code-block:: python @@ -222,6 +222,8 @@ The entire code can be found here: ``Demos/CompuCellPythonTutorial/ElongatedCell def start(self): self.create_arranged_cells(x_s=25, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + for cell in self.cell_list: + print("cell id=", cell.id, " cluster_id=", cell.clusterId) def create_arranged_cells(self, x_s, y_s, size, cell_type_ids=None): """ @@ -245,6 +247,165 @@ type that is placed 5 pixel above previous cell. This way after we run it we wil |img006| +Adding convenience functions to your steppables will make your code easier to read and maintain + +Making Compartmentalized Cell +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To understand better the concept of compartmentalized cell we added a printout in the ``start`` function that prints +cells' ``cell.id`` and ``clusterId``. When we dont have compartmentalized cells in our simulation, no two cells share +the same ``clusterId`` or each cell's ``id`` is paired with a distinct ``clusterId`` - as we can see from the printout +below: + +.. code-block:: console + + cell id= 1 clusterId= 1 + cell id= 2 clusterId= 2 + cell id= 3 clusterId= 3 + cell id= 4 clusterId= 4 + cell id= 5 clusterId= 5 + cell id= 6 clusterId= 6 + + +Let's change it. Instead of creating 6 independent cells let's assign them to the same cluster so that our six cells +will now be turned into compartments of a single cell with ``clusterId`` 1. From the modeling point of view this +corresponds to a situation where you would like your biological cells be represented with more level of internal details. +Perhaps you would like to simulate polarized cells , or perhaps you may want to better control shape of cells. + +Here the code (``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_05``) that turns six +independent cells in to six compartments of a single compartmentalized cell: + +.. code-block:: python + + def create_arranged_cells(self, x_s, y_s, size, cell_type_ids=None): + """ + this function creates vertically arranged cells. + + x_s, ys - coordinates of bottom_left corner of the cell arrangement + size - size of the cell arrangement + cell_type_ids - list of cell type ids + + """ + cluster_id = None + for i, cell_type_id in enumerate(cell_type_ids): + cell = self.new_cell(cell_type=cell_type_id) + + if i == 0: + cluster_id = cell.clusterId + else: + # to make all cells created by this function, we must reassign clusterId + # of all the cells created by this function except the first one + # When the first cell gets created, it gets reassigned clusterId by + # CompuCell3D and we will use this clusterId to assign it to all other cells created by this function + self.reassign_cluster_id(cell=cell, cluster_id=cluster_id) + self.cell_field[x_s : x_s + size, y_s + i * size : y_s + (i + 1) * size, 0] = cell + +and here is the printout of cell ``id``s and ``clusterId``s: + +.. code-block:: console + + cell id= 1 clusterId= 1 + cell id= 2 clusterId= 1 + cell id= 3 clusterId= 1 + cell id= 4 clusterId= 1 + cell id= 5 clusterId= 1 + cell id= 6 clusterId= 1 + + +As we can tell all 6 cells share the same ``clusterId`` which means they represent single compartmentalized cells +that is composed of 6 compartments. + +It is interesting how we have accomplished this assignment. It is worth pointing out that naive assignment of ``cell.id`` +or ``cell.clusterId`` , for example ``cell.clusterId = 20`` will lead to an error: + +.. code-block:: console + + AttributeError: ASSIGNMENT cell. clusterId=1 is illegal. clusterId is read only variable + +Instead you must use steppable built-in function called ``self.reassign_cluster_id`` to reassign ``clusterId`` of a cell + +If we look at the code - ``create_arranged_cells`` - notice that when we iterate over list of ``cell_type_ids`` +we first create cell and then we keep track of the ``clusterId`` of the first cell that was created inside the ``for`` +loop. For each subsequently created cell we reassign it's ``clusterId`` attribute to match the ``clusterId`` of the +cell that was created first. Normally when new cell gets created CC3D will bump both ``cell.id`` and ``cell.clusterId`` +but by reassigning we are correcting CC3D default behavior so all sx cells end up with ``clusterId`` 1. +Here is the initial configuration of the cell field: + +|img007| + + +But if we run simulation a bit longer we will get the following: + +|img008| + +This is not what we expected. In the previous simulation all cells were nicely separated, but now, with the same energy +parameters we are getting a completely different simulation where cells are pixelized and intermixed with each other. +The only change we did was reassigning ``clusterId``s. What is then the explanation of this behavior: + +The explanation is simple but not obvious. The Contact energy plugin that controls whether cells like to stick to each +other or like to be surrounded by Medium works only between cells that are members of different cluster. In our case this means that +Contact energy plugin will only contribute energy that comes from Contact between cell and a Medium (because they are +from different clusters since medium is a special cell). On the other hand Contact energy plugin WILL NOT include any +contributions coming from contact between e.g. ``cell.id`` 1 and ``cell.id`` 2. Those contact cell-cell interfaces will +not contribute anything to the change of energy. Therefore, when in order to minimize energy CC3D will bundle cells together +(because cell-cell interfaces contribute 0 units of energy) in order to minimize cell-Medium interfaces where +each such interface contributes 15 units of energy (see XML definition of Contact energy plugin) + +To make sure this is indeed the case, go back to ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_04`` and change +definition of Contact energy to looks as follows: + +.. code-block:: XML + + + 0 + 0 + 15 + 15 + 0 + 0 + 4 + + +and you will get exactly the same cell shape as we did in the current simulation with compartmentalized cells. + +ContactInternal Plugin +++++++++++++++++++++++ + +To restore the expected behavior (where we have 6 cells that are members of the same cluster but are not +intermingled with each other) we need to add a plugin that will count energy contributions coming from interfaces +between cells that belong to the same cluster. Here is the XML code we need to include - +``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_06``: + +.. code-block:: XML + + + 0 + 30 + 15 + 30 + 30 + 15 + + 4 + + + + + 30 + 30 + 30 + + + 4 + + + +Contact and ContactInternal work in tandem. Contact takes care of interfaces between cells that belong to different clusters +while ContactInternal computes energies coming from interfaces between cells belonging to the same cluster. Now each cell-cell +interface coming from same cluster will add 30 units of energy which combined with 15 units between cell and Medium will cause cells +to avoid intermingling. + +|img009| .. |img001| image:: images/elongated_cells_tutorial/img001.png @@ -261,6 +422,15 @@ type that is placed 5 pixel above previous cell. This way after we run it we wil .. |img005| image:: images/elongated_cells_tutorial/img005.png :scale: 50% + .. |img006| image:: images/elongated_cells_tutorial/img006.png :scale: 50% +.. |img007| image:: images/elongated_cells_tutorial/img007.png + :scale: 50% + +.. |img008| image:: images/elongated_cells_tutorial/img008.png + :scale: 50% + +.. |img009| image:: images/elongated_cells_tutorial/img009.png + :scale: 50% \ No newline at end of file diff --git a/docs/images/elongated_cells_tutorial/img007.png b/docs/images/elongated_cells_tutorial/img007.png new file mode 100644 index 0000000000000000000000000000000000000000..d17411acfd72f4d461f00261967daf8ee28f2eea GIT binary patch literal 3399 zcmeAS@N?(olHy`uVBq!ia0y~yVDbavKn^yb$mW|CyMf|-o-U3d6>)EG8+PT~p6Yt> z{?boN`%Z*2UuD?pHqR>1Rf<*V*{+|Zlg@~LIA_piY#Fm{Cr5|E9B-(U^{qFX6L-I^6=KH3<%%g5j31=E8kGH=PZTgcFrUKUKCf*8P&QwK zvCoEA5opQ%04AAADJS{b%G&RtZNd!s6Byk074ytBm@^vbSEVd}Z#q6sgBY@7uk?Mif{o+KZzsg$+8e-i5K%MMkq?jNOy^XtXw*Sqbj|IdU)#rb0w zK7IMO5_edT6pT;4zDfY0@ zVhleLISYVZ{qt77{{K^G{7CpQ#HcX#(TxHYkWWir)R;qZWd6s?kDl;7)poLpqm4Yoa>*5QvPrv+k#lM93o`E5Ua}F7(OjsXJwrm>O`tkBZ!MENFXa}TSU-OJBzv{*o+F=#Y$W(R!A#_w#@jo zSz5n}M%vCf)BP}IhGfcz^g0Jrhg9rlM+WpRtsp6uLIwKC-MMi;mTXJhpZ!?)ag%fJ zx%d5e-sgF8?&%$T4t0Lgd;kEITUf9Q03r`wjCo}EGR$e=Ut0mX77Mtr@U0f*5)h=NAjRyhKU%R7)eju3K^18# z5~UOT3(kVlOg#ubOht;%qyps;ihr?)qIQ)KYdUumQAPtoizKd)2|16OmhsY@u6V%S zNtBHB1zWtuXRaTNG?%I}K(K()o++Y$Lp)Tolm{w4CQ5pC6V<;a$VFWVU_g)1f{BaL zoPB|7e9^FgKSSez=srq&ow)w1^NveL^^O>P&AOW?LEu+rE=o=00e?27od9DRSJyGh z(g}zo#ZP9FJB7~77f;uO_1;qxf(Iv_4@)pB~lQ*tT zJWGBFT!u%G@9tyaEwzyL*qTptT~oY-wp}NtYB)2nkmzuNe5LGUS9gehczJ=gBsapc zxB|sNxo@hLh%i$8n|*I;9H9@ffY_P$!ZvDgu*?C|LpYI*sej(93;Y**%1;i|)C|{q zZ-=Cw==lrE0O+lC$=SUxY!j91@pZsU)bp89YK;7CekD;gWgy{pV(lW&7TrEkO8 zQe%cd4%SsjlXA3wn`9MT#<~XwKPVav$2ux&O~6m3wCfz3f{T->*Ce5_@#ngeHAJtvGsAPvkO4j-o-s zHf>^MC%0@=`i!b~AR|l{koeHp)d}0+#F3e3Gd}#UVK?Fh8ji2t)HY(mb%xi)RvchT zWzhi^mJYGV#j!|AqQ}N7W9-~XgT;jHq|1aZ8W_+a@#{68Yn8G1-e!Zb);Ze74$OKL zacUY&Zq7TLw8CClJuNhkhkGJT<5X}6PN|XHS*~U}M*C%k4sX`DwSxg}uf#JfG7~00 zFpFJPVT-*T3l9PG1gx%nMJqr!uNpsPR2?AGhjx>aHS3tU%gq-`@)}h#SZ$JI;oq(dm z6$hAk(3k}I!^P{AAb7IypR6cL576&OL%&RwYHPL7M%F@=|IBh8DQ#7%UfN_b)gTGw zsA9Rg{##pv7-vuqdP S+zkBp0o*P80?X#I&wdAg^7w=R literal 0 HcmV?d00001 diff --git a/docs/images/elongated_cells_tutorial/img009.png b/docs/images/elongated_cells_tutorial/img009.png new file mode 100644 index 0000000000000000000000000000000000000000..95d3c6ca23ba2b64ee8fbb2657de419d2fa70e55 GIT binary patch literal 3198 zcmeAS@N?(olHy`uVBq!ia0y~yVDbiG4mP03_q~^x7#Mh5JzX3_D&pSWHOx~vxzP3E z%}YOK^`5xSw6!6!*CzK-y@0?+smk^@>+;gHR+scVj!{tZh&u22Vf+2M-*5jjF#HGr z8Zw!I;eZMQg8?T4gU={;G&DvN!)RV8;Qs&b`u%-JKE^Rr1Tft>bo;{3-}e7Mp5{?w zs0(De)3lN0fUn8{T?uc7J1*$lm{&i(-rC-G_<1@|`p+Vk9aqA87xhEgQ-C_psvcO{ zqsow{$EcU8!&p$vS)iHB*)ZF?!CMk&UJR4|o7?9<$rtWXzYo1*+2bNFNho zFrR*aySn7Wp8lDSZRb~h;RRdvpw-qY<=*i#ALpI7`PBw?)d!|~Y=_+YlAl)hJ>UPl z;va}Am9d*|Ij^?-&uxYS%|aE7_Qp|irQf9Oji>e1vori);@s1)x&6%S&G!waG3@AM zi92x9`PtcE zenuXzuK(8i_-6U>`|J$=yoD+f`}t;`uQADxt9`tG$96t87vG8YK#mGo(v2Lc(@JAOa9C+zF%y^&miy7u>6ZzL*4(!=jGE37(X-% zJfLFJ+KyNLyQh%-dSKECvg^J0~3q5H$_^j zrH$*KT2$==CZFiz=8Qk)Ph;?ZdGTP12oXNgl--~4TkyCw!vlT#*2e`a>;J#bkAGC5 z&rmZFm|uap{cpd0{mg^la1R1!A%^KjzyRIJvI8{-`xXAFdK-QG;b-H%@_p9-WEegy zV6iv~%<%4#KA_BR(FzRz$zBb?z}#xH5`%m6X7bA)qIb6U*>f}4C@}gJ9*wZt$H@>6 zWCD}=hb2M}M1Z#YYhiE;|2Vz9TlnRV4lp7os~lLmFUtUuTCf)>F{gkr{7mRU(DC(; z>yCcR1La(zn>z=V_Wi&A7FZfEK1ks#Sh=0?%lG Date: Sat, 31 Aug 2024 15:42:38 -0600 Subject: [PATCH 04/11] finished case study of how to build elongated cells --- ...compartmental_elongated_cells_tutorial.rst | 369 ++++++++++++++++++ .../elongated_cells_tutorial/img010.png | Bin 0 -> 3391 bytes .../elongated_cells_tutorial/img011.png | Bin 0 -> 3655 bytes .../elongated_cells_tutorial/img012.png | Bin 0 -> 3503 bytes .../elongated_cells_tutorial/img013.png | Bin 0 -> 3301 bytes .../elongated_cells_tutorial/img014.png | Bin 0 -> 7255 bytes .../elongated_cells_tutorial/img015.png | Bin 0 -> 7927 bytes .../elongated_cells_tutorial/img016.png | Bin 0 -> 8415 bytes .../elongated_cells_tutorial/img017.png | Bin 0 -> 7260 bytes 9 files changed, 369 insertions(+) create mode 100644 docs/images/elongated_cells_tutorial/img010.png create mode 100644 docs/images/elongated_cells_tutorial/img011.png create mode 100644 docs/images/elongated_cells_tutorial/img012.png create mode 100644 docs/images/elongated_cells_tutorial/img013.png create mode 100644 docs/images/elongated_cells_tutorial/img014.png create mode 100644 docs/images/elongated_cells_tutorial/img015.png create mode 100644 docs/images/elongated_cells_tutorial/img016.png create mode 100644 docs/images/elongated_cells_tutorial/img017.png diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst index 0064405..3d5385d 100644 --- a/docs/example_compartmental_elongated_cells_tutorial.rst +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -408,6 +408,351 @@ to avoid intermingling. |img009| +FocalPointPlasticity Plugin - constraining intercellular distances +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Now that we understand how to handle Contact and COntactInternal plugins . let us focus attention on energy terms that will +allow us to constrain distances between cells. FocalPointPlasticity Plugin (**FPP**) is one of the solutions. + +This plugin implements energy term that penalizes deviations from target distance between two cells that are connected +by FPP link. This plugin is described in details in PLugins section of the Reference Manual but it is worth mentioning that +this plugin has separate mechanisms for handling links between cells that are part of the same cluster and cells that +are part of different clusters. The simulation code we will use in this section is in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_07`` + +In order to add spring-like links between members of the same cluster we need to add the following section to the XML + +.. code-block:: XML + + + + + 100.0 + -50.0 + 5 + 10.0 + 1 + + + + 100.0 + -50.0 + 5 + 10.0 + 2 + + + + +Because in our initial compartment arrangement we have two ``Top`` cells capping the "ends" of the cluster we want to allow only +a single internal (i.e. between compartments) link between ``Top`` and ``Center`` cells. However for ``Center`` cells +we will allow two internal links. Let's run the simulation and turn on visualization of the links (Visualization-> FPP Links): + +After few MCS (FPP links might take few MCS to form because there is stochasticity involved in establishing links between cells) +we will see the following picture + +|img010| + +If we let the simulation run for a while, however, we will see that while the distance between cells is maintained the cells do not +form "elongated cell" + +|img011| + +Additionally, if we lower FPP Lambdas from 100 to 10: + +.. code-block:: XML + + + + + 10.0 + -50.0 + 5 + 10.0 + 1 + + + + 10.0 + -50.0 + 5 + 10.0 + 2 + + + + + +We will see that ``Center`` cells that initially touched ``Top`` cell form additional links between themselves. +This happens because those two ``Center`` cells can form two links between Center themselves. The first link is formed +at the beginning of the simulation but during the course of the simulation , when those two ``Center`` cells come together +(e.g. due to weak FPP Lambda) there is nothing keeping them form forming another link. + +|img012| + +.. note:: + + CC3D will add additional constraint on the max number of links a given cell type can form which will solve this problem + but in the current version we have to deal possible issues that might arise when cells may form extra link that we do not want + + +Curvature Plugin +++++++++++++++++ + +Let us now put everything together an implement elongated compartmentalized cell. The solution that will prevent two +``Center`` cells (the ones that initially were touching ``Top`` cell), from forming an extra FPP link, +is to use Curvature Plugin. The way Curvature plugin works is by constraining the angle that two adjacent links can form +By using high value of Curvature lambda you may constrain two adjacent links to form a straight line +and by adiabatically lowering the lambda you can control how much elongated cell can bend. +The code for this section is in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_08`` + +HEre is the code that we add to the XML to enable Curvature energy calculations: + +.. code-block:: XML + + + + + 1000.0 + -50.0 + + + + 1000.0 + -50.0 + + + + + + + + + + + + +With this extra addition the compartments will form a line even if we let the simulation run for a very long time: + +|img013| + + +As you probably have noticed, the syntax for this plugin resembles the syntax of the FPP plugin - we have ````, +````, ``MaxNumberOfJunctions`` . This is because Curvature plugin establishes its own set of "links" between +cells but those links are not used to penalize intercellular distance but rather to penalize the deviation from straight line +arrangement of compartment cells + +Adding persistent motion to cells ++++++++++++++++++++++++++++++++++ + +Let us add a bit more code to make this simulation more interesting. First, we will create more cells. We will use +our convenience function ``create_arranged_cells`` and as a result all of those cells will be arranged vertically - +this will not be a problem though because, next, we will be applying random force to the "first" cell of each cluster i.e. +to the cell that is created first in each cluster. We will store a list of "first" cells inside member variable +``self.list_of_leading_cells = []`` which is a list. . we have to be careful to ensure that cells stored in that list do +not disappear because if the do disappear and we try to reference them we will get Segmentation Fault Error. +We will show later how we could avoid this issue in the code , just to show you how to handle situation of that type. +Before we apply any force, we will give simulation a generous 300 MCS for all the FPP links to get established. +If we applied force before links are established it is likely that some ``Top`` cell could have moved away from the +cluster before links had a chance to form. Next, every 500 MCS we will reassign random forces applied to "first" cells. + +The simulation code can be found in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_09`` + + +In terms of XML modification, we only need to add a one-liner that enavbles ExternalPotential plugin that simulates +external force: + +.. code-block:: XML + + + +Notice that we do not specify any parameters because we will use Python to set force vectors applied to "first" cells + +The ``ElongatedCellsSteppables.py`` is more interesting: + +.. code-block:: Python + + from cc3d.core.PySteppables import * + import random + + + class ElongatedCellsSteppable(SteppableBasePy): + def __init__(self, frequency=1): + + SteppableBasePy.__init__(self, frequency) + self.list_of_leading_cells = [] + self.maxAbsLambdaX = 10 + + def start(self): + self.create_arranged_cells(x_s=25, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + self.create_arranged_cells(x_s=40, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + + self.create_arranged_cells(x_s=50, y_s=5, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + self.create_arranged_cells(x_s=60, y_s=40, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + self.create_arranged_cells(x_s=70, y_s=60, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + + for cell in self.cell_list: + print("cell id=", cell.id, " clusterId=", cell.clusterId) + + def create_arranged_cells(self, x_s, y_s, size, cell_type_ids=None): + """ + this function creates vertically arranged cells. + + x_s, ys - coordinates of bottom_left corner of the cell arrangement + size - size of the cell arrangement + cell_type_ids - list of cell type ids + + """ + cluster_id = None + for i, cell_type_id in enumerate(cell_type_ids): + cell = self.new_cell(cell_type=cell_type_id) + + if i == 0: + cluster_id = cell.clusterId + self.list_of_leading_cells.append(cell) + else: + # to make all cells created by this function, we must reassign clusterId + # of all the cells created by this function except the first one + # When the first cell gets created, it gets reassigned clusterId by + # CompuCell3D and we will use this clusterId to assign it to all other cells created by this function + self.reassign_cluster_id(cell=cell, cluster_id=cluster_id) + self.cell_field[x_s : x_s + size, y_s + i * size : y_s + (i + 1) * size, 0] = cell + + def step(self, mcs): + + if mcs < 300: + return + + if not mcs % 500: + # randomize force applied to leading cell + for cell in self.list_of_leading_cells: + cell.lambdaVecX = random.randint(-self.maxAbsLambdaX, self.maxAbsLambdaX) + cell.lambdaVecY = random.randint(-self.maxAbsLambdaX, self.maxAbsLambdaX) + + +Inside the ``step`` method we create not one but several linear clusters - notice how we vary location of +bottom left coordinates of each cluster. + +Inside constructor: + +.. code-block:: python + + def __init__(self, frequency=1): + + SteppableBasePy.__init__(self, frequency) + self.list_of_leading_cells = [] + self.maxAbsLambdaX = 10 + +we create ``self.list_of_leading_cells`` that holds cell objects representing "first" cells of each cluster. Storing of the +"first" cell of each cluster takes place inside ``self.create_arranged_cells`` method. +We also add a convenience variable ``self.maxAbsLambdaX = 10`` that determines absolute value of +force component - in x or y directions. +We also introduce ``step(self, mcs)`` which "does nothing" for first 300 MCS and after 300 mcs it assigns a random force to each cell +in the ``self.list_of_leading_cells`` every 500 MCS - we use ``if not mcs % 500:`` to execute code every 500 MCS. + +Here are few screenshots of the simulation: + +MCS=447: + +|img014| + + +MCS=1125: + +|img015| + +MCS=4006: + +|img016| + +MCS=8289: + +|img017| + + +Notice, how cells belonging to a different clusters in general to not "mix with each other". We can control this behavior +by adjusting Contact energy plugin coefficients - because they govern interactions between cells belonging to +different clusters + +.. note:: + + It is possible that you may apply a force that is too large and FPP links may break. To handle situations + like this you should run simulation many times and observe issues and write a code that addresses them + + +Let us write a more robust code is better prepared to handle cells that may disappear (``Top`` cells to which we apply the force) + +.. code-block:: python + + class ElongatedCellsSteppable(SteppableBasePy): + def __init__(self, frequency=1): + + SteppableBasePy.__init__(self, frequency) + self.leading_cells_ids = set() + self.maxAbsLambdaX = 10 + + def start(self): + self.create_arranged_cells(x_s=25, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + self.create_arranged_cells(x_s=40, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + + self.create_arranged_cells(x_s=50, y_s=5, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + self.create_arranged_cells(x_s=60, y_s=40, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + self.create_arranged_cells(x_s=70, y_s=60, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + + for cell in self.cell_list: + print("cell id=", cell.id, " clusterId=", cell.clusterId) + + def create_arranged_cells(self, x_s, y_s, size, cell_type_ids=None): + """ + this function creates vertically arranged cells. + + x_s, ys - coordinates of bottom_left corner of the cell arrangement + size - size of the cell arrangement + cell_type_ids - list of cell type ids + + """ + cluster_id = None + for i, cell_type_id in enumerate(cell_type_ids): + cell = self.new_cell(cell_type=cell_type_id) + + if i == 0: + cluster_id = cell.clusterId + self.leading_cells_ids.add(cell.id) + else: + # to make all cells created by this function, we must reassign clusterId + # of all the cells created by this function except the first one + # When the first cell gets created, it gets reassigned clusterId by + # CompuCell3D and we will use this clusterId to assign it to all other cells created by this function + self.reassign_cluster_id(cell=cell, cluster_id=cluster_id) + self.cell_field[x_s : x_s + size, y_s + i * size : y_s + (i + 1) * size, 0] = cell + + def step(self, mcs): + + if mcs < 300: + return + + if not mcs % 500: + # randomize force applied to leading cell + for cell in self.cell_list: + if cell.id in self.leading_cells_ids: + cell.lambdaVecX = random.randint(-self.maxAbsLambdaX, self.maxAbsLambdaX) + cell.lambdaVecY = random.randint(-self.maxAbsLambdaX, self.maxAbsLambdaX) + + +Let us outline the changes we made + +1. Instead of using ``self.list_of_leading_cells`` to store cell objects, we use a set ``self.leading_cells_ids`` to store cell ids (integers). +Python set has this nice property that lookups are instantaneous. + +2. Instead of iterating the list with cell objects we iterate over each cell in the simulation (yes, +a bit inefficient by we can speed it up by iterating over cells of type ``Top``) and we check if ``cell.id`` is in ``self.leading_cells_ids`` +and only then we apply the force. + +This change will avoid accessing ``Top`` cell object that was deleted in the course fo the simulation. + +In summary, in this case study we have demonstrated how to turn a very simple simulation involving just a single cell into +a not-so-trivial simulation that involves multiple motile, elongated compartmental cells. + + .. |img001| image:: images/elongated_cells_tutorial/img001.png :scale: 50% @@ -433,4 +778,28 @@ to avoid intermingling. :scale: 50% .. |img009| image:: images/elongated_cells_tutorial/img009.png + :scale: 50% + +.. |img010| image:: images/elongated_cells_tutorial/img010.png + :scale: 50% + +.. |img011| image:: images/elongated_cells_tutorial/img011.png + :scale: 50% + +.. |img012| image:: images/elongated_cells_tutorial/img012.png + :scale: 50% + +.. |img013| image:: images/elongated_cells_tutorial/img013.png + :scale: 50% + +.. |img014| image:: images/elongated_cells_tutorial/img014.png + :scale: 50% + +.. |img015| image:: images/elongated_cells_tutorial/img015.png + :scale: 50% + +.. |img016| image:: images/elongated_cells_tutorial/img016.png + :scale: 50% + +.. |img017| image:: images/elongated_cells_tutorial/img017.png :scale: 50% \ No newline at end of file diff --git a/docs/images/elongated_cells_tutorial/img010.png b/docs/images/elongated_cells_tutorial/img010.png new file mode 100644 index 0000000000000000000000000000000000000000..e8dc6bbbaaa38a06afd1e685a59e88a48c7bdeb8 GIT binary patch literal 3391 zcmeH~ZA?>V6vv-?>CkE#68O+jV4XpyV+Lf{P;D(QfoWy5=*(s^0#2d}bAiGt6lmzh zZMse92C^C^RxsI`W!V~;ANbI>#Mmw?wQ*gPR#%#oq>`=L3#`49mhN1XEz>|r=Er`x zU!Irqob&(x&Pnd4HIluo4V(=KA(nVw#X*E{DSTDyQ(#tA!uirSnSY zf*4mA;}dWfUU=2dB(kdh&*oy2(5P+bN`pWJgXnxF9VJubv#4NTb($*}Zou^gil z)}Zr7t7BG6%A@x$sUM^e_1iF!!`Z9zXQI&cf67pD=#=&m(gp~T!VERidB2F|3%qJU z=N?-)*Y*MCgMEA5wE#CBD{=kavEZ)3eZ>O_9*<2ZI`w`5=3|QqyH}v~+ChSi|0cI; z=4;suxBF-E9?KB>O)+cFK;{*dUiglbpX3|CI^`&1{10A}CIU*d$K^^cik3s!-N%JF zPDB)Fp7i+%fn;v7?e5$9z~ti3_^%x-wbmK?Jc3`gkrb$uUn)FBkDI}`3paha$y!St%%TLBj}80JJrEn zzk3OuvD^1LoO;P?>B!u_I^6uAqUiqj5j7NQN<*d|20zFj(3rENXQ5AupDN5VM9%+s zZRR?#lC__30gNwf!z9o|iV+6i0joXfzMW9mx@WQ3)pvp0As}u536ZJYri>*W!fmA& zbELK+jK+t?YM}r6|Jj$SU z=mWt3Zv@=v&Si$)p+^J^lU^W{wZ(FV9+UJTI7}OAG>Rj+&>$L`m1-bZe{;^Mil11T zCUn651WpEXZLZI=r`DmVQhYdk;891MPT>1hGe`Q?8P{3J>1nE#B~$UVqEr7p0r6)} z-e^^BManBsIy_Cc^*4!L^E<|0QNNpFDgF{6izfLcHF(AhgyNUQAAbAMq?rXjMo3&K LsraG%$f>^pbS+QP literal 0 HcmV?d00001 diff --git a/docs/images/elongated_cells_tutorial/img011.png b/docs/images/elongated_cells_tutorial/img011.png new file mode 100644 index 0000000000000000000000000000000000000000..e115388b05b0d5ea935561344f9b893c7ffdc0db GIT binary patch literal 3655 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 Z_x@shH_xk;34a(OsKct|7wvub{SRhf+AaV9 literal 0 HcmV?d00001 diff --git a/docs/images/elongated_cells_tutorial/img015.png b/docs/images/elongated_cells_tutorial/img015.png new file mode 100644 index 0000000000000000000000000000000000000000..b31e6524d1628a26f1d4a25d6ec6c31e6bb348cc GIT binary patch literal 7927 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 Z6Y4E30m&)j@Q(|KE!p0x(8A}~{{SCWBXj@& literal 0 HcmV?d00001 diff --git a/docs/images/elongated_cells_tutorial/img017.png b/docs/images/elongated_cells_tutorial/img017.png new file mode 100644 index 0000000000000000000000000000000000000000..c81dab133ba73f6a85edb2c9b08b6b8d320dcb38 GIT binary patch literal 7260 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 Tzmnj84Z%4>GlSx@ZrA?_|C%-q literal 0 HcmV?d00001 From be7f6ec872f6716a7aef3596927713c5cc639daf Mon Sep 17 00:00:00 2001 From: compucell3d Date: Sat, 14 Sep 2024 12:00:41 -0600 Subject: [PATCH 05/11] Addressed most PR comments --- docs/curvature.rst | 1 + ...compartmental_elongated_cells_tutorial.rst | 24 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/curvature.rst b/docs/curvature.rst index c50a0ad..929f6b8 100644 --- a/docs/curvature.rst +++ b/docs/curvature.rst @@ -1,3 +1,4 @@ +.. _curvature-plugin: Curvature Plugin ---------------- diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst index 3d5385d..7637c70 100644 --- a/docs/example_compartmental_elongated_cells_tutorial.rst +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -1,9 +1,9 @@ -Building Simulation of Elongated Cells. Case Study in using Compartments, FPP Links, Curvature energy terms. +Compartments, FPP Links and Curvature - how to build elongated cells. ------------------------------------------------------------------------------------------------------------ -The goal of this tutorial is to build a simulation of multiple elongated cells where each sell is composed of compartments. -We want the cells to stay elongated throughout the course of the simulation. In this tutorial we want to show you how -starting from a simulation involving a single cell you can scale up and build more sophisticated models +The goal of this tutorial is to teach you how to transform the most basic simulation involving just a single cell into +a simulation involving multiple elongated cells where each cell is composed of compartments. +We want the cells to stay elongated throughout the course of the simulation. Understanding Contact Energies - how to avoid pixelated cells @@ -19,9 +19,9 @@ and Curvature plugin. .. note:: Our intention is to teach you how you can start building complex simulation from grounds up - by starting with a single ce,, understand the behavior of the single cell under different set of parameters + by starting with a single cell understand the behavior of the single cell under different set of parameters and gradually adding complexity to your simulation. We strongly believe that in order to build robust and complex - simulations you firs must master simple cases and build confidence needed to bring your modeling skills + simulations you first must master simple cases and build confidence needed to bring your modeling skills to the "next level". It is very much like playing the piano, in general it is advised to learn how to play "Chopsticks" https://www.youtube.com/watch?v=JM5fjgiFrxg before attempting to play the "Flight of the Bumblebee" https://www.youtube.com/watch?v=M93qXQWaBdE @@ -500,7 +500,7 @@ Curvature Plugin Let us now put everything together an implement elongated compartmentalized cell. The solution that will prevent two ``Center`` cells (the ones that initially were touching ``Top`` cell), from forming an extra FPP link, -is to use Curvature Plugin. The way Curvature plugin works is by constraining the angle that two adjacent links can form +is to use Curvature Plugin. The :ref:`curvature-plugin` constrains the angle at which two adjacent links can form. By using high value of Curvature lambda you may constrain two adjacent links to form a straight line and by adiabatically lowering the lambda you can control how much elongated cell can bend. The code for this section is in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_08`` @@ -548,9 +548,7 @@ Let us add a bit more code to make this simulation more interesting. First, we w our convenience function ``create_arranged_cells`` and as a result all of those cells will be arranged vertically - this will not be a problem though because, next, we will be applying random force to the "first" cell of each cluster i.e. to the cell that is created first in each cluster. We will store a list of "first" cells inside member variable -``self.list_of_leading_cells = []`` which is a list. . we have to be careful to ensure that cells stored in that list do -not disappear because if the do disappear and we try to reference them we will get Segmentation Fault Error. -We will show later how we could avoid this issue in the code , just to show you how to handle situation of that type. +``self.list_of_leading_cells = []`` which is a list. Before we apply any force, we will give simulation a generous 300 MCS for all the FPP links to get established. If we applied force before links are established it is likely that some ``Top`` cell could have moved away from the cluster before links had a chance to form. Next, every 500 MCS we will reassign random forces applied to "first" cells. @@ -567,6 +565,10 @@ external force: Notice that we do not specify any parameters because we will use Python to set force vectors applied to "first" cells +We also have to be careful to ensure that cells stored in that list do +not disappear because if the do disappear and we try to reference them we will get Segmentation Fault Error. +We will show later how we could avoid this issue in the code , just to show you how to handle situation of that type. + The ``ElongatedCellsSteppables.py`` is more interesting: .. code-block:: Python @@ -583,6 +585,8 @@ The ``ElongatedCellsSteppables.py`` is more interesting: self.maxAbsLambdaX = 10 def start(self): + # creating 5 "vertical" compartmental cells that are separated from each other in the x direction + # each compartmental consists of 5 compartments that have cell type ids: 1, 2, 2, 2, 1 respectively self.create_arranged_cells(x_s=25, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) self.create_arranged_cells(x_s=40, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) From 4200895b463bb4a798c41b5f7f087afa232232eb Mon Sep 17 00:00:00 2001 From: compucell3d Date: Sat, 14 Sep 2024 12:40:44 -0600 Subject: [PATCH 06/11] fixing index for real-world examples --- docs/index.rst | 5 ++++- ...n_real_world_examples => section_real_world_examples.rst} | 0 2 files changed, 4 insertions(+), 1 deletion(-) rename docs/{section_real_world_examples => section_real_world_examples.rst} (100%) diff --git a/docs/index.rst b/docs/index.rst index 4475663..97ed58a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -74,10 +74,13 @@ or watch the `CompuCell3D Workshop Python tutorial videos Date: Sun, 15 Sep 2024 11:11:38 -0600 Subject: [PATCH 07/11] Updated the tutorial to highlight the ability to use 2 to control a total number of links a given cell type can form --- ...compartmental_elongated_cells_tutorial.rst | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst index 7637c70..ab57e55 100644 --- a/docs/example_compartmental_elongated_cells_tutorial.rst +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -491,8 +491,32 @@ at the beginning of the simulation but during the course of the simulation , whe .. note:: - CC3D will add additional constraint on the max number of links a given cell type can form which will solve this problem - but in the current version we have to deal possible issues that might arise when cells may form extra link that we do not want + To prevent this situation where ``Center`` cells form a "triangle of links" you may add an override in the FocalPointPlasticity + Plugin that will cap number of total links that Center cells can form to 2 links: + + .. code-block:: xml + + + + + 100.0 + -50.0 + 5 + 10.0 + 1 + + + + 100.0 + -50.0 + 5 + 10.0 + 2 + + + 2 + + Curvature Plugin From b1492f2ecbde2920e324eb18d23fa6741c30aff4 Mon Sep 17 00:00:00 2001 From: compucell3d Date: Sun, 15 Sep 2024 11:23:16 -0600 Subject: [PATCH 08/11] updated FPP plugin manual to include : 1 1 --- docs/focal_point_plasticity.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/focal_point_plasticity.rst b/docs/focal_point_plasticity.rst index f2245b8..23f2b2d 100644 --- a/docs/focal_point_plasticity.rst +++ b/docs/focal_point_plasticity.rst @@ -122,6 +122,34 @@ example): +The total number of links a given cell can form is computed as a sum of ```` values coming from ```` +or ```` sections where a given cell type appears. In the example above ``Center`` can form maximum of 2 internal links (between compartments) + +CompuCell3D gives you ability to override this default algorithm by adding additional tag that control the total number of links: + + +.. code-block:: xml + + + + 1 + 1 + + + + 10.0 + ... + +In this example we are limiting the maximum number of links ``Center`` cells can form with Center cells of another cluster to 1 +``1`` and do the same for number of links the ``Center`` cells can form +with cells that are members of the same cluster: ``1`` + + + +where we can override this default algorithm. This feature can be useful when working with "elongated" compartmental cells where +you do not want Center cells to form more than two links + + We can also specify link constituent law and change it to different form that "spring relation". To do this we use the following syntax inside FocalPointPlasticity CC3DML plugin: From c21d39846b2406181e0075ffef1f488be671cf33 Mon Sep 17 00:00:00 2001 From: compucell3d Date: Sat, 28 Sep 2024 11:32:22 -0600 Subject: [PATCH 09/11] fixing the "Real World Examples" section --- docs/index.rst | 10 ++++------ docs/section_real_world_examples.rst | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 97ed58a..e7658b3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -74,13 +74,11 @@ or watch the `CompuCell3D Workshop Python tutorial videos Date: Sat, 28 Sep 2024 12:32:34 -0600 Subject: [PATCH 10/11] Implementing PR changes --- ...compartmental_elongated_cells_tutorial.rst | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst index ab57e55..5c07ae4 100644 --- a/docs/example_compartmental_elongated_cells_tutorial.rst +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -101,6 +101,8 @@ and Python file with steppables is also not too complex: self.cell_field[45:50, 25:30, 0] = top In the steppable class ``ElongatedCellsSteppable`` we create a cell of type 1 (this is cell of type ``Top`` - see XML above). +The syntax ``self.cell_field[45:50, 25:30, 0] = top`` assigns pointer to cell ``top`` to all locations of the field enclosed +between pixels 45 to 50 along x-axis, pixels 45 to 50 along y-axis and pixels for which z=0. It follows the numpy (https://numpy.org/) convention. The XML is also very simple. We defined 3 cell types there and set ``TargetVolume`` and ``LambdaVolume`` to ``25`` and 2.0 All contact energy coefficients are 0 - effectively stating that contact energy included in the actual simulation is always 0. @@ -116,12 +118,12 @@ and any cell shape as long as the total number of pixel in the single cell is ro Let's try using contact energy to see if we can make the cell non-pixelized - ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_02`` The rationale is as follows: Volume energy will asure the number of pixel in the cell is roughly 25 and the contact energy's task will be to keep cell from pixelizing by -penalizing cell-Medium interface. As you recall CC3D minimizes energy so if we use positive contact coefficient -between cell and the Medium the simulation the pixelized cell will have quite a high energy - because many single +penalizing cell-Medium interface. As you recall, CC3D minimizes energy so if we use positive contact coefficient +between cell and the Medium, the simulation the pixelated cell will have quite a high energy - because many single pixels are surrounded by Medium and each such pixel will bring up total energy by multiples of contact energy coefficient. -The actual number of interfaces between single pixel and Medium is control by ```` input in Contact PLugin. -In our case we are including interfaces up to 4th nearest neighbor - ``4`` . +The actual number of interfaces between single pixel and Medium is control by ```` input in Contact Plugin. +In our case, we are including interfaces up to 4th nearest neighbor - ``4`` . Let's look at the new specification of Contact energy: @@ -182,9 +184,12 @@ Let's add few more cells (including of type ``Center``). + and let's create a situation where cells "prefer" to be surrounded by Medium and not touch each other. This means contact energy coefficient between cell and Medium is lower than contact energy between two cells: + + .. code-block:: XML @@ -203,7 +208,7 @@ When we run this new simulation (``Demos/CompuCellPythonTutorial/ElongatedCellsT |img004| -Cells that initially stick to each other after few steps are separated but each cell is i a non-pixelized form. +Cells that initially stick to each other after few steps are separated but each cell is in a non-pixelated form. Writing Convenience function to create elongated cell +++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -216,27 +221,27 @@ The entire code can be found here: ``Demos/CompuCellPythonTutorial/ElongatedCell .. code-block:: python class ElongatedCellsSteppable(SteppableBasePy): - def __init__(self, frequency=1): + def __init__(self, frequency=1): - SteppableBasePy.__init__(self, frequency) + SteppableBasePy.__init__(self, frequency) - def start(self): - self.create_arranged_cells(x_s=25, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) - for cell in self.cell_list: - print("cell id=", cell.id, " cluster_id=", cell.clusterId) + def start(self): + self.create_arranged_cells(x_s=25, y_s=25, size=5, cell_type_ids=[1, 2, 2, 2, 2, 1]) + for cell in self.cell_list: + print("cell id=", cell.id, " cluster_id=", cell.clusterId) - def create_arranged_cells(self, x_s, y_s, size, cell_type_ids=None): - """ - this function creates vertically arranged cells. + def create_arranged_cells(self, x_s, y_s, size, cell_type_ids=None): + """ + this function creates vertically arranged cells. - x_s, ys - coordinates of bottom_left corner of the cell arrangement - size - size of the cell arrangement - cell_type_ids - list of cell type ids + x_s, ys - coordinates of bottom_left corner of the cell arrangement + size - size of the cell arrangement + cell_type_ids - list of cell type ids - """ - for i, cell_type_id in enumerate(cell_type_ids): - cell = self.new_cell(cell_type=cell_type_id) - self.cell_field[x_s : x_s + size, y_s + i * size : y_s + (i + 1) * size, 0] = cell + """ + for i, cell_type_id in enumerate(cell_type_ids): + cell = self.new_cell(cell_type=cell_type_id) + self.cell_field[x_s : x_s + size, y_s + i * size : y_s + (i + 1) * size, 0] = cell This function iterates over a list of ``cell_type_ids`` and for each new cell type listed it creates a new cell of this @@ -270,7 +275,7 @@ below: Let's change it. Instead of creating 6 independent cells let's assign them to the same cluster so that our six cells will now be turned into compartments of a single cell with ``clusterId`` 1. From the modeling point of view this corresponds to a situation where you would like your biological cells be represented with more level of internal details. -Perhaps you would like to simulate polarized cells , or perhaps you may want to better control shape of cells. +Perhaps you would like to simulate polarized cells, or perhaps you may want to better control shape of cells. Here the code (``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_05``) that turns six independent cells in to six compartments of a single compartmentalized cell: @@ -328,7 +333,7 @@ If we look at the code - ``create_arranged_cells`` - notice that when we iterate we first create cell and then we keep track of the ``clusterId`` of the first cell that was created inside the ``for`` loop. For each subsequently created cell we reassign it's ``clusterId`` attribute to match the ``clusterId`` of the cell that was created first. Normally when new cell gets created CC3D will bump both ``cell.id`` and ``cell.clusterId`` -but by reassigning we are correcting CC3D default behavior so all sx cells end up with ``clusterId`` 1. +but by reassigning we are correcting CC3D default behavior so all six cells end up with ``clusterId`` 1. Here is the initial configuration of the cell field: |img007| @@ -339,17 +344,18 @@ But if we run simulation a bit longer we will get the following: |img008| This is not what we expected. In the previous simulation all cells were nicely separated, but now, with the same energy -parameters we are getting a completely different simulation where cells are pixelized and intermixed with each other. -The only change we did was reassigning ``clusterId``s. What is then the explanation of this behavior: - -The explanation is simple but not obvious. The Contact energy plugin that controls whether cells like to stick to each -other or like to be surrounded by Medium works only between cells that are members of different cluster. In our case this means that -Contact energy plugin will only contribute energy that comes from Contact between cell and a Medium (because they are -from different clusters since medium is a special cell). On the other hand Contact energy plugin WILL NOT include any -contributions coming from contact between e.g. ``cell.id`` 1 and ``cell.id`` 2. Those contact cell-cell interfaces will -not contribute anything to the change of energy. Therefore, when in order to minimize energy CC3D will bundle cells together -(because cell-cell interfaces contribute 0 units of energy) in order to minimize cell-Medium interfaces where -each such interface contributes 15 units of energy (see XML definition of Contact energy plugin) +parameters we are getting a completely different simulation where cells are pixelated and intermixed with each other. +The only change we did was reassigning ``clusterId``s. The explanation is simple but not obvious. +The Contact energy plugin that controls whether cells like to stick to each +other or like to be surrounded by Medium works only between cells that are members of different clusters. +Contact energy plugin computes adhesion energy between cells that are members of different clusters but when two cells that belong +to the same cluster touch each other such junctions are ignored by contact energy. In other words, if we have 5 compartments, i.e. +5 cells that are members of the same cluster the contribution of Contact energy will be 0 regardles if those cells are far +apart of clustered together. Those cell-cell interfaces within a single cluster will +not contribute anything to the change of energy. Therefore, in order to minimize energy CC3D will bundle cells together, +in order to minimize cell-Medium interfaces because Medium is considered a separate cluster so in our simulation we will have two clusters - Medium +and cluster composed of 5 cells. Each such interface between those two clusters contributes 15 units of energy and CC3D minimizes those contributions by bundling cells together into a single domain + To make sure this is indeed the case, go back to ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_04`` and change definition of Contact energy to looks as follows: From c40d75e930a28525810159d1f46ca0ed8453209a Mon Sep 17 00:00:00 2001 From: compucell3d Date: Sat, 28 Sep 2024 12:51:57 -0600 Subject: [PATCH 11/11] addressing PR comments --- ...compartmental_elongated_cells_tutorial.rst | 25 ++++++++++++------- docs/focal_point_plasticity.rst | 1 + 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/example_compartmental_elongated_cells_tutorial.rst b/docs/example_compartmental_elongated_cells_tutorial.rst index 5c07ae4..a72f037 100644 --- a/docs/example_compartmental_elongated_cells_tutorial.rst +++ b/docs/example_compartmental_elongated_cells_tutorial.rst @@ -30,6 +30,11 @@ The goal is to make the cell look non-pixelized and do not disappear. The code for this simulation can be found in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_01`` +.. note:: + + The Demos can be open from Player using ``File -> Demo Browser`` menu. + Alternatively you may navigate to https://github.com/CompuCell3D/CompuCell3D/tree/master/CompuCell3D/core/Demos + Here is the XML .. code-block:: xml @@ -245,7 +250,10 @@ The entire code can be found here: ``Demos/CompuCellPythonTutorial/ElongatedCell This function iterates over a list of ``cell_type_ids`` and for each new cell type listed it creates a new cell of this -type that is placed 5 pixel above previous cell. This way after we run it we will see the following initial configuration (after first MCS and after several MCS): +type that is placed 5 pixel above previous cell. Note that we want to have cell types of "first" and "last" cell to be different because +they will play a special role as we start using FocalPointPlasticity Links and ExternalPotential plugins later in the chapter + +When we run the simulation we will see the following initial configuration (after first MCS and after several MCS): |img005| @@ -417,11 +425,11 @@ to avoid intermingling. FocalPointPlasticity Plugin - constraining intercellular distances ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Now that we understand how to handle Contact and COntactInternal plugins . let us focus attention on energy terms that will -allow us to constrain distances between cells. FocalPointPlasticity Plugin (**FPP**) is one of the solutions. +Now that we understand how to handle Contact and ContactInternal plugins, let us focus attention on energy terms that will +allow us to constrain distances between cells. :ref:`fpp-plugin` (**FPP**) is one of the solutions. This plugin implements energy term that penalizes deviations from target distance between two cells that are connected -by FPP link. This plugin is described in details in PLugins section of the Reference Manual but it is worth mentioning that +by FPP link. This plugin is described in details in :ref:`fpp-plugin`, but it is worth mentioning that this plugin has separate mechanisms for handling links between cells that are part of the same cluster and cells that are part of different clusters. The simulation code we will use in this section is in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_07`` @@ -458,8 +466,7 @@ we will see the following picture |img010| -If we let the simulation run for a while, however, we will see that while the distance between cells is maintained the cells do not -form "elongated cell" +If we let the simulation run for a while, however, we will see that while the distance between cells is maintained, the cells do not become elongated. |img011| @@ -528,14 +535,14 @@ at the beginning of the simulation but during the course of the simulation , whe Curvature Plugin ++++++++++++++++ -Let us now put everything together an implement elongated compartmentalized cell. The solution that will prevent two +Let us now put everything together and implement elongated compartmentalized cell. The solution that will prevent two ``Center`` cells (the ones that initially were touching ``Top`` cell), from forming an extra FPP link, is to use Curvature Plugin. The :ref:`curvature-plugin` constrains the angle at which two adjacent links can form. By using high value of Curvature lambda you may constrain two adjacent links to form a straight line and by adiabatically lowering the lambda you can control how much elongated cell can bend. The code for this section is in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_08`` -HEre is the code that we add to the XML to enable Curvature energy calculations: +Here is the code that we add to the XML to enable Curvature energy calculations: .. code-block:: XML @@ -586,7 +593,7 @@ cluster before links had a chance to form. Next, every 500 MCS we will reassign The simulation code can be found in ``Demos/CompuCellPythonTutorial/ElongatedCellsTutorial/Tutorial_09`` -In terms of XML modification, we only need to add a one-liner that enavbles ExternalPotential plugin that simulates +In terms of XML modification, we only need to add a one-liner that enables ExternalPotential plugin that simulates external force: .. code-block:: XML diff --git a/docs/focal_point_plasticity.rst b/docs/focal_point_plasticity.rst index 23f2b2d..dc6c369 100644 --- a/docs/focal_point_plasticity.rst +++ b/docs/focal_point_plasticity.rst @@ -1,3 +1,4 @@ +.. _fpp-plugin: FocalPointPlasticity Plugin ---------------------------