## User parameters in PhysiCell

As of release 1.4.0, users can add any number of Boolean, integer, double, and string parameters to an XML configuration file. (These are stored by default in ./config/. The default parameter file is ./config/PhysiCell_settings.xml.) These parameters are automatically parsed into a parameters data structure, and accessible throughout a PhysiCell project.

This tutorial will show you the key techniques to use these features. (See the User_Guide for full documentation.) First, let’s create a barebones 2D project by populating the 2D template project. In a terminal shell in your root PhysiCell directory, do this:

make template2D


We will use this 2D project template for the remainder of the tutorial. We assume you already have a working copy of PhysiCell installed, version 1.4.0 or later. (If not, visit the PhysiCell tutorials to find installation instructions for your operating system.)

### User parameters in the XML configuration file

Next, let’s look at the parameter file. In your text editor of choice, open up ./config/PhysiCell_settings.xml, and browse down to <user_parameters>, which will have some sample parameters from the 2D template project.

	<user_parameters>
<random_seed type="int" units="dimensionless">0</random_seed>
<!-- example parameters from the template -->

<!-- motile cell type parameters -->
<motile_cell_persistence_time type="double" units="min">15</motile_cell_persistence_time>
<motile_cell_migration_speed type="double" units="micron/min">0.5</motile_cell_migration_speed>
<motile_cell_relative_adhesion type="double" units="dimensionless">0.05</motile_cell_relative_adhesion>
<motile_cell_apoptosis_rate type="double" units="1/min">0.0</motile_cell_apoptosis_rate>
<motile_cell_relative_cycle_entry_rate type="double" units="dimensionless">0.1</motile_cell_relative_cycle_entry_rate>
</user_parameters>


Notice a few trends:

• Each XML element (tag) under <user_parameters> is a user parameter, whose name is the element name.
• Each variable requires an attribute named “type”, with one of the following four values:
• bool for a Boolean parameter
• int for an integer parameter
• double for a double (floating point) parameter
• string for text string parameter

While we do not encourage it, if no valid type is supplied, PhysiCell will attempt to interpret the parameter as a double.

• Each variable here has an (optional) attribute “units”. PhysiCell does not convert units, but these are helpful for clarity between users and developers. By default, PhysiCell uses minutes for all time units, and microns for all spatial units.
• Then, between the tags, you list the value of your parameter.

Let’s add the following parameters to the configuration file:

• A string parameter called motile_color that sets the color of the motile_cell type in SVG outputs. Please refer to the User Guide (in the documentation folder) for more information on allowed color formats, including rgb values and named colors. Let’s use the value darkorange.
• A double parameter called base_cycle_entry_rate that will give the rate of entry to the S cycle phase from the G1 phase for the default cell type in the code. Let’s use a ridiculously high value of 0.01 min-1.
• A double parameter called base_apoptosis_rate for the default cell type. Let’s set the value at 1e-7 min-1.
• A double parameter that sets the (relative) maximum cell-cell adhesion sensing distance, relative to the cell’s radius. Let’s set it at 2.5 (dimensionless). (The default is 1.25.)
• A bool parameter that enables or disables placing a single motile cell in the initial setup. Let’s set it at true.

If you edit the <user_parameters> to include these, it should look like this:

	<user_parameters>
<random_seed type="int" units="dimensionless">0</random_seed>
<!-- example parameters from the template -->

<!-- motile cell type parameters -->
<motile_cell_persistence_time type="double" units="min">15</motile_cell_persistence_time>
<motile_cell_migration_speed type="double" units="micron/min">0.5</motile_cell_migration_speed>
<motile_cell_relative_adhesion type="double" units="dimensionless">0.05</motile_cell_relative_adhesion>
<motile_cell_apoptosis_rate type="double" units="1/min">0.0</motile_cell_apoptosis_rate>
<motile_cell_relative_cycle_entry_rate type="double" units="dimensionless">0.1</motile_cell_relative_cycle_entry_rate>

<!-- for the tutorial -->
<motile_color type="string" units="dimensionless">darkorange</motile_color>

