Building Growth Steppable In the Developer Zone folder
Quite often you will want to build a steppable in a “non-intrusive” way i.e. without adding it to the main
CC3D code-base. The way to do it is to utilize functionality of DeveloperZone
.
This time we will use Windows system and our CC3D git repository is cloned to D:\CC3D_PY3_GIT\CompuCell3D
To add a steppable or plugin in the DeveloperZone you open up Twedit and from CC3D C++
menu select
Generate New Module...
.
Notice that in the Module Directory
in the dialog box we put D:\CC3D_PY3_GIT\CompuCell3D\DeveloperZone
.
Previously we put there a path to the Steppable folder in the main CC3D Code base (give where our repository is cloned
this path would be D:\CC3D_PY3_GIT\CompuCell3D\core\CompuCell3D\steppables\
)
Notice that we also checked Python Wrap
option to generate Python bindings. We will show you how you ca
be creative here and leverage both XML and Python as a way to pass parameters to the Steppable. As you
remember you do not have to generate Python bindings and it is perfectly OK to to stick with C++ and XML.
After we press OK
button Twedit++ will generate , a template Steppable code:
Now we copy code from our earlier example into appropriate files - we are only showing files that we modified:
GrowthSteppable.h
:
1#ifndef GROWTHSTEPPABLESTEPPABLE_H
2#define GROWTHSTEPPABLESTEPPABLE_H
3#include <CompuCell3D/CC3D.h>
4#include "GrowthSteppableDLLSpecifier.h"
5
6namespace CompuCell3D {
7
8 template <class T> class Field3D;
9
10 template <class T> class WatchableField3D;
11
12 class Potts3D;
13
14 class Automaton;
15
16 class BoundaryStrategy;
17
18 class CellInventory;
19
20 class CellG;
21
22 class GROWTHSTEPPABLE_EXPORT GrowthSteppable : public Steppable {
23
24 WatchableField3D<CellG *> *cellFieldG;
25
26 Simulator * sim;
27
28 Potts3D *potts;
29
30 CC3DXMLElement *xmlData;
31
32 Automaton *automaton;
33
34 BoundaryStrategy *boundaryStrategy;
35
36 CellInventory * cellInventoryPtr;
37
38 Dim3D fieldDim;
39
40 public:
41
42 GrowthSteppable ();
43
44 virtual ~GrowthSteppable ();
45
46 std::map<unsigned int, double> growthRateMap;
47
48 // SimObject interface
49
50 virtual void init(Simulator *simulator, CC3DXMLElement *_xmlData=0);
51
52 virtual void extraInit(Simulator *simulator);
53
54
55 //steppable interface
56
57 virtual void start();
58
59 virtual void step(const unsigned int currentStep);
60
61 virtual void finish() {}
62
63
64 //SteerableObject interface
65
66 virtual void update(CC3DXMLElement *_xmlData, bool _fullInitFlag=false);
67
68 virtual std::string steerableName();
69
70 virtual std::string toString();
71
72 };
73
74};
75
76#endif
and GrowthSteppable.cpp
1#include <CompuCell3D/CC3D.h>
2using namespace CompuCell3D;
3using namespace std;
4#include "GrowthSteppable.h"
5
6
7GrowthSteppable::GrowthSteppable() :
8cellFieldG(0),sim(0),potts(0),xmlData(0),
9boundaryStrategy(0),automaton(0),cellInventoryPtr(0){}
10
11GrowthSteppable::~GrowthSteppable() {
12
13}
14
15void GrowthSteppable::init(Simulator *simulator, CC3DXMLElement *_xmlData) {
16
17 xmlData=_xmlData;
18
19 potts = simulator->getPotts();
20
21 cellInventoryPtr=& potts->getCellInventory();
22
23 sim=simulator;
24
25 cellFieldG = (WatchableField3D<CellG *> *)potts->getCellFieldG();
26
27 fieldDim=cellFieldG->getDim();
28
29 simulator->registerSteerableObject(this);
30
31 update(_xmlData,true);
32}
33
34void GrowthSteppable::extraInit(Simulator *simulator){
35
36}
37
38void GrowthSteppable::start(){
39
40 CellInventory::cellInventoryIterator cInvItr;
41 CellG * cell = 0;
42
43 for (cInvItr = cellInventoryPtr->cellInventoryBegin(); cInvItr != cellInventoryPtr->cellInventoryEnd(); ++cInvItr)
44 {
45
46 cell = cellInventoryPtr->getCell(cInvItr);
47 cell->targetVolume = 25.0;
48 cell->lambdaVolume = 2.0;
49 }
50}
51
52void GrowthSteppable::step(const unsigned int currentStep){
53
54 CellInventory::cellInventoryIterator cInvItr;
55
56 CellG * cell=0;
57
58 if (currentStep > 100)
59 return;
60
61 std::map<unsigned int, double>::iterator mitr;
62
63 for(cInvItr=cellInventoryPtr->cellInventoryBegin() ; cInvItr !=cellInventoryPtr->cellInventoryEnd() ;++cInvItr )
64 {
65
66 cell=cellInventoryPtr->getCell(cInvItr);
67
68 mitr = this->growthRateMap.find((unsigned int)cell->type);
69
70 if (mitr != this->growthRateMap.end()){
71 cell->targetVolume += mitr->second;
72 }
73
74 }
75
76}
77
78void GrowthSteppable::update(CC3DXMLElement *_xmlData, bool _fullInitFlag){
79
80 automaton = potts->getAutomaton();
81
82 ASSERT_OR_THROW("CELL TYPE PLUGIN WAS NOT PROPERLY INITIALIZED YET. MAKE SURE THIS IS THE FIRST PLUGIN THAT YOU SET", automaton)
83
84 set<unsigned char> cellTypesSet;
85
86 CC3DXMLElementList growthVec = _xmlData->getElements("GrowthRate");
87
88 for (int i = 0; i < growthVec.size(); ++i) {
89 unsigned int cellType = growthVec[i]->getAttributeAsUInt("CellType");
90 double growthRateTmp = growthVec[i]->getAttributeAsDouble("Rate");
91 this->growthRateMap[cellType] = growthRateTmp;
92 }
93
94 //boundaryStrategy has information about pixel neighbors
95 boundaryStrategy=BoundaryStrategy::getInstance();
96
97}
98
99std::string GrowthSteppable::toString(){
100
101 return "GrowthSteppable";
102}
103
104std::string GrowthSteppable::steerableName(){
105
106 return toString();
107}
As you can see based on the previous discussion the update
function where we parse XML is designed to
handle the following syntax for the GrowthSteppable:
<Steppable Type="GrowthSteppable">
<GrowthRate CellType="1" Rate="1.3"/>
<GrowthRate CellType="2" Rate="1.7"/>
</Steppable>
Note
Starting from version 4.3.0
of CC3D the DeveloperZone compilation setup (for any compiler) is is done automatically. All you need to do is to follow procedure outlined in Configuring Developer Zone
After we generated plugin code and added our modification to those two files, we are ready to begin compilation.
We will show how to compile code on Windows. Compilation on Linux system is analogous up to CMake configuration
part but then instead of using Visual Studio you will type make
and make install
in the terminal. For now
let’s stick with Windows compilation. After Twedit++ generated new files in the Developer Zone
we need to use
CMake tool (GUI - as we will go here, or console based tool) to configure our compilation. This is how CMake
configuration looks in our case
First we point to the folder where DeveloperZone
is (Where the source code is
). In our case it is
D:\CC3D_PY3_GIT\CompuCell3D\DeveloperZone
and location for our Visual Studio project D:/CC3D_PY3_GIT_build_developer_zone
(see Where to build the binaries
)
Then we after click Configure
CMake will display the following dialog:
Make sure to select Visual Studio 14 2015 Win64
(we assume we are using 64-bit version of CC3D). If you are using
32-bit version then you would select Visual Studio 14 2015
Next, we set CMAKE_INSTALL_PREFIX
and COMPUCELL3D_INSTALL_PATH
to the folder where CC3D is installed -
D:\Program Files\cc3d_py3_demo_new
.
We also set where main CC3D code-base is COMPUCELL3D_FULL_SOURCE_PATH
D:/CC3D_PY3_GIT/CompuCell3D/core/CompuCell3D
Next, we set version number (4, 0, 0). We are almost done but since DeveloperZone
also compiles Python module
we must set Python paths as follows (you need to specify Python include directory and Python library path):
Note
It is perfectly fine to compile DeveloperZone
modules without using Python. If this is what you would like to do, just comment out line add_subdirectory(pyinterface)
in DeveloperZone/CMakeLists.txt
After we configured all paths in CMake GUI we press Configure
button and then Generate
button. The
VisualStudio Project will be placed in D:/CC3D_PY3_GIT_build_developer_zone
(see
Where to build the binaries
at the top of CMake GUI). We will open it next and
will show you how to compile plugins and steppables in the DeveloperZone
Compiling DeveloperZone
in Visual Studio
Now that we created Visual Studio project for Developer Zone we will show you how to set up compilation.
We open up Visual Studio and navigate to File->Open->Project/Solution...
and in the File Open Dialog we go to
D:/CC3D_PY3_GIT_build_developer_zone
and select ALL_BUILD.vcxproj
After DeveloperZone
Visual Studio project gets loaded we go to Build->Configuration Manager...
and from the
pull down menu Active Solution Configuration
(at the top of the dialog box) we select RelWithDebInfo
:
Next, to start compilation, we right-click on ALL_BUILD
and from the context menu select Build
:
Notice that there are additional modules in addition to our GrowthSteppable
. Take a looks at those. They show
how to write simple modules (plugins or steppables).
After the compilation finished and there are no errors, we right-click at INSTALL
subproject and from the context
menu we select Build
. This will install our newly created GrowthSteppable
in the CC3D installation directory
that we specified during CMake configuration (D:/Program Files/cc3d_py3_demo_new
)
At this point we can build a simulation that will use newly created GrowthSteppable
Using DeveloperZone steppable in the simulation
Writing C++ code and compiling it was a hard-part of the project. Using newly created steppable in the simulation is easy. In fact all we need to do is to add
<Steppable Type="GrowthSteppable">
<GrowthRate CellType="1" Rate="1.3"/>
<GrowthRate CellType="2" Rate="1.7"/>
</Steppable>
to any simulation where we want cell of type 1 to increase target volume at 1.3 pixels/MCS rate and for cells of type 2 the growth would be 1.7.
Note
The name of the steppable or plugin that we reference from XML is not based on module name but on the label encoded in the proxy file. In our case GrowthSteppableProxy.cpp
has the following line growthSteppableProxy("GrowthSteppable", ...
and there we have label GrowthSteppable
that we use in XML. If we changed this label to e.g. growthSteppableProxy(“MyGrowthSteppable”, …` then we would need to change first line of XML for GrowthSteppable to <Steppable Type="GrowthSteppable">
Here are the results of the simulation at MCS 0, 20, and 40:
As you can see there are 3 cell types here but we specified growth rates for two of them As a result “red” cells are getting squashed by growing neighbors and at MCS 40 they disappear. Also notice that green cells are bigger than blue ones. This is what we expect when we have different growth rates.
Since we are modifying target volume we must use Volume
plugin where we control all parameters for each cell individually - we use “local flex” version of Volume constraint <Plugin Name="Volume"/>
where we only load Volume
plugin but dont pass any parameters to it. Those parameters targetVolume
lambdaVolume
are set in C++ code:
<CompuCell3D Revision="20190604" Version="4.0.0">
<Potts>
<!-- Basic properties of CPM (GGH) algorithm -->
<Dimensions x="100" y="100" z="1"/>
<Steps>100000</Steps>
<Temperature>10.0</Temperature>
<NeighborOrder>1</NeighborOrder>
</Potts>
<Plugin Name="CellType">
<!-- Listing all cell types in the simulation -->
<CellType TypeId="0" TypeName="Medium"/>
<CellType TypeId="1" TypeName="A"/>
<CellType TypeId="2" TypeName="B"/>
<CellType TypeId="3" TypeName="C"/>
</Plugin>
<Plugin Name="Volume"/>
<Plugin Name="CenterOfMass">
<!-- Module tracking center of mass of each cell -->
</Plugin>
<Plugin Name="Contact">
<!-- Specification of adhesion energies -->
<Energy Type1="Medium" Type2="Medium">10.0</Energy>
<Energy Type1="Medium" Type2="A">10.0</Energy>
<Energy Type1="Medium" Type2="B">10.0</Energy>
<Energy Type1="Medium" Type2="C">10.0</Energy>
<Energy Type1="A" Type2="A">10.0</Energy>
<Energy Type1="A" Type2="B">10.0</Energy>
<Energy Type1="A" Type2="C">10.0</Energy>
<Energy Type1="B" Type2="B">10.0</Energy>
<Energy Type1="B" Type2="C">10.0</Energy>
<Energy Type1="C" Type2="C">10.0</Energy>
<NeighborOrder>4</NeighborOrder>
</Plugin>
<Steppable Type="UniformInitializer">
<!-- Initial layout of cells in the form of rectangular slab -->
<Region>
<BoxMin x="20" y="20" z="0"/>
<BoxMax x="80" y="80" z="1"/>
<Gap>0</Gap>
<Width>5</Width>
<Types>A,B,C</Types>
</Region>
</Steppable>
<Steppable Type="GrowthSteppable">
<GrowthRate CellType="1" Rate="1.3"/>
<GrowthRate CellType="2" Rate="1.7"/>
</Steppable>
</CompuCell3D>
Note
We placed GrowthSteppable
last. This is not coincidence. We must place it after steppable that creates cells UniformInitializer
. If we reversed the order of those two steppables GrowthSteppable would be called first and in particular its start
function would be called before UniformInitializer
function and as a result the code that is supposed to set initaial volume constraint parameters from GrowthSteppable
(start
function) woudl iterate over empty cell inventory. Therefore, listing UniformInitializer
before GrowthSteppable
is the rihght thing to to. Simply put order of appearances of steppables in the XML determines the order in which CC3D will call them
Note
Specified growth rates of 1.3 and 1.7 are very high and we used them for illustration purposes. In your simulation you should much smaller rates to allow cells on the lattice to “equilibrate”
Full simulation can be downloaded here zip
and full code for
GrowthSteppable
is here zip
. You can also access both example
and c++ code by going directly to CompuCell3D/DeveloperZone