diff --git a/Makefile b/Makefile index 5d256d1c3..55cb573b2 100644 --- a/Makefile +++ b/Makefile @@ -299,6 +299,17 @@ template_BM: mkdir ./scripts/ cp ./sample_projects_intracellular/boolean/template_BM/scripts/* ./scripts/ +spheroid_tnf: + cp ./sample_projects_intracellular/spheroid_tnf/custom_modules/* ./custom_modules/ + touch main.cpp && cp main.cpp main-backup.cpp + cp ./sample_projects_intracellular/spheroid_tnf/main.cpp ./main.cpp + cp Makefile Makefile-backup + cp ./sample_projects_intracellular/spheroid_tnf/Makefile . + cp ./config/PhysiCell_settings.xml ./config/PhysiCell_settings-backup.xml + cp -r ./sample_projects_intracellular/spheroid_tnf/config/* ./config/ + mkdir ./scripts/ + cp ./sample_projects_intracellular/spheroid_tnf/scripts/* ./scripts/ + # early examples for convergence testing physicell_test_mech1: $(PhysiCell_OBJECTS) ./examples/PhysiCell_test_mechanics_1.cpp diff --git a/addons/PhysiBoSS/src/maboss_intracellular.cpp b/addons/PhysiBoSS/src/maboss_intracellular.cpp index e85eafb41..345870f78 100644 --- a/addons/PhysiBoSS/src/maboss_intracellular.cpp +++ b/addons/PhysiBoSS/src/maboss_intracellular.cpp @@ -23,6 +23,8 @@ MaBoSSIntracellular::MaBoSSIntracellular(pugi::xml_node& node) MaBoSSIntracellular::MaBoSSIntracellular(MaBoSSIntracellular* copy) { + pre_update_intracellular = copy->pre_update_intracellular; + post_update_intracellular = copy->post_update_intracellular; intracellular_type = copy->intracellular_type; bnd_filename = copy->bnd_filename; cfg_filename = copy->cfg_filename; @@ -424,7 +426,14 @@ void MaBoSSIntracellular::initialize_intracellular_from_pugixml(pugi::xml_node& } MaBoSSIntracellular* getMaBoSSModel(PhysiCell::Phenotype& phenotype) { - return static_cast(phenotype.intracellular); + for (auto* intracellular : phenotype.intracellulars) + { + if (intracellular->intracellular_type == "maboss") + { + return static_cast(intracellular); + } + } + return nullptr; } void MaBoSSIntracellular::display(std::ostream& os) @@ -480,8 +489,16 @@ void MaBoSSIntracellular::save(std::string filename) state_file << "ID,state" << std::endl; for( auto cell : *PhysiCell::all_cells ) - if (cell->phenotype.intracellular != NULL && cell->phenotype.intracellular->intracellular_type == "maboss") - state_file << cell->ID << "," << static_cast(cell->phenotype.intracellular)->get_state() << std::endl; - + { + if (cell->phenotype.intracellulars.size() > 0) + { + // This only works if there is one maboss intracellular model per cell, which is the ok + for (auto& intracellular : cell->phenotype.intracellulars) { + if (intracellular->intracellular_type == "maboss") { + state_file << cell->ID << "," << static_cast(intracellular)->get_state() << std::endl; + } + } + } + } state_file.close(); } \ No newline at end of file diff --git a/addons/PhysiBoSS/src/maboss_intracellular.h b/addons/PhysiBoSS/src/maboss_intracellular.h index 06242a8c7..3adcc0ef8 100644 --- a/addons/PhysiBoSS/src/maboss_intracellular.h +++ b/addons/PhysiBoSS/src/maboss_intracellular.h @@ -51,10 +51,10 @@ class MaBoSSIntracellular : public PhysiCell::Intracellular { MaBoSSIntracellular(MaBoSSIntracellular* copy); Intracellular* clone() { - return static_cast(new MaBoSSIntracellular(this)); + return static_cast(new MaBoSSIntracellular(this)); } Intracellular* getIntracellularModel() { - return static_cast(this); + return static_cast(this); } void initialize_intracellular_from_pugixml(pugi::xml_node& node); @@ -80,9 +80,9 @@ class MaBoSSIntracellular : public PhysiCell::Intracellular { return PhysiCell::PhysiCell_globals.current_time >= this->next_physiboss_run; } - void inherit(PhysiCell::Cell * cell) { + void inherit(PhysiCell::Intracellular* intracellular) { maboss.inherit_state( - static_cast(cell->phenotype.intracellular)->maboss.get_maboss_state(), + static_cast(intracellular)->maboss.get_maboss_state(), inherit_state, inherit_nodes ); } diff --git a/addons/libRoadrunner/CMakeLists.txt b/addons/libRoadrunner/CMakeLists.txt index cdbb597b9..ad40f6ba4 100644 --- a/addons/libRoadrunner/CMakeLists.txt +++ b/addons/libRoadrunner/CMakeLists.txt @@ -36,7 +36,7 @@ FetchContent_Declare( FetchContent_MakeAvailable(roadrunner) target_include_directories(libRoadrunner - PUBLIC ${roadrunner_SOURCE_DIR}/include/rr/C) + PUBLIC ${roadrunner_SOURCE_DIR}/include/rr) target_link_directories(libRoadrunner PUBLIC ${roadrunner_SOURCE_DIR}/lib) target_link_libraries(libRoadrunner PUBLIC roadrunner_c_api) target_compile_definitions(libRoadrunner PUBLIC ADDON_ROADRUNNER) diff --git a/addons/libRoadrunner/src/librr_intracellular.cpp b/addons/libRoadrunner/src/librr_intracellular.cpp index 1765c9532..ec844e1b3 100644 --- a/addons/libRoadrunner/src/librr_intracellular.cpp +++ b/addons/libRoadrunner/src/librr_intracellular.cpp @@ -3,56 +3,528 @@ #include #include +void RoadRunnerMapping::initialize_mapping( void ) +{ + bool use_for_input = io_type == "input"; + + int behavior_ind = PhysiCell::find_behavior_index(physicell_name); + int signal_ind = PhysiCell::find_signal_index(physicell_name); + if (behavior_ind != -1) + { + physicell_dictionary_name = "behaviors"; + index = behavior_ind; + if (use_for_input) + { + value_map = [this](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(this->sbml_species, PhysiCell::get_single_behavior(pCell, this->index)); }; + } + else + { + value_map = [this](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { PhysiCell::set_single_behavior(pCell, this->index, intracellular->get_parameter_value(this->sbml_species)); }; + } + } + else if (signal_ind != -1) + { + physicell_dictionary_name = "signals"; + index = signal_ind; + if (use_for_input) + { + value_map = [this](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(this->sbml_species, PhysiCell::get_single_signal(pCell, this->index)); }; + } + else + { + value_map = select_signal_setter(physicell_name, sbml_species); + } + } + else if (is_physicell_phenotype_token(physicell_name)) + { + physicell_dictionary_name = "tokens"; + if (use_for_input) + { + value_map = select_phenotype_by_token_inputter(physicell_name, sbml_species); + } + else + { + value_map = select_phenotype_by_token_outputter(physicell_name, sbml_species); + } + } + else + { + std::cerr << "ERROR: " << physicell_name << " is not a valid entry for the libRoadRunner mapping." << std::endl + << " The available entries are: " << std::endl + << " - signals (see dictionaries.txt in output)" << std::endl + << " - behaviors (see dictionaries.txt in output)" << std::endl + << " - tokens: " << std::endl + << " - mms, mpt, mmb, da, dn, vtsc, vtsn, vff" << std::endl + << " - ctr__" << std::endl + << " - _ where prefix is one of: sur, ssr, ssd, ser" << std::endl << std::endl + << "You can also defined your own pre- and post-update functions in the custom.cpp file." << std::endl + << " - Set them using `pCD->functions.pre_update_intracellular = foo;` and `pCD->functions.post_update_intracellular = bar;`" << std::endl + << " - These functions should have the signature `void foo(Cell* pCell, Phenotype& phenotype, double dt)`" << std::endl; + exit(-1); + } + mapping_initialized = true; + return; +} + +// PhysiCell does not have an API for setting signals, but libRoadRunner does in limited cases +MappingFunction select_signal_setter(const std::string& name, const std::string& sbml_species) +{ + // if "intracellular " or "internalized ", set the internalized substrate amount + if (name.find("intracellular") == 0 || name.find("internalized") == 0) + { + size_t space_ind = name.find(" "); + if (space_ind != std::string::npos) + { + std::string substrate_name = name.substr(space_ind + 1, std::string::npos); + int density_index = microenvironment.find_density_index(substrate_name); + if (density_index != -1) + { + return [density_index, sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.molecular.internalized_total_substrates[density_index] = intracellular->get_parameter_value(sbml_species) * pCell->phenotype.volume.total; }; + } + } + std::cerr << "ERROR: \"" << name << "\" is not a valid signal that can be set using libRoadRunner." << std::endl + << " Somehow, this signal was recognized by the signals dictionary but now it seems malformed." << std::endl + << " I honestly don't know what to say...or how to help you :/" << std::endl; + exit(-1); + } + + // if "volume", set the cell volume + else if (name == "volume") + { + std::cout << "WARNING: setting the volume using libRoadRunner will do so by rescaling ALL cell volumes, not just setting the total volume." + << " To only set the total volume (or to set other components of the volume), use the `pCell->functions.post_update_intracellular`." << std::endl; + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.volume.multiply_by_ratio(intracellular->get_parameter_value(sbml_species) / pCell->phenotype.volume.total); }; + } + + // if "damage", set the cell damage + else if (name == "damage") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.cell_integrity.damage = intracellular->get_parameter_value(sbml_species); }; + } + + // if begins with "custom", check that it is custom data and set that + else if (name.find("custom") == 0) + { + std::cerr << "ERROR: custom data should be handled using the behavior dictionary, not the signal dictionary." << std::endl + << " It is simpler to use the behavior setters." << std::endl + << " How did you even end up here?" << std::endl; + exit(-1); + } + else + { + std::cerr << "ERROR: \"" << name << "\" is not a signal that can be set using libRoadRunner." << std::endl + << " The available signals are: " << std::endl + << " - intracellular " << std::endl + << " - internalized " << std::endl + << " - volume" << std::endl + << " - damage" << std::endl + << " - custom:" << std::endl; + exit(-1); + } +} + +bool is_physicell_phenotype_token(const std::string& name) +{ + if (name[0] == 'm') + { + std::cout << "WARNING: The token \"" << name << "\" can be replaced with the relevant behavior name. The mapping is as follows:" << std::endl + << " - mms -> migration speed" << std::endl + << " - mpt -> persistence time" << std::endl + << " - mmb -> migration bias" << std::endl << std::endl + << "Doing so will allow the libRoadRunner addon to validate that there are not competing mappings." << std::endl; + return name == "mms" || name == "mpt" || name == "mmb"; + } + else if (name[0] == 'd') + { + std::cout << "WARNING: The token \"" << name << "\" can be replaced with the relevant death model name. The mapping is as follows:" << std::endl + << " - da -> apoptosis" << std::endl + << " - dn -> necrosis" << std::endl << std::endl + << "Doing so will allow the libRoadRunner addon to validate that there are not competing mappings." << std::endl; + return name == "da" || name == "dn"; + } + else if (name[0] == 's') + { + std::cout << "WARNING: The token \"" << name << "\" can be replaced with the relevant substrate name. The mapping is as follows:" << std::endl + << " - sur -> uptake" << std::endl + << " - ssr -> secretion" << std::endl + << " - ssd -> secretion target" << std::endl + << " - ser -> export" << std::endl + << "Doing so will allow the libRoadRunner addon to validate that there are not competing mappings." << std::endl; + if (name.substr(0, 3) != "sur" && name.substr(0, 3) != "ssr" && name.substr(0, 3) != "ssd" && name.substr(0, 3) != "ser") + { + return false; + } + if (name[3] != '_') + { + return false; + } + return microenvironment.find_density_index(name.substr(4, std::string::npos)) != -1; + } + else if (name[0] == 'c') + { + std::cout << "WARNING: The token \"" << name << "\" can be replaced with the relevant cycle transition rate name. The mapping is as follows:" << std::endl + << " - ctr__ -> exit from cycle phase " << std::endl + << "Doing so will allow the libRoadRunner addon to validate that there are not competing mappings." << std::endl; + std::vector indices = parse_ctr_token(name); + return indices[0] >= 0 && indices[1] >= 0; + } + else if (name[0] == 'v') + { + return name == "vtsc" || name == "vtsn" || name == "vff"; + } + return false; +} + +std::vector parse_ctr_token(const std::string &name) +{ + if (name.substr(0, 3) != "ctr" || name[3] != '_') + { + throw_invalid_ctr_token(name); + } + size_t pos = name.find("_", 4); + if (pos == std::string::npos) + { + throw_invalid_ctr_token(name); + } + int start_index; + int end_index; + try + { + start_index = atoi(name.substr(4, pos - 1).c_str()); + end_index = atoi(name.substr(pos + 1, std::string::npos).c_str()); + } + catch(const std::exception& e) + { + throw_invalid_ctr_token(name); + } + return {start_index, end_index}; +} + +void throw_invalid_ctr_token(const std::string& name) +{ + std::cerr << "ERROR: \"" << name << "\" is not a valid token format. The available cycle tranisition rate (ctr) tokens are \"ctr__\"." + << " For example: \"ctr_0_1\" or \"ctr_2_3\"." << std::endl; + exit(-1); +} + +MappingFunction select_phenotype_by_token_inputter(const std::string& name, const std::string& sbml_species) +{ + if (name[0] == 'm') + { + if (name == "mms") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.motility.migration_speed); }; + } + else if (name == "mpt") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.motility.persistence_time); }; + } + else if (name == "mmb") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.motility.migration_bias); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized motility token. The available motility tokens are \"mms\", \"mpt\", and \"mmb\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else if (name[0] == 'd') + { + if (name == "da") + { + int death_model_index = PhysiCell::cell_defaults.phenotype.death.find_death_model_index(PhysiCell::PhysiCell_constants::apoptosis_death_model); + return [sbml_species, death_model_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.death.rates[death_model_index]); }; + } + else if (name == "dn") + { + int death_model_index = PhysiCell::cell_defaults.phenotype.death.find_death_model_index(PhysiCell::PhysiCell_constants::necrosis_death_model); + return [sbml_species, death_model_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.death.rates[death_model_index]); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized death token. The available death tokens are \"da\" and \"dn\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else if (name[0] == 's') + { + size_t pos = name.find("_"); + std::string substrate_name = name.substr(pos + 1, std::string::npos); + int substrate_index = microenvironment.find_density_index(substrate_name); + + if (substrate_index == -1) + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << substrate_name << "\" is not a recognized substrate in this model." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + + std::string token_prefix = name.substr(0, 3); + + if (token_prefix == "sur") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.secretion.uptake_rates[substrate_index]); }; + } + else if (token_prefix == "ssr") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.secretion.secretion_rates[substrate_index]); }; + } + else if (token_prefix == "ssd") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.secretion.saturation_densities[substrate_index]); }; + } + else if (token_prefix == "ser") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.secretion.net_export_rates[substrate_index]); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized secretion token. The available secretion tokens are \"sur\", \"ssr\", \"ssd\", and \"ser\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else if (name[0] == 'c') + { + std::vector indices = parse_ctr_token(name); + int start_index = indices[0]; + int end_index = indices[1]; + + return [sbml_species, start_index, end_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.cycle.data.transition_rate(start_index, end_index)); }; + } + else if (name[0] == 'v') + { + if (name == "vtsc") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.volume.target_solid_cytoplasmic); }; + } + else if (name == "vtsn") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.volume.target_solid_nuclear); }; + } + else if (name == "vff") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { intracellular->set_parameter_value(sbml_species, pCell->phenotype.volume.target_fluid_fraction); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized volume token. The available volume tokens are \"vtsc\", \"vtsn\", and \"vff\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized token. It must start with \"m\", \"d\", \"s\", \"c\", or \"v\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } +} + +MappingFunction select_phenotype_by_token_outputter(const std::string& name, const std::string& sbml_species) +{ + if (name[0] == 'm') + { + if (name == "mms") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.motility.migration_speed = intracellular->get_parameter_value(sbml_species); }; + } + else if (name == "mpt") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.motility.persistence_time = intracellular->get_parameter_value(sbml_species); }; + } + else if (name == "mmb") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.motility.migration_bias = intracellular->get_parameter_value(sbml_species); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized motility token. The available motility tokens are \"mms\", \"mpt\", and \"mmb\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else if (name[0] == 'd') + { + if (name == "da") + { + int death_model_index = PhysiCell::cell_defaults.phenotype.death.find_death_model_index(PhysiCell::PhysiCell_constants::apoptosis_death_model); + return [sbml_species, death_model_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.death.rates[death_model_index] = intracellular->get_parameter_value(sbml_species); }; + } + else if (name == "dn") + { + int death_model_index = PhysiCell::cell_defaults.phenotype.death.find_death_model_index(PhysiCell::PhysiCell_constants::necrosis_death_model); + return [sbml_species, death_model_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.death.rates[death_model_index] = intracellular->get_parameter_value(sbml_species); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized death token. The available death tokens are \"da\" and \"dn\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else if (name[0] == 's') + { + size_t pos = name.find("_"); + std::string substrate_name = name.substr(pos + 1, std::string::npos); + int substrate_index = microenvironment.find_density_index(substrate_name); + + if (substrate_index == -1) + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << substrate_name << "\" is not a substrate name in this model." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + + std::string token_prefix = name.substr(0, 3); + + if (token_prefix == "sur") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.secretion.uptake_rates[substrate_index] = intracellular->get_parameter_value(sbml_species); }; + } + else if (token_prefix == "ssr") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.secretion.secretion_rates[substrate_index] = intracellular->get_parameter_value(sbml_species); }; + } + else if (token_prefix == "ssd") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.secretion.saturation_densities[substrate_index] = intracellular->get_parameter_value(sbml_species); }; + } + else if (token_prefix == "ser") + { + return [sbml_species, substrate_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.secretion.net_export_rates[substrate_index] = intracellular->get_parameter_value(sbml_species); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized secretion token. The available secretion tokens are \"sur\", \"ssr\", \"ssd\", and \"ser\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else if (name[0] == 'c') + { + std::vector indices = parse_ctr_token(name); + int start_index = indices[0]; + int end_index = indices[1]; + + return [sbml_species, start_index, end_index](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.cycle.data.transition_rate(start_index, end_index) = intracellular->get_parameter_value(sbml_species); }; + } + else if (name[0] == 'v') + { + if (name == "vtsc") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.volume.target_solid_cytoplasmic = intracellular->get_parameter_value(sbml_species); }; + } + else if (name == "vtsn") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.volume.target_solid_nuclear = intracellular->get_parameter_value(sbml_species); }; + } + else if (name == "vff") + { + return [sbml_species](PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) + { pCell->phenotype.volume.target_fluid_fraction = intracellular->get_parameter_value(sbml_species); }; + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized volume token. The available volume tokens are \"vtsc\", \"vtsn\", and \"vff\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } + } + else + { + std::cerr<< std::endl; + std::cerr << "ERROR: \"" << name << "\" is not a recognized token. It must start with \"m\", \"d\", \"s\", \"c\", or \"v\"." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); + } +} + RoadRunnerIntracellular::RoadRunnerIntracellular() : Intracellular() { intracellular_type = "sbml"; std::cout << "====== " << __FUNCTION__ << "() intracellular_type=" << intracellular_type << std::endl; std::cout << "====== " << __FUNCTION__ << "() sbml_filename = " << sbml_filename << std::endl; - // initial_values.clear(); - // mutations.clear(); parameters.clear(); } // constructor using XML node RoadRunnerIntracellular::RoadRunnerIntracellular(pugi::xml_node& node) { - // std::cout << "======rwh " << __FUNCTION__ << ": node.name() =" << node.name() << std::endl; intracellular_type = "roadrunner"; initialize_intracellular_from_pugixml(node); - // std::cout << "======rwh " << __FUNCTION__ << "(node) intracellular_type=" << intracellular_type << std::endl; - // std::cout << "======rwh " << __FUNCTION__ << "(node) sbml_filename = " << sbml_filename << std::endl; - // std::cout << "======rwh " << __FUNCTION__ << "(node) this=" << this << std::endl; - // std::cout << "======rwh " << __FUNCTION__ << "(node) this->sbml_filename=" << this->sbml_filename << std::endl; } -// Intracellular* RoadRunnerIntracellular::clone() // --> 'Intracellular' does not name a type -// { -// return static_cast(new RoadRunnerIntracellular(this)); -// } - -// rwh: review this RoadRunnerIntracellular::RoadRunnerIntracellular(RoadRunnerIntracellular* copy) { + update_time_step = copy->update_time_step; + previous_update_time = PhysiCell::PhysiCell_globals.current_time; + next_librr_run = PhysiCell::PhysiCell_globals.current_time + update_time_step; intracellular_type = copy->intracellular_type; sbml_filename = copy->sbml_filename; - // cfg_filename = copy->cfg_filename; - // time_step = copy->time_step; - // discrete_time = copy->discrete_time; - // time_tick = copy->time_tick; - // scaling = copy->scaling; - // initial_values = copy->initial_values; - // mutations = copy->mutations; parameters = copy->parameters; - + input_mappings = copy->input_mappings; + output_mappings = copy->output_mappings; + mappings_initialized = copy->mappings_initialized; } -// Parse the info in the .xml for (possibly) each , e.g. -// -// ./config/Toy_SBML_Model_2.xml -// 1 -// Oxy -// Glc -// Energy void RoadRunnerIntracellular::initialize_intracellular_from_pugixml(pugi::xml_node& node) { pugi::xml_node node_sbml = node.child( "sbml_filename" ); @@ -61,265 +533,219 @@ void RoadRunnerIntracellular::initialize_intracellular_from_pugixml(pugi::xml_no sbml_filename = PhysiCell::xml_get_my_string_value (node_sbml); std::cout << "\n------------- " << __FUNCTION__ << ": sbml_filename = " << sbml_filename << std::endl; } - - pugi::xml_node node_species = node.child( "map" ); - while( node_species ) - { - // --------- substrate - - std::string substrate_name = node_species.attribute( "PC_substrate" ).value(); - if( substrate_name != "" ) - { - //std::cout << "-----------" << node_species.attribute( "sbml_species" ).value() << std::endl; - std::string species_name = node_species.attribute( "sbml_species" ).value(); - substrate_species[substrate_name] = species_name; - std::cout << "\n------------- " << __FUNCTION__ << ": species_name= " << species_name << std::endl; - } - // --------- custom_data - std::string custom_data_name = node_species.attribute( "PC_custom_data" ).value(); - if( custom_data_name != "" ) - { - std::string species_name = node_species.attribute( "sbml_species" ).value(); - custom_data_species[custom_data_name] = species_name; - // std::cout << "\n------------- " << __FUNCTION__ << ": species_name= " << species_name << std::endl; - } - - - // --------- phenotype_data - std::string phenotype_name = node_species.attribute( "PC_phenotype" ).value(); - - if( phenotype_name != "" ) - { - std::string species_name = node_species.attribute( "sbml_species" ).value(); - phenotype_species[phenotype_name] = species_name; - // std::cout << "\n------------- " << __FUNCTION__ << ": species_name= " << species_name << std::endl; - } - - node_species = node_species.next_sibling( "map" ); - } - - std::cout << " ------- substrate_species map:" << std::endl; - for(auto elm : substrate_species) - { - std::cout << " " << elm.first << " -> " << elm.second << std::endl; - } - std::cout << " ------- custom_data_species map:" << std::endl; - for(auto elm : custom_data_species) - { - std::cout << " " << elm.first << " -> " << elm.second << std::endl; + + update_time_step = PhysiCell::intracellular_dt; // default to this, but overwrite below if defined in XML + pugi::xml_node node_update_time_step = node.child( "intracellular_dt" ); + if ( node_update_time_step ) + { + update_time_step = PhysiCell::xml_get_my_double_value (node_update_time_step); + std::cout << "\n------------- " << __FUNCTION__ << ": intracellular_dt = " << update_time_step << std::endl; } - std::cout << std::endl; - std::cout << " ------- phenotype_species map:" << std::endl; - for(auto elm : phenotype_species) + std::vector new_input_mappings; + std::vector new_output_mappings; + + pugi::xml_node node_map = node.child( "map" ); + while ( node_map ) { - std::cout << " " << elm.first << " -> " << elm.second << std::endl; + std::string io_type = node_map.attribute( "type" ).value(); + if (io_type != "io" && io_type != "input" && io_type != "output") + { + std::cout << "\n------------- " << __FUNCTION__ << ": ERROR: type must be io, input, or output" << std::endl; + exit(-1); + } + + std::string physicell_name = node_map.attribute( "physicell_name" ).value(); + std::string sbml_species = node_map.attribute( "sbml_species" ).value(); + + if (io_type == "input" || io_type == "io") + { + new_input_mappings.push_back(new RoadRunnerMapping(physicell_name, sbml_species, "input")); + } + if (io_type == "output" || io_type == "io") + { + new_output_mappings.push_back(new RoadRunnerMapping(physicell_name, sbml_species, "output")); + } + + node_map = node_map.next_sibling("map"); } - std::cout << std::endl; + validate_mappings(new_input_mappings, true); + validate_mappings(new_output_mappings, false); + input_mappings = std::move(new_input_mappings); + output_mappings = std::move(new_output_mappings); } +void validate_mappings(std::vector mappings, bool is_inputs) +{ + if (mappings.empty()) + { return; } + std::vector values_already_set; + std::string name_to_add; + for (auto mapping : mappings) + { + name_to_add = is_inputs ? mapping->sbml_species : mapping->physicell_name; + if (std::find(values_already_set.begin(), values_already_set.end(), name_to_add) != values_already_set.end()) + { + std::cout << "ERROR: the " << (is_inputs ? "SBML species " : "PhysiCell name ") << name_to_add << " is set by multiple " << (is_inputs ? "inputs" : "outputs") << std::endl; + exit(-1); + } + values_already_set.push_back(name_to_add); + } +} void RoadRunnerIntracellular::start() { // called when a new cell is created; creates the unique 'rrHandle' rrc::RRVectorPtr vptr; - //std::cout << "\n------------ " << __FUNCTION__ << ": librr_intracellular.cpp: start() called\n"; - // this->enabled = true; - - //std::cout << "\n------------ " << __FUNCTION__ << ": doing: rrHandle = createRRInstance()\n"; - rrHandle = createRRInstance(); - //std::cout << "\n------------ " << __FUNCTION__ << ": rrHandle = " << rrHandle << std::endl; - - // if (!rrc::loadSBML (rrHandle, get_cell_definition("lung epithelium").sbml_filename.c_str())) - //std::cout << " sbml_filename = " << sbml_filename << std::endl; - - // TODO: don't hard-code name if ( !rrc::loadSBML(rrHandle, (sbml_filename).c_str() ) ) - // std::cout << " for now, hard-coding sbml_file = ./config/Toy_SBML_Model_1.xml" << std::endl; - // if (!rrc::loadSBML(rrHandle, "./config/Toy_SBML_Model_1.xml") ) { std::cerr << "------------->>>>> Error while loading SBML file <-------------\n\n"; - // return -1; - // printf ("Error message: %s\n", getLastError()); - exit (0); + exit(-1); } - // std::cout << " rrHandle=" << rrHandle << std::endl; - int r = rrc::getNumberOfReactions(rrHandle); int m = rrc::getNumberOfFloatingSpecies(rrHandle); int b = rrc::getNumberOfBoundarySpecies(rrHandle); int p = rrc::getNumberOfGlobalParameters(rrHandle); int c = rrc::getNumberOfCompartments(rrHandle); - - //std::cerr << "Number of reactions = " << r << std::endl; - //std::cerr << "Number of floating species = " << m << std::endl; // 4 - //std::cerr << "Number of boundary species = " << b << std::endl; // 0 - //std::cerr << "Number of compartments = " << c << std::endl; // 1 - - //std::cerr << "Floating species names:\n"; - //std::cerr << "-----------------------\n"; std::string species_names_str = stringArrayToString(rrc::getFloatingSpeciesIds(rrHandle)); - //std::cerr << species_names_str <<"\n"<< std::endl; std::stringstream iss(species_names_str); std::string species_name; int idx = 0; while (iss >> species_name) { species_result_column_index[species_name] = idx; - //std::cout << species_name << " -> " << idx << std::endl; idx++; } vptr = rrc::getFloatingSpeciesConcentrations(rrHandle); - //std::cerr << vptr->Count << std::endl; -/* for (int kdx=0; kdxCount; kdx++) - { - std::cerr << kdx << ") " << vptr->Data[kdx] << std::endl; - } */ - //std::cerr << "---------- end start() -------------\n"; rrc::freeVector(vptr); - // return 0; + + initialize_mappings(); } bool RoadRunnerIntracellular::need_update() { - return PhysiCell::PhysiCell_globals.current_time >= this->next_librr_run; + return PhysiCell::PhysiCell_globals.current_time >= this->next_librr_run - 0.5 * PhysiCell::diffusion_dt; } -// solve the intracellular model -void RoadRunnerIntracellular::update() +void RoadRunnerIntracellular::update(PhysiCell::Cell* pCell, PhysiCell::Phenotype& phenotype, double dt) { + pre_update(pCell); + // update the intracellular model static double start_time = 0.0; - static double end_time = 0.01; - // static double end_time = 10.0; - // static int num_vals = 1; - // static int num_vals = 10; - static int num_vals = 2; - - // result = rrc::simulateEx (pCell->phenotype.molecular.model_rr, 0, 10, 10); // start time, end time, and number of points - //std::cout << __FUNCTION__ << " ----- update(): this=" << this << std::endl; - //std::cout << __FUNCTION__ << " ----- update(): rrHandle=" << this->rrHandle << std::endl; + static int num_vals = 2; // start time and end time - // if (this->result != 0) // apparently not necessary (done in freeRRCData hopefully) rrc::freeRRCData (this->result); - this->result = rrc::simulateEx (this->rrHandle, start_time, end_time, num_vals); // start time, end time, and number of points + this->result = rrc::simulateEx (this->rrHandle, start_time, PhysiCell::PhysiCell_globals.current_time - previous_update_time, num_vals); // start time, end time, and number of points + this->previous_update_time = PhysiCell::PhysiCell_globals.current_time; + this->next_librr_run = PhysiCell::PhysiCell_globals.current_time + update_time_step; + post_update(pCell); +} - // this->next_librr_run += this->rrHandle.get_time_to_update(); - // std::cout << "----- update(): result=" << result << std::endl; - //std::cout << "----- update(): result->CSize=" << this->result->CSize << std::endl; - //std::cout << "----- update(): result->RSize=" << this->result->RSize << std::endl; // should be = num_vals - // std::cout << "----- update(): result->ColumnHeaders[0]=" << result->ColumnHeaders[0] << std::endl; // = "time" +void RoadRunnerIntracellular::initialize_mappings() +{ + for (auto mapping : input_mappings) + { + if (mapping->mapping_initialized) + { continue; } + mapping->initialize_mapping(); + } + for (auto mapping : output_mappings) + { + if (mapping->mapping_initialized) + { continue; } + mapping->initialize_mapping(); + } + mappings_initialized = true; +} - // debug - does it generate expected data? - int index = 0; - // Print out column headers... typically time and species. - for (int col = 0; col < this->result->CSize; col++) +void RoadRunnerIntracellular::pre_update(PhysiCell::Cell* pCell) +{ + for (auto mapping : input_mappings) { - // std::cout << result->ColumnHeaders[index++]; - // std::cout << std::left << std::setw(15) << result->ColumnHeaders[index++]; - //std::cout << std::left << this->result->ColumnHeaders[index++]; - // if (col < result->CSize - 1) - // { - // // std::cout << "\t"; - // std::cout << " "; - // } + mapping->value_map(pCell, this); } - //std::cout << "\n"; +} - index = 0; - // Print out the data - for (int row = 0; row < this->result->RSize; row++) +void RoadRunnerIntracellular::post_update(PhysiCell::Cell* pCell) +{ + for (auto mapping : output_mappings) { - for (int col = 0; col < this->result->CSize; col++) + mapping->value_map(pCell, this); + } +} + +RoadRunnerMapping* RoadRunnerIntracellular::find_input_mapping(std::string sbml_species) +{ + for (auto mapping : input_mappings) + { + if (mapping->sbml_species == sbml_species) { - // std::cout << result->Data[index++]; - //std::cout << std::left << std::setw(15) << this->result->Data[index++]; - // if (col < result->CSize -1) - // { - // // std::cout << "\t"; - // std::cout << " "; - // } + return mapping; } - // std::cout << "\n"; } - // int idx = (result->RSize - 1) * result->CSize + 1; - // std::cout << "Saving last energy value (cell custom var) = " << result->Data[idx] << std::endl; - // pCell->custom_data[energy_cell_idx] = result->Data[idx]; - - // return 0; + return nullptr; } -double RoadRunnerIntracellular::get_parameter_value(std::string param_name) +RoadRunnerMapping* RoadRunnerIntracellular::find_output_mapping(std::string physicell_name) { - rrc::RRVectorPtr vptr; - - //std::cout << "-----------" << __FUNCTION__ << "-----------" << std::endl; - // std::cout << " substrate_name = " << substrate_name << std::endl; - //std::cout << " param_name = " << param_name << std::endl; - - // TODO: optimize this eventually - // std::map species_result_column_index; - // int num_columns = result->CSize; - // int offset = (num_rows_result_table-1) * result->CSize - 1; - // int offset = (num_rows_result_table-1) * result->CSize; - // offset += (num_rows_result_table-1) * result->CSize - 1; - - // int offset = species_result_column_index[name]; - // std::string species_name = this->substrate_species[substrate_name]; - // std::cout << " species_name = " << species_name << std::endl; - - vptr = rrc::getFloatingSpeciesConcentrations(this->rrHandle); - //std::cerr << vptr->Count << std::endl; - for (int kdx=0; kdxCount; kdx++) + for (auto mapping : output_mappings) { - //std::cerr << kdx << ") " << vptr->Data[kdx] << std::endl; + if (mapping->physicell_name == physicell_name) + { + return mapping; + } } + return nullptr; +} - int offset = species_result_column_index[param_name]; - //std::cout << " result offset = "<< offset << std::endl; - // double res = this->result->Data[offset]; - double res = vptr->Data[offset]; - //std::cout << " res = " << res << std::endl; - rrc::freeVector(vptr); - return res; +double RoadRunnerIntracellular::get_parameter_value(std::string param_name) +{ + double return_value = 0.0; + rrc::getFloatingSpeciesByIndex(this->rrHandle, species_result_column_index[param_name], &return_value); + return return_value; } // rwh: might consider doing a multi-[species_name, value] "set" method +// vn: Actually its better that way. In case there is a species which is linked to an assignment rule, +// we can't use the setFloatingSpecies method without getting an error message, which breaks the thread-safety. void RoadRunnerIntracellular::set_parameter_value(std::string species_name, double value) { - rrc::RRVectorPtr vptr; - - vptr = rrc::getFloatingSpeciesConcentrations(this->rrHandle); - int idx = species_result_column_index[species_name]; - vptr->Data[idx] = value; - // rrc::setFloatingSpeciesConcentrations(pCell->phenotype.molecular.model_rr, vptr); - rrc::setFloatingSpeciesConcentrations(this->rrHandle, vptr); - rrc::freeVector(vptr); - // return 0; + rrc::setFloatingSpeciesByIndex(this->rrHandle, species_result_column_index[species_name], value); } RoadRunnerIntracellular* getRoadRunnerModel(PhysiCell::Phenotype& phenotype) { - return static_cast(phenotype.intracellular); + for (auto* intracellular : phenotype.intracellulars) + { + if (intracellular->intracellular_type == "sbml" || intracellular->intracellular_type == "roadrunner") + { + return static_cast(intracellular); + } + } + return nullptr; +} + +RoadRunnerIntracellular* getRoadRunnerModel(PhysiCell::Cell* pCell) { + return getRoadRunnerModel(pCell->phenotype); } void RoadRunnerIntracellular::save_libRR(std::string path, std::string index) { std::string state_file_name = path + "/states_" + index + ".dat"; -// std::string state_file_name = path + "/states_" + index + ".csv"; std::ofstream state_file( state_file_name ); state_file << "--------- dummy output from save_libRR ---------" << std::endl; state_file << "ID,state" << std::endl; for( auto cell : *PhysiCell::all_cells ) - state_file << cell->ID << "," << cell->phenotype.intracellular->get_state() << std::endl; + state_file << cell->ID << "," << getRoadRunnerModel(cell)->get_state() << std::endl; state_file.close(); } @@ -328,349 +754,41 @@ std::string RoadRunnerIntracellular::get_state() return sbml_filename; } - -int RoadRunnerIntracellular::update_phenotype_parameters(PhysiCell::Phenotype& phenotype) +int RoadRunnerIntracellular::validate_PhysiCell_tokens(PhysiCell::Phenotype& phenotype) { - for(auto elm : phenotype_species) - { - // motility params - if (elm.first[0] == 'm') - { - if (elm.first == "mms") - { - phenotype.motility.migration_speed = phenotype.intracellular->get_parameter_value(elm.second); - } - else if (elm.first == "mpt") - { - phenotype.motility.persistence_time = phenotype.intracellular->get_parameter_value(elm.second); - } - else if (elm.first == "mmb") - { - phenotype.motility.migration_bias = phenotype.intracellular->get_parameter_value(elm.second); - } - else - { - } - } - // death params - else if (elm.first[0] == 'd') - { - if (elm.first == "da") - { - phenotype.death.rates[0] = phenotype.intracellular->get_parameter_value(elm.second); - } - else if (elm.first == "dn") - { - phenotype.death.rates[1] = phenotype.intracellular->get_parameter_value(elm.second); - } - else - { - } - } - // secretion params - else if (elm.first[0] == 's') - { - // parsing attribute and getting substrate name - std::string s = elm.first; - std::string delimiter = "_"; - - size_t pos = 0; - std::string token; - while ((pos = s.find(delimiter)) != std::string::npos) { - token = s.substr(0, pos); - s.erase(0, pos + delimiter.length()); - } - int sub_index = microenvironment.find_density_index(s); - - //transport types - //uptake rate - if (elm.first.substr(0,3) == "sur") - { - //std::cout << sub_index << std::endl; - //std::cout << "Before sur1 : " << phenotype.secretion.uptake_rates[sub_index] << std::endl; - phenotype.secretion.uptake_rates[1] = phenotype.intracellular->get_parameter_value(elm.second); - //std::cout << "After sur1 : " << phenotype.secretion.uptake_rates[sub_index] << std::endl; - } - //secretion rate - else if (elm.first.substr(0,3) == "ssr") - { - phenotype.secretion.secretion_rates[sub_index] = phenotype.intracellular->get_parameter_value(elm.second); - } - //secretion density - else if (elm.first.substr(0,3) == "ssd") - { - phenotype.secretion.saturation_densities[sub_index] = phenotype.intracellular->get_parameter_value(elm.second); - } - //net export rate - else if (elm.first.substr(0,3) == "ser") - { - phenotype.secretion.net_export_rates[sub_index] = phenotype.intracellular->get_parameter_value(elm.second); - } - else - { - } - } - - // cycle params - else if (elm.first[0] == 'c') - { - if (elm.first.substr(0,3) == "ctr") - { - // parsing attribute and getting substrate name - std::string s = elm.first; - std::string delimiter = "_"; - - size_t pos = 0; - std::string token; - int counter = 0; - int start_index; - while ((pos = s.find(delimiter)) != std::string::npos) { - token = s.substr(0, pos); - //std::cout << counter << " : "<< token << std::endl; - if (counter == 1) - { - start_index = atoi( token.c_str() ); - } - s.erase(0, pos + delimiter.length()); - counter += 1; - } - int end_index = atoi( s.c_str() ); - //std::cout << "START INDEX : " << start_index << std::endl; - //std::cout << "END INDEX : " << end_index << std::endl; - phenotype.cycle.data.transition_rate(start_index,end_index) = phenotype.intracellular->get_parameter_value(elm.second); - } - else - { - } - } - - // volume params - else if (elm.first[0] == 'v') - { - if (elm.first == "vtsc") - { - phenotype.volume.target_solid_cytoplasmic = phenotype.intracellular->get_parameter_value(elm.second); - } - else if (elm.first == "vtsn") - { - phenotype.volume.target_solid_nuclear = phenotype.intracellular->get_parameter_value(elm.second); - } - else if (elm.first == "vff") - { - phenotype.volume.target_fluid_fraction = phenotype.intracellular->get_parameter_value(elm.second); - } - else - { - } - } - else - { - } - - } - //std::cout << std::endl; + // the mappings are not yet intialized by this time because the signals/behaviors dictionaries are not yet initialized + int num_of_phases = (&(phenotype.cycle.model()))->phases.size(); + validate_cycle_mappings(input_mappings, num_of_phases); + validate_cycle_mappings(output_mappings, num_of_phases); return 0; } - -int RoadRunnerIntracellular::validate_PhysiCell_tokens(PhysiCell::Phenotype& phenotype) +void validate_cycle_mappings(std::vector mappings, int num_of_phases) { - for(auto elm : phenotype_species) + for (auto mapping : mappings) { - //std::cout << "PhysiCell_token_validation" << std::endl; - //std::cout << elm.first << " : " << elm.second << std::endl; - - // motility params - if (elm.first[0] == 'm') - { - if (elm.first == "mms") - { - } - else if (elm.first == "mpt") - { - } - else if (elm.first == "mmb") - { - } - else - { - std::cout<< std::endl; - std::cout << "ERROR: There is no specified token parameters in the name of \"" << elm.first << "\" at motility parameters. Please take a look token specifications." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - } - // death params - else if (elm.first[0] == 'd') - { - if (elm.first == "da") - { - } - else if (elm.first == "dn") - { - } - else - { - std::cout<< std::endl; - std::cout << "ERROR: There is no specified token parameters in the name of \"" << elm.first << "\" at death parameters. Please take a look token specifications." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - } - // secretion params - else if (elm.first[0] == 's') - { - // parsing attribute and getting substrate name - std::string s = elm.first; - std::string delimiter = "_"; - size_t pos = 0; - std::string token; - while ((pos = s.find(delimiter)) != std::string::npos) { - token = s.substr(0, pos); - s.erase(0, pos + delimiter.length()); - } - int sub_index = microenvironment.find_density_index(s); - //std::cout << "SUBSTRATE_INDEX = : " << sub_index << std::endl; - if ( sub_index < 0 ) - { - std::cout<< std::endl; - std::cout << "ERROR: There is no substrate named in the name of \"" << s << "\" at microenvironment. Please take a look token specifications." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - - if (elm.first.substr(0,3) == "sur") - { - } - else if (elm.first.substr(0,3) == "ssr") - { - } - else if (elm.first.substr(0,3) == "ssd") - { - } - else if (elm.first.substr(0,3) == "ser") - { - } - else - { - std::cout<< std::endl; - std::cout << "ERROR: There is no specified token parameters in the name of \"" << elm.first << "\" at secretion parameters. Please take a look token specifications." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - } - else if (elm.first[0] == 'c') - { - if (elm.first.substr(0,3) == "ctr") - { - // getting num of phases - int num_of_phases = (&(phenotype.cycle.model()))->phases.size(); - //std::cout << num_of_phases << std::endl; - - // getting start and end indices - std::string s = elm.first; - std::string delimiter = "_"; - size_t pos = 0; - std::string token; - int counter = 0; - int start_index; - while ((pos = s.find(delimiter)) != std::string::npos) { - token = s.substr(0, pos); - if (counter == 1) - { - start_index = atoi( token.c_str() ); - } - s.erase(0, pos + delimiter.length()); - counter += 1; - } - int end_index = atoi( s.c_str() ); - - // validating the indices - if ( start_index > num_of_phases - 1) - { - std::cout<< std::endl; - std::cout << "ERROR: Given transition start index is beyond cycle indices. Please double check it." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - if ( end_index > num_of_phases - 1) - { - std::cout<< std::endl; - std::cout << "ERROR: Given transition end index is beyond cycle indices. Please double check it." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - } - else - { - std::cout<< std::endl; - std::cout << "ERROR: There is no specified token parameters in the name of \"" << elm.first << "\" at cycle parameters. Please take a look token specifications." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - } - - else if (elm.first[0] == 'v') - { - if (elm.first == "vtsc") - { - } - else if (elm.first == "vtsn") - { - } - else if (elm.first == "vff") - { - } - else - { - std::cout<< std::endl; - std::cout << "ERROR: There is no specified token parameters in the name of \"" << elm.first << "\" at volume parameters. Please take a look token specifications." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; - } - } - else + // check that the mapping uses a cycle transition rate, i.e. starts with "ctr_" + if (mapping->physicell_name.find("ctr_") != 0) + { continue; } + + std::vector indices = parse_ctr_token(mapping->physicell_name); + if (indices[0] > num_of_phases - 1 || indices[1] > num_of_phases - 1) { - std::cout<< std::endl; - std::cout << "ERROR: There is no specified token parameters in the name of \"" << elm.first << "\" at phenotypic parameters. Please take a look token specifications." << std::endl; - std::cout<< std::endl; - std::cout<< std::endl; - exit (-1); - return -1; + std::cerr << "ERROR: The token \"" << mapping->physicell_name << "\" is invalid for this cell type. The indices are out of range." << std::endl + << " The phase indices must be between 0 and " << num_of_phases - 1 << "." << std::endl; + exit(-1); } - } - std::cout << "---- Specified PhysiCell tokens at config file are validated. ----- " << std::endl; - - return 0; } int RoadRunnerIntracellular::validate_SBML_species() { - //std::cout << "---------VALIDATING_SBML_SPECIES START-------" << std::endl; - // reading SBML rrHandle = createRRInstance(); if ( !rrc::loadSBML(rrHandle, (sbml_filename).c_str() ) ) { std::cerr << "------------->>>>> Error while loading SBML file <-------------\n\n"; - return -1; + exit(-1); } // getting Species Names std::string species_names_str = stringArrayToString(rrc::getFloatingSpeciesIds(rrHandle)); @@ -684,105 +802,32 @@ int RoadRunnerIntracellular::validate_SBML_species() { species_result_column_index[species_name] = idx; all_species.push_back(species_name); - //std::cout << species_name << " -> " << idx << std::endl; idx++; } - // Phenotype Species - for (auto elm : phenotype_species) - { - bool exist = 0; - // std::cout << species_name.size() << std::endl; - for (int i=0; i < all_species.size(); i++) - { - //std::cout << all_species[i] << std::endl;; - //std::cout << "Comparing " << all_species[i] << " with " << elm.second << std::endl; - if ( all_species[i] == elm.second ) - { - //std::cout << "And they are the same..... " < all_species, std::vector mappings) +{ + for (auto mapping : mappings) { - bool exist = 0; - // std::cout << species_name.size() << std::endl; - for (int i=0; i < all_species.size(); i++) + if (std::find(all_species.begin(), all_species.end(), mapping->sbml_species) == all_species.end()) { - //std::cout << all_species[i] << std::endl;; - //std::cout << "Comparing " << all_species[i] << " with " << elm.second << std::endl; - if ( all_species[i] == elm.second ) - { - //std::cout << "And they are the same..... " <sbml_species << "\" at " << mapping->io_type << " mapping. Please take a look SBML species specifications." << std::endl; + std::cerr<< std::endl; + std::cerr<< std::endl; + exit(-1); } - //std::cout << "existence check : " << elm.second <<": " << exist << std::endl; - } - - - //std::cout << "---------VALIDATING_SBML_SPECIES END-------" << std::endl; - - - std::cout << "---- Specified SBML species at config file are validated. ----- " << std::endl; - return 0; + } } int RoadRunnerIntracellular::create_custom_data_for_SBML(PhysiCell::Phenotype& phenotype) { - //std::cout << "Test" << std::endl; - return 0; } diff --git a/addons/libRoadrunner/src/librr_intracellular.h b/addons/libRoadrunner/src/librr_intracellular.h index 82b0b7f78..3d2f09da6 100644 --- a/addons/libRoadrunner/src/librr_intracellular.h +++ b/addons/libRoadrunner/src/librr_intracellular.h @@ -18,42 +18,67 @@ // #include "rrc_types.h" #include "rrc_api.h" #include "rrc_types.h" +#include +#include + // #include "rrc_utilities.h" extern "C" rrc::RRHandle createRRInstance(); // #endif +class RoadRunnerIntracellular; + +typedef std::function MappingFunction; + +class RoadRunnerMapping +{ +public: + std::string physicell_name; + std::string sbml_species; + std::string io_type; + std::string physicell_dictionary_name; + int index; + MappingFunction value_map = [] (PhysiCell::Cell *pCell, RoadRunnerIntracellular *intracellular) {}; // default to a function that does nothing + bool mapping_initialized = false; + + RoadRunnerMapping() {}; + RoadRunnerMapping(std::string physicell_name, std::string sbml_species, std::string io_type) + : physicell_name(physicell_name), sbml_species(sbml_species), io_type(io_type) {}; + + void initialize_mapping(void); +}; + +MappingFunction select_signal_setter(const std::string& name, const std::string& sbml_species); + +bool is_physicell_phenotype_token(const std::string& name); +MappingFunction select_phenotype_by_token_inputter(const std::string& name, const std::string& sbml_species); +MappingFunction select_phenotype_by_token_outputter(const std::string& name, const std::string& sbml_species); + +void validate_mappings(std::vector mappings, bool is_inputs); + +std::vector parse_ctr_token(const std::string &name); +void throw_invalid_ctr_token(const std::string& name); +void validate_cycle_mappings(std::vector mappings, int num_of_phases); class RoadRunnerIntracellular : public PhysiCell::Intracellular { private: public: - - // static long counter; - std::string sbml_filename; - // bool enabled = false; - int num_rows_result_table = 1; - - // double time_step = 12; - // bool discrete_time = false; - // double time_tick = 0.5; - // double scaling = 1.0; - - // std::map initial_values; + std::map parameters; - std::map substrate_species; - std::map custom_data_species; - std::map phenotype_species; + bool mappings_initialized = false; + void initialize_mappings(); + std::vector input_mappings; + std::vector output_mappings; std::map species_result_column_index; - // rrc::RRHandle rrHandle = createRRInstance(); - rrc::RRHandle rrHandle; - // rrc::RRHandle rrHandle; - // rrc::RRVectorPtr vptr; + rrc::RRHandle rrHandle = NULL; rrc::RRCDataPtr result = 0; // start time, end time, and number of points - double next_librr_run = 0; + double update_time_step = 0.01; + double previous_update_time = 0.0; + double next_librr_run = 0.0; RoadRunnerIntracellular(); @@ -61,15 +86,18 @@ class RoadRunnerIntracellular : public PhysiCell::Intracellular RoadRunnerIntracellular(RoadRunnerIntracellular* copy); - // rwh: review this + ~RoadRunnerIntracellular() + { + if (this->rrHandle != NULL) + { + rrc::freeRRInstance(this->rrHandle); + this->rrHandle = NULL; + } + } + Intracellular* clone() { - // return static_cast(new RoadRunnerIntracellular(this)); RoadRunnerIntracellular* clone = new RoadRunnerIntracellular(this); - clone->sbml_filename = this->sbml_filename; - clone->substrate_species = this->substrate_species; - clone->phenotype_species = this->phenotype_species; - clone->custom_data_species = this->custom_data_species; return static_cast(clone); } @@ -78,26 +106,35 @@ class RoadRunnerIntracellular : public PhysiCell::Intracellular std::cout << "------ librr_intracellular: getIntracellularModel called\n"; return static_cast(this); } - - void initialize_intracellular_from_pugixml(pugi::xml_node& node); - - // Need 'int' return type to avoid bizarre compile errors? But 'void' to match MaBoSS. + + void initialize_intracellular_from_pugixml(pugi::xml_node &node); + + // Need 'int' return type to avoid bizarre compile errors? But 'void' to match MaBoSS. void start(); bool need_update(); - // Need 'int' return type to avoid bizarre compile errors. - void update(); - void update(PhysiCell::Cell* cell, PhysiCell::Phenotype& phenotype, double dt) { - update(); - update_phenotype_parameters(phenotype); - } + void update() {}; // needed because the base class has this function + void update(PhysiCell::Cell* cell, PhysiCell::Phenotype& phenotype, double dt); + + void pre_update(PhysiCell::Cell* cell); + void post_update(PhysiCell::Cell* cell); - void inherit(PhysiCell::Cell * cell) {} + void inherit(PhysiCell::Intracellular * intracellular) {} - int update_phenotype_parameters(PhysiCell::Phenotype& phenotype); + // These find__mapping functions are not currently used, but since I made them, we'll keep them around. + RoadRunnerMapping *find_input_mapping(std::string sbml_species); // sbml_species is unique for inputs (below is for convenience) + RoadRunnerMapping *find_input_mapping(std::string physicell_name, std::string sbml_species) + { return find_input_mapping(sbml_species); } // sbml_species is unique for inputs + + RoadRunnerMapping *find_output_mapping(std::string physicell_name); // physicell_name is unique for outputs (below is for convenience) + RoadRunnerMapping *find_output_mapping(std::string physicell_name, std::string sbml_species) + { return find_output_mapping(physicell_name); } // physicell_name is unique for outputs + + int update_phenotype_parameters(PhysiCell::Phenotype& phenotype) {return 0;}; // all handled within update int validate_PhysiCell_tokens(PhysiCell::Phenotype& phenotype); int validate_SBML_species(); + void validate_SBML_species(std::vector all_species, std::vector mappings); int create_custom_data_for_SBML(PhysiCell::Phenotype& phenotype); double get_parameter_value(std::string name); @@ -114,4 +151,6 @@ class RoadRunnerIntracellular : public PhysiCell::Intracellular static void save_libRR(std::string path, std::string index); }; +RoadRunnerIntracellular* getRoadRunnerModel(PhysiCell::Phenotype& phenotype); +RoadRunnerIntracellular* getRoadRunnerModel(PhysiCell::Cell* pCell); #endif \ No newline at end of file diff --git a/beta/setup_libroadrunner.py b/beta/setup_libroadrunner.py index bf6148f06..e0f6b882d 100644 --- a/beta/setup_libroadrunner.py +++ b/beta/setup_libroadrunner.py @@ -8,7 +8,6 @@ import urllib.request import os import sys -import tarfile import zipfile def reminder_dynamic_link_path_macos(): @@ -27,15 +26,12 @@ def reminder_dynamic_link_path_linux(): print("\n* To make this permanent, add this line to the bottom of the respective shell startup file, e.g., .bashrc, .bash_profile, or .zshenv in your home directory.") print("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n") -os_type = platform.system() - -# Old: -# if os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "addons", "libRoadrunner", "roadrunner")): +os_type = platform.system() # can test that it downloads correct OS .zip by overriding this value # New: July 2023 - trying to be smarter about deciding whether to (re)download libRR # NOTE: needs to be tested cross-platform! -if os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "addons", "libRoadrunner", "roadrunner","include","rr","C","rrc_api.h")): - print('\nlibroadrunner already installed.\n') +if os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "addons", "libRoadrunner", "roadrunner","include","rr","rrc_api.h")): + print('\nNote: libroadrunner is already installed so we will not re-install it. \nIf you want to force a re-install, delete the "roadrunner" directory in /addons/libRoadrunner then re-compile.\n') # regardless, let's remind the user about the env var requirement! if os_type.lower() == 'darwin': @@ -55,38 +51,31 @@ def reminder_dynamic_link_path_linux(): if os_type.lower() == 'darwin': reminder_dynamic_link_path_macos() if "ARM64" in platform.uname().version: - # pass - # print('... for the arm64 processor.') - # url = "https://github.com/PhysiCell-Tools/intracellular_libs/raw/main/ode/libs/macos12_arm64/libroadrunner_c_api.dylib" - rr_file = "roadrunner_macos_arm64.tar.gz" - url = "https://github.com/PhysiCell-Tools/intracellular_libs/raw/main/ode/roadrunner_macos_arm64.tar.gz" + rr_file = "roadrunner_macos_arm64.zip" + url = "https://github.com/PhysiCell-Tools/intracellular_libs/raw/main/ode/roadrunner_macos_arm64.zip" mac_silicon = True else: - rr_file = "roadrunner-osx-10.9-cp36m.tar.gz" - url = "https://sourceforge.net/projects/libroadrunner/files/libroadrunner-1.4.18/" + rr_file + "/download" + rr_file = "roadrunner_macos_x86_64.zip" + url = "https://github.com/PhysiCell-Tools/intracellular_libs/raw/main/ode/roadrunner_macos_x86_64.zip" elif os_type.lower().startswith("win"): - rr_file = "roadrunner-win64-vs14-cp35m.zip" - url = "https://sourceforge.net/projects/libroadrunner/files/libroadrunner-1.4.18/" + rr_file + "/download" + rr_file = "roadrunner_win_x86_64.zip" + url = "https://github.com/PhysiCell-Tools/intracellular_libs/raw/main/ode/roadrunner_win_x86_64.zip" elif os_type.lower().startswith("linux"): reminder_dynamic_link_path_linux() - rr_file = "cpplibroadrunner-1.3.0-linux_x86_64.tar.gz" - url = "https://sourceforge.net/projects/libroadrunner/files/libroadrunner-1.3/" + rr_file + "/download" + # the following "manylinux" seems to work on more flavors/releases of Linux than the roadrunner_ubuntu_24.zip which still exists on github.com/PhysiCell-Tools/intracellular_libs + rr_file = "roadrunner_manylinux.zip" + url = "https://github.com/PhysiCell-Tools/intracellular_libs/raw/main/ode/roadrunner_manylinux.zip" else: - print("Your operating system seems to be unsupported. Please submit a ticket at https://sourceforge.net/p/physicell/tickets/ ") + print("Your operating system seems to be unsupported. Please create an issue on the PhysiCell GitHub repo or reach out on our Slack channel.") sys.exit(1) print("url=",url) - if mac_silicon: - fname = url.split('/')[-1] - else: - fname = url.split('/')[-2] + fname = url.split('/')[-1] print("fname=",fname) - # home = os.path.expanduser("~") print('libRoadRunner will now be installed into this location:') - # dir_name = os.path.join(home, 'libroadrunner') dir_name = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons', 'libRoadrunner') - print(dir_name + '\n') + print(f'Will create {dir_name} if it does not exist.') # print(' - Press ENTER to confirm the location') # print(' - Press CTL-C to abort the installation') # print(' - Or specify a different location below\n') @@ -121,17 +110,8 @@ def reminder_dynamic_link_path_linux(): my_file = os.path.join(dir_name, fname) print('my_file = ',my_file) - if os_type.lower().startswith("win"): - rrlib_dir = my_file[:-4] - else: # darwin or linux - if mac_silicon: - # idx_end = my_file.rindex('/') - # rrlib_dir = my_file[:idx_end] - rrlib_dir = my_file[:-7] - # rrlib_dir = my_file - else: - rrlib_dir = my_file[:-7] - print('rrlib_dir = ',rrlib_dir) + # rrlib_dir = my_file[:-4] # assume all are .zip + # print('rrlib_dir = ',rrlib_dir) def download_cb(blocknum, blocksize, totalsize): readsofar = blocknum * blocksize @@ -148,44 +128,31 @@ def download_cb(blocknum, blocksize, totalsize): urllib.request.urlretrieve(url, my_file, download_cb) new_dir_name = "roadrunner" + print(f"chdir to {dir_name}") os.chdir(dir_name) print('installing (uncompressing) the file...') - if os_type.lower().startswith("win"): - try: - with zipfile.ZipFile(rr_file) as zf: - zf.extractall('.') - os.rename("roadrunner-win64-vs14-cp35m", new_dir_name) - except: - print('error unzipping the file') - exit(1) - else: # Darwin or Linux - try: - print("untarring ",rr_file) - tar = tarfile.open(rr_file) - tar.extractall() - tar.close() - if 'darwin' in os_type.lower(): - if mac_silicon: - os.rename("roadrunner_macos_arm64", new_dir_name) - else: - os.rename("roadrunner-osx-10.9-cp36m", new_dir_name) - else: - os.rename("libroadrunner", new_dir_name) - except: - if mac_silicon: - print() - # pass - else: - print('error untarring the file') - exit(1) - - print('Done.\n') - - # # LIBRR_DIR := /Users/heiland/libroadrunner/roadrunner-osx-10.9-cp36m - # print("Replace the following variables in your PhysiCell Makefile with these:\n") - # #print("LIBRR_DIR := /Users/heiland/libroadrunner/roadrunner-osx-10.9-cp36m") - # print("LIBRR_DIR := " + rrlib_dir) - # if os_type == 'Windows': - # print("LIBRR_LIBS := " + rrlib_dir + "/bin\n") - # else: - # print("LIBRR_LIBS := " + rrlib_dir + "/lib\n") + try: + with zipfile.ZipFile(rr_file) as zf: + zf.extractall('.') # should create "roadrunner" directory + except: + print('error unzipping the file') + exit(1) + + + # Hack to maintain backwards compatibility. Originally our header path was .../include/rr/C, + # but newer releases of the libroadrunner C API seems to have dropped the "/C" directory and put everything in "/rr" + dst = "roadrunner/include/rr/C" + try: + os.remove(dst) + except FileNotFoundError: + print(f"File '{dst}' does not exist.") + + try: + src = "." + os.symlink(src, dst) + print(f"Symbolic link '{dst}' created, pointing to '{src}'") + except FileExistsError: + print(f"Symlink '{dst}' already exists") + except OSError as e: + print(f"Error creating symlink: {e}") + print('Done.\n') diff --git a/core/PhysiCell_cell.cpp b/core/PhysiCell_cell.cpp index 1f3e2646b..4ead8eeaf 100644 --- a/core/PhysiCell_cell.cpp +++ b/core/PhysiCell_cell.cpp @@ -653,10 +653,12 @@ Cell* Cell::divide( ) // child->set_phenotype( phenotype ); child->phenotype = phenotype; - if (child->phenotype.intracellular){ - child->phenotype.intracellular->start(); - child->phenotype.intracellular->inherit(this); + for (size_t i=0; i < child->phenotype.intracellulars.size(); i++) + { + child->phenotype.intracellulars[i]->start(); + child->phenotype.intracellulars[i]->inherit(this->phenotype.intracellulars[i]); } + // #ifdef ADDON_PHYSIDFBA // child->fba_model = this->fba_model; // #endif @@ -1124,8 +1126,8 @@ Cell* create_cell( Cell_Definition& cd ) pNew->functions = cd.functions; pNew->phenotype = cd.phenotype; - if (pNew->phenotype.intracellular) - pNew->phenotype.intracellular->start(); + for (auto* intracellular: pNew->phenotype.intracellulars) + intracellular->start(); pNew->is_movable = cd.is_movable; // true; pNew->is_out_of_domain = false; @@ -1908,9 +1910,9 @@ void display_cell_definitions( std::ostream& os ) // intracellular - if (pCD->phenotype.intracellular != NULL) + for (auto intracellular: pCD->phenotype.intracellulars) { - pCD->phenotype.intracellular->display(os); + intracellular->display(os); } Custom_Cell_Data* pCCD = &(pCD->custom_data); @@ -3151,13 +3153,13 @@ Cell_Definition* initialize_cell_definition_from_pugixml( pugi::xml_node cd_node #ifdef ADDON_PHYSIBOSS if (model_type == "maboss") { // If it has already be copied - if (pParent != NULL && pParent->phenotype.intracellular != NULL) { - pCD->phenotype.intracellular->initialize_intracellular_from_pugixml(node); + if (pParent != NULL && pParent->phenotype.intracellulars.size() > 0) { + pCD->phenotype.intracellulars[0]->initialize_intracellular_from_pugixml(node); // Otherwise we need to create a new one } else { MaBoSSIntracellular* pIntra = new MaBoSSIntracellular(node); - pCD->phenotype.intracellular = pIntra->getIntracellularModel(); + pCD->phenotype.intracellulars.push_back(pIntra->getIntracellularModel()); } } #endif @@ -3166,19 +3168,21 @@ Cell_Definition* initialize_cell_definition_from_pugixml( pugi::xml_node cd_node if (model_type == "roadrunner") { // If it has already be copied - if (pParent != NULL && pParent->phenotype.intracellular != NULL) + if (pParent != NULL && pParent->phenotype.intracellulars.size() > 0) { // std::cout << "------ " << __FUNCTION__ << ": copying another\n"; - pCD->phenotype.intracellular->initialize_intracellular_from_pugixml(node); + pCD->phenotype.intracellulars[0]->initialize_intracellular_from_pugixml(node); + pCD->phenotype.intracellulars[0]->validate_PhysiCell_tokens(pCD->phenotype); + pCD->phenotype.intracellulars[0]->validate_SBML_species(); } // Otherwise we need to create a new one else { - std::cout << "\n------ " << __FUNCTION__ << ": creating new RoadRunnerIntracellular\n"; RoadRunnerIntracellular* pIntra = new RoadRunnerIntracellular(node); - pCD->phenotype.intracellular = pIntra->getIntracellularModel(); - pCD->phenotype.intracellular->validate_PhysiCell_tokens(pCD->phenotype); - pCD->phenotype.intracellular->validate_SBML_species(); + pIntra->validate_PhysiCell_tokens(pCD->phenotype); + pIntra->validate_SBML_species(); + pCD->phenotype.intracellulars.push_back(pIntra->getIntracellularModel()); + } } #endif @@ -3186,22 +3190,98 @@ Cell_Definition* initialize_cell_definition_from_pugixml( pugi::xml_node cd_node #ifdef ADDON_PHYSIDFBA if (model_type == "dfba") { // If it has already be copied - if (pParent != NULL && pParent->phenotype.intracellular != NULL) { - pCD->phenotype.intracellular->initialize_intracellular_from_pugixml(node); + if (pParent != NULL && pParent->phenotype.intracellulars.size() > 0) { + pCD->phenotype.intracellulars[0]->initialize_intracellular_from_pugixml(node); // Otherwise we need to create a new one } else { dFBAIntracellular* pIntra = new dFBAIntracellular(node); - pCD->phenotype.intracellular = pIntra->getIntracellularModel(); + pCD->phenotype.intracellulars.push_back(pIntra->getIntracellularModel()); } } #endif } else{ - pCD->phenotype.intracellular = NULL; + pCD->phenotype.intracellulars.clear(); } + + node = cd_node.child( "phenotype" ); + node = node.child( "intracellulars" ); + if( node ) + { + //If there are intracellular models, we clear whatever existed before, including if there was an old format intracellular model + pCD->phenotype.intracellulars.clear(); + + pugi::xml_node intracellular = node.child( "intracellular" ); + size_t intracellular_count = 0; + while( intracellular ) + { + // which substrate? + + + std::string model_type = intracellular.attribute( "type" ).value(); + +#ifdef ADDON_PHYSIBOSS + if (model_type == "maboss") { + // If it has already be copied + if (pParent != NULL && pParent->phenotype.intracellulars.size() >= intracellular_count) { + pCD->phenotype.intracellulars[intracellular_count]->initialize_intracellular_from_pugixml(intracellular); + + // Otherwise we need to create a new one + } else { + MaBoSSIntracellular* pIntra = new MaBoSSIntracellular(intracellular); + pCD->phenotype.intracellulars.push_back(pIntra->getIntracellularModel()); + } + } +#endif + +#ifdef ADDON_ROADRUNNER + if (model_type == "roadrunner") + { + // If it has already be copied + if (pParent != NULL && pParent->phenotype.intracellulars.size() >= intracellular_count) + { + // std::cout << "------ " << __FUNCTION__ << ": copying another\n"; + pCD->phenotype.intracellulars[intracellular_count]->initialize_intracellular_from_pugixml(node); + } + // Otherwise we need to create a new one + else + { + std::cout << "\n------ " << __FUNCTION__ << ": creating new RoadRunnerIntracellular\n"; + RoadRunnerIntracellular* pIntra = new RoadRunnerIntracellular(intracellular); + pIntra->validate_PhysiCell_tokens(pCD->phenotype); + pIntra->validate_SBML_species(); + pCD->phenotype.intracellulars.push_back(pIntra->getIntracellularModel()); + + } + } +#endif + +#ifdef ADDON_PHYSIDFBA + if (model_type == "dfba") { + // If it has already be copied + if (pParent != NULL && pParent->phenotype.intracellulars.size() > intracellular_count) { + pCD->phenotype.intracellulars[intracellular_count]->initialize_intracellular_from_pugixml(intracellular); + // Otherwise we need to create a new one + } else { + PhysiCelldFBA::dFBAIntracellular* pIntra = new PhysiCelldFBA::dFBAIntracellular(intracellular); + pCD->phenotype.intracellulars.push_back(pIntra->getIntracellularModel()); + } + } +#endif + +// } else{ + +// pCD->phenotype.intracellulars.clear(); + +// } + intracellular = intracellular.next_sibling( "intracellular" ); + intracellular_count += 1; + } + } + // set up custom data node = cd_node.child( "custom_data" ); pugi::xml_node node1 = node.first_child(); diff --git a/core/PhysiCell_cell_container.cpp b/core/PhysiCell_cell_container.cpp index 0c5850b1d..96a8f347a 100644 --- a/core/PhysiCell_cell_container.cpp +++ b/core/PhysiCell_cell_container.cpp @@ -146,19 +146,27 @@ void Cell_Container::update_all_cells(double t, double phenotype_dt_ , double me { if( (*all_cells)[i]->is_out_of_domain == false && initialzed ) { - if( (*all_cells)[i]->phenotype.intracellular != NULL && (*all_cells)[i]->phenotype.intracellular->need_update()) + if( (*all_cells)[i]->phenotype.intracellulars.size() > 0) { - if ((*all_cells)[i]->functions.pre_update_intracellular != NULL) - (*all_cells)[i]->functions.pre_update_intracellular( (*all_cells)[i], (*all_cells)[i]->phenotype , diffusion_dt_ ); + for (auto * intracellular: (*all_cells)[i]->phenotype.intracellulars) + { + if (intracellular->need_update()) + { + if (intracellular->pre_update_intracellular != NULL) + (intracellular->pre_update_intracellular)( (*all_cells)[i], (*all_cells)[i]->phenotype , intracellular, diffusion_dt_ ); - (*all_cells)[i]->phenotype.intracellular->update( (*all_cells)[i], (*all_cells)[i]->phenotype , diffusion_dt_ ); + intracellular->update( (*all_cells)[i], (*all_cells)[i]->phenotype , diffusion_dt_ ); - if ((*all_cells)[i]->functions.post_update_intracellular != NULL) - (*all_cells)[i]->functions.post_update_intracellular( (*all_cells)[i], (*all_cells)[i]->phenotype , diffusion_dt_ ); + if (intracellular->post_update_intracellular != NULL) + (intracellular->post_update_intracellular)( (*all_cells)[i], (*all_cells)[i]->phenotype , intracellular, diffusion_dt_ ); + + } + } + } } } - + if( time_since_last_cycle > phenotype_dt_ - 0.5 * diffusion_dt_ || !initialzed ) { // Reset the max_radius in each voxel. It will be filled in set_total_volume diff --git a/core/PhysiCell_phenotype.cpp b/core/PhysiCell_phenotype.cpp index e725c0170..a045aa9fa 100644 --- a/core/PhysiCell_phenotype.cpp +++ b/core/PhysiCell_phenotype.cpp @@ -1150,9 +1150,6 @@ Cell_Functions::Cell_Functions() update_phenotype = NULL; custom_cell_rule = NULL; - pre_update_intracellular = NULL; - post_update_intracellular = NULL; - update_velocity = NULL; add_cell_basement_membrane_interactions = NULL; calculate_distance_to_membrane = NULL; @@ -1181,20 +1178,26 @@ Phenotype::Phenotype() flagged_for_removal = false; // sync the molecular stuff here automatically? - intracellular = NULL; + intracellulars.clear(); return; } Phenotype::Phenotype(const Phenotype &p) { - intracellular = NULL; + + intracellulars.clear(); *this = p; } Phenotype::~Phenotype() { - if (intracellular != NULL) - delete intracellular; + if (intracellulars.size() > 0) { + for (auto * intracellular: intracellulars){ + delete intracellular; + intracellular = NULL; + } + intracellulars.clear(); + } } Phenotype& Phenotype::operator=(const Phenotype &p ) { @@ -1214,18 +1217,45 @@ Phenotype& Phenotype::operator=(const Phenotype &p ) { cell_integrity = p.cell_integrity; - delete intracellular; + if (intracellulars.size() > 0) { + for (auto * intracellular: intracellulars){ + delete intracellular; + intracellular = NULL; + } + intracellulars.clear(); + } - if (p.intracellular != NULL) - { intracellular = p.intracellular->clone(); } - else - { intracellular = NULL; } + if (p.intracellulars.size() > 0) + { + for (auto * intracellular: p.intracellulars) + { + intracellulars.push_back(intracellular->clone()); + } + } cell_interactions = p.cell_interactions; cell_transformations = p.cell_transformations; return *this; } +Intracellular::Intracellular() +{ + this->pre_update_intracellular = NULL; + this->post_update_intracellular = NULL; +} + +Intracellular::Intracellular(const Intracellular *intracellular) +{ + this->pre_update_intracellular = intracellular->pre_update_intracellular; + this->post_update_intracellular = intracellular->post_update_intracellular; +} + +Intracellular* Intracellular::operator=(const Intracellular *intracellular ) { + + this->pre_update_intracellular = intracellular->pre_update_intracellular; + this->post_update_intracellular = intracellular->post_update_intracellular; + return this; +} /* class Bools { diff --git a/core/PhysiCell_phenotype.h b/core/PhysiCell_phenotype.h index 13edc0c40..13ad767ae 100644 --- a/core/PhysiCell_phenotype.h +++ b/core/PhysiCell_phenotype.h @@ -503,9 +503,6 @@ class Cell_Functions void (*custom_cell_rule)( Cell* pCell, Phenotype& phenotype, double dt ); void (*update_phenotype)( Cell* pCell, Phenotype& phenotype, double dt ); // used in celll - void (*pre_update_intracellular) ( Cell* pCell, Phenotype& phenotype, double dt ); - void (*post_update_intracellular) ( Cell* pCell, Phenotype& phenotype, double dt ); - void (*update_velocity)( Cell* pCell, Phenotype& phenotype, double dt ); void (*add_cell_basement_membrane_interactions)(Cell* pCell, Phenotype& phenotype, double dt ); @@ -622,6 +619,9 @@ class Intracellular std::string intracellular_type; // specified in XML : "maboss", "sbml", ... // bool enabled; + void (*pre_update_intracellular) ( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); + void (*post_update_intracellular) ( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); + // ========== specific to SBML ============== // std::string sbml_filename; @@ -641,7 +641,7 @@ class Intracellular virtual void update(Cell* cell, Phenotype& phenotype, double dt) = 0; // This function deals with inheritance from mother to daughter cells - virtual void inherit(Cell* cell) = 0; + virtual void inherit(Intracellular* intracellular) = 0; // Get value for model parameter virtual double get_parameter_value(std::string name) = 0; @@ -657,6 +657,9 @@ class Intracellular virtual ~Intracellular(){}; + Intracellular(); // done + Intracellular(const Intracellular *intracellular); + virtual Intracellular* operator=(const Intracellular* intracellular ); // ================ specific to "maboss" ================ virtual bool has_variable(std::string name) = 0; @@ -790,7 +793,7 @@ class Phenotype // We need it to be a pointer to allow polymorphism // then this object could be a MaBoSSIntracellular, or a RoadRunnerIntracellular - Intracellular* intracellular; + std::vector intracellulars; Cell_Interactions cell_interactions; Cell_Transformations cell_transformations; diff --git a/core/PhysiCell_signal_behavior.cpp b/core/PhysiCell_signal_behavior.cpp index 8780e8d7c..daad14bfa 100644 --- a/core/PhysiCell_signal_behavior.cpp +++ b/core/PhysiCell_signal_behavior.cpp @@ -725,10 +725,8 @@ int find_signal_index( std::string signal_name ) auto search = signal_to_int.find( signal_name ); // safety first! if( search != signal_to_int.end() ) - { return search->second; } - - std::cout << "having trouble finding " << signal_name << std::endl; - + { return search->second; } + return -1; } diff --git a/sample_projects/Makefile-default b/sample_projects/Makefile-default index 5d256d1c3..55cb573b2 100644 --- a/sample_projects/Makefile-default +++ b/sample_projects/Makefile-default @@ -299,6 +299,17 @@ template_BM: mkdir ./scripts/ cp ./sample_projects_intracellular/boolean/template_BM/scripts/* ./scripts/ +spheroid_tnf: + cp ./sample_projects_intracellular/spheroid_tnf/custom_modules/* ./custom_modules/ + touch main.cpp && cp main.cpp main-backup.cpp + cp ./sample_projects_intracellular/spheroid_tnf/main.cpp ./main.cpp + cp Makefile Makefile-backup + cp ./sample_projects_intracellular/spheroid_tnf/Makefile . + cp ./config/PhysiCell_settings.xml ./config/PhysiCell_settings-backup.xml + cp -r ./sample_projects_intracellular/spheroid_tnf/config/* ./config/ + mkdir ./scripts/ + cp ./sample_projects_intracellular/spheroid_tnf/scripts/* ./scripts/ + # early examples for convergence testing physicell_test_mech1: $(PhysiCell_OBJECTS) ./examples/PhysiCell_test_mechanics_1.cpp diff --git a/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.cpp b/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.cpp index d36cd42f8..682ab3962 100644 --- a/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.cpp +++ b/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.cpp @@ -129,8 +129,8 @@ void create_cell_types( void ) This is a good place to set custom functions. */ - cell_defaults.functions.pre_update_intracellular = pre_update_intracellular; - cell_defaults.functions.post_update_intracellular = post_update_intracellular; + cell_defaults.phenotype.intracellulars[0]->pre_update_intracellular = pre_update_intracellular; + cell_defaults.phenotype.intracellulars[0]->post_update_intracellular = post_update_intracellular; cell_defaults.functions.update_phenotype = phenotype_function; cell_defaults.functions.custom_cell_rule = custom_function; @@ -138,15 +138,15 @@ void create_cell_types( void ) Cell_Definition* pCD = find_cell_definition( "epithelial"); - pCD->functions.pre_update_intracellular = pre_update_intracellular; - pCD->functions.post_update_intracellular = post_update_intracellular; + pCD->phenotype.intracellulars[0]->pre_update_intracellular = pre_update_intracellular; + pCD->phenotype.intracellulars[0]->post_update_intracellular = post_update_intracellular; pCD->functions.custom_cell_rule = custom_function; pCD->functions.contact_function = contact_function; pCD->functions.update_velocity = standard_update_cell_velocity; pCD = find_cell_definition( "mesenchymal"); - pCD->functions.pre_update_intracellular = pre_update_intracellular; - pCD->functions.post_update_intracellular = post_update_intracellular; + pCD->phenotype.intracellulars[0]->pre_update_intracellular = pre_update_intracellular; + pCD->phenotype.intracellulars[0]->post_update_intracellular = post_update_intracellular; pCD->functions.custom_cell_rule = custom_function; pCD->functions.contact_function = contact_function; pCD->functions.update_velocity = standard_update_cell_velocity; @@ -301,11 +301,11 @@ void contact_function( Cell* pMe, Phenotype& phenoMe , Cell* pOther, Phenotype& return; } -void pre_update_intracellular(Cell* pCell, Phenotype& phenotype, double dt){ +void pre_update_intracellular(Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt){ return; } -void post_update_intracellular(Cell* pCell, Phenotype& phenotype, double dt){ +void post_update_intracellular(Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt){ return; } diff --git a/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.h b/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.h index ccc4e80e0..1e61e6bed 100644 --- a/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.h +++ b/sample_projects_intracellular/boolean/cancer_invasion/custom_modules/custom.h @@ -97,8 +97,8 @@ inline double get_motility_amplitude( double percent ) void contact_function( Cell* pMe, Phenotype& phenoMe , Cell* pOther, Phenotype& phenoOther , double dt ); void add_ecm_interaction( Cell* pCell, int index_ecm, int index_voxel ); -void pre_update_intracellular(Cell* pCell, Phenotype& phenotype, double dt); -void post_update_intracellular(Cell* pCell, Phenotype& phenotype, double dt); +void pre_update_intracellular(Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt); +void post_update_intracellular(Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt); std::string my_coloring_function_for_stroma( double concentration, double max_conc, double min_conc ); void color_node(Cell* pCell); \ No newline at end of file diff --git a/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.cpp b/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.cpp index c89c8e043..9310cee89 100644 --- a/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.cpp +++ b/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.cpp @@ -95,8 +95,6 @@ void create_cell_types( void ) cell_defaults.functions.update_velocity = NULL; cell_defaults.functions.update_phenotype = NULL; cell_defaults.functions.update_migration_bias = NULL; - cell_defaults.functions.pre_update_intracellular = pre_update_intracellular; - cell_defaults.functions.post_update_intracellular = post_update_intracellular; cell_defaults.functions.custom_cell_rule = NULL; cell_defaults.functions.add_cell_basement_membrane_interactions = NULL; @@ -115,6 +113,8 @@ void create_cell_types( void ) This is a good place to set custom functions. */ + PhysiCell::cell_definitions_by_name["last_one"]->phenotype.intracellulars[0]->pre_update_intracellular = pre_update_intracellular; + PhysiCell::cell_definitions_by_name["last_one"]->phenotype.intracellulars[0]->post_update_intracellular = post_update_intracellular; /* This builds the map of cell definitions and summarizes the setup. @@ -158,26 +158,26 @@ void setup_tissue( void ) load_cells_from_pugixml(); } -void pre_update_intracellular( Cell* pCell, Phenotype& phenotype, double dt ) +void pre_update_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ) { if (PhysiCell::PhysiCell_globals.current_time >= 100.0 - && pCell->phenotype.intracellular->get_parameter_value("$time_scale") == 0.0 + && intracellular->get_parameter_value("$time_scale") == 0.0 ){ - pCell->phenotype.intracellular->set_parameter_value("$time_scale", 0.1); + intracellular->set_parameter_value("$time_scale", 0.1); } } -void post_update_intracellular( Cell* pCell, Phenotype& phenotype, double dt ) +void post_update_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ) { - color_node(pCell); + color_node(pCell, intracellular); } std::vector my_coloring_function( Cell* pCell ) { std::vector< std::string > output( 4 , "rgb(0,0,0)" ); - if ( !pCell->phenotype.intracellular->get_boolean_variable_value( parameters.strings("node_to_visualize") ) ) + if ( !pCell->phenotype.intracellulars[0]->get_boolean_variable_value( parameters.strings("node_to_visualize") ) ) { output[0] = "rgb(255,0,0)"; output[2] = "rgb(125,0,0)"; @@ -191,7 +191,7 @@ std::vector my_coloring_function( Cell* pCell ) return output; } -void color_node(Cell* pCell){ +void color_node(Cell* pCell, Intracellular* intracellular){ std::string node_name = parameters.strings("node_to_visualize"); - pCell->custom_data[node_name] = pCell->phenotype.intracellular->get_boolean_variable_value(node_name); + pCell->custom_data[node_name] = intracellular->get_boolean_variable_value(node_name); } \ No newline at end of file diff --git a/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.h b/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.h index 44cd833d9..66e235036 100644 --- a/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.h +++ b/sample_projects_intracellular/boolean/physiboss_cell_lines/custom_modules/custom.h @@ -84,8 +84,8 @@ void setup_microenvironment( void ); std::vector my_coloring_function( Cell* ); // custom cell phenotype functions could go here -void pre_update_intracellular( Cell* pCell, Phenotype& phenotype, double dt ); -void post_update_intracellular( Cell* pCell, Phenotype& phenotype, double dt ); -void color_node(Cell* pCell); +void pre_update_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); +void post_update_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); +void color_node(Cell* pCell, Intracellular* intracellular); #endif \ No newline at end of file diff --git a/sample_projects_intracellular/ode/ode_energy/Makefile b/sample_projects_intracellular/ode/ode_energy/Makefile index 42168464c..2a1dc1683 100644 --- a/sample_projects_intracellular/ode/ode_energy/Makefile +++ b/sample_projects_intracellular/ode/ode_energy/Makefile @@ -17,10 +17,6 @@ OSFLAG := ifeq ($(OS),Windows_NT) OSFLAG += -D WIN32 OMP_LIB := -# LIBRR_DIR := C:\Users\heiland\libroadrunner\roadrunner-win64-vs14-cp35m -# LIBRR_LIBS := C:\Users\heiland\libroadrunner\roadrunner-win64-vs14-cp35m/bin -# LIBRR_CFLAGS := -I${LIBRR_DIR}/include/rr/C -# CFLAGS := -march=$(ARCH) -fomit-frame-pointer -fopenmp -m64 -std=c++11 -D ADDON_ROADRUNNER LIBRR_DIR := .\addons\libRoadrunner\roadrunner LIBRR_CFLAGS := -I${LIBRR_DIR}\include\rr\C LIBRR_LIBS := ${LIBRR_DIR}\lib @@ -47,21 +43,6 @@ else LIBRR_LIBS := ${LIBRR_DIR}/lib endif -# Not sure if useful later or not. -# UNAME_P := $(shell uname -p) -# ifeq ($(UNAME_P),x86_64) -# OSFLAG += -D AMD64 -# LIBRR_DIR := $(shell pwd)/intracellular_libs/roadrunner -# LIBRR_CFLAGS := -I${LIBRR_DIR}/include/rr/C -# # CFLAGS := -march=$(ARCH) -fomit-frame-pointer -fopenmp -m64 -std=c++11 -D LIBROADRUNNER -# CFLAGS := -march=$(ARCH) -fomit-frame-pointer -fopenmp -m64 -std=c++11 -D ADDON_ROADRUNNER -# endif -# ifneq ($(filter %86,$(UNAME_P)),) -# OSFLAG += -D IA32 -# endif -# ifneq ($(filter arm%,$(UNAME_P)),) -# OSFLAG += -D ARM -# endif endif COMPILE_COMMAND := $(CC) $(CFLAGS) $(LIBRR_CFLAGS) @@ -100,6 +81,10 @@ all: libRoadrunner main.cpp $(ALL_OBJECTS) @echo @echo created $(PROGRAM_NAME) @echo + @echo 'remember on Mac: export DYLD_LIBRARY_PATH=$$DYLD_LIBRARY_PATH:./addons/libRoadrunner/roadrunner/lib' + @echo 'remember on Linux: export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:./addons/libRoadrunner/roadrunner/lib' + @echo 'You can safely delete the downloaded .zip file in addons/libRoadrunner' + @echo name: @echo "" diff --git a/sample_projects_intracellular/ode/ode_energy/config/PhysiCell_settings.xml b/sample_projects_intracellular/ode/ode_energy/config/PhysiCell_settings.xml index f0a40f2f4..589c27b19 100644 --- a/sample_projects_intracellular/ode/ode_energy/config/PhysiCell_settings.xml +++ b/sample_projects_intracellular/ode/ode_energy/config/PhysiCell_settings.xml @@ -90,7 +90,8 @@ 1440 min micron - + + 0.01 0.01 0.1 6 @@ -307,23 +308,27 @@ ./config/Toy_Metabolic_Model.xml - 0.01 - - - - - - - + 0.1 + + + + + + + + + + + - 0.0 - 0.0 + 0.8 + 15.0 0.0 - 0.0 + 450.0 @@ -347,10 +352,6 @@ 0 - 0.8 - 15 - 0 - 450 diff --git a/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.cpp b/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.cpp index acbd054a6..9ca79abec 100644 --- a/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.cpp +++ b/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.cpp @@ -69,12 +69,6 @@ #include "../BioFVM/BioFVM.h" using namespace BioFVM; - -#include "rrc_api.h" -#include "rrc_types.h" -// #include "rrc_utilities.h" -extern "C" rrc::RRHandle createRRInstance(); - void create_cell_types( void ) { // set the random seed @@ -133,38 +127,16 @@ void setup_microenvironment( void ) void setup_tissue( void ) { - static int oxygen_substrate_index = microenvironment.find_density_index( "oxygen" ); static int glucose_substrate_index = microenvironment.find_density_index( "glucose" ); static int lactate_substrate_index = microenvironment.find_density_index( "lactate"); - - 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 cells Cell* pCell; double cell_radius = cell_defaults.phenotype.geometry.radius; - double cell_spacing = 0.8 * 2.0 * cell_radius; double initial_tumor_radius = 100; - double retval; std::vector> positions = create_cell_circle_positions(cell_radius,initial_tumor_radius); @@ -174,86 +146,17 @@ void setup_tissue( void ) pCell = create_cell(get_cell_definition("default")); pCell->assign_position( positions[i] ); - set_single_behavior( pCell , "custom:intra_oxy" , parameters.doubles("initial_internal_oxygen")); - set_single_behavior( pCell , "custom:intra_glu" , parameters.doubles("initial_internal_glucose")); - set_single_behavior( pCell , "custom:intra_lac" , parameters.doubles("initial_internal_lactate")); - set_single_behavior( pCell , "custom:intra_energy" , parameters.doubles("initial_energy")); - -/* pCell->custom_data[i_Oxy_i] = parameters.doubles("initial_internal_oxygen"); - pCell->custom_data[i_Glu_i] = parameters.doubles("initial_internal_glucose"); - pCell->custom_data[i_Lac_i] = parameters.doubles("initial_internal_lactate"); - pCell->custom_data[energy_vi] = parameters.doubles("initial_energy"); */ - double cell_volume = pCell->phenotype.volume.total; - //std::cout << "oxygen custom data : " << pCell->custom_data[i_Oxy_i] << std::endl; - //std::cout << "oxygen custom data : SIGNAL" << get_single_signal( pCell, "custom:intra_oxy") << std::endl; - - - set_single_behavior( pCell , "custom:intra_oxy" , parameters.doubles("initial_internal_oxygen")); - - pCell->phenotype.molecular.internalized_total_substrates[oxygen_substrate_index]= get_single_signal( pCell, "custom:intra_oxy") * cell_volume; pCell->phenotype.molecular.internalized_total_substrates[glucose_substrate_index]= get_single_signal( pCell, "custom:intra_glu") * cell_volume; pCell->phenotype.molecular.internalized_total_substrates[lactate_substrate_index]= get_single_signal( pCell, "custom:intra_lac") * cell_volume; - pCell->phenotype.intracellular->start(); - (*all_cells)[i]->phenotype.intracellular->set_parameter_value("Energy",get_single_signal( pCell, "custom:intra_energy")); - + pCell->phenotype.intracellular->set_parameter_value("Energy",get_single_signal( pCell, "custom:intra_energy")); } return; } -void update_intracellular() -{ - // BioFVM Indices - static int oxygen_substrate_index = microenvironment.find_density_index( "oxygen" ); - static int glucose_substrate_index = microenvironment.find_density_index( "glucose" ); - static int lactate_substrate_index = microenvironment.find_density_index( "lactate"); - - #pragma omp parallel for - for( int i=0; i < (*all_cells).size(); i++ ) - { - if( (*all_cells)[i]->is_out_of_domain == false ) - { - // Cell Volume - double cell_volume = (*all_cells)[i]->phenotype.volume.total; - - // Get Intracellular Concentrations - double oxy_val_int = get_single_signal((*all_cells)[i], "intracellular oxygen"); - double glu_val_int = get_single_signal((*all_cells)[i], "intracellular glucose"); - double lac_val_int = get_single_signal((*all_cells)[i], "intracellular lactate"); - - // Update SBML - (*all_cells)[i]->phenotype.intracellular->set_parameter_value("Oxygen",oxy_val_int); - (*all_cells)[i]->phenotype.intracellular->set_parameter_value("Glucose",glu_val_int); - (*all_cells)[i]->phenotype.intracellular->set_parameter_value("Lactate",lac_val_int); - - // SBML Simulation - (*all_cells)[i]->phenotype.intracellular->update(); - - // Phenotype Simulation - (*all_cells)[i]->phenotype.intracellular->update_phenotype_parameters((*all_cells)[i]->phenotype); - - // Internalized Chemical Update After SBML Simulation - (*all_cells)[i]->phenotype.molecular.internalized_total_substrates[oxygen_substrate_index] = (*all_cells)[i]->phenotype.intracellular->get_parameter_value("Oxygen") * cell_volume; - (*all_cells)[i]->phenotype.molecular.internalized_total_substrates[glucose_substrate_index] = (*all_cells)[i]->phenotype.intracellular->get_parameter_value("Glucose") * cell_volume; - (*all_cells)[i]->phenotype.molecular.internalized_total_substrates[lactate_substrate_index] = (*all_cells)[i]->phenotype.intracellular->get_parameter_value("Lactate") * cell_volume; - - - //Save custom data - set_single_behavior( (*all_cells)[i] , "custom:intra_oxy" , (*all_cells)[i]->phenotype.intracellular->get_parameter_value("Oxygen") ); - set_single_behavior( (*all_cells)[i] , "custom:intra_glu" , (*all_cells)[i]->phenotype.intracellular->get_parameter_value("Glucose") ); - set_single_behavior( (*all_cells)[i] , "custom:intra_lac" , (*all_cells)[i]->phenotype.intracellular->get_parameter_value("Lactate") ); - set_single_behavior( (*all_cells)[i] , "custom:intra_energy" , (*all_cells)[i]->phenotype.intracellular->get_parameter_value("Energy") ); - - } - } - -} - - - std::vector my_coloring_function( Cell* pCell ) { @@ -288,8 +191,6 @@ std::vector my_coloring_function( Cell* pCell ) return output; } - - std::vector> create_cell_circle_positions(double cell_radius, double sphere_radius) { std::vector> cells; diff --git a/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.h b/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.h index 8062d09b0..9a3c6f552 100644 --- a/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.h +++ b/sample_projects_intracellular/ode/ode_energy/custom_modules/custom.h @@ -82,12 +82,6 @@ void setup_microenvironment( void ); // custom pathology coloring function std::vector my_coloring_function( Cell* ); -void update_intracellular(); // custom functions can go here - -void predator_hunting_function( Cell* pCell, Phenotype& phenotype, double dt ); -void predator_cycling_function( Cell* pCell, Phenotype& phenotype, double dt ); - -void prey_cycling_function( Cell* pCell , Phenotype& phenotype, double dt ); std::vector> create_cell_circle_positions(double cell_radius, double sphere_radius); \ No newline at end of file diff --git a/sample_projects_intracellular/ode/ode_energy/main.cpp b/sample_projects_intracellular/ode/ode_energy/main.cpp index 828ce4dc9..d791331c4 100644 --- a/sample_projects_intracellular/ode/ode_energy/main.cpp +++ b/sample_projects_intracellular/ode/ode_energy/main.cpp @@ -161,14 +161,6 @@ int main( int argc, char* argv[] ) report_file<<"simulated time\tnum cells\tnum division\tnum death\twall time"<update_all_cells( PhysiCell_globals.current_time ); @@ -226,17 +210,6 @@ int main( int argc, char* argv[] ) Custom add-ons could potentially go here. */ - double time_since_last_intracellular = PhysiCell_globals.current_time - last_intracellular_time; - - //update_intracellular(); - - if( PhysiCell_globals.current_time >= next_intracellular_update ) - { - update_intracellular(); - - next_intracellular_update += intracellular_dt; - } - PhysiCell_globals.current_time += diffusion_dt; } diff --git a/sample_projects_intracellular/spheroid_tnf/Makefile b/sample_projects_intracellular/spheroid_tnf/Makefile new file mode 100644 index 000000000..6b27d91e1 --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/Makefile @@ -0,0 +1,414 @@ +VERSION := $(shell grep . VERSION.txt | cut -f1 -d:) +PROGRAM_NAME := project + +ifndef CC + CC := gcc +endif +ifndef CXX + CXX := g++ +endif +# CXX := g++-mp-7 # typical macports compiler name +# CXX := g++-7 # typical homebrew compiler name + +# Check for environment definitions of compiler +# e.g., on CXX = g++-7 on OSX +ifdef PHYSICELL_CPP + CXX := $(PHYSICELL_CPP) +endif +ifdef PHYSICELL_CC + CC := $(PHYSICELL_CC) +endif + +### MaBoSS configuration +# MaBoSS max nodes +ifndef MABOSS_MAX_NODES +MABOSS_MAX_NODES = 256 +endif + +# MaBoSS directory +MABOSS_DIR = addons/PhysiBoSS/MaBoSS/engine +CUR_DIR = $(shell pwd) +EXT_DIR = $(CUR_DIR)/addons/dFBA/ext + +ifndef STATIC_LAPACK + STATIC_LAPACK = -llapack +endif + +ifndef STATIC_LIBBZ2 + STATIC_LIBBZ2 = -lbz2 +endif + +ifndef STATIC_LIBZ + STATIC_LIBZ = -lz +endif + +LIB_FBA := -L$(EXT_DIR)/libsbml/lib/ -L$(EXT_DIR)/coin-or/lib/ -lsbml-static -lxml2 -lClp -lCoinUtils $(STATIC_LAPACK) $(STATIC_LIBBZ2) $(STATIC_LIBZ) +INC_FBA := -DADDON_PHYSIDFBA -I$(EXT_DIR)/libsbml/include -I$(EXT_DIR)/coin-or/include -I$(CUR_DIR)/addons/dFBA/src + +ifneq ($(OS), Windows_NT) + LDL_FLAG = -ldl +endif + +LIB := -L$(CUR_DIR)/$(MABOSS_DIR)/lib -lMaBoSS-static $(LDL_FLAG) +INC := -DADDON_PHYSIBOSS -I$(CUR_DIR)/$(MABOSS_DIR)/include -DMAXNODES=$(MABOSS_MAX_NODES) + + +# If max nodes > 64, change lib path +ifeq ($(shell expr $(MABOSS_MAX_NODES) '>' 64), 1) +LIB := -L$(CUR_DIR)/$(MABOSS_DIR)/lib -lMaBoSS_$(MABOSS_MAX_NODES)n-static $(LDL_FLAG) +endif + +ifndef STATIC_OPENMP + STATIC_OPENMP = -fopenmp +endif + +ifndef STATIC_LAPACK + STATIC_LAPACK = -llapack +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 + +ifeq ($(OS),Windows_NT) + LIBRR_DIR := .\addons\libRoadrunner\roadrunner + INC_LIBRR := -DADDON_ROADRUNNER -I${LIBRR_DIR}\include\rr + LIBRR_LIBS := -L${LIBRR_DIR}\lib -lroadrunner_c_api +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Darwin) + UNAME_P := $(shell uname -p) + var := $(shell which $(CXX) | xargs file) + ifeq ($(lastword $(var)),arm64) + CFLAGS := -march=$(ARCH) -O3 -fomit-frame-pointer -fopenmp -m64 -std=c++11 + endif + endif + LIBRR_DIR := ./addons/libRoadrunner/roadrunner + INC_LIBRR := -DADDON_ROADRUNNER -I${LIBRR_DIR}/include/rr + LIBRR_LIBS := -L${LIBRR_DIR}/lib -lroadrunner_c_api +endif + +CFLAGS_LINK := $(shell echo $(CFLAGS) | sed -e "s/-fopenmp//g") +COMPILE_COMMAND := $(CXX) $(CFLAGS) $(EXTRA_FLAGS) +LINK_COMMAND := $(CXX) $(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) +MaBoSS := ./addons/PhysiBoSS/MaBoSS/engine/src/BooleanNetwork.h +libRR := ./addons/libRoadrunner/include/rr/rrc_api.h + +PhysiBoSS_OBJECTS := maboss_network.o maboss_intracellular.o +ROADRUNNER_OBJECTS := librr_intracellular.o + +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) $(PhysiBoSS_OBJECTS) $(ROADRUNNER_OBJECTS) + +# compile the project + +all: main.cpp $(ALL_OBJECTS) $(MaBoSS) + $(COMPILE_COMMAND) $(INC) -o $(PROGRAM_NAME) $(ALL_OBJECTS) main.cpp $(LIB) $(LIBRR_LIBS) + make name + +static: main.cpp $(ALL_OBJECTS) $(MaBoSS) + $(LINK_COMMAND) $(INC) -o $(PROGRAM_NAME) $(ALL_OBJECTS) main.cpp -static-libgcc -static-libstdc++ $(STATIC_OPENMP) $(LIB) $(LIBRR_LIBS) + +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 $(MaBoSS) $(libRR) + $(COMPILE_COMMAND) $(INC) $(INC_LIBRR) -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 $(MaBoSS) $(libRR) + $(COMPILE_COMMAND) $(INC) $(INC_LIBRR) -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 + +Compile_MaBoSS: ./addons/PhysiBoSS/MaBoSS/engine/src/BooleanNetwork.h + cd ./addons/PhysiBoSS/MaBoSS/engine/src;make CXX=$(CXX) CC=$(CC) MAXNODES=$(MABOSS_MAX_NODES) install_alib;make clean; cd ../../../../.. + +$(MaBoSS): +ifeq ($(OS), Windows_NT) + python addons/PhysiBoSS/setup_libmaboss.py +else + python3 addons/PhysiBoSS/setup_libmaboss.py +endif + +maboss_network.o: ./addons/PhysiBoSS/src/maboss_network.cpp $(MaBoSS) + $(COMPILE_COMMAND) $(INC) -c ./addons/PhysiBoSS/src/maboss_network.cpp + +maboss_intracellular.o: ./addons/PhysiBoSS/src/maboss_intracellular.cpp $(MaBoSS) + $(COMPILE_COMMAND) $(INC) -c ./addons/PhysiBoSS/src/maboss_intracellular.cpp + +$(libRR): +ifeq ($(OS), Windows_NT) + python beta/setup_libroadrunner.py +else + python3 beta/setup_libroadrunner.py +endif + +librr_intracellular.o: ./addons/libRoadrunner/src/librr_intracellular.cpp ./addons/libRoadrunner/src/librr_intracellular.h + $(COMPILE_COMMAND) $(INC_LIBRR) -c ./addons/libRoadrunner/src/librr_intracellular.cpp + +custom.o: ./custom_modules/custom.cpp $(MaBoSS) $(libRR) + $(COMPILE_COMMAND) $(INC) $(INC_LIBRR) -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 + rm -fr ./config/cells.csv ./config/cell_rules.csv + rm -rf ./scripts + +MaBoSS-clean: + rm -fr addons/PhysiBoSS/MaBoSS + +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 + +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 -r ./config/* ./user_projects/$(PROJ)/config + cp -r ./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 -r ./user_projects/$(PROJ)/config/* ./config/ + cp -r ./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_intracellular/spheroid_tnf/config/PhysiCell_settings.xml b/sample_projects_intracellular/spheroid_tnf/config/PhysiCell_settings.xml new file mode 100644 index 000000000..871584634 --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/config/PhysiCell_settings.xml @@ -0,0 +1,393 @@ + + + + + + + + -500 + 500 + -500 + 500 + -10 + 10 + 20 + 20 + 20 + true + + + + 2880 + min + micron + + 0.1 + 0.5 + 6 + + + + 16 + + + + output + + + 60 + true + + + + 60 + true + + + + false + + + + + false + true + false + 0 + + + + + + 300.0 + 0.01 + + 0.0 + 0.0 + + 13.0 + 13.0 + 13.0 + 13.0 + 0.0 + 0.0 + + + + true + true + + + ./config/initial.mat + + + + ./config/dirichlet.mat + + + + + + + + + + + + + + + + + 300.0 + 480 + 240 + 60 + + + + + + 0.0 + + + + 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.8 + 15.12 + + 4.0 + 10.0 + 0.01 + 0.0 + 0.0 + + + + 1 + 1 + .5 + + false + true + + false + TNF + -1 + + + false + false + + 0.0 + + + + + + + 0 + 0 + 0 + 0 + + + + + 0 + + 0 + + + 0 + + 1 + + 0 + + + + + 0 + + + + + + + + config/cellfate.bnd + config/cellfate.cfg + + 720 + 0.5 + 60 + 0.0 + + + + + + activation + 1 + 0 + + + + + activation + 1000000 + 0 + 0 + + + + + activation + 1000000 + 0 + 0 + + + + + + config/tnf_receptor.sbml + 0.1 + + + + + + + + + 0.0 + 0.0 + + + + + + + ./config + cells.csv + + + + + + + ./config + cell_rules.csv + + + + + + + + + diff --git a/sample_projects_intracellular/spheroid_tnf/config/cell_rules.csv b/sample_projects_intracellular/spheroid_tnf/config/cell_rules.csv new file mode 100644 index 000000000..078426a60 --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/config/cell_rules.csv @@ -0,0 +1 @@ +// \ No newline at end of file diff --git a/sample_projects_intracellular/spheroid_tnf/config/cellfate.bnd b/sample_projects_intracellular/spheroid_tnf/config/cellfate.bnd new file mode 100644 index 000000000..e6aa8b908 --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/config/cellfate.bnd @@ -0,0 +1,183 @@ +node FASL { + rate_up = 0; + rate_down = 0; +} + +node TNF { + logic = TNF; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node TNFR { + logic = TNF; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node FADD { + rate_up = 0; + rate_down = 0; +} + +node DISC_TNF { + logic = FADD AND TNFR; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node DISC_FAS { + logic = FASL AND FADD; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node CASP8 { + logic = (DISC_TNF OR (DISC_FAS OR CASP3)) AND (NOT cFLIP); + rate_up = ($Low_CASP8 ? 0 : (@logic ? 1 : 0)); + rate_down = ($Low_CASP8 ? 1e+100 : (@logic ? 0 : 1)); +} + +node RIP1 { + logic = (DISC_FAS OR TNFR) AND (NOT CASP8); + rate_up = ($Low_RIP1 ? 0 : (@logic ? 1 : 0)); + rate_down = ($Low_RIP1 ? 1e+100 : (@logic ? 0 : 1)); +} + +node cIAP { + logic = (mcIAP AND (NOT SMAC)); + rate_up = ($Low_cIAP ? 0 : (@logic ? $TransRate : 0)); + rate_down = ($Low_cIAP ? 1e+100 : ((SMAC) ? 1 : 0)); +} + +node RIP1ub { + logic = cIAP AND RIP1; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node RIP1K { + logic = RIP1; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node IKK { + logic = RIP1ub; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node CASP3 { + logic = apoptosome AND (NOT XIAP); + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node NFkB { + logic = IKK AND (NOT CASP3); + rate_up = ($High_NFkB ? 1e+100 : (@logic ? 1 : 0)); + rate_down = ($High_NFkB ? 0 : (@logic ? 0 : 1)); +} + +node cFLIP { + logic = NFkB; + rate_up = (@logic) ? $TransRate : 0; + rate_down = (@logic ? 0 : 1); +} + +node BCL2 { + logic = NFkB; + rate_up = (@logic ? $TransRate : 0); + rate_down = @logic ? 0 : 1; +} + +node BAX { + logic = CASP8 AND (NOT BCL2); + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node mROS { + logic = (NOT NFkB); + rate_up = @logic ? $TransRate : 0; + rate_down = @logic ? 0 : 1; +} + +node MPT { + logic = (NOT BCL2) AND ROS; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node ROS { + logic = (mROS) AND (MPT OR RIP1K); + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node ATP { + logic = NOT MPT; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node MOMP { + logic = BAX OR MPT; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node SMAC { + logic = MOMP; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node mcIAP { + logic = (NFkB); + rate_up = @logic ? $TransRate : 0; + rate_down = @logic ? 0 : 1; +} + +node Cyt_c { + logic = MOMP; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node mXIAP { + logic = (NFkB); + rate_up = @logic ? $TransRate : 0; + rate_down = @logic ? 0 : 1; +} + +node XIAP { + logic = (NOT SMAC) AND mXIAP; + rate_up = (@logic) ? 1 : 0; + rate_down = (@logic ? 0 : 1); +} + +node apoptosome { + logic = Cyt_c AND (ATP AND (NOT XIAP)); + rate_up = (@logic) ? 1 : 0; + rate_down = (@logic ? 0 : 1); +} + +node NonACD { + logic = NOT ATP; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node Apoptosis { + logic = CASP3; + rate_up = @logic ? 1 : 0; + rate_down = @logic ? 0 : 1; +} + +node Survival { + logic = NFkB; + rate_up = @logic ? $TransRate : 0; + rate_down = @logic ? 0 : 1; +} diff --git a/sample_projects_intracellular/spheroid_tnf/config/cellfate.cfg b/sample_projects_intracellular/spheroid_tnf/config/cellfate.cfg new file mode 100644 index 000000000..d7e737e15 --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/config/cellfate.cfg @@ -0,0 +1,117 @@ +// +// MaBoSS 2.0 configuration generated at Tue Jan 10 22:13:14 2023 +// + +time_tick = 0.01; +max_time = 1; +sample_count = 1; +discrete_time = 0; +use_physrandgen = 0; +seed_pseudorandom = 233814379; +display_traj = 0; +statdist_traj_count = 0; +statdist_cluster_threshold = 0.8; +thread_count = 8; +statdist_similarity_cache_max_size = 20000; + +$High_NFkB = 0; +$Low_CASP8 = 0; +$Low_RIP1 = 0; +$Low_cIAP = 0; +$TransRate = 1/24; + +FASL.is_internal = 1; +TNF.is_internal = 0; +TNFR.is_internal = 1; +FADD.is_internal = 1; +DISC_TNF.is_internal = 1; +DISC_FAS.is_internal = 1; +CASP8.is_internal = 1; +RIP1.is_internal = 1; +cIAP.is_internal = 1; +RIP1ub.is_internal = 1; +RIP1K.is_internal = 1; +IKK.is_internal = 1; +CASP3.is_internal = 1; +NFkB.is_internal = 1; +cFLIP.is_internal = 1; +BCL2.is_internal = 1; +BAX.is_internal = 1; +mROS.is_internal = 1; +MPT.is_internal = 1; +ROS.is_internal = 1; +ATP.is_internal = 1; +MOMP.is_internal = 1; +SMAC.is_internal = 1; +mcIAP.is_internal = 1; +Cyt_c.is_internal = 1; +mXIAP.is_internal = 1; +XIAP.is_internal = 1; +apoptosome.is_internal = 1; +NonACD.is_internal = 0; +Apoptosis.is_internal = 0; +Survival.is_internal = 0; + +FASL.refstate = -1; +TNF.refstate = -1; +TNFR.refstate = -1; +FADD.refstate = -1; +DISC_TNF.refstate = -1; +DISC_FAS.refstate = -1; +CASP8.refstate = -1; +RIP1.refstate = -1; +cIAP.refstate = -1; +RIP1ub.refstate = -1; +RIP1K.refstate = -1; +IKK.refstate = -1; +CASP3.refstate = -1; +NFkB.refstate = -1; +cFLIP.refstate = -1; +BCL2.refstate = -1; +BAX.refstate = -1; +mROS.refstate = -1; +MPT.refstate = -1; +ROS.refstate = -1; +ATP.refstate = -1; +MOMP.refstate = -1; +SMAC.refstate = -1; +mcIAP.refstate = -1; +Cyt_c.refstate = -1; +mXIAP.refstate = -1; +XIAP.refstate = -1; +apoptosome.refstate = -1; +NonACD.refstate = -1; +Apoptosis.refstate = -1; +Survival.refstate = -1; + +FADD.istate = 1; +TNF.istate = 0; +FASL.istate = 0; +NonACD.istate = 0; +Apoptosis.istate = 0; +Survival.istate = 0; +ATP.istate = 1; +cIAP.istate = 1; +TNFR.istate = 0; +DISC_TNF.istate = 0; +DISC_FAS.istate = 0; +RIP1.istate = 0; +RIP1ub.istate = 0; +RIP1K.istate = 0; +IKK.istate = 0; +NFkB.istate = 0; +CASP8.istate = 0; +BAX.istate = 0; +BCL2.istate = 0; +ROS.istate = 0; +mROS.istate = 0; +MPT.istate = 0; +MOMP.istate = 0; +SMAC.istate = 0; +mcIAP.istate = 0; +Cyt_c.istate = 0; +XIAP.istate = 0; +mXIAP.istate = 0; +apoptosome.istate = 0; +CASP3.istate = 0; +cFLIP.istate = 0; diff --git a/sample_projects_intracellular/spheroid_tnf/config/cells.csv b/sample_projects_intracellular/spheroid_tnf/config/cells.csv new file mode 100644 index 000000000..7a69d55d1 --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/config/cells.csv @@ -0,0 +1,800 @@ +x,y,z,type +-81.74578904091533,-235.42875790157268,0.0,default +-64.92036794500686,-235.42875790157268,0.0,default +-48.09494684909839,-235.42875790157268,0.0,default +-31.269525753189924,-235.42875790157268,0.0,default +-14.444104657281457,-235.42875790157268,0.0,default +2.3813164386270103,-235.42875790157268,0.0,default +19.206737534535478,-235.42875790157268,0.0,default +36.03215863044397,-235.42875790157268,0.0,default +52.85757972635241,-235.42875790157268,0.0,default +69.68300082226085,-235.42875790157268,0.0,default +-106.98392068477803,-220.85751580314536,0.0,default +-90.15849958886956,-220.85751580314536,0.0,default +-73.33307849296109,-220.85751580314536,0.0,default +-56.50765739705263,-220.85751580314536,0.0,default +-39.682236301144165,-220.85751580314536,0.0,default +-22.856815205235698,-220.85751580314536,0.0,default +-6.031394109327229,-220.85751580314536,0.0,default +10.794026986581239,-220.85751580314536,0.0,default +27.619448082489704,-220.85751580314536,0.0,default +44.4448691783982,-220.85751580314536,0.0,default +61.27029027430664,-220.85751580314536,0.0,default +78.09571137021508,-220.85751580314536,0.0,default +94.92113246612358,-220.85751580314536,0.0,default +111.74655356203208,-220.85751580314536,0.0,default +-132.22205232864073,-206.28627370471804,0.0,default +-115.39663123273226,-206.28627370471804,0.0,default +-98.5712101368238,-206.28627370471804,0.0,default +-81.74578904091533,-206.28627370471804,0.0,default +-64.92036794500686,-206.28627370471804,0.0,default +-48.09494684909839,-206.28627370471804,0.0,default +-31.269525753189924,-206.28627370471804,0.0,default +-14.444104657281457,-206.28627370471804,0.0,default +2.3813164386270103,-206.28627370471804,0.0,default +19.206737534535478,-206.28627370471804,0.0,default +36.03215863044397,-206.28627370471804,0.0,default +52.85757972635241,-206.28627370471804,0.0,default +69.68300082226085,-206.28627370471804,0.0,default +86.50842191816935,-206.28627370471804,0.0,default +103.33384301407784,-206.28627370471804,0.0,default +120.15926410998628,-206.28627370471804,0.0,default +136.98468520589472,-206.28627370471804,0.0,default +-157.46018397250344,-191.71503160629072,0.0,default +-140.63476287659498,-191.71503160629072,0.0,default +-123.8093417806865,-191.71503160629072,0.0,default +-106.98392068477803,-191.71503160629072,0.0,default +-90.15849958886956,-191.71503160629072,0.0,default +-73.33307849296109,-191.71503160629072,0.0,default +-56.50765739705263,-191.71503160629072,0.0,default +-39.682236301144165,-191.71503160629072,0.0,default +-22.856815205235698,-191.71503160629072,0.0,default +-6.031394109327229,-191.71503160629072,0.0,default +10.794026986581239,-191.71503160629072,0.0,default +27.619448082489704,-191.71503160629072,0.0,default +44.4448691783982,-191.71503160629072,0.0,default +61.27029027430664,-191.71503160629072,0.0,default +78.09571137021508,-191.71503160629072,0.0,default +94.92113246612358,-191.71503160629072,0.0,default +111.74655356203208,-191.71503160629072,0.0,default +128.5719746579405,-191.71503160629072,0.0,default +145.39739575384894,-191.71503160629072,0.0,default +-165.87289452045766,-177.1437895078634,0.0,default +-149.0474734245492,-177.1437895078634,0.0,default +-132.22205232864073,-177.1437895078634,0.0,default +-115.39663123273226,-177.1437895078634,0.0,default +-98.5712101368238,-177.1437895078634,0.0,default +-81.74578904091533,-177.1437895078634,0.0,default +-64.92036794500686,-177.1437895078634,0.0,default +-48.09494684909839,-177.1437895078634,0.0,default +-31.269525753189924,-177.1437895078634,0.0,default +-14.444104657281457,-177.1437895078634,0.0,default +2.3813164386270103,-177.1437895078634,0.0,default +19.206737534535478,-177.1437895078634,0.0,default +36.03215863044397,-177.1437895078634,0.0,default +52.85757972635241,-177.1437895078634,0.0,default +69.68300082226085,-177.1437895078634,0.0,default +86.50842191816935,-177.1437895078634,0.0,default +103.33384301407784,-177.1437895078634,0.0,default +120.15926410998628,-177.1437895078634,0.0,default +136.98468520589472,-177.1437895078634,0.0,default +153.81010630180322,-177.1437895078634,0.0,default +170.6355273977117,-177.1437895078634,0.0,default +-174.2856050684119,-162.57254740943608,0.0,default +-157.46018397250344,-162.57254740943608,0.0,default +-140.63476287659498,-162.57254740943608,0.0,default +-123.8093417806865,-162.57254740943608,0.0,default +-106.98392068477803,-162.57254740943608,0.0,default +-90.15849958886956,-162.57254740943608,0.0,default +-73.33307849296109,-162.57254740943608,0.0,default +-56.50765739705263,-162.57254740943608,0.0,default +-39.682236301144165,-162.57254740943608,0.0,default +-22.856815205235698,-162.57254740943608,0.0,default +-6.031394109327229,-162.57254740943608,0.0,default +10.794026986581239,-162.57254740943608,0.0,default +27.619448082489704,-162.57254740943608,0.0,default +44.4448691783982,-162.57254740943608,0.0,default +61.27029027430664,-162.57254740943608,0.0,default +78.09571137021508,-162.57254740943608,0.0,default +94.92113246612358,-162.57254740943608,0.0,default +111.74655356203208,-162.57254740943608,0.0,default +128.5719746579405,-162.57254740943608,0.0,default +145.39739575384894,-162.57254740943608,0.0,default +162.22281684975744,-162.57254740943608,0.0,default +179.04823794566593,-162.57254740943608,0.0,default +-199.5237367122746,-148.00130531100876,0.0,default +-182.69831561636613,-148.00130531100876,0.0,default +-165.87289452045766,-148.00130531100876,0.0,default +-149.0474734245492,-148.00130531100876,0.0,default +-132.22205232864073,-148.00130531100876,0.0,default +-115.39663123273226,-148.00130531100876,0.0,default +-98.5712101368238,-148.00130531100876,0.0,default +-81.74578904091533,-148.00130531100876,0.0,default +-64.92036794500686,-148.00130531100876,0.0,default +-48.09494684909839,-148.00130531100876,0.0,default +-31.269525753189924,-148.00130531100876,0.0,default +-14.444104657281457,-148.00130531100876,0.0,default +2.3813164386270103,-148.00130531100876,0.0,default +19.206737534535478,-148.00130531100876,0.0,default +36.03215863044397,-148.00130531100876,0.0,default +52.85757972635241,-148.00130531100876,0.0,default +69.68300082226085,-148.00130531100876,0.0,default +86.50842191816935,-148.00130531100876,0.0,default +103.33384301407784,-148.00130531100876,0.0,default +120.15926410998628,-148.00130531100876,0.0,default +136.98468520589472,-148.00130531100876,0.0,default +153.81010630180322,-148.00130531100876,0.0,default +170.6355273977117,-148.00130531100876,0.0,default +187.46094849362015,-148.00130531100876,0.0,default +-207.93644726022885,-133.43006321258144,0.0,default +-191.11102616432038,-133.43006321258144,0.0,default +-174.2856050684119,-133.43006321258144,0.0,default +-157.46018397250344,-133.43006321258144,0.0,default +-140.63476287659498,-133.43006321258144,0.0,default +-123.8093417806865,-133.43006321258144,0.0,default +-106.98392068477803,-133.43006321258144,0.0,default +-90.15849958886956,-133.43006321258144,0.0,default +-73.33307849296109,-133.43006321258144,0.0,default +-56.50765739705263,-133.43006321258144,0.0,default +-39.682236301144165,-133.43006321258144,0.0,default +-22.856815205235698,-133.43006321258144,0.0,default +-6.031394109327229,-133.43006321258144,0.0,default +10.794026986581239,-133.43006321258144,0.0,default +27.619448082489704,-133.43006321258144,0.0,default +44.4448691783982,-133.43006321258144,0.0,default +61.27029027430664,-133.43006321258144,0.0,default +78.09571137021508,-133.43006321258144,0.0,default +94.92113246612358,-133.43006321258144,0.0,default +111.74655356203208,-133.43006321258144,0.0,default +128.5719746579405,-133.43006321258144,0.0,default +145.39739575384894,-133.43006321258144,0.0,default +162.22281684975744,-133.43006321258144,0.0,default +179.04823794566593,-133.43006321258144,0.0,default +195.87365904157437,-133.43006321258144,0.0,default +-216.34915780818307,-118.85882111415413,0.0,default +-199.5237367122746,-118.85882111415413,0.0,default +-182.69831561636613,-118.85882111415413,0.0,default +-165.87289452045766,-118.85882111415413,0.0,default +-149.0474734245492,-118.85882111415413,0.0,default +-132.22205232864073,-118.85882111415413,0.0,default +-115.39663123273226,-118.85882111415413,0.0,default +-98.5712101368238,-118.85882111415413,0.0,default +-81.74578904091533,-118.85882111415413,0.0,default +-64.92036794500686,-118.85882111415413,0.0,default +-48.09494684909839,-118.85882111415413,0.0,default +-31.269525753189924,-118.85882111415413,0.0,default +-14.444104657281457,-118.85882111415413,0.0,default +2.3813164386270103,-118.85882111415413,0.0,default +19.206737534535478,-118.85882111415413,0.0,default +36.03215863044397,-118.85882111415413,0.0,default +52.85757972635241,-118.85882111415413,0.0,default +69.68300082226085,-118.85882111415413,0.0,default +86.50842191816935,-118.85882111415413,0.0,default +103.33384301407784,-118.85882111415413,0.0,default +120.15926410998628,-118.85882111415413,0.0,default +136.98468520589472,-118.85882111415413,0.0,default +153.81010630180322,-118.85882111415413,0.0,default +170.6355273977117,-118.85882111415413,0.0,default +187.46094849362015,-118.85882111415413,0.0,default +204.2863695895286,-118.85882111415413,0.0,default +-224.7618683561373,-104.2875790157268,0.0,default +-207.93644726022885,-104.2875790157268,0.0,default +-191.11102616432038,-104.2875790157268,0.0,default +-174.2856050684119,-104.2875790157268,0.0,default +-157.46018397250344,-104.2875790157268,0.0,default +-140.63476287659498,-104.2875790157268,0.0,default +-123.8093417806865,-104.2875790157268,0.0,default +-106.98392068477803,-104.2875790157268,0.0,default +-90.15849958886956,-104.2875790157268,0.0,default +-73.33307849296109,-104.2875790157268,0.0,default +-56.50765739705263,-104.2875790157268,0.0,default +-39.682236301144165,-104.2875790157268,0.0,default +-22.856815205235698,-104.2875790157268,0.0,default +-6.031394109327229,-104.2875790157268,0.0,default +10.794026986581239,-104.2875790157268,0.0,default +27.619448082489704,-104.2875790157268,0.0,default +44.4448691783982,-104.2875790157268,0.0,default +61.27029027430664,-104.2875790157268,0.0,default +78.09571137021508,-104.2875790157268,0.0,default +94.92113246612358,-104.2875790157268,0.0,default +111.74655356203208,-104.2875790157268,0.0,default +128.5719746579405,-104.2875790157268,0.0,default +145.39739575384894,-104.2875790157268,0.0,default +162.22281684975744,-104.2875790157268,0.0,default +179.04823794566593,-104.2875790157268,0.0,default +195.87365904157437,-104.2875790157268,0.0,default +212.6990801374828,-104.2875790157268,0.0,default +-233.17457890409153,-89.71633691729949,0.0,default +-216.34915780818307,-89.71633691729949,0.0,default +-199.5237367122746,-89.71633691729949,0.0,default +-182.69831561636613,-89.71633691729949,0.0,default +-165.87289452045766,-89.71633691729949,0.0,default +-149.0474734245492,-89.71633691729949,0.0,default +-132.22205232864073,-89.71633691729949,0.0,default +-115.39663123273226,-89.71633691729949,0.0,default +-98.5712101368238,-89.71633691729949,0.0,default +-81.74578904091533,-89.71633691729949,0.0,default +-64.92036794500686,-89.71633691729949,0.0,default +-48.09494684909839,-89.71633691729949,0.0,default +-31.269525753189924,-89.71633691729949,0.0,default +-14.444104657281457,-89.71633691729949,0.0,default +2.3813164386270103,-89.71633691729949,0.0,default +19.206737534535478,-89.71633691729949,0.0,default +36.03215863044397,-89.71633691729949,0.0,default +52.85757972635241,-89.71633691729949,0.0,default +69.68300082226085,-89.71633691729949,0.0,default +86.50842191816935,-89.71633691729949,0.0,default +103.33384301407784,-89.71633691729949,0.0,default +120.15926410998628,-89.71633691729949,0.0,default +136.98468520589472,-89.71633691729949,0.0,default +153.81010630180322,-89.71633691729949,0.0,default +170.6355273977117,-89.71633691729949,0.0,default +187.46094849362015,-89.71633691729949,0.0,default +204.2863695895286,-89.71633691729949,0.0,default +221.1117906854371,-89.71633691729949,0.0,default +-224.7618683561373,-75.14509481887217,0.0,default +-207.93644726022885,-75.14509481887217,0.0,default +-191.11102616432038,-75.14509481887217,0.0,default +-174.2856050684119,-75.14509481887217,0.0,default +-157.46018397250344,-75.14509481887217,0.0,default +-140.63476287659498,-75.14509481887217,0.0,default +-123.8093417806865,-75.14509481887217,0.0,default +-106.98392068477803,-75.14509481887217,0.0,default +-90.15849958886956,-75.14509481887217,0.0,default +-73.33307849296109,-75.14509481887217,0.0,default +-56.50765739705263,-75.14509481887217,0.0,default +-39.682236301144165,-75.14509481887217,0.0,default +-22.856815205235698,-75.14509481887217,0.0,default +-6.031394109327229,-75.14509481887217,0.0,default +10.794026986581239,-75.14509481887217,0.0,default +27.619448082489704,-75.14509481887217,0.0,default +44.4448691783982,-75.14509481887217,0.0,default +61.27029027430664,-75.14509481887217,0.0,default +78.09571137021508,-75.14509481887217,0.0,default +94.92113246612358,-75.14509481887217,0.0,default +111.74655356203208,-75.14509481887217,0.0,default +128.5719746579405,-75.14509481887217,0.0,default +145.39739575384894,-75.14509481887217,0.0,default +162.22281684975744,-75.14509481887217,0.0,default +179.04823794566593,-75.14509481887217,0.0,default +195.87365904157437,-75.14509481887217,0.0,default +212.6990801374828,-75.14509481887217,0.0,default +229.5245012333913,-75.14509481887217,0.0,default +-233.17457890409153,-60.57385272044485,0.0,default +-216.34915780818307,-60.57385272044485,0.0,default +-199.5237367122746,-60.57385272044485,0.0,default +-182.69831561636613,-60.57385272044485,0.0,default +-165.87289452045766,-60.57385272044485,0.0,default +-149.0474734245492,-60.57385272044485,0.0,default +-132.22205232864073,-60.57385272044485,0.0,default +-115.39663123273226,-60.57385272044485,0.0,default +-98.5712101368238,-60.57385272044485,0.0,default +-81.74578904091533,-60.57385272044485,0.0,default +-64.92036794500686,-60.57385272044485,0.0,default +-48.09494684909839,-60.57385272044485,0.0,default +-31.269525753189924,-60.57385272044485,0.0,default +-14.444104657281457,-60.57385272044485,0.0,default +2.3813164386270103,-60.57385272044485,0.0,default +19.206737534535478,-60.57385272044485,0.0,default +36.03215863044397,-60.57385272044485,0.0,default +52.85757972635241,-60.57385272044485,0.0,default +69.68300082226085,-60.57385272044485,0.0,default +86.50842191816935,-60.57385272044485,0.0,default +103.33384301407784,-60.57385272044485,0.0,default +120.15926410998628,-60.57385272044485,0.0,default +136.98468520589472,-60.57385272044485,0.0,default +153.81010630180322,-60.57385272044485,0.0,default +170.6355273977117,-60.57385272044485,0.0,default +187.46094849362015,-60.57385272044485,0.0,default +204.2863695895286,-60.57385272044485,0.0,default +221.1117906854371,-60.57385272044485,0.0,default +237.93721178134558,-60.57385272044485,0.0,default +-241.58728945204578,-46.00261062201753,0.0,default +-224.7618683561373,-46.00261062201753,0.0,default +-207.93644726022885,-46.00261062201753,0.0,default +-191.11102616432038,-46.00261062201753,0.0,default +-174.2856050684119,-46.00261062201753,0.0,default +-157.46018397250344,-46.00261062201753,0.0,default +-140.63476287659498,-46.00261062201753,0.0,default +-123.8093417806865,-46.00261062201753,0.0,default +-106.98392068477803,-46.00261062201753,0.0,default +-90.15849958886956,-46.00261062201753,0.0,default +-73.33307849296109,-46.00261062201753,0.0,default +-56.50765739705263,-46.00261062201753,0.0,default +-39.682236301144165,-46.00261062201753,0.0,default +-22.856815205235698,-46.00261062201753,0.0,default +-6.031394109327229,-46.00261062201753,0.0,default +10.794026986581239,-46.00261062201753,0.0,default +27.619448082489704,-46.00261062201753,0.0,default +44.4448691783982,-46.00261062201753,0.0,default +61.27029027430664,-46.00261062201753,0.0,default +78.09571137021508,-46.00261062201753,0.0,default +94.92113246612358,-46.00261062201753,0.0,default +111.74655356203208,-46.00261062201753,0.0,default +128.5719746579405,-46.00261062201753,0.0,default +145.39739575384894,-46.00261062201753,0.0,default +162.22281684975744,-46.00261062201753,0.0,default +179.04823794566593,-46.00261062201753,0.0,default +195.87365904157437,-46.00261062201753,0.0,default +212.6990801374828,-46.00261062201753,0.0,default +229.5245012333913,-46.00261062201753,0.0,default +-233.17457890409153,-31.43136852359021,0.0,default +-216.34915780818307,-31.43136852359021,0.0,default +-199.5237367122746,-31.43136852359021,0.0,default +-182.69831561636613,-31.43136852359021,0.0,default +-165.87289452045766,-31.43136852359021,0.0,default +-149.0474734245492,-31.43136852359021,0.0,default +-132.22205232864073,-31.43136852359021,0.0,default +-115.39663123273226,-31.43136852359021,0.0,default +-98.5712101368238,-31.43136852359021,0.0,default +-81.74578904091533,-31.43136852359021,0.0,default +-64.92036794500686,-31.43136852359021,0.0,default +-48.09494684909839,-31.43136852359021,0.0,default +-31.269525753189924,-31.43136852359021,0.0,default +-14.444104657281457,-31.43136852359021,0.0,default +2.3813164386270103,-31.43136852359021,0.0,default +19.206737534535478,-31.43136852359021,0.0,default +36.03215863044397,-31.43136852359021,0.0,default +52.85757972635241,-31.43136852359021,0.0,default +69.68300082226085,-31.43136852359021,0.0,default +86.50842191816935,-31.43136852359021,0.0,default +103.33384301407784,-31.43136852359021,0.0,default +120.15926410998628,-31.43136852359021,0.0,default +136.98468520589472,-31.43136852359021,0.0,default +153.81010630180322,-31.43136852359021,0.0,default +170.6355273977117,-31.43136852359021,0.0,default +187.46094849362015,-31.43136852359021,0.0,default +204.2863695895286,-31.43136852359021,0.0,default +221.1117906854371,-31.43136852359021,0.0,default +237.93721178134558,-31.43136852359021,0.0,default +-241.58728945204578,-16.86012642516289,0.0,default +-224.7618683561373,-16.86012642516289,0.0,default +-207.93644726022885,-16.86012642516289,0.0,default +-191.11102616432038,-16.86012642516289,0.0,default +-174.2856050684119,-16.86012642516289,0.0,default +-157.46018397250344,-16.86012642516289,0.0,default +-140.63476287659498,-16.86012642516289,0.0,default +-123.8093417806865,-16.86012642516289,0.0,default +-106.98392068477803,-16.86012642516289,0.0,default +-90.15849958886956,-16.86012642516289,0.0,default +-73.33307849296109,-16.86012642516289,0.0,default +-56.50765739705263,-16.86012642516289,0.0,default +-39.682236301144165,-16.86012642516289,0.0,default +-22.856815205235698,-16.86012642516289,0.0,default +-6.031394109327229,-16.86012642516289,0.0,default +10.794026986581239,-16.86012642516289,0.0,default +27.619448082489704,-16.86012642516289,0.0,default +44.4448691783982,-16.86012642516289,0.0,default +61.27029027430664,-16.86012642516289,0.0,default +78.09571137021508,-16.86012642516289,0.0,default +94.92113246612358,-16.86012642516289,0.0,default +111.74655356203208,-16.86012642516289,0.0,default +128.5719746579405,-16.86012642516289,0.0,default +145.39739575384894,-16.86012642516289,0.0,default +162.22281684975744,-16.86012642516289,0.0,default +179.04823794566593,-16.86012642516289,0.0,default +195.87365904157437,-16.86012642516289,0.0,default +212.6990801374828,-16.86012642516289,0.0,default +229.5245012333913,-16.86012642516289,0.0,default +246.3499223292998,-16.86012642516289,0.0,default +-233.17457890409153,-2.2888843267355696,0.0,default +-216.34915780818307,-2.2888843267355696,0.0,default +-199.5237367122746,-2.2888843267355696,0.0,default +-182.69831561636613,-2.2888843267355696,0.0,default +-165.87289452045766,-2.2888843267355696,0.0,default +-149.0474734245492,-2.2888843267355696,0.0,default +-132.22205232864073,-2.2888843267355696,0.0,default +-115.39663123273226,-2.2888843267355696,0.0,default +-98.5712101368238,-2.2888843267355696,0.0,default +-81.74578904091533,-2.2888843267355696,0.0,default +-64.92036794500686,-2.2888843267355696,0.0,default +-48.09494684909839,-2.2888843267355696,0.0,default +-31.269525753189924,-2.2888843267355696,0.0,default +-14.444104657281457,-2.2888843267355696,0.0,default +2.3813164386270103,-2.2888843267355696,0.0,default +19.206737534535478,-2.2888843267355696,0.0,default +36.03215863044397,-2.2888843267355696,0.0,default +52.85757972635241,-2.2888843267355696,0.0,default +69.68300082226085,-2.2888843267355696,0.0,default +86.50842191816935,-2.2888843267355696,0.0,default +103.33384301407784,-2.2888843267355696,0.0,default +120.15926410998628,-2.2888843267355696,0.0,default +136.98468520589472,-2.2888843267355696,0.0,default +153.81010630180322,-2.2888843267355696,0.0,default +170.6355273977117,-2.2888843267355696,0.0,default +187.46094849362015,-2.2888843267355696,0.0,default +204.2863695895286,-2.2888843267355696,0.0,default +221.1117906854371,-2.2888843267355696,0.0,default +237.93721178134558,-2.2888843267355696,0.0,default +-241.58728945204578,12.28235777169175,0.0,default +-224.7618683561373,12.28235777169175,0.0,default +-207.93644726022885,12.28235777169175,0.0,default +-191.11102616432038,12.28235777169175,0.0,default +-174.2856050684119,12.28235777169175,0.0,default +-157.46018397250344,12.28235777169175,0.0,default +-140.63476287659498,12.28235777169175,0.0,default +-123.8093417806865,12.28235777169175,0.0,default +-106.98392068477803,12.28235777169175,0.0,default +-90.15849958886956,12.28235777169175,0.0,default +-73.33307849296109,12.28235777169175,0.0,default +-56.50765739705263,12.28235777169175,0.0,default +-39.682236301144165,12.28235777169175,0.0,default +-22.856815205235698,12.28235777169175,0.0,default +-6.031394109327229,12.28235777169175,0.0,default +10.794026986581239,12.28235777169175,0.0,default +27.619448082489704,12.28235777169175,0.0,default +44.4448691783982,12.28235777169175,0.0,default +61.27029027430664,12.28235777169175,0.0,default +78.09571137021508,12.28235777169175,0.0,default +94.92113246612358,12.28235777169175,0.0,default +111.74655356203208,12.28235777169175,0.0,default +128.5719746579405,12.28235777169175,0.0,default +145.39739575384894,12.28235777169175,0.0,default +162.22281684975744,12.28235777169175,0.0,default +179.04823794566593,12.28235777169175,0.0,default +195.87365904157437,12.28235777169175,0.0,default +212.6990801374828,12.28235777169175,0.0,default +229.5245012333913,12.28235777169175,0.0,default +246.3499223292998,12.28235777169175,0.0,default +-233.17457890409153,26.85359987011907,0.0,default +-216.34915780818307,26.85359987011907,0.0,default +-199.5237367122746,26.85359987011907,0.0,default +-182.69831561636613,26.85359987011907,0.0,default +-165.87289452045766,26.85359987011907,0.0,default +-149.0474734245492,26.85359987011907,0.0,default +-132.22205232864073,26.85359987011907,0.0,default +-115.39663123273226,26.85359987011907,0.0,default +-98.5712101368238,26.85359987011907,0.0,default +-81.74578904091533,26.85359987011907,0.0,default +-64.92036794500686,26.85359987011907,0.0,default +-48.09494684909839,26.85359987011907,0.0,default +-31.269525753189924,26.85359987011907,0.0,default +-14.444104657281457,26.85359987011907,0.0,default +2.3813164386270103,26.85359987011907,0.0,default +19.206737534535478,26.85359987011907,0.0,default +36.03215863044397,26.85359987011907,0.0,default +52.85757972635241,26.85359987011907,0.0,default +69.68300082226085,26.85359987011907,0.0,default +86.50842191816935,26.85359987011907,0.0,default +103.33384301407784,26.85359987011907,0.0,default +120.15926410998628,26.85359987011907,0.0,default +136.98468520589472,26.85359987011907,0.0,default +153.81010630180322,26.85359987011907,0.0,default +170.6355273977117,26.85359987011907,0.0,default +187.46094849362015,26.85359987011907,0.0,default +204.2863695895286,26.85359987011907,0.0,default +221.1117906854371,26.85359987011907,0.0,default +237.93721178134558,26.85359987011907,0.0,default +-241.58728945204578,41.42484196854639,0.0,default +-224.7618683561373,41.42484196854639,0.0,default +-207.93644726022885,41.42484196854639,0.0,default +-191.11102616432038,41.42484196854639,0.0,default +-174.2856050684119,41.42484196854639,0.0,default +-157.46018397250344,41.42484196854639,0.0,default +-140.63476287659498,41.42484196854639,0.0,default +-123.8093417806865,41.42484196854639,0.0,default +-106.98392068477803,41.42484196854639,0.0,default +-90.15849958886956,41.42484196854639,0.0,default +-73.33307849296109,41.42484196854639,0.0,default +-56.50765739705263,41.42484196854639,0.0,default +-39.682236301144165,41.42484196854639,0.0,default +-22.856815205235698,41.42484196854639,0.0,default +-6.031394109327229,41.42484196854639,0.0,default +10.794026986581239,41.42484196854639,0.0,default +27.619448082489704,41.42484196854639,0.0,default +44.4448691783982,41.42484196854639,0.0,default +61.27029027430664,41.42484196854639,0.0,default +78.09571137021508,41.42484196854639,0.0,default +94.92113246612358,41.42484196854639,0.0,default +111.74655356203208,41.42484196854639,0.0,default +128.5719746579405,41.42484196854639,0.0,default +145.39739575384894,41.42484196854639,0.0,default +162.22281684975744,41.42484196854639,0.0,default +179.04823794566593,41.42484196854639,0.0,default +195.87365904157437,41.42484196854639,0.0,default +212.6990801374828,41.42484196854639,0.0,default +229.5245012333913,41.42484196854639,0.0,default +246.3499223292998,41.42484196854639,0.0,default +-233.17457890409153,55.99608406697371,0.0,default +-216.34915780818307,55.99608406697371,0.0,default +-199.5237367122746,55.99608406697371,0.0,default +-182.69831561636613,55.99608406697371,0.0,default +-165.87289452045766,55.99608406697371,0.0,default +-149.0474734245492,55.99608406697371,0.0,default +-132.22205232864073,55.99608406697371,0.0,default +-115.39663123273226,55.99608406697371,0.0,default +-98.5712101368238,55.99608406697371,0.0,default +-81.74578904091533,55.99608406697371,0.0,default +-64.92036794500686,55.99608406697371,0.0,default +-48.09494684909839,55.99608406697371,0.0,default +-31.269525753189924,55.99608406697371,0.0,default +-14.444104657281457,55.99608406697371,0.0,default +2.3813164386270103,55.99608406697371,0.0,default +19.206737534535478,55.99608406697371,0.0,default +36.03215863044397,55.99608406697371,0.0,default +52.85757972635241,55.99608406697371,0.0,default +69.68300082226085,55.99608406697371,0.0,default +86.50842191816935,55.99608406697371,0.0,default +103.33384301407784,55.99608406697371,0.0,default +120.15926410998628,55.99608406697371,0.0,default +136.98468520589472,55.99608406697371,0.0,default +153.81010630180322,55.99608406697371,0.0,default +170.6355273977117,55.99608406697371,0.0,default +187.46094849362015,55.99608406697371,0.0,default +204.2863695895286,55.99608406697371,0.0,default +221.1117906854371,55.99608406697371,0.0,default +237.93721178134558,55.99608406697371,0.0,default +-224.7618683561373,70.56732616540103,0.0,default +-207.93644726022885,70.56732616540103,0.0,default +-191.11102616432038,70.56732616540103,0.0,default +-174.2856050684119,70.56732616540103,0.0,default +-157.46018397250344,70.56732616540103,0.0,default +-140.63476287659498,70.56732616540103,0.0,default +-123.8093417806865,70.56732616540103,0.0,default +-106.98392068477803,70.56732616540103,0.0,default +-90.15849958886956,70.56732616540103,0.0,default +-73.33307849296109,70.56732616540103,0.0,default +-56.50765739705263,70.56732616540103,0.0,default +-39.682236301144165,70.56732616540103,0.0,default +-22.856815205235698,70.56732616540103,0.0,default +-6.031394109327229,70.56732616540103,0.0,default +10.794026986581239,70.56732616540103,0.0,default +27.619448082489704,70.56732616540103,0.0,default +44.4448691783982,70.56732616540103,0.0,default +61.27029027430664,70.56732616540103,0.0,default +78.09571137021508,70.56732616540103,0.0,default +94.92113246612358,70.56732616540103,0.0,default +111.74655356203208,70.56732616540103,0.0,default +128.5719746579405,70.56732616540103,0.0,default +145.39739575384894,70.56732616540103,0.0,default +162.22281684975744,70.56732616540103,0.0,default +179.04823794566593,70.56732616540103,0.0,default +195.87365904157437,70.56732616540103,0.0,default +212.6990801374828,70.56732616540103,0.0,default +229.5245012333913,70.56732616540103,0.0,default +-233.17457890409153,85.13856826382835,0.0,default +-216.34915780818307,85.13856826382835,0.0,default +-199.5237367122746,85.13856826382835,0.0,default +-182.69831561636613,85.13856826382835,0.0,default +-165.87289452045766,85.13856826382835,0.0,default +-149.0474734245492,85.13856826382835,0.0,default +-132.22205232864073,85.13856826382835,0.0,default +-115.39663123273226,85.13856826382835,0.0,default +-98.5712101368238,85.13856826382835,0.0,default +-81.74578904091533,85.13856826382835,0.0,default +-64.92036794500686,85.13856826382835,0.0,default +-48.09494684909839,85.13856826382835,0.0,default +-31.269525753189924,85.13856826382835,0.0,default +-14.444104657281457,85.13856826382835,0.0,default +2.3813164386270103,85.13856826382835,0.0,default +19.206737534535478,85.13856826382835,0.0,default +36.03215863044397,85.13856826382835,0.0,default +52.85757972635241,85.13856826382835,0.0,default +69.68300082226085,85.13856826382835,0.0,default +86.50842191816935,85.13856826382835,0.0,default +103.33384301407784,85.13856826382835,0.0,default +120.15926410998628,85.13856826382835,0.0,default +136.98468520589472,85.13856826382835,0.0,default +153.81010630180322,85.13856826382835,0.0,default +170.6355273977117,85.13856826382835,0.0,default +187.46094849362015,85.13856826382835,0.0,default +204.2863695895286,85.13856826382835,0.0,default +221.1117906854371,85.13856826382835,0.0,default +-224.7618683561373,99.70981036225567,0.0,default +-207.93644726022885,99.70981036225567,0.0,default +-191.11102616432038,99.70981036225567,0.0,default +-174.2856050684119,99.70981036225567,0.0,default +-157.46018397250344,99.70981036225567,0.0,default +-140.63476287659498,99.70981036225567,0.0,default +-123.8093417806865,99.70981036225567,0.0,default +-106.98392068477803,99.70981036225567,0.0,default +-90.15849958886956,99.70981036225567,0.0,default +-73.33307849296109,99.70981036225567,0.0,default +-56.50765739705263,99.70981036225567,0.0,default +-39.682236301144165,99.70981036225567,0.0,default +-22.856815205235698,99.70981036225567,0.0,default +-6.031394109327229,99.70981036225567,0.0,default +10.794026986581239,99.70981036225567,0.0,default +27.619448082489704,99.70981036225567,0.0,default +44.4448691783982,99.70981036225567,0.0,default +61.27029027430664,99.70981036225567,0.0,default +78.09571137021508,99.70981036225567,0.0,default +94.92113246612358,99.70981036225567,0.0,default +111.74655356203208,99.70981036225567,0.0,default +128.5719746579405,99.70981036225567,0.0,default +145.39739575384894,99.70981036225567,0.0,default +162.22281684975744,99.70981036225567,0.0,default +179.04823794566593,99.70981036225567,0.0,default +195.87365904157437,99.70981036225567,0.0,default +212.6990801374828,99.70981036225567,0.0,default +-216.34915780818307,114.28105246068299,0.0,default +-199.5237367122746,114.28105246068299,0.0,default +-182.69831561636613,114.28105246068299,0.0,default +-165.87289452045766,114.28105246068299,0.0,default +-149.0474734245492,114.28105246068299,0.0,default +-132.22205232864073,114.28105246068299,0.0,default +-115.39663123273226,114.28105246068299,0.0,default +-98.5712101368238,114.28105246068299,0.0,default +-81.74578904091533,114.28105246068299,0.0,default +-64.92036794500686,114.28105246068299,0.0,default +-48.09494684909839,114.28105246068299,0.0,default +-31.269525753189924,114.28105246068299,0.0,default +-14.444104657281457,114.28105246068299,0.0,default +2.3813164386270103,114.28105246068299,0.0,default +19.206737534535478,114.28105246068299,0.0,default +36.03215863044397,114.28105246068299,0.0,default +52.85757972635241,114.28105246068299,0.0,default +69.68300082226085,114.28105246068299,0.0,default +86.50842191816935,114.28105246068299,0.0,default +103.33384301407784,114.28105246068299,0.0,default +120.15926410998628,114.28105246068299,0.0,default +136.98468520589472,114.28105246068299,0.0,default +153.81010630180322,114.28105246068299,0.0,default +170.6355273977117,114.28105246068299,0.0,default +187.46094849362015,114.28105246068299,0.0,default +204.2863695895286,114.28105246068299,0.0,default +221.1117906854371,114.28105246068299,0.0,default +-207.93644726022885,128.8522945591103,0.0,default +-191.11102616432038,128.8522945591103,0.0,default +-174.2856050684119,128.8522945591103,0.0,default +-157.46018397250344,128.8522945591103,0.0,default +-140.63476287659498,128.8522945591103,0.0,default +-123.8093417806865,128.8522945591103,0.0,default +-106.98392068477803,128.8522945591103,0.0,default +-90.15849958886956,128.8522945591103,0.0,default +-73.33307849296109,128.8522945591103,0.0,default +-56.50765739705263,128.8522945591103,0.0,default +-39.682236301144165,128.8522945591103,0.0,default +-22.856815205235698,128.8522945591103,0.0,default +-6.031394109327229,128.8522945591103,0.0,default +10.794026986581239,128.8522945591103,0.0,default +27.619448082489704,128.8522945591103,0.0,default +44.4448691783982,128.8522945591103,0.0,default +61.27029027430664,128.8522945591103,0.0,default +78.09571137021508,128.8522945591103,0.0,default +94.92113246612358,128.8522945591103,0.0,default +111.74655356203208,128.8522945591103,0.0,default +128.5719746579405,128.8522945591103,0.0,default +145.39739575384894,128.8522945591103,0.0,default +162.22281684975744,128.8522945591103,0.0,default +179.04823794566593,128.8522945591103,0.0,default +195.87365904157437,128.8522945591103,0.0,default +212.6990801374828,128.8522945591103,0.0,default +-199.5237367122746,143.42353665753762,0.0,default +-182.69831561636613,143.42353665753762,0.0,default +-165.87289452045766,143.42353665753762,0.0,default +-149.0474734245492,143.42353665753762,0.0,default +-132.22205232864073,143.42353665753762,0.0,default +-115.39663123273226,143.42353665753762,0.0,default +-98.5712101368238,143.42353665753762,0.0,default +-81.74578904091533,143.42353665753762,0.0,default +-64.92036794500686,143.42353665753762,0.0,default +-48.09494684909839,143.42353665753762,0.0,default +-31.269525753189924,143.42353665753762,0.0,default +-14.444104657281457,143.42353665753762,0.0,default +2.3813164386270103,143.42353665753762,0.0,default +19.206737534535478,143.42353665753762,0.0,default +36.03215863044397,143.42353665753762,0.0,default +52.85757972635241,143.42353665753762,0.0,default +69.68300082226085,143.42353665753762,0.0,default +86.50842191816935,143.42353665753762,0.0,default +103.33384301407784,143.42353665753762,0.0,default +120.15926410998628,143.42353665753762,0.0,default +136.98468520589472,143.42353665753762,0.0,default +153.81010630180322,143.42353665753762,0.0,default +170.6355273977117,143.42353665753762,0.0,default +187.46094849362015,143.42353665753762,0.0,default +204.2863695895286,143.42353665753762,0.0,default +-191.11102616432038,157.99477875596494,0.0,default +-174.2856050684119,157.99477875596494,0.0,default +-157.46018397250344,157.99477875596494,0.0,default +-140.63476287659498,157.99477875596494,0.0,default +-123.8093417806865,157.99477875596494,0.0,default +-106.98392068477803,157.99477875596494,0.0,default +-90.15849958886956,157.99477875596494,0.0,default +-73.33307849296109,157.99477875596494,0.0,default +-56.50765739705263,157.99477875596494,0.0,default +-39.682236301144165,157.99477875596494,0.0,default +-22.856815205235698,157.99477875596494,0.0,default +-6.031394109327229,157.99477875596494,0.0,default +10.794026986581239,157.99477875596494,0.0,default +27.619448082489704,157.99477875596494,0.0,default +44.4448691783982,157.99477875596494,0.0,default +61.27029027430664,157.99477875596494,0.0,default +78.09571137021508,157.99477875596494,0.0,default +94.92113246612358,157.99477875596494,0.0,default +111.74655356203208,157.99477875596494,0.0,default +128.5719746579405,157.99477875596494,0.0,default +145.39739575384894,157.99477875596494,0.0,default +162.22281684975744,157.99477875596494,0.0,default +179.04823794566593,157.99477875596494,0.0,default +-165.87289452045766,172.56602085439226,0.0,default +-149.0474734245492,172.56602085439226,0.0,default +-132.22205232864073,172.56602085439226,0.0,default +-115.39663123273226,172.56602085439226,0.0,default +-98.5712101368238,172.56602085439226,0.0,default +-81.74578904091533,172.56602085439226,0.0,default +-64.92036794500686,172.56602085439226,0.0,default +-48.09494684909839,172.56602085439226,0.0,default +-31.269525753189924,172.56602085439226,0.0,default +-14.444104657281457,172.56602085439226,0.0,default +2.3813164386270103,172.56602085439226,0.0,default +19.206737534535478,172.56602085439226,0.0,default +36.03215863044397,172.56602085439226,0.0,default +52.85757972635241,172.56602085439226,0.0,default +69.68300082226085,172.56602085439226,0.0,default +86.50842191816935,172.56602085439226,0.0,default +103.33384301407784,172.56602085439226,0.0,default +120.15926410998628,172.56602085439226,0.0,default +136.98468520589472,172.56602085439226,0.0,default +153.81010630180322,172.56602085439226,0.0,default +170.6355273977117,172.56602085439226,0.0,default +-157.46018397250344,187.13726295281958,0.0,default +-140.63476287659498,187.13726295281958,0.0,default +-123.8093417806865,187.13726295281958,0.0,default +-106.98392068477803,187.13726295281958,0.0,default +-90.15849958886956,187.13726295281958,0.0,default +-73.33307849296109,187.13726295281958,0.0,default +-56.50765739705263,187.13726295281958,0.0,default +-39.682236301144165,187.13726295281958,0.0,default +-22.856815205235698,187.13726295281958,0.0,default +-6.031394109327229,187.13726295281958,0.0,default +10.794026986581239,187.13726295281958,0.0,default +27.619448082489704,187.13726295281958,0.0,default +44.4448691783982,187.13726295281958,0.0,default +61.27029027430664,187.13726295281958,0.0,default +78.09571137021508,187.13726295281958,0.0,default +94.92113246612358,187.13726295281958,0.0,default +111.74655356203208,187.13726295281958,0.0,default +128.5719746579405,187.13726295281958,0.0,default +145.39739575384894,187.13726295281958,0.0,default +162.22281684975744,187.13726295281958,0.0,default +-132.22205232864073,201.7085050512469,0.0,default +-115.39663123273226,201.7085050512469,0.0,default +-98.5712101368238,201.7085050512469,0.0,default +-81.74578904091533,201.7085050512469,0.0,default +-64.92036794500686,201.7085050512469,0.0,default +-48.09494684909839,201.7085050512469,0.0,default +-31.269525753189924,201.7085050512469,0.0,default +-14.444104657281457,201.7085050512469,0.0,default +2.3813164386270103,201.7085050512469,0.0,default +19.206737534535478,201.7085050512469,0.0,default +36.03215863044397,201.7085050512469,0.0,default +52.85757972635241,201.7085050512469,0.0,default +69.68300082226085,201.7085050512469,0.0,default +86.50842191816935,201.7085050512469,0.0,default +103.33384301407784,201.7085050512469,0.0,default +120.15926410998628,201.7085050512469,0.0,default +136.98468520589472,201.7085050512469,0.0,default +-123.8093417806865,216.27974714967422,0.0,default +-106.98392068477803,216.27974714967422,0.0,default +-90.15849958886956,216.27974714967422,0.0,default +-73.33307849296109,216.27974714967422,0.0,default +-56.50765739705263,216.27974714967422,0.0,default +-39.682236301144165,216.27974714967422,0.0,default +-22.856815205235698,216.27974714967422,0.0,default +-6.031394109327229,216.27974714967422,0.0,default +10.794026986581239,216.27974714967422,0.0,default +27.619448082489704,216.27974714967422,0.0,default +44.4448691783982,216.27974714967422,0.0,default +61.27029027430664,216.27974714967422,0.0,default +78.09571137021508,216.27974714967422,0.0,default +94.92113246612358,216.27974714967422,0.0,default +111.74655356203208,216.27974714967422,0.0,default +-81.74578904091533,230.85098924810154,0.0,default +-64.92036794500686,230.85098924810154,0.0,default +-48.09494684909839,230.85098924810154,0.0,default +-31.269525753189924,230.85098924810154,0.0,default +-14.444104657281457,230.85098924810154,0.0,default +2.3813164386270103,230.85098924810154,0.0,default +19.206737534535478,230.85098924810154,0.0,default +36.03215863044397,230.85098924810154,0.0,default +52.85757972635241,230.85098924810154,0.0,default +69.68300082226085,230.85098924810154,0.0,default +86.50842191816935,230.85098924810154,0.0,default +-39.682236301144165,245.42223134652886,0.0,default +-22.856815205235698,245.42223134652886,0.0,default +-6.031394109327229,245.42223134652886,0.0,default +10.794026986581239,245.42223134652886,0.0,default +27.619448082489704,245.42223134652886,0.0,default +44.4448691783982,245.42223134652886,0.0,default diff --git a/sample_projects_intracellular/spheroid_tnf/config/cells_test.csv b/sample_projects_intracellular/spheroid_tnf/config/cells_test.csv new file mode 100644 index 000000000..482156ebe --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/config/cells_test.csv @@ -0,0 +1,2 @@ +x,y,z,type +0.0,0.0,0.0,default diff --git a/sample_projects_intracellular/spheroid_tnf/config/tnf_receptor.sbml b/sample_projects_intracellular/spheroid_tnf/config/tnf_receptor.sbml new file mode 100644 index 000000000..1a4087e8d --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/config/tnf_receptor.sbml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + unbound_external_tnfr + tnfr_endocytosis_rate + + + + bound_internal_tnfr + tnfr_recycling_rate + + + + + + + + + + + + + + + + + + unbound_external_tnfr + tnfr_endocytosis_rate + + + + + + + + + + + + + + + + bound_external_tnfr + tnfr_endocytosis_rate + + + + + + + + + + + + + + + + bound_internal_tnfr + tnfr_recycling_rate + + + + + + + diff --git a/sample_projects_intracellular/spheroid_tnf/custom_modules/custom.cpp b/sample_projects_intracellular/spheroid_tnf/custom_modules/custom.cpp new file mode 100644 index 000000000..b34638f57 --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/custom_modules/custom.cpp @@ -0,0 +1,233 @@ +/* +############################################################################### +# 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" + +void create_cell_types( void ) +{ + // set the random seed + if (parameters.ints.find_index("random_seed") != -1) + { + SeedRandom(parameters.ints("random_seed")); + } + + /* + 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. + */ + + 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; + + /* + This parses the cell definitions in the XML config file. + */ + + initialize_cell_definitions_from_pugixml(); + + /* + This builds the map of cell definitions and summarizes the setup. + */ + + build_cell_definitions_maps(); + + /* + This intializes cell signal and response dictionaries + */ + + setup_signal_behavior_dictionaries(); + + /* + 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; + + PhysiCell::Cell_Definition* pCD = PhysiCell::cell_definitions_by_index[0]; + + pCD->phenotype.intracellulars[0]->pre_update_intracellular = pre_update_boolean_intracellular; + pCD->phenotype.intracellulars[0]->post_update_intracellular = post_update_boolean_intracellular; + pCD->phenotype.intracellulars[1]->pre_update_intracellular = pre_update_ode_intracellular; + pCD->phenotype.intracellulars[1]->post_update_intracellular = post_update_ode_intracellular; + + /* + This builds the map of cell definitions and summarizes the 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 ) +{ + // load cells from your CSV file (if enabled) + load_cells_from_pugixml(); + + return; +} + +void pre_update_boolean_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ) +{ + +} + +void post_update_boolean_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ) +{ +} + +void pre_update_ode_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ) +{ +} + +void post_update_ode_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ) +{ +} + + + +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; } + +void treatment_function () +{ + if (PhysiCell::parameters.bools.find_index("treatment") != -1) + { + int treatment_substrate_index = BioFVM::microenvironment.find_density_index(PhysiCell::parameters.strings("treatment_substrate")); + + if (PhysiCell::parameters.bools("treatment")){ + + if ( + (((int)PhysiCell::PhysiCell_globals.current_time) % PhysiCell::parameters.ints("treatment_period")) == 0 + && !BioFVM::microenvironment.get_substrate_dirichlet_activation(treatment_substrate_index) + ) + { + std::cout << PhysiCell::parameters.strings("treatment_substrate") << " activation at t=" << PhysiCell::PhysiCell_globals.current_time << std::endl; + BioFVM::microenvironment.set_substrate_dirichlet_activation(treatment_substrate_index, true); + } + + if ( + (((int)PhysiCell::PhysiCell_globals.current_time) % PhysiCell::parameters.ints("treatment_period")) == PhysiCell::parameters.ints("treatment_duration") + && BioFVM::microenvironment.get_substrate_dirichlet_activation(treatment_substrate_index) + ) + { + std::cout << PhysiCell::parameters.strings("treatment_substrate") << " inactivation at t=" << PhysiCell::PhysiCell_globals.current_time << std::endl; + BioFVM::microenvironment.set_substrate_dirichlet_activation(treatment_substrate_index, false); + } + + } else if ( BioFVM::microenvironment.get_substrate_dirichlet_activation(treatment_substrate_index) ){ + std::cout << PhysiCell::parameters.strings("treatment_substrate") << " inactivation (NO TREATMENT) at t=" << PhysiCell::PhysiCell_globals.current_time << std::endl; + BioFVM::microenvironment.set_substrate_dirichlet_activation(treatment_substrate_index, false); + } + } +} \ No newline at end of file diff --git a/sample_projects_intracellular/spheroid_tnf/custom_modules/custom.h b/sample_projects_intracellular/spheroid_tnf/custom_modules/custom.h new file mode 100644 index 000000000..661f15e4c --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/custom_modules/custom.h @@ -0,0 +1,98 @@ +/* +############################################################################### +# 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 pre_update_boolean_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); +void post_update_boolean_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); +void pre_update_ode_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); +void post_update_ode_intracellular( Cell* pCell, Phenotype& phenotype, Intracellular* intracellular, double dt ); + +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 ); + +void treatment_function (); \ No newline at end of file diff --git a/sample_projects_intracellular/spheroid_tnf/main.cpp b/sample_projects_intracellular/spheroid_tnf/main.cpp new file mode 100644 index 000000000..01ca86ace --- /dev/null +++ b/sample_projects_intracellular/spheroid_tnf/main.cpp @@ -0,0 +1,259 @@ +/* +############################################################################### +# 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. # +# # +############################################################################### +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "./core/PhysiCell.h" +#include "./modules/PhysiCell_standard_modules.h" + +// put custom code modules here! + +#include "./custom_modules/custom.h" +#include "./addons/PhysiBoSS/src/maboss_intracellular.h" + +using namespace BioFVM; +using namespace PhysiCell; + +int main( int argc, char* argv[] ) +{ + // load and parse settings file(s) + + bool XML_status = false; + char copy_command [1024]; + if( argc > 1 ) + { + XML_status = load_PhysiCell_config_file( argv[1] ); + sprintf( copy_command , "cp %s %s/PhysiCell_settings.xml" , argv[1] , PhysiCell_settings.folder.c_str() ); + } + else + { + XML_status = load_PhysiCell_config_file( "./config/PhysiCell_settings.xml" ); + sprintf( copy_command , "cp ./config/PhysiCell_settings.xml %s" , PhysiCell_settings.folder.c_str() ); + } + if( !XML_status ) + { exit(-1); } + + // copy config file to output directry + system( copy_command ); + + // OpenMP setup + omp_set_num_threads(PhysiCell_settings.omp_num_threads); + + // time setup + std::string time_units = "min"; + + /* Microenvironment setup */ + + setup_microenvironment(); // modify this in the custom code + + /* PhysiCell setup */ + + // set mechanics voxel size, and match the data structure to BioFVM + double mechanics_voxel_size = 30; + Cell_Container* cell_container = create_cell_container_for_microenvironment( microenvironment, mechanics_voxel_size ); + + /* Users typically start modifying here. START USERMODS */ + + create_cell_types(); + + setup_tissue(); + + /* Users typically stop modifying here. END USERMODS */ + + // 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 ); + + // save a simulation snapshot + + char filename[1024]; + sprintf( filename , "%s/initial" , PhysiCell_settings.folder.c_str() ); + save_PhysiCell_to_MultiCellDS_v2( filename , microenvironment , PhysiCell_globals.current_time ); + + // save a quick SVG cross section through z = 0, after setting its + // length bar to 200 microns + + PhysiCell_SVG_options.length_bar = 200; + + // for simplicity, set a pathology coloring function + + std::vector (*cell_coloring_function)(Cell*) = my_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 ); + + sprintf( filename , "%s/legend.svg" , PhysiCell_settings.folder.c_str() ); + create_plot_legend( filename , cell_coloring_function ); + + add_software_citation( "PhysiBoSS" , PhysiBoSS_Version , PhysiBoSS_DOI, PhysiBoSS_URL); + + display_citations(); + + // set the performance timers + + BioFVM::RUNTIME_TIC(); + BioFVM::TIC(); + + std::ofstream report_file; + 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"< PhysiCell_globals.next_full_save_time - 0.5 * diffusion_dt ) + { + display_simulation_status( std::cout ); + if( PhysiCell_settings.enable_legacy_saves == true ) + { + log_output( PhysiCell_globals.current_time , PhysiCell_globals.full_output_index, microenvironment, report_file); + } + + 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 ); + } + + PhysiCell_globals.full_output_index++; + PhysiCell_globals.next_full_save_time += PhysiCell_settings.full_save_interval; + } + + // save SVG plot if it's time + if( PhysiCell_globals.current_time > PhysiCell_globals.next_SVG_save_time - 0.5 * diffusion_dt ) + { + 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 ); + + PhysiCell_globals.SVG_output_index++; + PhysiCell_globals.next_SVG_save_time += PhysiCell_settings.SVG_save_interval; + } + } + + // Configure treatments + treatment_function(); + + // update the microenvironment + microenvironment.simulate_diffusion_decay( diffusion_dt ); + + // run PhysiCell + ((Cell_Container *)microenvironment.agent_container)->update_all_cells( PhysiCell_globals.current_time ); + + /* + Custom add-ons could potentially go here. + */ + + PhysiCell_globals.current_time += diffusion_dt; + } + + if( PhysiCell_settings.enable_legacy_saves == true ) + { + log_output(PhysiCell_globals.current_time, PhysiCell_globals.full_output_index, microenvironment, report_file); + report_file.close(); + } + } + catch( const std::exception& e ) + { // reference to the base of a polymorphic object + std::cout << e.what(); // information from length_error printed + } + + // save a final simulation snapshot + + sprintf( filename , "%s/final" , PhysiCell_settings.folder.c_str() ); + save_PhysiCell_to_MultiCellDS_v2( filename , microenvironment , PhysiCell_globals.current_time ); + + sprintf( filename , "%s/final.svg" , PhysiCell_settings.folder.c_str() ); + SVG_plot( filename , microenvironment, 0.0 , PhysiCell_globals.current_time, cell_coloring_function ); + + // timer + + std::cout << std::endl << "Total simulation runtime: " << std::endl; + BioFVM::display_stopwatch_value( std::cout , BioFVM::runtime_stopwatch_value() ); + + return 0; +} diff --git a/sample_projects_intracellular/spheroid_tnf/scripts/empty.txt b/sample_projects_intracellular/spheroid_tnf/scripts/empty.txt new file mode 100644 index 000000000..e69de29bb