<base_cycle_entry_rate type="double" units="1/min">0.01</base_cycle_entry_rate>
<base_apoptosis_rate type="double" units="1/min">1e-7</base_apoptosis_rate>
<base_cell_adhesion_distance type="double" units="dimensionless">2.5</base_cell_adhesion_distance>

<include_motile_cell type="bool" units="dimensionless">true</include_motile_cell>
</user_parameters>


### Viewing the loaded parameters

Let’s compile and run the project.

make
./project2D


At the beginning of the simulation, PhysiCell parses the <user_parameters> block into a global data structure called parameters, with sub-parts bools, ints, doubles, and strings. It displays these loaded parameters at the start of the simulation. Here’s what it looks like:

shell$./project2D Using config file ./config/PhysiCell_settings.xml ... User parameters in XML config file: Bool parameters:: include_motile_cell: 1 [dimensionless] Int parameters:: random_seed: 0 [dimensionless] Double parameters:: motile_cell_persistence_time: 15 [min] motile_cell_migration_speed: 0.5 [micron/min] motile_cell_relative_adhesion: 0.05 [dimensionless] motile_cell_apoptosis_rate: 0 [1/min] motile_cell_relative_cycle_entry_rate: 0.1 [dimensionless] base_cycle_entry_rate: 0.01 [1/min] base_apoptosis_rate: 1e-007 [1/min] base_cell_adhesion_distance: 2.5 [dimensionless] String parameters:: motile_color: darkorange [dimensionless]  ### Getting parameter values Within a PhysiCell project, you can access the value of any parameter by either its index or its name, so long as you know its type. Here’s an example of accessing the base_cell_adhesion_distance by its name: /* this directly accesses the value of the parameter */ double temp = parameters.doubles( "base_cell_adhesion_distance" ); std::cout << temp << std::endl; /* this streams a formatted output including the parameter name and units */ std::cout << parameters.doubles[ "base_cell_adhesion_distance" ] << std::endl; std::cout << parameters.doubles["base_cell_adhesion_distance"].name << " " << parameters.doubles["base_cell_adhesion_distance"].value << " " << parameters.doubles["base_cell_adhesion_distance"].units << std::endl;  Notice that accessing by () gets the value of the parameter in a user-friendly way, whereas accessing by [] gets the entire parameter, including its name, value, and units. You can more efficiently access the parameter by first finding its integer index, and accessing by index: /* this directly accesses the value of the parameter */ int my_index = parameters.doubles.find_index( "base_cell_adhesion_distance" ); double temp = parameters.doubles( my_index ); std::cout << temp << std::endl; /* this streams a formatted output including the parameter name and units */ std::cout << parameters.doubles[ my_index ] << std::endl; std::cout << parameters.doubles[ my_index ].name << " " << parameters.doubles[ my_index ].value << " " << parameters.doubles[ my_index ].units << std::endl;  Similarly, we can access string and Boolean parameters. For example: if( parameters.bools("include_motile_cell") == true ) { std::cout << "I shall include a motile cell." << std::endl; } int rand_ind = parameters.ints.find_index( "random_seed" ); std::cout << parameters.ints[rand_ind].name << " is at index " << rand_ind << std::endl; std::cout << "We'll use this nice color: " << parameters.strings( "motile_color" );  ### Using the parameters in custom functions Let’s use these new parameters when setting up the parameter values of the simulation. For this project, all custom code is in ./custom_modules/custom.cpp. Open that source file in your favorite text editor. Look for the function called “create_cell_types“. In the code snipped below, we access the parameter values to set the appropriate parameters in the default cell definition, rather than hard-coding them.  // add custom data here, if any /* for the tutorial */ cell_defaults.phenotype.cycle.data.transition_rate(G0G1_index,S_index) = parameters.doubles("base_cycle_entry_rate"); cell_defaults.phenotype.death.rates[apoptosis_model_index] = parameters.doubles("base_apoptosis_rate"); cell_defaults.phenotype.mechanics.set_relative_maximum_adhesion_distance( parameters.doubles("base_cell_adhesion_distance") );  Next, let’s change the tissue setup (“setup_tissue“) to check our Boolean variable before placing the initial motile cell.  // now create a motile cell /* remove this conditional for the normal project */ if( parameters.bools("include_motile_cell") == true ) { pC = create_cell( motile_cell ); pC->assign_position( 15.0, -18.0, 0.0 ); }  Lastly, let’s make use of the string parameter to change the plotting. Search for my_coloring_function and edit the source file to use the new color:  // if the cell is motile and not dead, paint it black static std::string motile_color = parameters.strings( "motile_color" ); // tutorial if( pCell->phenotype.death.dead == false && pCell->type == 1 ) { output[0] = motile_color; output[2] = motile_color; }  Notice the static here: We intend to call this function many, many times. For performance reasons, we don’t want to declare a string, instantiate it with motile_color, pass it to parameters.strings(), and then deallocate it once done. Instead, we store the search statically within the function, so that all future function calls will have access to that search result. And that’s it! Compile your code, and give it a go. make ./project2D  This should create a lot of data in the ./output directory, including SVG files that color motile cells as darkorange, like this one below. Now that this project is parsing the XML file to get parameter values, we don’t need to recompile to change a model parameter. For example, change motile_color to mediumpurple, set motile_cell_migration_speed to 0.25, and set motile_cell_relative_cycle_entry_rate to 2.0. Rerun the code (without compiling): ./project2D  And let’s look at the change in the final SVG output (output00000120.svg): ### More notes on configuration files You may notice other sections in the XML configuration file. I encourage you to explore them, but the meanings should be evident: you can set the computational domain size, the number of threads (for OpenMP parallelization), and how frequently (and where) data are stored. In future PhysiCell releases, we will continue adding more and more options to these XML files to simplify setup and configuration of PhysiCell models. Share this: ## Adding a directory to your Windows path When you’re setting your BioFVM / PhysiCell g++ development environment, you’ll need to add the compiler, MSYS, and your text editor (like Notepad++) to your system path. For example, you may need to add folders like these to your system PATH variable: 1. c:\Program Files\mingw-w64\x86_64-5.3.0-win32-seh-rt_v4_rev0\mingw64\bin\ 2. c:\Program Files (x86)\Notepad++\ 3. C:\MinGW\msys\1.0\bin\ Here’s how to do that in various versions of Windows. ### Windows XP, 7, and 8 First, open up a text editor, and concatenate your three paths into a single block of text, separated by semicolons (;): 1. Open notepad ([Windows]+R, notepad) 2. Type a semicolon, paste in the first path, and append a semicolon. It should look like this: ;c:\Program Files\mingw-w64\x86_64-5.3.0-win32-seh-rt_v4_rev0\mingw64\bin\; 3. Paste in the next path, and append a semicolon. It should look like this: ;c:\Program Files\mingw-w64\x86_64-5.3.0-win32-seh-rt_v4_rev0\mingw64\bin\;C:\Program Files (x86)\Notepad++\; 4. Paste in the last path, and append a semicolon. It should look something like this: ;c:\Program Files\mingw-w64\x86_64-5.3.0-win32-seh-rt_v4_rev0\mingw64\bin\;C:\Program Files (x86)\Notepad++\;c:\MinGW\msys\1.0\bin\; Lastly, add these paths to the system path: 1. Go the Start Menu, the right-click “This PC” or “My Computer”, and choose “Properties.” 2. Click on “Advanced system settings” 3. Click on “Environment Variables…” in the “Advanced” tab 4. Scroll through the “System Variables” below until you find Path. 5. Select “Path”, then click “Edit…” 6. At the very end of “Variable Value”, paste what you made in Notepad in the prior steps. Make sure to paste at the end of the existing value, rather than overwriting it! 7. Hit OK, OK, and OK to completely exit the “Advanced system settings.” ### Windows 10: Windows 10 has made it harder to find these settings, but easier to edit them. First, let’s find the system path: 1. At the “run / search / Cortana” box next to the start menu, type “view advanced”, and you should see “view advanced system settings” auto-complete: 2. Click to enter the advanced system settings, then choose environment variables … at the bottom of this box, and scroll down the list of user variables to Path 3. Click on edit, then click New to add a new path. In the new entry (a new line), paste in your first new path (the compiler): 4. Repeat this for the other two paths, then click OK, OK, Apply, OK to apply the new paths and exit. Share this: ## Running the PhysiCell sample projects ### Introduction In PhysiCell 1.2.1 and later, we include four sample projects on cancer heterogeneity, bioengineered multicellular systems, and cancer immunology. This post will walk you through the steps to build and run the examples. If you are new to PhysiCell, you should first make sure you’re ready to run it. (Please note that this applies in particular for OSX users, as Xcode’s g++ is not compatible out-of-the-box.) Here are tutorials on getting ready to Run PhysiCell: 1. Setting up a 64-bit gcc environment in Windows. 2. Setting up gcc / OpenMP on OSX (MacPorts edition) 3. Setting up gcc / OpenMP on OSX (Homebrew edition) Note: This is the preferred method for Mac OSX. 4. Getting started with a PhysiCell Virtual Appliance (for virtual machines like VirtualBox) Note: The “native” setups above are preferred, but the Virtual Appliance is a great “plan B” if you run into trouble Please note that we expect to expand this tutorial. ### Building, running, and viewing the sample projects All of these projects will create data of the following forms: 1. Scalable vector graphics (SVG) cross-section plots through = 0.0 μm at each output time. Filenames will look like snapshot00000000.svg. 2. Matlab (Level 4) .mat files to store raw BioFVM data. Filenames will look like output00000000_microenvironment0.mat (for the chemical substrates) and output00000000_cells.mat (for basic agent data). 3. Matlab .mat files to store additional PhysiCell agent data. Filenames will look like output00000000_cells_physicell.mat. 4. MultiCellDS .xml files that give further metadata and structure for the .mat files. Filenames will look like output00000000.xml. You can read the combined data in the XML and MAT files with the read_MultiCellDS_xml function, stored in the matlab directory of every PhysiCell download. (Copy the read_MultiCellDS_xml.m and set_MultiCelLDS_constants.m files to the same directory as your data for the greatest simplicity.) (If you are using Mac OSX and PhysiCell version > 1.2.1, remember to set the PHYSICELL_CPP environment variable to be an OpenMP-capable compiler – rf. Homebrew setup.) #### Biorobots (2D) Type the following from a terminal window in your root PhysiCell directory: make biorobots-sample make ./biorobots make reset # optional -- gets a clean slate to try other samples  Because this is a 2-D example, the SVG snapshot files will provide the simplest method of visualizing these outputs. You can use utilities like ImageMagick to convert them into other formats for publications, such as PNG or EPS. #### Anti-cancer biorobots (2D) make cancer-biorobots-sample make ./cancer_biorobots make reset # optional -- gets a clean slate to try other samples  #### Cancer heterogeneity (2D) make heterogeneity-sample make project ./heterogeneity make reset # optional -- gets a clean slate to try other samples  #### Cancer immunology (3D) make cancer-immune-sample make ./cancer_immune_3D make reset # optional -- gets a clean slate to try other samples  Share this: ## Getting started with a PhysiCell Virtual Appliance Note: This is part of a series of “how-to” blog posts to help new users and developers of BioFVM and PhysiCell. This guide is for for users in OSX, Linux, or Windows using the VirtualBox virtualization software to run a PhysiCell virtual appliance. These instructions should get you up and running without needed to install a compiler, makefile capabilities, or any other software (beyond the virtual machine and the PhysiCell virtual appliance). We note that using the PhysiCell source with your own compiler is still the preferred / ideal way to get started, but the virtual appliance option is a fast way to start even if you’re having troubles setting up your development environment. ### What’s a Virtual Machine? What’s a Virtual Appliance? A virtual machine is a full simulated computer (with its own disk space, operating system, etc.) running on another. They are designed to let a user test on a completely different environment, without affecting the host (main) environment. They also allow a very robust way of taking and reproducing the state of a full working environment. A virtual appliance is just this: a full image of an installed system (and often its saved state) on a virtual machine, which can easily be installed on a new virtual machine. In this tutorial, you will download our PhysiCell virtual appliance and use its pre-configured compiler and other tools. ### What you’ll need: • VirtualBox: This is a free, cross-platform program to run virtual machines on OSX, Linux, Windows, and other platforms. It is a safe and easy way to install one full operating (a client system) on your main operating system (the host system). For us, this means that we can distribute a fully working Linux environment with a working copy of all the tools you need to compile and run PhysiCell. As of August 1, 2017, this will download Version 5.1.26. • PhysiCell Virtual Appliance: This is a single-file distribution of a virtual machine running Alpine Linux, including all key tools needed to compile and run PhysiCell. As of July 31, 2017, this will download PhysiCell 1.2.2 with g++ 6.3.0. • A computer with hardware support for virtualization: Your CPU needs to have hardware support for virtualization (almost all of them do now), and it has to be enabled in your BIOS. Consult your computer maker on how to turn this on if you get error messages later. ### Main steps: #### 1) Install VirtualBox. Double-click / open the VirtualBox download. Go ahead and accept all the default choices. If asked, go ahead and download/install the extensions pack. #### 2) Import the PhysiCell Virtual Appliance Go the “File” menu and choose “Import Virtual Appliance”. Browse to find the .ova file you just downloaded. Click on “Next,” and import with all the default options. That’s it! #### 3) [Optional] Change settings You most likely won’t need this step, but you can increase/decrease the amount of RAM used for the virtual machine if you select the PhysiCell VM, click the Settings button (orange gear), and choose “System”:We set the Virtual Machine to have 4 GB of RAM. If you have a machine with lots of RAM (16 GB or more), you may want to set this to 8 GB. Also, you can choose how many virtual CPUs to give to your VM: We selected 4 when we set up the Virtual Appliance, but you should match the number of physical processor cores on your machine. In my case, I have a quad core processor with hyperthreading. This means 4 real cores, 8 virtual cores, so I select 4 here. #### 4) Start the Virtual Machine and log in Select the PhysiCell machine, and click the green “start” button. After the virtual machine boots (with the good old LILO boot manager that I’ve missed), you should see this: Click the "More ..." button, and log in with username: physicell, password: physicell #### 5) Test the compiler and run your first simulation Notice that PhysiCell is already there on the desktop in the PhysiCell folder. Right-click, and choose “open terminal here.” You’ll already be in the main PhysiCell root directory. Now, let’s compile your first project! Type “make template2D && make” And run your project! Type “./project” and let it go!Go ahead and run either the first few days of the simulation (until about 7200 minutes), then hit <control>-C to cancel out. Or run the whole simulation–that’s fine, too. #### 6) Look at the results We bundled a few tools to easily look at results. First, ristretto is a very fast image viewer. Let’s view the SVG files: As a nice tip, you can press the left and right arrows to advance through the SVG images, or hold the right arrow down to advance through quickly. Now, let’s use ImageMagick to convert the SVG files into JPG file: call “magick mogrify -format jpg snap*.svg” Next, let’s turn those images into a movie. I generally create moves that are 24 frames pers se, so that 1 second of the movie is 1 hour of simulations time. We’ll use mencoder, with options below given to help get a good quality vs. size tradeoff: When you’re done, view the movie with mplayer. The options below scale the window to fit within the virtual monitor: If you want to loop the movie, add “-loop 999” to your command. #### 7) Get familiar with other tools Use nano (useage: nano <filename>) to quickly change files at the command line. Hit <control>-O to save your results. Hit <control>-X to exit. <control>-W will search within the file. Use nedit (useage: nedit <filename> &) to open up one more text files in a graphical editor. This is a good way to edit multiple files at once. Sometimes, you need to run commands at elevated (admin or root) privileges. Use sudo. Here’s an example, searching the Alpine Linux package manager apk for clang: physicell:~$ sudo apk search gcc
[sudo] password for physicell:
physicell:~$sudo apk search clang clang-analyzer-4.0.0-r0 clang-libs-4.0.0-r0 clang-dev-4.0.0-r0 clang-static-4.0.0-r0 emscripten-fastcomp-1.37.10-r0 clang-doc-4.0.0-r0 clang-4.0.0-r0 physicell:~/Desktop/PhysiCell$


