diff --git a/BioFVM/BioFVM_vector.cpp b/BioFVM/BioFVM_vector.cpp index c6a49c4d8..533d4aa0c 100644 --- a/BioFVM/BioFVM_vector.cpp +++ b/BioFVM/BioFVM_vector.cpp @@ -185,6 +185,20 @@ std::ostream& operator<<(std::ostream& os, const std::vector& v ) return os; } +std::ostream& operator<<(std::ostream& os, const std::vector& v ) +{ + for( unsigned int i=0; i < v.size(); i++ ) + { os << v[i] << " " ; } + return os; +} + +std::ostream& operator<<(std::ostream& os, const std::vector& v ) +{ + for( unsigned int i=0; i < v.size(); i++ ) + { os << v[i] << " " ; } + return os; +} + // this one returns a new vector that has been normalized std::vector normalize( std::vector& v ) { diff --git a/BioFVM/BioFVM_vector.h b/BioFVM/BioFVM_vector.h index 2acf8eb34..228577046 100644 --- a/BioFVM/BioFVM_vector.h +++ b/BioFVM/BioFVM_vector.h @@ -80,6 +80,8 @@ void operator/=( std::vector& v1, const double& a ); /* other commonly needed operations on vectors */ std::ostream& operator<<(std::ostream& os, const std::vector& v ); +std::ostream& operator<<(std::ostream& os, const std::vector& v ); +std::ostream& operator<<(std::ostream& os, const std::vector& v ); // this one returns a new vector that has been normalized std::vector normalize( std::vector& v ); diff --git a/CITATION.txt b/CITATION.txt index bddd3bd65..fcc60673e 100644 --- a/CITATION.txt +++ b/CITATION.txt @@ -1,7 +1,7 @@ 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 1.10.1) [1]. +We implemented and solved the model using PhysiCell (Version 1.10.2) [1]. [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, PhysiCell: an Open Source Physics-Based Cell Simulator for Multicellu- @@ -11,7 +11,7 @@ We implemented and solved the model using PhysiCell (Version 1.10.1) [1]. Because PhysiCell extensively uses BioFVM, we suggest you also cite BioFVM as below: -We implemented and solved the model using PhysiCell (Version 1.10.1) [1], +We implemented and solved the model using PhysiCell (Version 1.10.2) [1], with BioFVM [2] to solve the transport equations. [1] A Ghaffarizadeh, R Heiland, SH Friedman, SM Mumenthaler, and P Macklin, diff --git a/README.md b/README.md index 28b25556a..dbf72a2b5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # PhysiCell: an Open Source Physics-Based Cell Simulator for 3-D Multicellular Systems -**Version:** 1.10.1 +**Version:** 1.10.2 -**Release date:** 15 May 2022 +**Release date:** 24 May 2022 ## Overview: PhysiCell is a flexible open source framework for building agent-based multicellular models in 3-D tissue environments. @@ -24,20 +24,20 @@ Visit http://MathCancer.org/blog for the latest tutorials and help. **make \[project-name\]**: populates the indicated sample project. Use "make" to compile it. - \[project-name\] choices: - template - biorobots-sample - cancer-biorobots-sample - cancer-immune-sample - celltypes3-sample - heterogeneity-sample - pred-prey-farmer - virus-macrophage-sample - worm-sample - ode-energy-sample - physiboss-cell-lines-sample - cancer-metabolism-sample - interaction-sample + * **\[project-name\]** choices: + * template + * biorobots-sample + * cancer-biorobots-sample + * cancer-immune-sample + * celltypes3-sample + * heterogeneity-sample + * pred-prey-farmer + * virus-macrophage-sample + * worm-sample + * ode-energy-sample + * physiboss-cell-lines-sample + * cancer-metabolism-sample + * interaction-sample **make list-projects** : list all available sample projects @@ -71,21 +71,21 @@ See changes.md for the full change log. * * * ## Release summary: - -Version 1.10.1 introduces bugfixes to increase XML parser robustness and to fix missing PhysiBoSS makefiles. +Version 1.10.2 introduces bugfixes to the behavior "dictionary" functiouns, data saves, and updating neighbor lists for nearby non-adhesive cells. It also introduces a number of ease-of-access functions to the phenotype for death rates, secretion, and internalized substrates. The 1.10.0 release introduced major new phenotype functionality, including standardized support for cell-cell interactions (phagocytosis, cell attack that increases a tracked damage variable, and cell fusion), cell transformations, advanced chemotaxis, and cell adhesion affinities for preferential adhesion. This release also includes new, auto-generated "dictionaries" of signals and behaviors to facilitate writing cell behavioral models and intracellular models, as well as standardized Hill and linear response functions for use in intracellular models. Lastly, this release includes a number of bugfixes, most notably pseudorandom number generators with improved thread safety. A blog post and tutorial on the new phenotype elements can be found at http://www.mathcancer.org/blog/introducing-cell-interactions-and-transformations. -A blog post and tutorial on the new signal and behavior dictionaries can be found at http://www.mathcancer.org/blog/introducing-cell-signal-and-behavior-dictionaries. - +A blog post and tutorial on the new signal and behavior dictionaries can be found at http://www.mathcancer.org/blog/introducing-cell-signal-and-behavior-dictionaries. **NOTE 1:** MacOS users need to define a PHYSICELL_CPP environment variable to specify their OpenMP-enabled g++. See the [Quickstart](documentation/Quickstart.md) for details. **NOTE 2:** Windows users need to follow an updated (from v1.8) MinGW64 installation procedure. This will install an updated version of g++, plus libraries that are needed for some of the intracellular models. See the [Quickstart](documentation/Quickstart.md) for details. ### Major new features and changes in the 1.10.z versions +#### 1.10.2 ++ None in this version. See 1.10.0 #### 1.10.1 + None in this version. See 1.10.0 #### 1.10.0 @@ -193,9 +193,28 @@ A blog post and tutorial on the new signal and behavior dictionaries can be foun + With default parameters, bacteria kill off cells ot form abscesses, until death attracts macrophages to activate immune response to kill the invaders, after which the tissue can regrow. ### Minor new features and changes: +#### 1.10.2 ++ Added `operator<<` for vectors of ints and vectors of strings. So that `std::cout << v << std::endl;` will work if `v` is `std::vector` of `std::vector`. It was truly annoying that these were missing, so sorry! ++ Added `dead` to the signals dictionaries, which returns 0.0 or 1.0 based on `phenotype.death.dead`. ++ Added `time` to the signals dictionaries, which returns the current simulation time based on `PhysiCell_Globals.current_time`. ++ Added a brief protocol on how to add new signals and behaviors to the dictionaries in the `/protocols` directory. ++ Added new functions `double& apoptosis_rate()` and `double& necrosis_rate()` to easily read and write these rates. Access via `cell.phenotype.death.apoptosis_rate()` and `cell.phenotype.death.necrosis_rate()`. ++ Added new ease of access functions for secretion: + + `double& Secretion::secretion_rate( std::string name )` allows you to easily read/write the secretion rate of a substrate by name. For example: + ```pCell->phenotype.secretion.secretion_rate("oxygen") = 0.1``` + + `double& Secretion::uptake_rate( std::string name )` allows you to easily read/write the uptake rate of a substrate by name. For example: + ```pCell->phenotype.secretion.uptake_rate("oxygen") = 0.1``` + + `double& Secretion::saturation_density( std::string name )` allows you to easily read/write the secretion target of a substrate by name. For example: + ```pCell->phenotype.secretion.saturation_density("oxygen") = 38``` + + `double& Secretion::net_export_rate( std::string name )` allows you to easily read/write the net export rate of a substrate by name. For example: + ```pCell->phenotype.secretion.net_export_rate("oxygen") = -100``` + ++ Added new ease of access function for internalized substrates: + + `double& Molecular::internalized_total_substrate( std::string name )` allows you to easily read/write the total amount of internalized substrate by name. For example: + ```pCell->phenotype.molecular.internalized_total_substrate( "oxygen" ) = 0.01`` + #### 1.10.1 + None in this version. See 1.10.0. - #### 1.10.0 + All sample projects have a new rule "make name" to tell you the name of the executable. @@ -206,9 +225,10 @@ A blog post and tutorial on the new signal and behavior dictionaries can be foun + `create_cell( Cell_Definition )` now uses "`is_movable`" from the cell definition. ### Beta features (not fully supported): - #### 1.10.1 +#### 1.10.2 ++ None in this version. See 1.10.0. +#### 1.10.1 + None in this version. See 1.10.0. - #### 1.10.0 + Started writing a standardized set of functions for Hill functions and promoter/inhibitor signaling. @@ -221,6 +241,15 @@ A blog post and tutorial on the new signal and behavior dictionaries can be foun + Added simple contour plotting of a substrate (anim_substrate2D.py in /beta; copy to /output) ### Bugfixes: +#### 1.10.2 ++ Fixed error in `double get_single_behavior()` where the `cell-cell adhesion elastic constant` behavior was not found. + ++ Fixed error in `double get_single_base_behavior()` where the `cell-cell adhesion elastic constant` behavior was not found. + ++ Fixed bug in `add_PhysiCell_cells_to_open_xml_pugi()` that mistakenly used the wrong size (number of cell species rather than number of substrate species) when writing the chemotactic sensitivities. + ++ The cell `neighbors` list did not add non-adhesive cells within interaction distance. This is now fixed. + #### 1.10.1 + XML parsing has been made more robust to "survive" using an incorrect substrate in the `chemotactic_sensitivities` section. diff --git a/VERSION.txt b/VERSION.txt index e33692ab6..70ad429ec 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.10.1 \ No newline at end of file +1.10.2 \ No newline at end of file diff --git a/changes.md b/changes.md index 9c94f4272..288db1e70 100644 --- a/changes.md +++ b/changes.md @@ -1,8 +1,8 @@ # PhysiCell: an Open Source Physics-Based Cell Simulator for 3-D Multicellular Systems -**Version:** 1.10.1 +**Version:** 1.10.2 -**Release date:** 15 May 2022 +**Release date:** 24 May 2022 ## Overview: PhysiCell is a flexible open source framework for building agent-based multicellular models in 3-D tissue environments. @@ -24,20 +24,20 @@ Visit http://MathCancer.org/blog for the latest tutorials and help. **make \[project-name\]**: populates the indicated sample project. Use "make" to compile it. - \[project-name\] choices: - template - biorobots-sample - cancer-biorobots-sample - cancer-immune-sample - celltypes3-sample - heterogeneity-sample - pred-prey-farmer - virus-macrophage-sample - worm-sample - ode-energy-sample - physiboss-cell-lines-sample - cancer-metabolism-sample - interaction-sample + * **\[project-name\]** choices: + * template + * biorobots-sample + * cancer-biorobots-sample + * cancer-immune-sample + * celltypes3-sample + * heterogeneity-sample + * pred-prey-farmer + * virus-macrophage-sample + * worm-sample + * ode-energy-sample + * physiboss-cell-lines-sample + * cancer-metabolism-sample + * interaction-sample **make list-projects** : list all available sample projects @@ -70,6 +70,239 @@ Visit http://MathCancer.org/blog for the latest tutorials and help. See changes.md for the full change log. * * * +## Release summary: +Version 1.10.2 introduces bugfixes to the behavior "dictionary" functiouns, data saves, and updating neighbor lists for nearby non-adhesive cells. It also introduces a number of ease-of-access functions to the phenotype for death rates, secretion, and internalized substrates. + +The 1.10.0 release introduced major new phenotype functionality, including standardized support for cell-cell interactions (phagocytosis, cell attack that increases a tracked damage variable, and cell fusion), cell transformations, advanced chemotaxis, and cell adhesion affinities for preferential adhesion. This release also includes new, auto-generated "dictionaries" of signals and behaviors to facilitate writing cell behavioral models and intracellular models, as well as standardized Hill and linear response functions for use in intracellular models. Lastly, this release includes a number of bugfixes, most notably pseudorandom number generators with improved thread safety. + +A blog post and tutorial on the new phenotype elements can be found at http://www.mathcancer.org/blog/introducing-cell-interactions-and-transformations. + +A blog post and tutorial on the new signal and behavior dictionaries can be found at http://www.mathcancer.org/blog/introducing-cell-signal-and-behavior-dictionaries. + +**NOTE 1:** MacOS users need to define a PHYSICELL_CPP environment variable to specify their OpenMP-enabled g++. See the [Quickstart](documentation/Quickstart.md) for details. + +**NOTE 2:** Windows users need to follow an updated (from v1.8) MinGW64 installation procedure. This will install an updated version of g++, plus libraries that are needed for some of the intracellular models. See the [Quickstart](documentation/Quickstart.md) for details. + +### Major new features and changes in the 1.10.z versions +#### 1.10.2 ++ None in this version. See 1.10.0 +#### 1.10.1 ++ None in this version. See 1.10.0 +#### 1.10.0 ++ Created `Cell_Interactions` in `Phenotype` as a standard representation of essential cell-cell interactions, including phagocytosis, "attack", and fusion. + + Users can set phagocytosis rates for dead cells via `phenotype.cell_interactions.dead_phagocytosis_rate`. Cells automatically phagocytose live and dead neighbors at each mechancis time step based upon the phagocytosis rates. + + Users can set phagocytosis rates for each live cell type via `phenotype.cell_interactions.live_phagocytosis_rates`. There is one rate for each cell type in the simulation. Cells automatically phagocytose live and dead neighbors at each mechancis time step based upon the phagocytosis rates. Phagocytosis absorbs the target cell's volume and internal contents and flags the target for removal. The cell will eventually shrink back towards its target volume. + + For convenience, the phagocytosis rates can be accessed (read or written) via `phenotype.cell_interactions.live_phagocytosis_rate(name)` where `name` (a `std::string`) is the human-readable name of a cell type. + + Users can set attack rates for live cells via `phenotype.cell_interactions.attack_rates`. There is one rate for each cell type in the simulation. Cells automaticaly attack neighbors at each mechanics time step based upon the rates. An attack event increases the target cell's `cell.state.damage` by `damage_rate * dt_mechanics` and `cell.state.total_attack_time` by `dt_mechanics`. It is up to the scientist user to set additional hypotheses that increases cell death with accumulated damage or attack time. + + For convenience, the attack rates can be accessed via `phenotype.cell_interactions.attack_rate(name)` where `name` (a `std::string`) is the human-readable name of a cell type. + + Users can set fusion rates for live cells via `phenotype.cell_interactions.fusion_rates`. There is one rate for each cell type in the simulation. Cells automaticaly fuse with at each mechanics time step based upon the rates. Fusion will merge the two cells' volumes and internal contents, add their nuclei (recorded in `cell.state.number_of_nuclei`), and move the combine cell to the prior center of volume. The combined cell's new target volume is the sum of the two original cells' target volumes. + + For convenience, the fusion rates can be accessed via `phenotype.cell_interactions.fusion_rate(name)` where `name` (a `std::string`) is the human-readable name of a cell type. + ++ Created `Cell_Transformations` in `Phenotype` as a standard representation of cell transformations such as differentation or transdifferentiation. + + Users can set transformation rates for each live cell type via `phenotype.cell_transformations_transformation_rates`. There is one rate for each cell type in the simulation. Cells automatically attempt to transform to these types at each phenotype time step based upon the phagocytosis rates. + + For convenience, the transformation rates can be accessed (read or written) via `phenotype.cell_transformations.transformation_rate(name)` where `name` (a `std::string`) is the human-readable name of a cell type. + ++ Updated `Cell_State` to track the number of nuclei (for fusion), total damage (e.g., for cell attack) and total attack time. + ++ Added a new `advanced_chemotaxis` function with data stored in `phenotype.motility` to allow chemotaxis up a linear combination of gradients. + + `cell.phenotype.motility.chemotactic_sensitivities` is a vector of chemotactic sensitivies, one for each substrate in the environment. By default, these are all zero for backwards compatibility. A positive sensitivity denotes chemotaxis up a corresponding substrate's gradient (towards higher values), whereas a negative sensitivity gives chemotaxis against a gradient (towards lower values). + + For convenience, you can access (read and write) a substrate's chemotactic sensitivity via `phenotype.motility.chemotactic_sensitivity(name)`, where `name` is the human-readable name of a substrate in the simulation. + + If the user sets `cell.cell_functions.update_migration_bias = advanced_chemotaxis_function`, then these sensitivities are used to set the migration bias direction via `d_mot = sensitivity_0 * grad(rho_0) + sensitivity_1 * grad(rho_1) + ... + sensitivity_n * grad(rho_n)`. + + If the user sets `cell.cell_functions.update_migration_bias = advanced_chemotaxis_function_normalized`, then these sensitivities are used to set the migration bias direction via `d_mot = sensitivity_0 * |grad(rho_0)| + sensitivity_1 * |grad(rho_1)| + ... + sensitivity_n * |grad(rho_n)|.` + ++ Added a new `adhesion_affinities` to `phenotype.mechanics` to allow preferential adhesion. + + `cell.phenotype.mechanics.adhesion_affinities` is a vector of adhesive affinities, one for each cell type in the simulation. By default, these are all one for backwards compatibility. + + For convenience, you can access (read and write) a cell's adhesive affinity for a specific cell type via `phenotype.mechanics.adhesive_affinity(name)`, where `name` is the human-readable name of a cell type in the simulation. + + The standard mechanics function (based on potentials) uses this as follows. If cell `i` has an cell-cell adhesion strength `a_i` and an adhesive affinity `p_ij` to cell type `j` , and if cell `j` has a cell-cell adhesion strength of `a_j` and an adhesive affinity `p_ji` to cell type `i`, then the strength of their adhesion is `sqrt( a_i p_ij a_j p_ji )`. Notice that if `a_i = a_j` and `p_ij = p_ji`, then this reduces to `a_i a_pj`. + + The standard elastic spring function (`standard_elastic_contact_function`) uses this as follows. If cell `i` has an elastic constant `a_i` and an adhesive affinity `p_ij` to cell type `j` , and if cell `j` has an elastic constant `a_j` and an adhesive affinity `p_ji` to cell type `i`, then the strength of their adhesion is `sqrt( a_i p_ij a_j p_ji )`. Notice that if `a_i = a_j` and `p_ij = p_ji`, then this reduces to `a_i a_pj`. + ++ `PhysiCell_basic_signaling` now includes standard Hill and linear response functions: + + `Hill_response_function( double s, double half_max , double hill_power )` is a Hill function responding to signal `s` with a half-max of `half_max` and Hill coefficient of `hill_power`. We note that this function is an order of magnitude faster when the `hill_power` is an integer (e.g., 1 or 2) rather than a non-integer power (e.g., 1.4). + + `double linear_response_function( double s, double s_min , double s_max )` is a linear ramping from 0.0 (for inputs `s` below `s_min`) to 1.0 (for inputs `s` above `s_max`). The outputs are clamped to the range [0,1]. + + `double decreasing_linear_response_function( double s, double s_min , double s_max )` is a linear ramping from 1.0 (for inputs `s` below `s_min`) to 0.0 (for inputs `s` above `s_max`). The outputs are clamped to the range [0,1]. + ++ We introduced a "dictionary" of standard signals that can be used as inputs to intracellular and rule-based models. This dictionary is automatically constructed at the start of each simulation based upon the combinations of signaling substrates and cell types. + + Major classes of signals include: + + extracellular and intracellular substrate concentrations + + substrate gradients + + contact with dead cells + + contact with cells (of type X) + + damage + + pressure + + Use `display_signal_dictionary()` to quickly display a list of available signals. + + Substantial functionality to query signals + + `int find_signal_index( std::string signal_name )` : get the index of the named signal + + `std::vector find_signal_indices( std::vector signal_names );` get a vector of indices for a vector of named signals + + `std::string signal_name( int i );` display the name of the signal with the given index + + `std::vector get_signals( Cell* pCell );` get a vector of all known signals for the cell + + `std::vector get_cell_contact_signals( Cell* pCell );` get a vector of the cell contact associated signals for the cell + + `std::vector get_selected_signals( Cell* pCell , std::vector indices );` get a vector of signals for the cell, with the supplied indices + + `std::vector get_selected_signals( Cell* pCell , std::vector names );` get a vector of signals for the cell, with the supplied human-readable names of the signals + + `double get_single_signal( Cell* pCell, int index );` get a single signal for the cell with the indicated index + + `double get_single_signal( Cell* pCell, std::string name );` get a single signal for the cell with the indicated human-readable name + ++ We introduced a "dictionary" of standard behaviors that can be used as outputs to intracellular and rule-based models. This dictionary is automatically constructed at the start of each simulation based upon the combinations of signaling substrates and cell types. + + Major classes of behaviors include: + + secretion, secretion target, uptake, and export rates + + cycle progression + + death rates + + motility parameters + + chemotactic parameters + + cell-cell adhesion and repulsion parameters + + cell adhesion affinities + + cell-BM adhesion and repulsion parameters + + phagocytosis rates + + attack rates + + fusion rates + + transformation rates + + Use `display_behavior_dictionary()` to quickly see a list of posible behaviors. + + Substantial functionality to query and set behaviors + + `int find_behavior_index( std::string response_name )` : get the index of the named behavior + + `std::vector find_behavior_indices( std::vector behavior_names )` get the indices for the given vector of behavior names. + + `std::string behavior_name( int i );` get the name of the behavior with the given index + + `std::vector create_empty_behavior_vector();` create an empty vector for the full set of behaviors + + `void set_behaviors( Cell* pCell , std::vector parameters );` write the full set of behaviors to the cell's phentoype + + `void set_selected_behaviors( Cell* pCell , std::vector indices , std::vector parameters );` write the selected set of behaviors (with supplied indices) to the cell's phenotype + + `void set_selected_behaviors( Cell* pCell , std::vector names , std::vector parameters );` write the selected set of behaviors (with supplied names) to the cell's phenotype + + `void set_single_behavior( Cell* pCell, int index , double parameter );` write a single behavior (by index) to the cell phentoype + + `void set_single_behavior( Cell* pCell, std::string name , double parameter );` write a single behavior (by name) to the cell phentoype + + Substantial functionality to query the cell's current behavior + + `std::vector get_behaviors( Cell* pCell );` get all the cell's current behaviors + + `std::vector get_behaviors( Cell* pCell , std::vector indices );` get a subset of behaviors (with given indices) + + `std::vector get_behaviors( Cell* pCell , std::vector names );` get a subset of behaviors (with given names) + + `double get_single_behavior( Cell* pCell , int index );` get a single behavior (by index) + + `double get_single_behavior( Cell* pCell , std::string name );` get a single behavior (by name) + + Substantial functionality to query the cell's referece behaviors (from its cell definition) + + `std::vector get_base_behaviors( Cell* pCell );` get all the cell's base behaviors + + `std::vector get_base_behaviors( Cell* pCell , std::vector indices );` get a subset of base behaviors (with given indices) + + `std::vector get_base_behaviors( Cell* pCell , std::vector names );` get a subset of base behaviors (with given names) + + `double get_single_base_behavior( Cell* pCell , int index );` get a single base behavior (by index) + + `double get_single_base_behavior( Cell* pCell , std::string name );` get a single base behavior (by name) + ++ Created a new `interaction-sample` project to illustrate the new interactions and transformations: + + Blood vessels release resource + + Virulet bacteria colonize near vessels (by chemotaxis up towards a secreted quorum factor and resource) + + Stem cells divide and differentiate into differentiated cells + + Differentiated cells divide until experiencing elevated pressure (to detect confluence) + + Bacteria-secreted virulence factor kills stem and differentiated cells. Dead cells release debris. + + Macrophages chemotax towards quorum factor and debris and secrete pro-inflammatory factor in presence of dead cells or bacteria + + Macrophages phagocytose dead cells + + CD8+ T cells chemotax towards pro-inflamatory factor and attack bacteria + + Neutrophils chemotax towards pro-inflammatory factor and phagocytose live bacteria + + Accumulated damage kills bacteria. + + With default parameters, bacteria kill off cells ot form abscesses, until death attracts macrophages to activate immune response to kill the invaders, after which the tissue can regrow. + +### Minor new features and changes: +#### 1.10.2 ++ Added `operator<<` for vectors of ints and vectors of strings. So that `std::cout << v << std::endl;` will work if `v` is `std::vector` of `std::vector`. It was truly annoying that these were missing, so sorry! ++ Added `dead` to the signals dictionaries, which returns 0.0 or 1.0 based on `phenotype.death.dead`. ++ Added `time` to the signals dictionaries, which returns the current simulation time based on `PhysiCell_Globals.current_time`. ++ Added a brief protocol on how to add new signals and behaviors to the dictionaries in the `/protocols` directory. ++ Added new functions `double& apoptosis_rate()` and `double& necrosis_rate()` to easily read and write these rates. Access via `cell.phenotype.death.apoptosis_rate()` and `cell.phenotype.death.necrosis_rate()`. ++ Added new ease of access functions for secretion: + + `double& Secretion::secretion_rate( std::string name )` allows you to easily read/write the secretion rate of a substrate by name. For example: + ```pCell->phenotype.secretion.secretion_rate("oxygen") = 0.1``` + + `double& Secretion::uptake_rate( std::string name )` allows you to easily read/write the uptake rate of a substrate by name. For example: + ```pCell->phenotype.secretion.uptake_rate("oxygen") = 0.1``` + + `double& Secretion::saturation_density( std::string name )` allows you to easily read/write the secretion target of a substrate by name. For example: + ```pCell->phenotype.secretion.saturation_density("oxygen") = 38``` + + `double& Secretion::net_export_rate( std::string name )` allows you to easily read/write the net export rate of a substrate by name. For example: + ```pCell->phenotype.secretion.net_export_rate("oxygen") = -100``` + ++ Added new ease of access function for internalized substrates: + + `double& Molecular::internalized_total_substrate( std::string name )` allows you to easily read/write the total amount of internalized substrate by name. For example: + ```pCell->phenotype.molecular.internalized_total_substrate( "oxygen" ) = 0.01`` + +#### 1.10.1 ++ None in this version. See 1.10.0. +#### 1.10.0 ++ All sample projects have a new rule "make name" to tell you the name of the executable. + ++ All sample projects output the executable name to screen for easier reference. + ++ `Cell_Definition` has a new Boolean `is_movable`, so that all cells of a type can be set to non-movable. (Default: `is_movable = true`;) This allows you to use agents as rigid objects or barriers. + ++ `create_cell( Cell_Definition )` now uses "`is_movable`" from the cell definition. + +### Beta features (not fully supported): +#### 1.10.2 ++ None in this version. See 1.10.0. +#### 1.10.1 + + None in this version. See 1.10.0. + #### 1.10.0 ++ Started writing a standardized set of functions for Hill functions and promoter/inhibitor signaling. + ++ [Model Builder Tool](https://github.com/PhysiCell-Tools/PhysiCell-model-builder/releases) + ++ Added a simple Qt GUI for plotting cells only (plot_cells.py and vis_tab_cells_only.py in /beta) + ++ Added a simple Qt GUI for plotting substrates and cells (plot_data.py and vis_tab.py in /beta) + ++ Added simple contour plotting of a substrate (anim_substrate2D.py in /beta; copy to /output) + +### Bugfixes: +#### 1.10.2 ++ Fixed error in `double get_single_behavior()` where the `cell-cell adhesion elastic constant` behavior was not found. + ++ Fixed error in `double get_single_base_behavior()` where the `cell-cell adhesion elastic constant` behavior was not found. + ++ Fixed bug in `add_PhysiCell_cells_to_open_xml_pugi()` that mistakenly used the wrong size (number of cell species rather than number of substrate species) when writing the chemotactic sensitivities. + ++ The cell `neighbors` list did not add non-adhesive cells within interaction distance. This is now fixed. + +#### 1.10.1 ++ XML parsing has been made more robust to "survive" using an incorrect substrate in the `chemotactic_sensitivities` section. + ++ Missing PhysiBoSS makefiles have been replaced. + ++ Fixed broken makefile for worms sample project. + +#### 1.10.0 ++ When the `cell_defaults` definition has been altered, new cell types may unwittingly copy nonzero parameter values from this default. Now, immediately after copying `cell_defaults`, the XML parsing will reset motility to off (with `NULL` function for bias direction), reset all secretion/uptake/export to zero, reset all cell interactions and transformations to zero. It will then continue to parse the XML file. Set `legacy_cell_defaults_copy = true` in the config file to override this bugfix. + ++ We refactored the pseudorandom number generator (at the basis of `UniformRandom()`) to improve thread safety. Previously, all threads shared a single PRNG, which was not thread safe. For newer fast processors with many threads, this could lead to sufficiently many "collisions" to introduce subtle biases in some cases (particularly for purely Brownian motion that is not dominated by chemotaxis, proliferation, and other behaviors). This is now corrected by creating a PRNG for each thread, each with its own seed. We used `std::seed_seq` to determinstically set a good spread of seeds to prevent correlation between the PRNGs, with the convention that the 0th thread's seed is either the user-specified seed or a random seed. This preserves original single-thread behavior from prior versions. + ++ Random motility now uses `UniformOnUnitCircle()` (in 2D) and `UniformOnUnitSphere()` (in 3D) to choose the random component of the migration direction, rather than hand-coding selection of the random vector. + ++ In response to PR 91 (https://github.com/MathCancer/PhysiCell/pull/91): Previoulsy, if the make jpeg rule fails, the `__*.txt` temporary files are left in place, so a subsequent "make jpeg" fails until these files are manually removed. Replacing `>>` (append) with `>` (overwrite) fixes the problem. Thanks [saikiRA1011](https://github.com/saikiRA1011)! + +### Notices for intended changes that may affect backwards compatibility: + ++ We intend to merge `Custom_Variable` and `Custom_Vector_Variable` in the very near future. + ++ We may change the role of `operator()` and `operator[]` in `Custom_Variable` to more closely mirror the functionality in `Parameters`. + ++ Some search functions (e.g., to find a substrate or a custom variable) will start to return -1 if no matches are found, rather than 0. + ++ We will change the timing of when `entry_function`s are executed within cycle models. Right now, they are evaluated immediately after the exit from the preceding phase (and prior to any cell division events), which means that only the parent cell executes it, rather than both daughter cells. Instead, we'll add an internal Boolean for "just exited a phase", and use this to execute the entry function at the next cycle call. This should make daughter cells independently execute the entry function. + ++ We might make `trigger_death` clear out all the cell's functions, or at least add an option to do this. + +### Planned future improvements: + ++ Further XML-based simulation setup. + ++ Read saved simulation states (as MultiCellDS digital snapshots) + ++ Add a new standard phenotype function that uses mechanobiology, where high pressure can arrest cycle progression. (See https://twitter.com/MathCancer/status/1022555441518338048.) + ++ Add module for standardized pharmacodynamics, as prototyped in the nanobio project. (See https://nanohub.org/resources/pc4nanobio.) + ++ Create an angiogenesis sample project + ++ Create a small library of angiogenesis and vascularization codes as an optional standard module in ./modules (but not as a core component) + ++ Improved plotting options in SVG + ++ Further update sample projects to make use of more efficient interaction testing available + ++ Major refresh of documentation. + +* * * +**Version:** 1.10.1 + +**Release date:** 15 May 2022 + ## Release summary: Version 1.10.1 introduces bugfixes to increase XML parser robustness and to fix missing PhysiBoSS makefiles. @@ -78,8 +311,7 @@ The 1.10.0 release introduced major new phenotype functionality, including stand A blog post and tutorial on the new phenotype elements can be found at http://www.mathcancer.org/blog/introducing-cell-interactions-and-transformations. -A blog post and tutorial on the new signal and behavior dictionaries can be found at http://www.mathcancer.org/blog/introducing-cell-signal-and-behavior-dictionaries. - +A blog post and tutorial on the new signal and behavior dictionaries can be found at http://www.mathcancer.org/blog/introducing-cell-signal-and-behavior-dictionaries. **NOTE 1:** MacOS users need to define a PHYSICELL_CPP environment variable to specify their OpenMP-enabled g++. See the [Quickstart](documentation/Quickstart.md) for details. @@ -267,6 +499,8 @@ A blog post and tutorial on the new signal and behavior dictionaries can be foun + Major refresh of documentation. +* * * + **Version:** 1.10.0 **Release date:** 13 May 2022 @@ -277,8 +511,7 @@ This release introduces major new phenotype functionality, including standardize A blog post and tutorial on the new phenotype elements can be found at http://www.mathcancer.org/blog/introducing-cell-interactions-and-transformations -A blog post and tutorial on the new signal and behavior dictionaries can be found at http://www.mathcancer.org/blog/introducing-cell-signal-and-behavior-dictionaries. - +A blog post and tutorial on the new signal and behavior dictionaries can be found at http://www.mathcancer.org/blog/introducing-cell-signal-and-behavior-dictionaries. **NOTE 1:** MacOS users need to define a PHYSICELL_CPP environment variable to specify their OpenMP-enabled g++. See the [Quickstart](documentation/Quickstart.md) for details. diff --git a/core/PhysiCell.h b/core/PhysiCell.h index b22247cf1..d1d17694a 100644 --- a/core/PhysiCell.h +++ b/core/PhysiCell.h @@ -72,7 +72,7 @@ #include #include -static std::string PhysiCell_Version = "1.10.1"; +static std::string PhysiCell_Version = "1.10.2"; static std::string PhysiCell_URL = "http://PhysiCell.MathCancer.org"; static std::string PhysiCell_DOI = "10.1371/journal.pcbi.1005991"; diff --git a/core/PhysiCell_cell.cpp b/core/PhysiCell_cell.cpp index 831dd049d..bd21c6c44 100644 --- a/core/PhysiCell_cell.cpp +++ b/core/PhysiCell_cell.cpp @@ -986,6 +986,8 @@ void Cell::add_potentials(Cell* other_agent) temp_a *= effective_adhesion; temp_r -= temp_a; + + state.neighbors.push_back(other_agent); // move here in 1.10.2 so non-adhesive cells also added. } ///////////////////////////////////////////////////////////////// if( fabs(temp_r) < 1e-16 ) @@ -998,7 +1000,7 @@ void Cell::add_potentials(Cell* other_agent) axpy( &velocity , temp_r , displacement ); - state.neighbors.push_back(other_agent); // new 1.8.0 + // state.neighbors.push_back(other_agent); // new 1.8.0 return; } diff --git a/core/PhysiCell_phenotype.cpp b/core/PhysiCell_phenotype.cpp index d21a30af2..7626eb29a 100644 --- a/core/PhysiCell_phenotype.cpp +++ b/core/PhysiCell_phenotype.cpp @@ -495,6 +495,19 @@ Cycle_Model& Death::current_model( void ) return *models[current_death_model_index]; } +double& Death::apoptosis_rate(void) +{ + static int nApoptosis = find_death_model_index( PhysiCell_constants::apoptosis_death_model ); + return rates[nApoptosis]; +} + +double& Death::necrosis_rate(void) +{ + static int nNecrosis = find_death_model_index( PhysiCell_constants::necrosis_death_model ); + return rates[nNecrosis]; +} + + Cycle::Cycle() { pCycle_Model = NULL; @@ -987,6 +1000,31 @@ void Secretion::scale_all_uptake_by_factor( double factor ) return; } +// ease of access +double& Secretion::secretion_rate( std::string name ) +{ + int index = microenvironment.find_density_index(name); + return secretion_rates[index]; +} + +double& Secretion::uptake_rate( std::string name ) +{ + int index = microenvironment.find_density_index(name); + return uptake_rates[index]; +} + +double& Secretion::saturation_density( std::string name ) +{ + int index = microenvironment.find_density_index(name); + return saturation_densities[index]; +} + +double& Secretion::net_export_rate( std::string name ) +{ + int index = microenvironment.find_density_index(name); + return net_export_rates[index]; +} + Molecular::Molecular() { pMicroenvironment = get_default_microenvironment(); @@ -1037,6 +1075,12 @@ void Molecular::sync_to_cell( Basic_Agent* pCell ) return; } +// ease of access +double& Molecular::internalized_total_substrate( std::string name ) +{ + int index = microenvironment.find_density_index(name); + return internalized_total_substrates[index]; +} /* void Molecular::advance( Basic_Agent* pCell, Phenotype& phenotype , double dt ) diff --git a/core/PhysiCell_phenotype.h b/core/PhysiCell_phenotype.h index 2c14be9a1..8269700c6 100644 --- a/core/PhysiCell_phenotype.h +++ b/core/PhysiCell_phenotype.h @@ -273,7 +273,11 @@ class Death void trigger_death( int death_model_index ); // done Cycle_Model& current_model( void ); // done - Death_Parameters& current_parameters( void ); // done + Death_Parameters& current_parameters( void ); // done ' + + // ease of access + double& apoptosis_rate(void); + double& necrosis_rate(void); }; class Volume @@ -451,6 +455,12 @@ class Secretion void set_all_uptake_to_zero( void ); // NEW void scale_all_secretion_by_factor( double factor ); // NEW void scale_all_uptake_by_factor( double factor ); // NEW + + // ease of access + double& secretion_rate( std::string name ); + double& uptake_rate( std::string name ); + double& saturation_density( std::string name ); + double& net_export_rate( std::string name ); }; class Cell_Functions @@ -560,6 +570,9 @@ class Molecular // use this void sync_to_cell( Basic_Agent* pCell ); + + // ease of access + double& internalized_total_substrate( std::string name ); }; diff --git a/core/PhysiCell_signal_behavior.cpp b/core/PhysiCell_signal_behavior.cpp index b51d42701..418a387e7 100644 --- a/core/PhysiCell_signal_behavior.cpp +++ b/core/PhysiCell_signal_behavior.cpp @@ -193,11 +193,26 @@ void setup_signal_behavior_dictionaries( void ) signal_to_int["damage"] = map_index; int_to_signal[map_index] = "damage"; + // live / dead state + map_index++; + signal_to_int["dead"] = map_index; + int_to_signal[map_index] = "dead"; + // synonym + signal_to_int["is dead"] = map_index; + // total attack time map_index++; signal_to_int["total attack time"] = map_index; int_to_signal[map_index] = "total attack time"; + // current time + map_index++; + signal_to_int["time"] = map_index; + int_to_signal[map_index] = "time"; + // synonyms + signal_to_int["current time"] = map_index; + signal_to_int["global time"] = map_index; + behavior_to_int.clear(); int_to_behavior.clear(); @@ -593,11 +608,19 @@ std::vector get_signals( Cell* pCell ) // damage static int damage_ind = find_signal_index( "damage"); signals[damage_ind] = pCell->state.damage; + + // live / dead state + static int dead_ind = find_signal_index( "dead" ); + signals[dead_ind] = (double) pCell->phenotype.death.dead; // integrated total attack time static int tot_attack_ind = find_signal_index( "total attack time"); signals[tot_attack_ind] = pCell->state.total_attack_time; + // time + static int time_ind = find_signal_index( "time" ); + signals[time_ind] = PhysiCell_globals.current_time; + // rescale signals /= signal_scales; @@ -788,6 +811,15 @@ double get_single_signal( Cell* pCell, int index ) return out; } + // live / dead state + static int dead_ind = find_signal_index( "dead" ); + if( index == dead_ind ) + { + out = (double) pCell->phenotype.death.dead; + out /= signal_scales[index]; + return out; + } + // integrated total attack time static int tot_attack_ind = find_signal_index( "total attack time"); if( index == tot_attack_ind ) @@ -797,6 +829,15 @@ double get_single_signal( Cell* pCell, int index ) return out; } + // time + static int time_ind = find_signal_index( "time" ); + if( index == time_ind ) + { + out = PhysiCell_globals.current_time; + out /= signal_scales[index]; + return out; + } + // unknown after here ! std::cout << "Warning: Requested unknown signal number " << index << "!" << std::endl @@ -1332,7 +1373,7 @@ double get_single_behavior( Cell* pCell , int index ) { return pCell->phenotype.mechanics.cell_cell_adhesion_strength; } // cell-cell "springs" - static int cca_spring_index = find_behavior_index( "cell-cell adhesion" ); + static int cca_spring_index = find_behavior_index( "cell-cell adhesion elastic constant" ); if( index == cca_spring_index ) { return pCell->phenotype.mechanics.attachment_elastic_constant; } @@ -1654,7 +1695,7 @@ double get_single_base_behavior( Cell* pCell , int index ) { return pCD->phenotype.mechanics.cell_cell_adhesion_strength; } // cell-cell "springs" - static int cca_spring_index = find_behavior_index( "cell-cell adhesion" ); + static int cca_spring_index = find_behavior_index( "cell-cell adhesion elastic constant" ); if( index == cca_spring_index ) { return pCD->phenotype.mechanics.attachment_elastic_constant; } diff --git a/intracellular/PhysiCell_intracellular.h b/intracellular/PhysiCell_intracellular.h deleted file mode 100644 index 9d445da8e..000000000 --- a/intracellular/PhysiCell_intracellular.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -############################################################################### -# 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-2018, 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. # -# # -############################################################################### -*/ - -#ifndef __PhysiCell_intracellular_h__ -#define __PhysiCell_intracellular_h__ - -// #undef LIBROADRUNNER // use g++ "-D LIBROADRUNNER" (or, -U) - -#ifdef LIBROADRUNNER -// These are for C -// #define STATIC_RRC -#include "rrc_api.h" -#include "rrc_types.h" -// #include "rrc_utilities.h" -extern "C" rrc::RRHandle createRRInstance(); -#endif // LIBROADRUNNER - - -#endif diff --git a/modules/PhysiCell_MultiCellDS.cpp b/modules/PhysiCell_MultiCellDS.cpp index 5f42fd4b0..1004fcbe1 100644 --- a/modules/PhysiCell_MultiCellDS.cpp +++ b/modules/PhysiCell_MultiCellDS.cpp @@ -365,9 +365,10 @@ void add_PhysiCell_cells_to_open_xml_pugi( pugi::xml_document& xml_dom, std::str extern std::unordered_map cell_definition_indices_by_name; int number_of_cell_defs = cell_definition_indices_by_name.size(); + int number_of_substrates = microenvironment.number_of_densities(); // new in 2022: chemotactic sensitivies - size = number_of_cell_defs; + size = number_of_substrates; // number_of_cell_defs; node_temp1 = node_temp1.append_child( "label" ); node_temp1.append_child( pugi::node_pcdata ).set_value( "chemotactic_sensitivities" ); attrib = node_temp1.append_attribute( "index" ); @@ -537,11 +538,12 @@ void add_PhysiCell_cells_to_open_xml_pugi( pugi::xml_document& xml_dom, std::str // figure out size of 2022 phenotype items extern std::unordered_map cell_definition_indices_by_name; + int number_of_substrates = microenvironment.number_of_densities(); int number_of_cell_defs = cell_definition_indices_by_name.size(); // advanced chemotaxis size_of_each_datum += - number_of_cell_defs; + number_of_substrates; // number_of_cell_defs; // cell adhesion affinities size_of_each_datum += @@ -638,7 +640,8 @@ void add_PhysiCell_cells_to_open_xml_pugi( pugi::xml_document& xml_dom, std::str // new in 2022: interactions : - fwrite( (char*) &( pCell->phenotype.motility.chemotactic_sensitivities ) , sizeof(double) , number_of_cell_defs , fp ); // chemotactic_sensitivities + // fwrite( (char*) &( pCell->phenotype.motility.chemotactic_sensitivities ) , sizeof(double) , number_of_cell_defs , fp ); // chemotactic_sensitivities + fwrite( (char*) &( pCell->phenotype.motility.chemotactic_sensitivities ) , sizeof(double) , number_of_substrates , fp ); // chemotactic_sensitivities fwrite( (char*) &( pCell->phenotype.mechanics.cell_adhesion_affinities ) , sizeof(double) , number_of_cell_defs , fp ); // cell_adhesion_affinities fwrite( (char*) &( pCell->phenotype.cell_interactions.dead_phagocytosis_rate ) , sizeof(double) , 1 , fp ); // dead_phagocytosis_rate fwrite( (char*) &( pCell->phenotype.cell_interactions.live_phagocytosis_rates ) , sizeof(double) , number_of_cell_defs , fp ); // live_phagocytosis_rates diff --git a/protocols/adding new signals or behaviors.md b/protocols/adding new signals or behaviors.md new file mode 100644 index 000000000..66d601bf6 --- /dev/null +++ b/protocols/adding new signals or behaviors.md @@ -0,0 +1,228 @@ +# Adding new signals and behaviors to the dictionaries (introduced in Version 1.10.0) + +## To add a new signal: (in 'PhysiCell_signal_behavior.cpp') + +Suppose you want to add a new signal "my signal name" to the dictionary, and that you can access that the cell's location at `pCell->something` + +1. Make sure the signal you want to add isn't already there! Take a look at the current dictionaries using: + + ``` + void display_signal_dictionary( void ); + void display_signal_dictionary_with_synonyms( void ); + ``` + +1. Make sure the signal name you have chosen is unique. (See the prior step.) + +1. Add the signal in `setup_signal_behavior_dictionaries()`: + + 1. Search for the function: `void setup_signal_behavior_dictionaries( void )` + + 1. Go to the end of the "signal" section. Just before these lines: + + ``` + behavior_to_int.clear(); + int_to_behavior.clear(); + ``` + + 1. Add the signal like this: + + ``` + map_index++; + signal_to_int["my signal name"] = map_index; + int_to_signal[map_index] = "my signal name"; + ``` + + 1. Add any synonyms (or common typos) to the dictionary. Append these just below your entry. + + ``` + // synonyms + signal_to_int["my alternate signal name"] = map_index; + ``` + +1. Add the signal to function to write a full vector of signals + + 1. Search for `std::vector get_signals( Cell* pCell )` + + 1. Go to the end of the signals. Just before these lines: + ``` + // rescale + signals /= signal_scales; + ``` + + 1. Add code to write your signal at the appropriate index, like this: + + ``` + static int my_signal_ind = find_signal_index( "my signal name" ); + signals[my_signal_ind] = pCell->something; + ``` + + Make SURE that `my_signal_ind` is unique! + +1. Add the signal to function to write a single individual signal in `get_single_signal()`: + + 1. Search for `double get_single_signal( Cell* pCell, int index )` + + 1. Go to the end of signals. Just before these lines: + ``` + // unknown after here ! + + std::cout << "Warning: Requested unknown signal number " << index << "!" << std::endl + << " Returning 0.0, but you should fix this!" << std::endl << std::endl; + + ``` + + 1. Add code to write your signal at the appropriate index, like this: + ``` + // my signal name + static int my_signal_ind = find_signal_index( "my signal name" ); + if( index == time_ind ) + { + out = pCell->something; + out /= signal_scales[index]; + return out; + } + ``` + + Make SURE that `my_signal_ind` is unique! + +## To add a new behavior: (in 'PhysiCell_signal_behavior.cpp') + +Suppose you want to add a new behavior "my behavior name" to the dictionary, and that you can access that at `pCell->something` + +1. Make sure the behavior you want to add isn't already there! Take a look at the current dictionaries using: + + ``` + void display_behavior_dictionary( void ); + void display_behavior_dictionary_with_synonyms( void ); + ``` + +1. Make sure the behavior name you have chosen is unique. (See the prior step.) + +1. Add the behavior in `setup_signal_behavior_dictionaries()`: + + 1. Search for the function: `void setup_signal_behavior_dictionaries( void )` + + 1. Go to the end of the "behavior" section. Just before these lines: + + ``` + // resize scales; + signal_scales.resize( int_to_signal.size() , 1.0 ); + ``` + + 1. Add the behavior like this: + + ``` + map_index++; + map_name = "my behavior name"; + behavior_to_int[map_name ] = map_index; + int_to_behavior[map_index] = map_name; + ``` + + 1. Add any synonyms (or common typos) to the dictionary. Append these just below your entry. + + ``` + // synonyms + behavior_to_int["my alternate behavior name"] = map_index; + ``` + +1. Add the behavior to function to write a full vector of behaviors + + 1. Search for `void set_behaviors( Cell* pCell , std::vector parameters )` + + 1. Go to the end the function. + + 1. Add code to write your behavior from the appropriate index, like this: + + ``` + // apoptosis + static int my_behavior_ind = find_behavior_index( "my behavior name"); + pCell->something = parameters[my_behavior_ind]; + ``` + + Make SURE that `my_behavior_ind` is unique! + +1. Add the signal to function to write a single individual behavior in `set_single_behavior()`: + + 1. Search for `void set_single_behavior( Cell* pCell, int index , double parameter )` + + 1. Go to the end of the function + + 1. Add code to write your behavior to the cell from at the appropriate index, like this: + ``` + // my behavior name + static int my_behavior_ind = find_behavior_index( "my behavior name" ); + if( index == my_behavior_ind ) + { pCell->something = parameter; return; } + ``` + + Make SURE that `my_behavior_ind` is unique! + +1. Add the behavior to function to get a full vector of behaviors from a cell + + 1. Search for `std::vector get_behaviors( Cell* pCell )` + + 1. Go to the end the function. + + 1. Add code to write your behavior to the appropriate index, like this: + + ``` + // my behavior + static int my_behavior_ind = find_behavior_index("my behavior name"); + parameters[my_behavior_ind] = pCell->something; + ``` + + Make SURE that `my_behavior_ind` is unique!**** + +1. Add the behavior to function to get a single behaviors from a cell + + 1. Search for `double get_single_behavior( Cell* pCell , int index )` + + 1. Go to the end the function. + + 1. Add code to write your behavior to the appropriate index, like this: + + ``` + // my behavior + static int my_behavior_ind = find_behavior_index( "my behavior name"); + if( index == my_behavior_ind ) + { return pCell->something; } + ``` + + Make SURE that `my_behavior_ind` is unique!**** + +1. Add the behavior to the function to get a vector of all base behaviors from a cell's cell definition + + 1. Search for `std::vector get_base_behaviors( Cell* pCell )` + + 1. Go to the end of the function. + + 3. Add code to write your behavior to the , like this: + + ``` + // my behavior + static int my_behavior_ind = find_behavior_index("my behavior name"); + parameters[my_behavior_ind] = pCD->something; + ``` + Make sure that `my_behavior_ind` is unique. + + Notice that `pCD` is set to `Cell_Definition` of the cell in `pCell`. + +1. Add the behavior to the function to get a single base behavior from a cell's cell definition + + 1. Search for `double get_single_base_behavior( Cell* pCell , int index )` + + 1. Go to the end of the function. + + 3. Add code to write your behavior to the , like this: + + ``` + // my behavior + static int my_behavior_ind = find_behavior_index("my behavior name" ); + if( index == my_behavior_ind ) + { return pCD->something; } + ``` + Make sure that `my_behavior_ind` is unique. + + Notice that `pCD` is set to `Cell_Definition` of the cell in `pCell`. + + diff --git a/sample_projects/interactions/custom_modules/custom.cpp b/sample_projects/interactions/custom_modules/custom.cpp index 5db318ba0..a141e9226 100644 --- a/sample_projects/interactions/custom_modules/custom.cpp +++ b/sample_projects/interactions/custom_modules/custom.cpp @@ -98,6 +98,18 @@ void create_cell_types( void ) */ 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(); /* Put any modifications to individual cell definitions here. diff --git a/sample_projects_intracellular/ode/ode1/Make-clang b/sample_projects_intracellular/ode/ode1/Make-clang index 31aed34c3..5cc69d8c4 100644 --- a/sample_projects_intracellular/ode/ode1/Make-clang +++ b/sample_projects_intracellular/ode/ode1/Make-clang @@ -208,7 +208,7 @@ PhysiCell_settings.o: ./modules/PhysiCell_settings.cpp # user-defined PhysiCell modules -custom.o: ./custom_modules/custom.cpp ./intracellular/PhysiCell_intracellular.h +custom.o: ./custom_modules/custom.cpp $(COMPILE_COMMAND) -c ./custom_modules/custom.cpp librr_intracellular.o: ./addons/libRoadrunner/src/librr_intracellular.cpp ./addons/libRoadrunner/src/librr_intracellular.h diff --git a/sample_projects_intracellular/ode/test_sbml1/Make-libroadrunner b/sample_projects_intracellular/ode/test_sbml1/Make-libroadrunner index fc6893f69..a10f66f5e 100644 --- a/sample_projects_intracellular/ode/test_sbml1/Make-libroadrunner +++ b/sample_projects_intracellular/ode/test_sbml1/Make-libroadrunner @@ -221,7 +221,7 @@ PhysiCell_settings.o: ./modules/PhysiCell_settings.cpp # user-defined PhysiCell modules -custom.o: ./custom_modules/custom.cpp ./intracellular/PhysiCell_intracellular.h +custom.o: ./custom_modules/custom.cpp $(COMPILE_COMMAND) -c ./custom_modules/custom.cpp submodel_data_structures.o: ./custom_modules/submodel_data_structures.cpp diff --git a/sample_projects_intracellular/ode/test_sbml1/Make-sbml b/sample_projects_intracellular/ode/test_sbml1/Make-sbml index e9905ff83..b938d641e 100644 --- a/sample_projects_intracellular/ode/test_sbml1/Make-sbml +++ b/sample_projects_intracellular/ode/test_sbml1/Make-sbml @@ -203,7 +203,7 @@ PhysiCell_settings.o: ./modules/PhysiCell_settings.cpp # user-defined PhysiCell modules -custom.o: ./custom_modules/custom.cpp ./intracellular/PhysiCell_intracellular.h +custom.o: ./custom_modules/custom.cpp $(COMPILE_COMMAND) -c ./custom_modules/custom.cpp submodel_data_structures.o: ./custom_modules/submodel_data_structures.cpp diff --git a/sample_projects_intracellular/ode/test_sbml1/Makefile b/sample_projects_intracellular/ode/test_sbml1/Makefile index a7d9fa7a9..2ded3fba1 100644 --- a/sample_projects_intracellular/ode/test_sbml1/Makefile +++ b/sample_projects_intracellular/ode/test_sbml1/Makefile @@ -192,7 +192,7 @@ PhysiCell_settings.o: ./modules/PhysiCell_settings.cpp # user-defined PhysiCell modules -custom.o: ./custom_modules/custom.cpp ./intracellular/PhysiCell_intracellular.h +custom.o: ./custom_modules/custom.cpp $(COMPILE_COMMAND) -c ./custom_modules/custom.cpp librr_intracellular.o: ./addons/libRoadrunner/src/librr_intracellular.cpp ./addons/libRoadrunner/src/librr_intracellular.h