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 + + + 60 + true + + substrate_a + YlOrRd + 0 + 1 + + + + 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