If you want to install clang/llvm (as an alternative compiler):

physicell:~$sudo apk add gcc [sudo] password for physicell: physicell:~$ sudo apk search clang
clang-analyzer-4.0.0-r0
clang-libs-4.0.0-r0
clang-dev-4.0.0-r0
clang-static-4.0.0-r0
emscripten-fastcomp-1.37.10-r0
clang-doc-4.0.0-r0
clang-4.0.0-r0
physicell:~/Desktop/PhysiCell\$


Notice that it asks for a password: use the password for root (which is physicell).

Coming soon.

### Why both with zipped source, then?

Given that we can get a whole development environment by just downloading and importing a virtual appliance, why
bother with all the setup of a native development environment, like this tutorial (Windows) or this tutorial (Mac)?

One word: performance. In my testing, I still have not found the performance running inside a
virtual machine to match compiling and running directly on your system. So, the Virtual Appliance is a great
option to get up and running quickly while trying things out, but I still recommend setting up natively with
one of the tutorials I linked in the preceding paragraphs.

### What’s next?

In the coming weeks, we’ll post further tutorials on using PhysiCell. In the meantime, have a look at the
PhysiCell project website, and these links as well:

1. BioFVM on MathCancer.org: http://BioFVM.MathCancer.org
2. BioFVM on SourceForge: http://BioFVM.sf.net
3. BioFVM Method Paper in BioInformatics: http://dx.doi.org/10.1093/bioinformatics/btv730
4. PhysiCell on MathCancer.org: http://PhysiCell.MathCancer.org
5. PhysiCell on Sourceforge: http://PhysiCell.sf.net
6. PhysiCell Method Paper (preprint): https://doi.org/10.1101/088773
7. PhysiCell tutorials: [click here]

