diff --git a/.github/workflows/build_binaries.yml b/.github/workflows/build_binaries.yml
index 758377a93..cd0e5b943 100644
--- a/.github/workflows/build_binaries.yml
+++ b/.github/workflows/build_binaries.yml
@@ -20,6 +20,7 @@ jobs:
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
+ {short_name: "episode", project: "episode-sample", name: "PhysiCell Episode", binary: "project", extra_run: ""},
]
runs-on: ubuntu-latest
@@ -32,7 +33,7 @@ jobs:
make ${{ matrix.projects.project }}
make clean
${{ matrix.projects.extra_run }}
- make static STATIC_OPENMP=/usr/lib/gcc/x86_64-linux-gnu/11/libgomp.a
+ make static STATIC_OPENMP=/usr/lib/gcc/x86_64-linux-gnu/12/libgomp.a
- name: Checking binary for ${{ matrix.projects.name }}
run: |
@@ -66,6 +67,7 @@ jobs:
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
+ {short_name: "episode", project: "episode-sample", name: "PhysiCell Episode", binary: "project", extra_run: ""},
]
runs-on: windows-latest
@@ -122,6 +124,7 @@ jobs:
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
+ {short_name: "episode", project: "episode-sample", name: "PhysiCell Episode", binary: "project", extra_run: ""},
]
runs-on: macos-13
@@ -171,6 +174,7 @@ jobs:
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
+ {short_name: "episode", project: "episode-sample", name: "PhysiCell Episode", binary: "project", extra_run: ""},
]
runs-on: macos-14
@@ -220,6 +224,7 @@ jobs:
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
+ {short_name: "episode", project: "episode-sample", name: "PhysiCell Episode", binary: "project", extra_run: ""},
]
runs-on: macos-13
@@ -266,4 +271,4 @@ jobs:
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ matrix.projects.short_name }}-macos.tar.gz
asset_path: ${{ github.workspace }}/${{ matrix.projects.short_name }}-macos.tar.gz
- asset_content_type: application/gzip
\ No newline at end of file
+ asset_content_type: application/gzip
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index e22ffd138..badff60f1 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -33,7 +33,8 @@ jobs:
{project: "interaction-sample", name: "PhysiCell interactions", binary: "interaction_demo", config: "config/PhysiCell_settings.xml", max_time: 120, output_folder: ""},
{project: "pred-prey-farmer", name: "PhysiCell prey predator", binary: "pred_prey", config: "config/PhysiCell_settings.xml", max_time: 120, output_folder: ""},
{project: "rules-sample", name: "PhysiCell rules sample", binary: "rules_sample", config: "config/PhysiCell_settings.xml", max_time: 120, output_folder: ""},
- {project: "asymmetric-division-sample", name: "PhysiCell asymmetric division", binary: "project", config: "config/PhysiCell_settings.xml", max_time: 120, output_folder: ""}
+ {project: "asymmetric-division-sample", name: "PhysiCell asymmetric division", binary: "project", config: "config/PhysiCell_settings.xml", max_time: 120, output_folder: ""},
+ {project: "episode-sample", name: "PhysiCell Episode", binary: "project", max_time: 120, config: "config/PhysiCell_settings.xml", output_folder: ""},
]
name: Testing ${{ matrix.projects.name }} on ${{ matrix.os.name }}
@@ -64,4 +65,4 @@ jobs:
- name: Check ${{ matrix.projects.name }} project simulation results
if: matrix.projects.output_folder != ''
run: |
- python beta/test_diff_svg.py ${{ matrix.projects.output_folder }} tests/cases/output_${{ matrix.projects.project }}
\ No newline at end of file
+ python beta/test_diff_svg.py ${{ matrix.projects.output_folder }} tests/cases/output_${{ matrix.projects.project }}
diff --git a/BioFVM/BioFVM_microenvironment.cpp b/BioFVM/BioFVM_microenvironment.cpp
index 47e3d5621..5d5261828 100644
--- a/BioFVM/BioFVM_microenvironment.cpp
+++ b/BioFVM/BioFVM_microenvironment.cpp
@@ -253,7 +253,7 @@ bool Microenvironment::get_substrate_dirichlet_activation( int substrate_index )
// TODO? fix confusing swapped usage of args
double Microenvironment::get_substrate_dirichlet_value( int substrate_index, int index )
{
- return dirichlet_value_vectors[index][substrate_index];
+ return dirichlet_value_vectors[index][substrate_index];
}
// new functions for finer-grained control of Dirichlet conditions -- 1.7.0
@@ -487,7 +487,7 @@ void Microenvironment::add_density( std::string name , std::string units )
void Microenvironment::add_density( std::string name , std::string units, double diffusion_constant, double decay_rate )
{
- // fix in PhysiCell preview November 2017
+ // check if density exist
if ( find_density_index( name ) != -1 )
{
std::cout << "ERROR: density named " << name << " already exists. You probably want your substrates all have unique names!" << std::endl;
@@ -1198,7 +1198,11 @@ void initialize_microenvironment( void )
}
// set the initial condition
+ set_microenvironment_initial_condition();
+}
+void set_microenvironment_initial_condition( void )
+{
if (default_microenvironment_options.initial_condition_from_file_enabled)
{
if (default_microenvironment_options.initial_condition_file_type=="matlab")
@@ -1389,51 +1393,6 @@ void initialize_microenvironment( void )
}
}
-
-/*
- if( default_microenvironment_options.outer_Dirichlet_conditions == true )
- {
-
- for( unsigned int k=0 ; k < microenvironment.mesh.z_coordinates.size() ; k++ )
- {
- // set Dirichlet conditions along the 4 outer edges
- for( unsigned int i=0 ; i < microenvironment.mesh.x_coordinates.size() ; i++ )
- {
- int J = microenvironment.mesh.y_coordinates.size()-1;
- microenvironment.add_dirichlet_node( microenvironment.voxel_index(i,0,k) , default_microenvironment_options.Dirichlet_condition_vector );
- microenvironment.add_dirichlet_node( microenvironment.voxel_index(i,J,k) , default_microenvironment_options.Dirichlet_condition_vector );
- }
- int I = microenvironment.mesh.x_coordinates.size()-1;
- for( unsigned int j=1; j < microenvironment.mesh.y_coordinates.size()-1 ; j++ )
- {
- microenvironment.add_dirichlet_node( microenvironment.voxel_index(0,j,k) , default_microenvironment_options.Dirichlet_condition_vector );
- microenvironment.add_dirichlet_node( microenvironment.voxel_index(I,j,k) , default_microenvironment_options.Dirichlet_condition_vector );
- }
- }
- // if 3-D, also along the corresponding additional faces
- if( default_microenvironment_options.simulate_2D == false )
- {
- int K = microenvironment.mesh.z_coordinates.size()-1;
- for( unsigned int j=1 ; j < microenvironment.mesh.y_coordinates.size()-1 ; j++ )
- {
- for( unsigned int i=1; i < microenvironment.mesh.x_coordinates.size()-1 ; i++ )
- {
- microenvironment.add_dirichlet_node( microenvironment.voxel_index(i,j,0) , default_microenvironment_options.Dirichlet_condition_vector );
- microenvironment.add_dirichlet_node( microenvironment.voxel_index(i,j,K) , default_microenvironment_options.Dirichlet_condition_vector );
- }
- }
- }
-
- }
-*/
-
- // April 2023: no longer necessary after flipping our approach and doing an "additive" instead of "subtractive" DCs handling. I.e., we assume DC activation is false by default; make true on-demand.
-
- // // set the Dirichlet condition activation vector to match the microenvironment options
- // for( int i=0 ; i < default_microenvironment_options.Dirichlet_activation_vector.size(); i++ )
- // {
- // microenvironment.set_substrate_dirichlet_activation( i , default_microenvironment_options.Dirichlet_activation_vector[i] );
- // }
microenvironment.display_information(std::cout);
return;
diff --git a/BioFVM/BioFVM_microenvironment.h b/BioFVM/BioFVM_microenvironment.h
index 8b894e880..a87ae6957 100644
--- a/BioFVM/BioFVM_microenvironment.h
+++ b/BioFVM/BioFVM_microenvironment.h
@@ -362,7 +362,8 @@ class Microenvironment_Options
extern Microenvironment_Options default_microenvironment_options;
extern Microenvironment microenvironment;
-void initialize_microenvironment( void );
+void initialize_microenvironment( void );
+void set_microenvironment_initial_condition( void );
void load_initial_conditions_from_matlab( std::string filename );
void load_initial_conditions_from_csv( std::string filename );
diff --git a/Makefile b/Makefile
index 6c5aff5c0..5d256d1c3 100644
--- a/Makefile
+++ b/Makefile
@@ -74,7 +74,7 @@ list-projects:
@echo "Sample projects: template biorobots-sample cancer-biorobots-sample cancer-immune-sample"
@echo " celltypes3-sample heterogeneity-sample pred-prey-farmer virus-macrophage-sample"
@echo " worm-sample interaction-sample mechano-sample rules-sample physimess-sample custom-division-sample"
- @echo " asymmetric-division-sample immune-function-sample"
+ @echo " asymmetric-division-sample immune-function-sample episode-sample"
@echo ""
@echo "Sample intracellular projects: template_BM ode-energy-sample physiboss-cell-lines-sample"
@echo " cancer-metabolism-sample physiboss-tutorial physiboss-tutorial-invasion"
@@ -225,6 +225,14 @@ immune-function-sample:
cp ./config/PhysiCell_settings.xml ./config/PhysiCell_settings-backup.xml
cp -r ./sample_projects/immune_function/config/* ./config/
+episode-sample:
+ cp -r ./sample_projects/episode/custom_modules/* ./custom_modules/
+ touch main.cpp && cp main.cpp main-backup.cpp
+ cp ./sample_projects/episode/main.cpp ./main.cpp
+ cp Makefile Makefile-backup
+ cp ./sample_projects/episode/Makefile .
+ cp -r ./sample_projects/episode/config/* ./config
+
# ---- intracellular projects
ode-energy-sample:
cp ./sample_projects_intracellular/ode/ode_energy/custom_modules/* ./custom_modules/
diff --git a/modules/PhysiCell_settings.cpp b/modules/PhysiCell_settings.cpp
index d4a25698e..2776ff140 100644
--- a/modules/PhysiCell_settings.cpp
+++ b/modules/PhysiCell_settings.cpp
@@ -79,10 +79,12 @@ bool physicell_config_dom_initialized = false;
pugi::xml_document physicell_config_doc;
pugi::xml_node physicell_config_root;
-bool load_PhysiCell_config_file( std::string filename )
+bool read_PhysiCell_config_file( std::string filename )
{
+ physicell_config_dom_initialized = false;
+
std::cout << "Using config file " << filename << " ... " << std::endl ;
- pugi::xml_parse_result result = physicell_config_doc.load_file( filename.c_str() );
+ pugi::xml_parse_result result = physicell_config_doc.load_file( filename.c_str() );
if( result.status != pugi::xml_parse_status::status_ok )
{
@@ -92,22 +94,28 @@ bool load_PhysiCell_config_file( std::string filename )
physicell_config_root = physicell_config_doc.child("PhysiCell_settings");
physicell_config_dom_initialized = true;
-
+ return true;
+}
+
+bool load_PhysiCell_config_file( std::string filename )
+{
+ if (!read_PhysiCell_config_file( filename ))
+ { return false; }
+
PhysiCell_settings.read_from_pugixml();
// now read the microenvironment (optional)
if( !setup_microenvironment_from_XML( physicell_config_root ) )
{
- std::cout << std::endl
- << "Warning: microenvironment_setup not found in " << filename << std::endl
- << " Either manually setup microenvironment in setup_microenvironment() (custom.cpp)" << std::endl
- << " or consult documentation to add microenvironment_setup to your configuration file." << std::endl << std::endl;
+ std::cout << std::endl
+ << "Warning: microenvironment_setup not found in " << filename << std::endl
+ << " Either manually setup microenvironment in setup_microenvironment() (custom.cpp)" << std::endl
+ << " or consult documentation to add microenvironment_setup to your configuration file." << std::endl << std::endl;
}
// now read user parameters
-
- parameters.read_from_pugixml( physicell_config_root );
+ parameters.read_from_pugixml( physicell_config_root );
create_output_directory( PhysiCell_settings.folder );
diff --git a/modules/PhysiCell_settings.h b/modules/PhysiCell_settings.h
index c211367b7..82a05d684 100644
--- a/modules/PhysiCell_settings.h
+++ b/modules/PhysiCell_settings.h
@@ -89,7 +89,8 @@ namespace PhysiCell{
extern pugi::xml_node physicell_config_root;
-bool load_PhysiCell_config_file( std::string filename );
+bool read_PhysiCell_config_file( std::string filename );
+bool load_PhysiCell_config_file( std::string filename );
class PhysiCell_Settings
{
diff --git a/sample_projects/Makefile-default b/sample_projects/Makefile-default
index 6c5aff5c0..5d256d1c3 100644
--- a/sample_projects/Makefile-default
+++ b/sample_projects/Makefile-default
@@ -74,7 +74,7 @@ list-projects:
@echo "Sample projects: template biorobots-sample cancer-biorobots-sample cancer-immune-sample"
@echo " celltypes3-sample heterogeneity-sample pred-prey-farmer virus-macrophage-sample"
@echo " worm-sample interaction-sample mechano-sample rules-sample physimess-sample custom-division-sample"
- @echo " asymmetric-division-sample immune-function-sample"
+ @echo " asymmetric-division-sample immune-function-sample episode-sample"
@echo ""
@echo "Sample intracellular projects: template_BM ode-energy-sample physiboss-cell-lines-sample"
@echo " cancer-metabolism-sample physiboss-tutorial physiboss-tutorial-invasion"
@@ -225,6 +225,14 @@ immune-function-sample:
cp ./config/PhysiCell_settings.xml ./config/PhysiCell_settings-backup.xml
cp -r ./sample_projects/immune_function/config/* ./config/
+episode-sample:
+ cp -r ./sample_projects/episode/custom_modules/* ./custom_modules/
+ touch main.cpp && cp main.cpp main-backup.cpp
+ cp ./sample_projects/episode/main.cpp ./main.cpp
+ cp Makefile Makefile-backup
+ cp ./sample_projects/episode/Makefile .
+ cp -r ./sample_projects/episode/config/* ./config
+
# ---- intracellular projects
ode-energy-sample:
cp ./sample_projects_intracellular/ode/ode_energy/custom_modules/* ./custom_modules/
diff --git a/sample_projects/episode/Makefile b/sample_projects/episode/Makefile
new file mode 100644
index 000000000..a9b43a58e
--- /dev/null
+++ b/sample_projects/episode/Makefile
@@ -0,0 +1,325 @@
+VERSION := $(shell grep . VERSION.txt | cut -f1 -d:)
+PROGRAM_NAME := project
+
+CC := g++
+# CC := g++-mp-7 # typical macports compiler name
+# CC := g++-7 # typical homebrew compiler name
+
+# Check for environment definitions of compiler
+# e.g., on CC = g++-7 on OSX
+ifdef PHYSICELL_CPP
+ CC := $(PHYSICELL_CPP)
+endif
+
+ifndef STATIC_OPENMP
+ STATIC_OPENMP = -fopenmp
+endif
+
+ARCH := native # best auto-tuning
+# ARCH := core2 # a reasonably safe default for most CPUs since 2007
+# ARCH := corei7
+# ARCH := corei7-avx # earlier i7
+# ARCH := core-avx-i # i7 ivy bridge or newer
+# ARCH := core-avx2 # i7 with Haswell or newer
+# ARCH := nehalem
+# ARCH := westmere
+# ARCH := sandybridge # circa 2011
+# ARCH := ivybridge # circa 2012
+# ARCH := haswell # circa 2013
+# ARCH := broadwell # circa 2014
+# ARCH := skylake # circa 2015
+# ARCH := bonnell
+# ARCH := silvermont
+# ARCH := skylake-avx512
+# ARCH := nocona #64-bit pentium 4 or later
+
+# CFLAGS := -march=$(ARCH) -Ofast -s -fomit-frame-pointer -mfpmath=both -fopenmp -m64 -std=c++11
+CFLAGS := -march=$(ARCH) -O3 -fomit-frame-pointer -mfpmath=both -fopenmp -m64 -std=c++11
+#CFLAGS := -march=$(ARCH) -ggdb -O0 -fomit-frame-pointer -mfpmath=both -fopenmp -m64 -std=c++11
+
+ifeq ($(OS),Windows_NT)
+else
+ UNAME_S := $(shell uname -s)
+ ifeq ($(UNAME_S),Darwin)
+ UNAME_P := $(shell uname -p)
+ var := $(shell which $(CC) | xargs file)
+ ifeq ($(lastword $(var)),arm64)
+ CFLAGS := -march=$(ARCH) -O3 -fomit-frame-pointer -fopenmp -m64 -std=c++11
+ #CFLAGS := -march=$(ARCH) -ggdb -O0 -fomit-frame-pointer -fopenmp -m64 -std=c++11
+ endif
+ endif
+endif
+
+CFLAGS_LINK := $(shell echo $(CFLAGS) | sed -e "s/-fopenmp//g")
+COMPILE_COMMAND := $(CC) $(CFLAGS) $(EXTRA_FLAGS)
+LINK_COMMAND := $(CC) $(CFLAGS_LINK) $(EXTRA_FLAGS)
+
+BioFVM_OBJECTS := BioFVM_vector.o BioFVM_mesh.o BioFVM_microenvironment.o BioFVM_solvers.o BioFVM_matlab.o \
+BioFVM_utilities.o BioFVM_basic_agent.o BioFVM_MultiCellDS.o BioFVM_agent_container.o
+
+PhysiCell_core_OBJECTS := PhysiCell_phenotype.o PhysiCell_cell_container.o PhysiCell_standard_models.o \
+PhysiCell_cell.o PhysiCell_custom.o PhysiCell_utilities.o PhysiCell_constants.o PhysiCell_basic_signaling.o \
+PhysiCell_signal_behavior.o PhysiCell_rules.o
+
+PhysiCell_module_OBJECTS := PhysiCell_SVG.o PhysiCell_pathology.o PhysiCell_MultiCellDS.o PhysiCell_various_outputs.o \
+PhysiCell_pugixml.o PhysiCell_settings.o PhysiCell_geometry.o
+
+# put your custom objects here (they should be in the custom_modules directory)
+
+PhysiCell_custom_module_OBJECTS := custom.o
+
+pugixml_OBJECTS := pugixml.o
+
+PhysiCell_OBJECTS := $(BioFVM_OBJECTS) $(pugixml_OBJECTS) $(PhysiCell_core_OBJECTS) $(PhysiCell_module_OBJECTS)
+ALL_OBJECTS := $(PhysiCell_OBJECTS) $(PhysiCell_custom_module_OBJECTS)
+
+# compile the project
+
+all: main.cpp $(ALL_OBJECTS)
+ $(COMPILE_COMMAND) -o $(PROGRAM_NAME) $(ALL_OBJECTS) main.cpp
+ make name
+
+static: main.cpp $(ALL_OBJECTS) $(MaBoSS)
+ $(LINK_COMMAND) $(INC) -o $(PROGRAM_NAME) $(ALL_OBJECTS) main.cpp $(LIB) -static-libgcc -static-libstdc++ $(STATIC_OPENMP)
+
+name:
+ @echo ""
+ @echo "Executable name is" $(PROGRAM_NAME)
+ @echo ""
+
+# PhysiCell core components
+
+PhysiCell_phenotype.o: ./core/PhysiCell_phenotype.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_phenotype.cpp
+
+PhysiCell_digital_cell_line.o: ./core/PhysiCell_digital_cell_line.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_digital_cell_line.cpp
+
+PhysiCell_cell.o: ./core/PhysiCell_cell.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_cell.cpp
+
+PhysiCell_cell_container.o: ./core/PhysiCell_cell_container.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_cell_container.cpp
+
+PhysiCell_standard_models.o: ./core/PhysiCell_standard_models.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_standard_models.cpp
+
+PhysiCell_utilities.o: ./core/PhysiCell_utilities.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_utilities.cpp
+
+PhysiCell_custom.o: ./core/PhysiCell_custom.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_custom.cpp
+
+PhysiCell_constants.o: ./core/PhysiCell_constants.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_constants.cpp
+
+PhysiCell_signal_behavior.o: ./core/PhysiCell_signal_behavior.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_signal_behavior.cpp
+
+PhysiCell_rules.o: ./core/PhysiCell_rules.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_rules.cpp
+
+# BioFVM core components (needed by PhysiCell)
+
+BioFVM_vector.o: ./BioFVM/BioFVM_vector.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_vector.cpp
+
+BioFVM_agent_container.o: ./BioFVM/BioFVM_agent_container.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_agent_container.cpp
+
+BioFVM_mesh.o: ./BioFVM/BioFVM_mesh.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_mesh.cpp
+
+BioFVM_microenvironment.o: ./BioFVM/BioFVM_microenvironment.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_microenvironment.cpp
+
+BioFVM_solvers.o: ./BioFVM/BioFVM_solvers.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_solvers.cpp
+
+BioFVM_utilities.o: ./BioFVM/BioFVM_utilities.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_utilities.cpp
+
+BioFVM_basic_agent.o: ./BioFVM/BioFVM_basic_agent.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_basic_agent.cpp
+
+BioFVM_matlab.o: ./BioFVM/BioFVM_matlab.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_matlab.cpp
+
+BioFVM_MultiCellDS.o: ./BioFVM/BioFVM_MultiCellDS.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/BioFVM_MultiCellDS.cpp
+
+pugixml.o: ./BioFVM/pugixml.cpp
+ $(COMPILE_COMMAND) -c ./BioFVM/pugixml.cpp
+
+# standard PhysiCell modules
+
+PhysiCell_SVG.o: ./modules/PhysiCell_SVG.cpp
+ $(COMPILE_COMMAND) -c ./modules/PhysiCell_SVG.cpp
+
+PhysiCell_pathology.o: ./modules/PhysiCell_pathology.cpp
+ $(COMPILE_COMMAND) -c ./modules/PhysiCell_pathology.cpp
+
+PhysiCell_MultiCellDS.o: ./modules/PhysiCell_MultiCellDS.cpp
+ $(COMPILE_COMMAND) -c ./modules/PhysiCell_MultiCellDS.cpp
+
+PhysiCell_various_outputs.o: ./modules/PhysiCell_various_outputs.cpp
+ $(COMPILE_COMMAND) -c ./modules/PhysiCell_various_outputs.cpp
+
+PhysiCell_pugixml.o: ./modules/PhysiCell_pugixml.cpp
+ $(COMPILE_COMMAND) -c ./modules/PhysiCell_pugixml.cpp
+
+PhysiCell_settings.o: ./modules/PhysiCell_settings.cpp
+ $(COMPILE_COMMAND) -c ./modules/PhysiCell_settings.cpp
+
+PhysiCell_basic_signaling.o: ./core/PhysiCell_basic_signaling.cpp
+ $(COMPILE_COMMAND) -c ./core/PhysiCell_basic_signaling.cpp
+
+PhysiCell_geometry.o: ./modules/PhysiCell_geometry.cpp
+ $(COMPILE_COMMAND) -c ./modules/PhysiCell_geometry.cpp
+
+# user-defined PhysiCell modules
+
+custom.o: ./custom_modules/custom.cpp
+ $(COMPILE_COMMAND) -c ./custom_modules/custom.cpp
+
+# cleanup
+
+reset:
+ rm -f *.cpp
+ cp ./sample_projects/Makefile-default Makefile
+ rm -f ./custom_modules/*
+ touch ./custom_modules/empty.txt
+ touch ALL_CITATIONS.txt
+ touch ./core/PhysiCell_cell.cpp
+ rm ALL_CITATIONS.txt
+ cp ./config/PhysiCell_settings-backup.xml ./config/PhysiCell_settings.xml
+ touch ./config/empty.csv
+ rm -f ./config/*.csv
+
+clean:
+ rm -f *.o
+ rm -f $(PROGRAM_NAME)*
+
+data-cleanup:
+ rm -rf ./output
+ mkdir ./output
+ touch ./output/empty.txt
+
+# archival
+
+checkpoint:
+ zip -r $$(date +%b_%d_%Y_%H%M).zip Makefile *.cpp *.h config/*.xml custom_modules/*
+
+zip:
+ zip -r latest.zip Makefile* *.cpp *.h BioFVM/* config/* core/* custom_modules/* matlab/* modules/* sample_projects/*
+ cp latest.zip $$(date +%b_%d_%Y_%H%M).zip
+ cp latest.zip VERSION_$(VERSION).zip
+ mv *.zip archives/
+
+tar:
+ tar --ignore-failed-read -czf latest.tar Makefile* *.cpp *.h BioFVM/* config/* core/* custom_modules/* matlab/* modules/* sample_projects/*
+ cp latest.tar $$(date +%b_%d_%Y_%H%M).tar
+ cp latest.tar VERSION_$(VERSION).tar
+ mv *.tar archives/
+
+unzip:
+ cp ./archives/latest.zip .
+ unzip latest.zip
+
+untar:
+ cp ./archives/latest.tar .
+ tar -xzf latest.tar
+
+# easier animation
+
+FRAMERATE := 24
+OUTPUT := output/episode00000000
+
+jpeg:
+ @magick identify -format "%h" $(OUTPUT)/initial.svg > __H.txt
+ @magick identify -format "%w" $(OUTPUT)/initial.svg > __W.txt
+ @expr 2 \* \( $$(grep . __H.txt) / 2 \) > __H1.txt
+ @expr 2 \* \( $$(grep . __W.txt) / 2 \) > __W1.txt
+ @echo "$$(grep . __W1.txt)!x$$(grep . __H1.txt)!" > __resize.txt
+ @magick mogrify -format jpg -resize $$(grep . __resize.txt) $(OUTPUT)/s*.svg
+ rm -f __H*.txt __W*.txt __resize.txt
+
+gif:
+ magick convert $(OUTPUT)/s*.svg $(OUTPUT)/out.gif
+
+movie:
+ ffmpeg -r $(FRAMERATE) -f image2 -i $(OUTPUT)/snapshot%08d.jpg -vcodec libx264 -pix_fmt yuv420p -strict -2 -tune animation -crf 15 -acodec none $(OUTPUT)/out.mp4
+
+# upgrade rules
+
+SOURCE := PhysiCell_upgrade.zip
+get-upgrade:
+ @echo $$(curl https://raw.githubusercontent.com/MathCancer/PhysiCell/master/VERSION.txt) > VER.txt
+ @echo https://github.com/MathCancer/PhysiCell/releases/download/$$(grep . VER.txt)/PhysiCell_V.$$(grep . VER.txt).zip > DL_FILE.txt
+ rm -f VER.txt
+ $$(curl -L $$(grep . DL_FILE.txt) --output PhysiCell_upgrade.zip)
+ rm -f DL_FILE.txt
+
+PhysiCell_upgrade.zip:
+ make get-upgrade
+
+upgrade: $(SOURCE)
+ unzip $(SOURCE) PhysiCell/VERSION.txt
+ mv -f PhysiCell/VERSION.txt .
+ unzip $(SOURCE) PhysiCell/core/*
+ cp -r PhysiCell/core/* core
+ unzip $(SOURCE) PhysiCell/modules/*
+ cp -r PhysiCell/modules/* modules
+ unzip $(SOURCE) PhysiCell/sample_projects/*
+ cp -r PhysiCell/sample_projects/* sample_projects
+ unzip $(SOURCE) PhysiCell/BioFVM/*
+ cp -r PhysiCell/BioFVM/* BioFVM
+ unzip $(SOURCE) PhysiCell/documentation/User_Guide.pdf
+ mv -f PhysiCell/documentation/User_Guide.pdf documentation
+ rm -f -r PhysiCell
+ rm -f $(SOURCE)
+
+# use: make save PROJ=your_project_name
+PROJ := my_project
+
+save:
+ echo "Saving project as $(PROJ) ... "
+ mkdir -p ./user_projects
+ mkdir -p ./user_projects/$(PROJ)
+ mkdir -p ./user_projects/$(PROJ)/custom_modules
+ mkdir -p ./user_projects/$(PROJ)/config
+ cp main.cpp ./user_projects/$(PROJ)
+ cp Makefile ./user_projects/$(PROJ)
+ cp VERSION.txt ./user_projects/$(PROJ)
+ cp ./config/* ./user_projects/$(PROJ)/config
+ cp ./custom_modules/* ./user_projects/$(PROJ)/custom_modules
+
+load:
+ echo "Loading project from $(PROJ) ... "
+ cp ./user_projects/$(PROJ)/main.cpp .
+ cp ./user_projects/$(PROJ)/Makefile .
+ cp ./user_projects/$(PROJ)/config/* ./config/
+ cp ./user_projects/$(PROJ)/custom_modules/* ./custom_modules/
+
+pack:
+ @echo " "
+ @echo "Preparing project $(PROJ) for sharing ... "
+ @echo " "
+ cd ./user_projects && zip -r $(PROJ).zip $(PROJ)
+ @echo " "
+ @echo "Share ./user_projects/$(PROJ).zip ... "
+ @echo "Other users can unzip $(PROJ).zip in their ./user_projects, compile, and run."
+ @echo " "
+
+unpack:
+ @echo " "
+ @echo "Preparing shared project $(PROJ).zip for use ... "
+ @echo " "
+ cd ./user_projects && unzip $(PROJ).zip
+ @echo " "
+ @echo "Load this project via make load PROJ=$(PROJ) ... "
+ @echo " "
+
+list-user-projects:
+ @echo "user projects::"
+ @cd ./user_projects && ls -dt1 * | grep . | sed 's!empty.txt!!'
diff --git a/sample_projects/episode/README.txt b/sample_projects/episode/README.txt
new file mode 100644
index 000000000..72be6d80a
--- /dev/null
+++ b/sample_projects/episode/README.txt
@@ -0,0 +1,12 @@
+# episode ~ PhysiCell sample project
+
+All this sample project does is running consecutive episodes of a PhysiCell
+model in one runtime.
+
+You simply cannot learn if you have to destroy the runtime after each episode
+to reset to the initial condition because you will at the same time erase
+everything you learned from this episode.
+
+We are currently working on a PhysiCell model that does reinforcement learning.
+The episode sample project figures as a template project for similar
+implementations and as a unit test for the necessary features.
diff --git a/sample_projects/episode/config/PhysiCell_settings.xml b/sample_projects/episode/config/PhysiCell_settings.xml
new file mode 100644
index 000000000..68ff43e83
--- /dev/null
+++ b/sample_projects/episode/config/PhysiCell_settings.xml
@@ -0,0 +1,652 @@
+
+
+
+ -500
+ 500
+ -500
+ 500
+ -10
+ 10
+ 20
+ 20
+ 20
+ true
+
+
+
+ 4320
+ min
+ micron
+ 0.01
+ 0.1
+ 6
+
+
+
+ 8
+
+
+
+ output
+
+ 60
+ true
+
+
+
+ false
+
+
+
+
+ false
+ true
+ false
+ 74
+
+
+
+
+
+ 30.0
+ 0.003
+
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+ 31.0
+ 0.0031
+
+ 0.0
+ 0.0
+
+
+
+
+
+
+
+
+
+
+
+ 32.0
+ 0.0032
+
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ true
+ true
+
+ ./config/initial.mat
+
+
+ ./config/dirichlet.mat
+
+
+
+
+
+
+
+
+
+ 300.0
+ 480.0
+ 240.0
+ 60.0
+
+
+ 1.0
+ 0
+ 0
+
+
+
+
+ 5.31667e-05
+
+ 516
+
+
+ 0.05
+ 0
+ 1.66667e-02
+ 5.83333e-03
+ 0
+ 2.0
+
+
+
+ 0.0
+
+ 0
+ 86400
+
+
+ 1.11667e-2
+ 8.33333e-4
+ 5.33333e-5
+ 2.16667e-3
+ 0
+ 2.0
+
+
+
+
+ 2494
+ 0.75
+ 540
+ 0.05
+ 0.0045
+ 0.0055
+ 0
+ 0
+ 2.0
+
+
+ 0.4
+ 10.0
+ 1.25
+
+ 1
+ 1
+ 1
+
+
+ 1.8
+ 15.12
+
+ 0.01
+ 0.0
+ 0.0
+ 12
+
+
+ 3
+ 3
+ .3
+
+ false
+ true
+
+ false
+ substrate_a
+ 1
+
+
+ false
+ false
+
+ 0.0
+ 0.0
+ 0.0
+
+
+
+
+
+
+ 30.0
+ 3.0
+ 0.0
+ 0.0
+
+
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+
+
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+
+
+
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+ 1
+ 0.1
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ 0.0
+ 0.0
+
+
+
+ 1.0
+
+
+
+ Volume
+ 4
+ 2
+ 100000
+
+
+ apoptosis
+ 1e-6
+ 1e-2
+
+
+
+
+
+
+
+ 300.0
+ 480.0
+ 240.0
+ 60.0
+
+
+ 0
+ 1.0
+ 0
+
+
+
+
+ 5.31667e-05
+
+ 516
+
+
+ 0.05
+ 0
+ 1.66667e-02
+ 5.83333e-03
+ 0
+ 2.0
+
+
+
+ 0.0
+
+ 0
+ 86400
+
+
+ 1.11667e-2
+ 8.33333e-4
+ 5.33333e-5
+ 2.16667e-3
+ 0
+ 2.0
+
+
+
+
+ 2494
+ 0.75
+ 540
+ 0.05
+ 0.0045
+ 0.0055
+ 0
+ 0
+ 2.0
+
+
+ 0.4
+ 10.0
+ 1.25
+
+ 1
+ 1
+ 1
+
+
+ 1.8
+ 15.12
+
+ 0.01
+ 0.0
+ 0.0
+ 12
+
+
+ 3
+ 3
+ .3
+
+ false
+ true
+
+ false
+ substrate_a
+ 1
+
+
+ false
+ false
+
+ 0.0
+ 0.0
+ 0.0
+
+
+
+
+
+
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+
+
+ 31.0
+ 3.1
+ 0.0
+ 0.0
+
+
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+
+
+
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+ 1
+ 0.1
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ 0.0
+ 0.0
+
+
+
+ 1.0
+
+
+
+ Volume
+ 4
+ 2
+ 100000
+
+
+ apoptosis
+ 1e-6
+ 1e-2
+
+
+
+
+
+
+
+ 300.0
+ 480.0
+ 240.0
+ 60.0
+
+
+ 0
+ 0
+ 1.0
+
+
+
+
+ 5.31667e-05
+
+ 516
+
+
+ 0.05
+ 0
+ 1.66667e-02
+ 5.83333e-03
+ 0
+ 2.0
+
+
+
+ 0.0
+
+ 0
+ 86400
+
+
+ 1.11667e-2
+ 8.33333e-4
+ 5.33333e-5
+ 2.16667e-3
+ 0
+ 2.0
+
+
+
+
+ 2494
+ 0.75
+ 540
+ 0.05
+ 0.0045
+ 0.0055
+ 0
+ 0
+ 2.0
+
+
+ 0.4
+ 10.0
+ 1.25
+
+ 1
+ 1
+ 1
+
+
+ 1.8
+ 15.12
+
+ 0.01
+ 0.0
+ 0.0
+ 12
+
+
+ 3
+ 3
+ .3
+
+ false
+ true
+
+ false
+ substrate_a
+ 1
+
+
+ false
+ false
+
+ 0.0
+ 0.0
+ 0.0
+
+
+
+
+
+
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+
+
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+
+
+ 32.0
+ 3.2
+ 0.0
+ 0.0
+
+
+
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+ 1
+ 0.1
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ 0.0
+ 0.0
+
+
+
+ 1.0
+
+
+
+ Volume
+ 4
+ 2
+ 100000
+
+
+ apoptosis
+ 1e-6
+ 1e-2
+
+
+
+
+
+
+
+ ./config
+ cells.csv
+
+
+
+
+
+
+ ./config
+ cell_rules.csv
+
+
+
+
+
+
+ 12
+ 0.0
+ 0
+ false
+ abc
+
+
\ No newline at end of file
diff --git a/sample_projects/episode/config/cell_rules.csv b/sample_projects/episode/config/cell_rules.csv
new file mode 100644
index 000000000..078426a60
--- /dev/null
+++ b/sample_projects/episode/config/cell_rules.csv
@@ -0,0 +1 @@
+//
\ No newline at end of file
diff --git a/sample_projects/episode/config/cells.csv b/sample_projects/episode/config/cells.csv
new file mode 100644
index 000000000..734bdc767
--- /dev/null
+++ b/sample_projects/episode/config/cells.csv
@@ -0,0 +1 @@
+0,0,0,0
\ No newline at end of file
diff --git a/sample_projects/episode/custom_modules/custom.cpp b/sample_projects/episode/custom_modules/custom.cpp
new file mode 100644
index 000000000..7e4fce145
--- /dev/null
+++ b/sample_projects/episode/custom_modules/custom.cpp
@@ -0,0 +1,208 @@
+/*
+###############################################################################
+# If you use PhysiCell in your project, please cite PhysiCell and the version #
+# number, such as below: #
+# #
+# We implemented and solved the model using PhysiCell (Version x.y.z) [1]. #
+# #
+# [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, #
+# PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu- #
+# lar Systems, PLoS Comput. Biol. 14(2): e1005991, 2018 #
+# DOI: 10.1371/journal.pcbi.1005991 #
+# #
+# See VERSION.txt or call get_PhysiCell_version() to get the current version #
+# x.y.z. Call display_citations() to get detailed information on all cite-#
+# able software used in your PhysiCell application. #
+# #
+# Because PhysiCell extensively uses BioFVM, we suggest you also cite BioFVM #
+# as below: #
+# #
+# We implemented and solved the model using PhysiCell (Version x.y.z) [1], #
+# with BioFVM [2] to solve the transport equations. #
+# #
+# [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, #
+# PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu- #
+# lar Systems, PLoS Comput. Biol. 14(2): e1005991, 2018 #
+# DOI: 10.1371/journal.pcbi.1005991 #
+# #
+# [2] A Ghaffarizadeh, SH Friedman, and P Macklin, BioFVM: an efficient para- #
+# llelized diffusive transport solver for 3-D biological simulations, #
+# Bioinformatics 32(8): 1256-8, 2016. DOI: 10.1093/bioinformatics/btv730 #
+# #
+###############################################################################
+# #
+# BSD 3-Clause License (see https://opensource.org/licenses/BSD-3-Clause) #
+# #
+# Copyright (c) 2015-2021, Paul Macklin and the PhysiCell Project #
+# All rights reserved. #
+# #
+# Redistribution and use in source and binary forms, with or without #
+# modification, are permitted provided that the following conditions are met: #
+# #
+# 1. Redistributions of source code must retain the above copyright notice, #
+# this list of conditions and the following disclaimer. #
+# #
+# 2. Redistributions in binary form must reproduce the above copyright #
+# notice, this list of conditions and the following disclaimer in the #
+# documentation and/or other materials provided with the distribution. #
+# #
+# 3. Neither the name of the copyright holder nor the names of its #
+# contributors may be used to endorse or promote products derived from this #
+# software without specific prior written permission. #
+# #
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE #
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
+# POSSIBILITY OF SUCH DAMAGE. #
+# #
+###############################################################################
+*/
+
+
+#include "custom.h"
+
+
+// constantes variables
+
+static const double ZERO = 0;
+static const std::vector VECTOR_ZERO (4, ZERO); // generate a 4 character long vector of zeros.
+
+
+// functions
+
+void create_cell_types( void )
+{
+ std::cout << "generate cell types ..." << std::endl;
+ std::cout << "cell types can only be defined the first episode of the runtime!" << std::endl;
+
+ // put any modifications to default cell definition here if you
+ // want to have "inherited" by other cell types.
+ // this is a good place to set default functions.
+
+ // cell_default initial definition
+ initialize_default_cell_definition();
+ cell_defaults.phenotype.secretion.sync_to_microenvironment( µenvironment );
+
+ cell_defaults.functions.volume_update_function = standard_volume_update_function;
+ cell_defaults.functions.update_velocity = standard_update_cell_velocity;
+
+ cell_defaults.functions.update_migration_bias = NULL;
+ cell_defaults.functions.update_phenotype = NULL; // update_cell_and_death_parameters_O2_based;
+ cell_defaults.functions.custom_cell_rule = NULL;
+ cell_defaults.functions.contact_function = NULL;
+
+ cell_defaults.functions.add_cell_basement_membrane_interactions = NULL;
+ cell_defaults.functions.calculate_distance_to_membrane = NULL;
+
+ // parse the cell definitions in the XML config file
+ initialize_cell_definitions_from_pugixml();
+
+ // generate the maps of cell definitions.
+ build_cell_definitions_maps();
+
+ // intializes cell signal and response dictionaries
+ setup_signal_behavior_dictionaries();
+
+ // initializ cell rule definitions
+ setup_cell_rules();
+
+ // put any modifications to individual cell definitions here.
+ // this is a good place to set custom functions.
+ cell_defaults.functions.update_phenotype = phenotype_function;
+ cell_defaults.functions.custom_cell_rule = custom_function;
+ cell_defaults.functions.contact_function = contact_function;
+
+ // summarize the cell defintion setup.
+ display_cell_definitions( std::cout );
+
+ return;
+}
+
+
+void setup_microenvironment( void )
+{
+ // set domain parameters
+
+ // put any custom code to set non-homogeneous initial conditions or
+ // extra Dirichlet nodes here.
+
+ // initialize BioFVM
+ initialize_microenvironment();
+
+ return;
+}
+
+
+void setup_tissue( void )
+{
+ double Xmin = microenvironment.mesh.bounding_box[0];
+ double Ymin = microenvironment.mesh.bounding_box[1];
+ double Zmin = microenvironment.mesh.bounding_box[2];
+
+ double Xmax = microenvironment.mesh.bounding_box[3];
+ double Ymax = microenvironment.mesh.bounding_box[4];
+ double Zmax = microenvironment.mesh.bounding_box[5];
+
+ if ( default_microenvironment_options.simulate_2D == true )
+ {
+ Zmin = 0.0;
+ Zmax = 0.0;
+ }
+
+ double Xrange = Xmax - Xmin;
+ double Yrange = Ymax - Ymin;
+ double Zrange = Zmax - Zmin;
+
+ // create some of each type of cell
+ Cell* pC;
+
+ for ( int k=0; k < cell_definitions_by_index.size(); k++ )
+ {
+ Cell_Definition* pCD = cell_definitions_by_index[k];
+ std::cout << "Placing cells of type " << pCD->name << " ... " << std::endl;
+ for ( int n = 0; n < parameters.ints( "number_of_cells" ); n++ )
+ {
+ std::vector position = {0,0,0};
+ position[0] = Xmin + UniformRandom() * Xrange;
+ position[1] = Ymin + UniformRandom() * Yrange;
+ position[2] = Zmin + UniformRandom() * Zrange;
+
+ pC = create_cell( *pCD );
+ pC->assign_position( position );
+ }
+ }
+ std::cout << std::endl;
+
+ // load cells from your CSV file (if enabled)
+ load_cells_from_pugixml();
+ set_parameters_from_distributions();
+
+ // add custom data vector
+ for ( int i = 0 ; i < all_cells->size(); i++ )
+ {
+ std::vector vector_double = VECTOR_ZERO;
+ ( *all_cells )[i]->custom_data.add_vector_variable( "my_vector", vector_double );
+ }
+
+ return;
+}
+
+std::vector my_coloring_function( Cell* pCell )
+{ return paint_by_number_cell_coloring( pCell ); }
+
+void phenotype_function( Cell* pCell, Phenotype& phenotype, double dt )
+{ return; }
+
+void custom_function( Cell* pCell, Phenotype& phenotype, double dt )
+{ return; }
+
+void contact_function( Cell* pMe, Phenotype& phenoMe, Cell* pOther, Phenotype& phenoOther, double dt )
+{ return; }
+
diff --git a/sample_projects/episode/custom_modules/custom.h b/sample_projects/episode/custom_modules/custom.h
new file mode 100644
index 000000000..4560f5050
--- /dev/null
+++ b/sample_projects/episode/custom_modules/custom.h
@@ -0,0 +1,89 @@
+/*
+###############################################################################
+# If you use PhysiCell in your project, please cite PhysiCell and the version #
+# number, such as below: #
+# #
+# We implemented and solved the model using PhysiCell (Version x.y.z) [1]. #
+# #
+# [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, #
+# PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu- #
+# lar Systems, PLoS Comput. Biol. 14(2): e1005991, 2018 #
+# DOI: 10.1371/journal.pcbi.1005991 #
+# #
+# See VERSION.txt or call get_PhysiCell_version() to get the current version #
+# x.y.z. Call display_citations() to get detailed information on all cite-#
+# able software used in your PhysiCell application. #
+# #
+# Because PhysiCell extensively uses BioFVM, we suggest you also cite BioFVM #
+# as below: #
+# #
+# We implemented and solved the model using PhysiCell (Version x.y.z) [1], #
+# with BioFVM [2] to solve the transport equations. #
+# #
+# [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, #
+# PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu- #
+# lar Systems, PLoS Comput. Biol. 14(2): e1005991, 2018 #
+# DOI: 10.1371/journal.pcbi.1005991 #
+# #
+# [2] A Ghaffarizadeh, SH Friedman, and P Macklin, BioFVM: an efficient para- #
+# llelized diffusive transport solver for 3-D biological simulations, #
+# Bioinformatics 32(8): 1256-8, 2016. DOI: 10.1093/bioinformatics/btv730 #
+# #
+###############################################################################
+# #
+# BSD 3-Clause License (see https://opensource.org/licenses/BSD-3-Clause) #
+# #
+# Copyright (c) 2015-2021, Paul Macklin and the PhysiCell Project #
+# All rights reserved. #
+# #
+# Redistribution and use in source and binary forms, with or without #
+# modification, are permitted provided that the following conditions are met: #
+# #
+# 1. Redistributions of source code must retain the above copyright notice, #
+# this list of conditions and the following disclaimer. #
+# #
+# 2. Redistributions in binary form must reproduce the above copyright #
+# notice, this list of conditions and the following disclaimer in the #
+# documentation and/or other materials provided with the distribution. #
+# #
+# 3. Neither the name of the copyright holder nor the names of its #
+# contributors may be used to endorse or promote products derived from this #
+# software without specific prior written permission. #
+# #
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE #
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
+# POSSIBILITY OF SUCH DAMAGE. #
+# #
+###############################################################################
+*/
+
+
+#include "../core/PhysiCell.h"
+#include "../modules/PhysiCell_standard_modules.h"
+
+using namespace BioFVM;
+using namespace PhysiCell;
+
+// setup functions to help us along
+void create_cell_types( void );
+void setup_tissue( void );
+
+// set up the BioFVM microenvironment
+void setup_microenvironment( void );
+
+// custom pathology coloring function
+std::vector my_coloring_function( Cell* );
+
+// custom functions can go here
+void phenotype_function( Cell* pCell, Phenotype& phenotype, double dt );
+void custom_function( Cell* pCell, Phenotype& phenotype, double dt );
+void contact_function( Cell* pMe, Phenotype& phenoMe, Cell* pOther, Phenotype& phenoOther, double dt );
+
diff --git a/sample_projects/episode/main.cpp b/sample_projects/episode/main.cpp
new file mode 100644
index 000000000..2f32cb696
--- /dev/null
+++ b/sample_projects/episode/main.cpp
@@ -0,0 +1,396 @@
+/*
+###############################################################################
+# If you use PhysiCell in your project, please cite PhysiCell and the version #
+# number, such as below: #
+# #
+# We implemented and solved the model using PhysiCell (Version x.y.z) [1]. #
+# #
+# [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, #
+# PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu- #
+# lar Systems, PLoS Comput. Biol. 14(2): e1005991, 2018 #
+# DOI: 10.1371/journal.pcbi.1005991 #
+# #
+# See VERSION.txt or call get_PhysiCell_version() to get the current version #
+# x.y.z. Call display_citations() to get detailed information on all cite-#
+# able software used in your PhysiCell application. #
+# #
+# Because PhysiCell extensively uses BioFVM, we suggest you also cite BioFVM #
+# as below: #
+# #
+# We implemented and solved the model using PhysiCell (Version x.y.z) [1], #
+# with BioFVM [2] to solve the transport equations. #
+# #
+# [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, #
+# PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu- #
+# lar Systems, PLoS Comput. Biol. 14(2): e1005991, 2018 #
+# DOI: 10.1371/journal.pcbi.1005991 #
+# #
+# [2] A Ghaffarizadeh, SH Friedman, and P Macklin, BioFVM: an efficient para- #
+# llelized diffusive transport solver for 3-D biological simulations, #
+# Bioinformatics 32(8): 1256-8, 2016. DOI: 10.1093/bioinformatics/btv730 #
+# #
+###############################################################################
+# #
+# BSD 3-Clause License (see https://opensource.org/licenses/BSD-3-Clause) #
+# #
+# Copyright (c) 2015-2022, Paul Macklin and the PhysiCell Project #
+# All rights reserved. #
+# #
+# Redistribution and use in source and binary forms, with or without #
+# modification, are permitted provided that the following conditions are met: #
+# #
+# 1. Redistributions of source code must retain the above copyright notice, #
+# this list of conditions and the following disclaimer. #
+# #
+# 2. Redistributions in binary form must reproduce the above copyright #
+# notice, this list of conditions and the following disclaimer in the #
+# documentation and/or other materials provided with the distribution. #
+# #
+# 3. Neither the name of the copyright holder nor the names of its #
+# contributors may be used to endorse or promote products derived from this #
+# software without specific prior written permission. #
+# #
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE #
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
+# POSSIBILITY OF SUCH DAMAGE. #
+# #
+###############################################################################
+*/
+
+
+// load standard library
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// loade PhysiCell library
+#include "./core/PhysiCell.h"
+#include "./modules/PhysiCell_standard_modules.h"
+#include "./custom_modules/custom.h"
+
+// load namespace
+using namespace BioFVM;
+using namespace PhysiCell;
+
+
+// main function
+int main( int argc, char* argv[] )
+ {
+
+ ////////////////////////
+ // EPISODE LOOP BEGIN //
+ ////////////////////////
+
+ for ( int i_episode = 0; i_episode < 4; i_episode++ )
+ {
+ ///////////
+ // start //
+ ///////////
+
+ std::cout << "\nrun episode: " << i_episode << " !" << std::endl;
+
+ // variables
+ char filename[1024];
+ std::ofstream report_file;
+ std::vector ( *cell_coloring_function )( Cell* ) = my_coloring_function; // set a pathology coloring function
+ std::string ( *substrate_coloring_function )( double, double, double ) = paint_by_density_percentage;
+
+ // generate output folder name
+ std::string s_episode = std::to_string( i_episode );
+ std::string folder = "output/episode" + s_episode.insert( 0, 8 - s_episode.length(), '0' );
+
+ // handle settings file
+ const char* settingxml = "config/PhysiCell_settings.xml";
+ if ( argc > 1 ) { settingxml = argv[1]; };
+
+ // reset global variables
+ std::cout << "(re)set global variables ..." << std::endl;
+ PhysiCell_globals = PhysiCell_Globals();
+
+ // time setup
+ std::string time_units = "min";
+
+ // densities and cell types can only be defined in the first episode
+ // and have to be reloaded in all following episodes!
+ if ( i_episode == 0 )
+ {
+ // load xml file
+ std::cout << "load setting xml " << settingxml << " ..." << std::endl;
+ bool XML_status = false;
+ XML_status = load_PhysiCell_config_file( settingxml );
+ PhysiCell_settings.folder = folder;
+ create_output_directory( PhysiCell_settings.folder );
+
+ // OpenMP setup
+ omp_set_num_threads( PhysiCell_settings.omp_num_threads );
+
+ // setup microenviroment and mechanics voxel size and match the data structure to BioFVM
+ std::cout << "set densities ..." << std::endl;
+ setup_microenvironment(); // modify this in the custom code
+ double mechanics_voxel_size = 30;
+ Cell_Container* cell_container = create_cell_container_for_microenvironment( microenvironment, mechanics_voxel_size );
+
+ // load cell type definition and setup tisse
+ std::cout << "load cell type definition and setup tissue ..." << std::endl;
+ create_cell_types(); // modify this in the custom code
+ setup_tissue(); // modify this in the custom code
+
+ // set MultiCellDS save options
+ set_save_biofvm_mesh_as_matlab( true );
+ set_save_biofvm_data_as_matlab( true );
+ set_save_biofvm_cell_data( true );
+ set_save_biofvm_cell_data_as_custom_matlab( true );
+
+ }
+ else
+ {
+ // load xml file
+ std::cout << "load setting xml " << settingxml << " ..." << std::endl;
+ bool XML_status = false;
+ XML_status = read_PhysiCell_config_file( settingxml );
+ if ( XML_status ) { PhysiCell_settings.read_from_pugixml(); }
+ if ( !XML_status ) { exit( -1 ); }
+ PhysiCell_settings.folder = folder;
+ create_output_directory( PhysiCell_settings.folder );
+
+ // OpenMP setup
+ omp_set_num_threads( PhysiCell_settings.omp_num_threads );
+
+ // reset cells
+ std::cout << "reset cells ..." << std::endl;
+ for ( Cell* pCell: (*all_cells) )
+ {
+ pCell->die();
+ }
+ BioFVM::reset_max_basic_agent_ID();
+
+ // reset mesh0
+ std::cout << "reset mesh0 ..." << std::endl;
+ BioFVM::reset_BioFVM_substrates_initialized_in_dom();
+
+ // reset microenvironment and mechanics voxel size and match the data structure to BioFVM
+ std::cout << "reset densities ..." << std::endl;
+ set_microenvironment_initial_condition();
+ microenvironment.display_information( std::cout );
+ double mechanics_voxel_size = 30;
+ Cell_Container* cell_container = create_cell_container_for_microenvironment( microenvironment, mechanics_voxel_size );
+
+ // reset tissue
+ std::cout << "reset tissue ..." << std::endl;
+ display_cell_definitions( std::cout );
+ setup_tissue(); // modify this in the custom code
+
+ // MultiCellDS save options
+ // have only to be set once per runtime
+ }
+
+ // copy config file to output directory
+ char copy_command [1024];
+ sprintf( copy_command, "cp %s %s", settingxml, PhysiCell_settings.folder.c_str() );
+ system( copy_command );
+
+ // save initial data simulation snapshot
+ sprintf( filename, "%s/initial", PhysiCell_settings.folder.c_str() );
+ save_PhysiCell_to_MultiCellDS_v2( filename, microenvironment, PhysiCell_globals.current_time );
+
+ // save data simulation snapshot output00000000
+ if ( PhysiCell_settings.enable_full_saves == true )
+ {
+ sprintf( filename, "%s/output%08u", PhysiCell_settings.folder.c_str(), PhysiCell_globals.full_output_index );
+ save_PhysiCell_to_MultiCellDS_v2( filename, microenvironment, PhysiCell_globals.current_time );
+ }
+
+ // save initial svg cross section through z = 0 and legend
+ PhysiCell_SVG_options.length_bar = 200; // set cross section length bar to 200 microns
+
+ sprintf( filename, "%s/legend.svg", PhysiCell_settings.folder.c_str() );
+ create_plot_legend( filename, cell_coloring_function );
+
+ sprintf( filename, "%s/initial.svg", PhysiCell_settings.folder.c_str() );
+ SVG_plot( filename, microenvironment, 0.0, PhysiCell_globals.current_time, cell_coloring_function, substrate_coloring_function );
+
+ // save svg cross section snapshot00000000
+ if ( PhysiCell_settings.enable_SVG_saves == true )
+ {
+ sprintf( filename, "%s/snapshot%08u.svg", PhysiCell_settings.folder.c_str(), PhysiCell_globals.SVG_output_index );
+ SVG_plot( filename, microenvironment, 0.0, PhysiCell_globals.current_time, cell_coloring_function, substrate_coloring_function );
+ }
+
+ // save legacy simulation report
+ if ( PhysiCell_settings.enable_legacy_saves == true )
+ {
+ sprintf( filename, "%s/simulation_report.txt", PhysiCell_settings.folder.c_str() );
+ report_file.open( filename ); // create the data log file
+ report_file << "simulated time\tnum cells\tnum division\tnum death\twall time" << std::endl;
+ log_output( PhysiCell_globals.current_time, PhysiCell_globals.full_output_index, microenvironment, report_file ); // output00000000
+ }
+
+ // standard output
+ display_citations();
+ display_simulation_status( std::cout ); // output00000000
+
+ // set the performance timers
+ BioFVM::RUNTIME_TIC();
+ BioFVM::TIC();
+
+
+ //////////
+ // step //
+ //////////
+
+ // main loop
+ try
+ {
+ // set time variables
+ double custom_dt = 60; // min
+ double custom_countdown = custom_dt;
+ double phenotype_countdown = phenotype_dt;
+ double mechanics_countdown = mechanics_dt;
+ double mcds_countdown = PhysiCell_settings.full_save_interval;
+ double svg_countdown = PhysiCell_settings.SVG_save_interval;
+
+ // run diffusion time step paced main loop
+ bool step = true;
+ while ( step )
+ {
+
+ // max time reached?
+ if ( PhysiCell_globals.current_time > PhysiCell_settings.max_time )
+ {
+ step = false;
+ }
+
+ // on custom time step
+ if ( custom_countdown < 0.5 * diffusion_dt )
+ {
+ custom_countdown += custom_dt;
+
+ // Put custom time scale code here!
+ //std::cout << "processing custom time step block ... " << std::endl;
+ // Custom add ons could potentially go here.
+ }
+
+ // on phenotype time step
+ if ( phenotype_countdown < 0.5 * diffusion_dt )
+ {
+ phenotype_countdown += phenotype_dt;
+
+ // Put phenotype time scale code here!
+ //std::cout << "processing phenotype time step observation block ... " << std::endl;
+ }
+
+ // on mechanics time step
+ if ( mechanics_countdown < 0.5 * diffusion_dt )
+ {
+ mechanics_countdown += mechanics_dt;
+
+ // Put mechanics time scale code here!
+ //std::cout << "processing mechanic time step observation block ... " << std::endl;
+ }
+
+ // on diffusion time step
+ // Put diffusion time scale code here!
+ //std::cout << "processing diffusion time step observation block ... " << std::endl << std::endl;
+
+ // run microenvironment
+ microenvironment.simulate_diffusion_decay( diffusion_dt );
+
+ // run PhysiCell
+ ( (Cell_Container *)microenvironment.agent_container )->update_all_cells ( PhysiCell_globals.current_time );
+
+ // update time
+ custom_countdown -= diffusion_dt;
+ phenotype_countdown -= diffusion_dt;
+ mechanics_countdown -= diffusion_dt;
+ mcds_countdown -= diffusion_dt;
+ svg_countdown -= diffusion_dt;
+ PhysiCell_globals.current_time += diffusion_dt;
+
+ // save data if it's time.
+ if ( mcds_countdown < 0.5 * diffusion_dt )
+ {
+ mcds_countdown += PhysiCell_settings.full_save_interval;
+ PhysiCell_globals.full_output_index++;
+
+ display_simulation_status( std::cout );
+
+ // save data simulation snapshot
+ if ( PhysiCell_settings.enable_full_saves == true )
+ {
+ sprintf( filename, "%s/output%08u", PhysiCell_settings.folder.c_str(), PhysiCell_globals.full_output_index );
+ save_PhysiCell_to_MultiCellDS_v2( filename, microenvironment, PhysiCell_globals.current_time );
+ }
+
+ // save legacy simulation report
+ if ( PhysiCell_settings.enable_legacy_saves == true )
+ {
+ log_output( PhysiCell_globals.current_time, PhysiCell_globals.full_output_index, microenvironment, report_file );
+ }
+ }
+
+ // save svg plot if it's time
+ if ( ( PhysiCell_settings.enable_SVG_saves == true ) and ( svg_countdown < 0.5 * diffusion_dt ) )
+ {
+ svg_countdown += PhysiCell_settings.SVG_save_interval;
+ PhysiCell_globals.SVG_output_index++;
+
+ // save final svg cross section
+ sprintf( filename, "%s/snapshot%08u.svg", PhysiCell_settings.folder.c_str(), PhysiCell_globals.SVG_output_index );
+ SVG_plot( filename, microenvironment, 0.0, PhysiCell_globals.current_time, cell_coloring_function, substrate_coloring_function );
+ }
+ }
+
+ }
+ catch ( const std::exception& e )
+ { // reference to the base of a polymorphic object
+ std::cout << e.what(); // information from length_error printed
+ }
+
+ //////////
+ // stop //
+ //////////
+
+ // save final data simulation snapshot
+ sprintf( filename, "%s/final", PhysiCell_settings.folder.c_str() );
+ save_PhysiCell_to_MultiCellDS_v2( filename, microenvironment, PhysiCell_globals.current_time );
+
+ // save final svg cross section
+ sprintf( filename, "%s/final.svg", PhysiCell_settings.folder.c_str() );
+ SVG_plot( filename, microenvironment, 0.0, PhysiCell_globals.current_time, cell_coloring_function, substrate_coloring_function );
+
+ // timer
+ std::cout << std::endl << "Total simulation runtime: " << std::endl;
+ BioFVM::display_stopwatch_value( std::cout, BioFVM::runtime_stopwatch_value() );
+ std::cout << std::endl;
+
+ // save legacy simulation report
+ if ( PhysiCell_settings.enable_legacy_saves == true )
+ {
+ log_output( PhysiCell_globals.current_time, PhysiCell_globals.full_output_index, microenvironment, report_file );
+ report_file.close();
+ }
+
+
+ //////////////////////
+ // EPISODE LOOP END //
+ //////////////////////
+
+ }
+
+ // going home
+ return 0;
+}
diff --git a/sample_projects/episode/scripts/empty.txt b/sample_projects/episode/scripts/empty.txt
new file mode 100644
index 000000000..e69de29bb