Share this:

## MathCancer C++ Style and Practices Guide

As PhysiCell, BioFVM, and other open source projects start to gain new users and contributors, it’s time to lay out a coding style. We have three goals here:

1. Consistency: It’s easier to understand and contribute to the code if it’s written in a consistent way.
2. Readability: We want the code to be as readable as possible.
3. Reducing errors: We want to avoid coding styles that are more prone to errors. (e.g., code that can be broken by introducing whitespace).

So, here is the guide (revised June 2017). I expect to revise this guide from time to time.

### Place braces on separate lines in functions and classes.

I find it much easier to read a class if the braces are on separate lines, with good use of whitespace. Remember: whitespace costs almost nothing, but reading and understanding (and time!) are expensive.

#### DON’T

class Cell{
public:
double some_variable;
bool some_extra_variable;

Cell(); };

class Phenotype{
public:
double some_variable;
bool some_extra_variable;

Phenotype();
};


#### DO:

class Cell
{
public:
double some_variable;
bool some_extra_variable;

Cell();
};

class Phenotype
{
public:
double some_variable;
bool some_extra_variable;

Phenotype();
};


### Enclose all logic in braces, even when optional.

In C/C++, you can omit the curly braces in some cases. For example, this is legal

if( distance > 1.5*cell_radius )
interaction = false;
force = 0.0; // is this part of the logic, or a separate statement?
error = false;


However, this code is ambiguous to interpret. Moreover, small changes to whitespace–or small additions to the logic–could mess things up here. Use braces to make the logic crystal clear:

#### DON’T

if( distance > 1.5*cell_radius )
interaction = false;
force = 0.0; // is this part of the logic, or a separate statement?
error = false;

if( condition1 == true )
do_something1 = true;
elseif( condition2 == true )
do_something2 = true;
else
do_something3 = true;


#### DO

if( distance > 1.5*cell_radius )
{
interaction = false;
force = 0.0;
}
error = false;

if( condition1 == true )
{ do_something1 = true; }
elseif( condition2 == true )
{ do_something2 = true; }
else
{ do_something3 = true; }


### Put braces on separate lines in logic, except for single-line logic.

This style rule relates to the previous point, to improve readability.

#### DON’T

if( distance > 1.5*cell_radius ){
interaction = false;
force = 0.0; }

if( condition1 == true ){ do_something1 = true; }
elseif( condition2 == true ){
do_something2 = true; }
else
{ do_something3 = true; error = true; }


#### DO

if( distance > 1.5*cell_radius )
{
interaction = false;
force = 0.0;
}

if( condition1 == true )
{ do_something1 = true; } // this is fine
elseif( condition2 == true )
{
do_something2 = true; // this is better
}
else
{
do_something3 = true;
error = true;
}


See how much easier that code is to read? The logical structure is crystal clear, and adding more to the logic is simple.

### End all functions with a return, even if void.

For clarity, definitively state that a function is done by using return.

#### DON’T

void my_function( Cell& cell )
{
cell.phenotype.volume.total *= 2.0;
cell.phenotype.death.rates[0] = 0.02;
// Are we done, or did we forget something?
// is somebody still working here?
}


#### DO

void my_function( Cell& cell )
{
cell.phenotype.volume.total *= 2.0;
cell.phenotype.death.rates[0] = 0.02;
return;
}


### Use tabs to indent the contents of a class or function.

This is to make the code easier to read. (Unfortunately PHP/HTML makes me use five spaces here instead of tabs.)

#### DON’T

class Secretion
{
public:
std::vector<double> secretion_rates;
std::vector<double> uptake_rates;
std::vector<double> saturation_densities;
};

void my_function( Cell& cell )
{
cell.phenotype.volume.total *= 2.0;
cell.phenotype.death.rates[0] = 0.02;
return;
}


#### DO

class Secretion
{
public:
std::vector<double> secretion_rates;
std::vector<double> uptake_rates;
std::vector<double> saturation_densities;
};

void my_function( Cell& cell )
{
cell.phenotype.volume.total *= 2.0;
cell.phenotype.death.rates[0] = 0.02;
return;
}


### Use a single space to indent public and other keywords in a class.

This gets us some nice formatting in classes, without needing two tabs everywhere.

#### DON’T

class Secretion
{
public:
std::vector<double> secretion_rates;
std::vector<double> uptake_rates;
std::vector<double> saturation_densities;
}; // not enough whitespace

class Errors
{
private:
std::string none_of_your_business
public:
std::string error_message;
int error_code;
}; // too much whitespace!


#### DO

class Secretion
{
private:
public:
std::vector<double> secretion_rates;
std::vector<double> uptake_rates;
std::vector<double> saturation_densities;
};

class Errors
{
private:
std::string none_of_your_business
public:
std::string error_message;
int error_code;
};


### Avoid arcane operators, when clear logic statements will do.

It can be difficult to decipher code with statements like this:

phenotype.volume.fluid=phenotype.volume.fluid<0?0:phenotype.volume.fluid;


Moreover, C and C++ can treat precedence of ternary operators very differently, so subtle bugs can creep in when using the “fancier” compact operators. Variations in how these operators work across languages are an additional source of error for programmers switching between languages in their daily scientific workflows. Wherever possible (and unless there is a significant performance reason to do so), use clear logical structures that are easy to read even if you only dabble in C/C++. Compiler-time optimizations will most likely eliminate any performance gains from these goofy operators.

#### DON’T

// if the fluid volume is negative, set it to zero
phenotype.volume.fluid=phenotype.volume.fluid<0.0?0.0:pCell->phenotype.volume.fluid;


#### DO

if( phenotype.volume.fluid < 0.0 )
{
phenotype.volume.fluid = 0.0;
}


Here’s the funny thing: the second logic is much clearer, and it took fewer characters, even with extra whitespace for readability!

### Pass by reference where possible.

Passing by reference is a great way to boost performance: we can avoid (1) allocating new temporary memory, (2) copying data into the temporary memory, (3) passing the temporary data to the function, and (4) deallocating the temporary memory once finished.

#### DON’T

double some_function( Cell cell )
{
return = cell.phenotype.volume.total + 3.0;
}
// This copies cell and all its member data!


#### DO

double some_function( Cell& cell )
{
return = cell.phenotype.volume.total + 3.0;
}
// This just accesses the original cell data without recopying it.


### Where possible, pass by reference instead of by pointer.

There is no performance advantage to passing by pointers over passing by reference, but the code is simpler / clearer when you can pass by reference. It makes code easier to write and understand if you can do so. (If nothing else, you save yourself character of typing each time you can replace “->” by “.”!)

#### DON’T

double some_function( Cell* pCell )
{
return = pCell->phenotype.volume.total + 3.0;
}
// Writing and debugging this code can be error-prone.


#### DO

double some_function( Cell& cell )
{
return = cell.phenotype.volume.total + 3.0;
}
// This is much easier to write.


### Be careful with static variables. Be thread safe!

PhysiCell relies heavily on parallelization by OpenMP, and so you should write functions under the assumption that they may be executed many times simultaneously. One easy source of errors is in static variables:

#### DON’T

double some_function( Cell& cell )
{
static double four_pi = 12.566370614359172;
static double output;
output = cell.phenotype.geometry.radius;
output *= output;
output *= four_pi;
return output;
}
// If two instances of some_function are running, they will both modify
// the *same copy* of output


#### DO

double some_function( Cell& cell )
{
static double four_pi = 12.566370614359172;
double output;
output = cell.phenotype.geometry.radius;
output *= output;
output *= four_pi;
return output;
}
// If two instances of some_function are running, they will both modify
// the their own copy of output, but still use the more efficient, once-
// allocated copy of four_pi. This one is safe for OpenMP.


### Use std:: instead of “using namespace std”

PhysiCell uses the BioFVM and PhysiCell namespaces to avoid potential collision with other codes. Other codes using PhysiCell may use functions that collide with the standard namespace. So, we formally use std:: whenever using functions in the standard namespace.

#### DON’T

using namespace std;

cout << "Hi, Mom, I learned to code today!" << endl;
string my_string = "Cheetos are good, but Doritos are better.";
cout << my_string << endl;

vector<double> my_vector;
vector.resize( 3, 0.0 );


#### DO

std::cout << "Hi, Mom, I learned to code today!" << std::endl;
std::string my_string = "Cheetos are good, but Doritos are better.";
std::cout << my_string << std::endl;

std::vector<double> my_vector;
my_vector.resize( 3, 0.0 );


### Camelcase is ugly. Use underscores.

This is purely an aesthetic distinction, but CamelCaseCodeIsUglyAndDoYouUseDNAorDna?

#### DON’T

double MyVariable1;
bool ProteinsInExosomes;
int RNAtranscriptionCount;

void MyFunctionDoesSomething( Cell& ImmuneCell );


#### DO

double my_variable1;
bool proteins_in_exosomes;
int RNA_transcription_count;

void my_function_does_something( Cell& immune_cell );


### Use capital letters to declare a class. Use lowercase for instances.

To help in readability and consistency, declare classes with capital letters (but no camelcase), and use lowercase for instances of those classes.

#### DON’T

class phenotype;

class cell
{
public:
std::vector<double> position;
phenotype Phenotype;
};

class ImmuneCell : public cell
{
public:
std::vector<double> surface_receptors;
};

void do_something( cell& MyCell , ImmuneCell& immuneCell );

cell Cell;
ImmuneCell MyImmune_cell;

do_something( Cell, MyImmune_cell );


#### DO

class Phenotype;

class Cell
{
public:
std::vector<double> position;
Phenotype phenotype;
};

class Immune_Cell : public Cell
{
public:
std::vector<double> surface_receptors;
};

void do_something( Cell& my_cell , Immune_Cell& immune_cell );

Cell cell;
Immune_Cell my_immune_cell;

do_something( cell, my_immune_cell );

Share this: