Abstract
The extracellular matrix is a complex assembly of macro-molecules, such as collagen fibres, which provides structural support for surrounding cells. In the context of cancer metastasis, it represents a barrier for the cells, that the migrating cells needs to degrade in order to leave the primary tumor and invade further tissues. Agent-based frameworks, such as PhysiCell, are often use to represent the spatial dynamics of tumor evolution. However, typically they only implement cells as agents, which are represented by either a circle (2D) or a sphere (3D). In order to accurately represent the extracellular matrix as a network of fibres, we require a new type of agent represented by a segment (2D) or a cylinder (3D).
In this article, we present PhysiMeSS, an addon of PhysiCell, which introduces a new type of agent to describe fibres, and their physical interactions with cells and other fibres. PhysiMeSS implementation is publicly available at https://github.com/PhysiMeSS/PhysiMeSS, as well as in the official Physi-Cell repository. We also provide simple examples to describe the extended possibilities of this new framework. We hope that this tool will serve to tackle important biological questions such as diseases linked to dis-regulation of the extracellular matrix, or the processes leading to cancer metastasis.
1 Introduction
Agent-based models (ABMs) establish independent agents that each behave according to a specific set of rules. Due to the independence of each agent, an ABM allows for both a highly stochastic modelling environment and an extremely fine-grained investigation of processes. Indeed, ABMs are a tool used to model biological systems on a refined scale especially in comparison to continuum models due to their focus on specific cell behaviours and not entire population dynamics. If the agents within an ABM are cells (or even sub-cellular components), then ABMs are capable of capturing detailed single-cell and inter-cellular processes. Individualising the cell behaviour can lead to emergent heterogeneity at the tissue scale which may not be captured by a continuum model. Furthermore, ABMs may also incorporate subcellular processes which inform and drive cell behaviour [10]. As such ABMs offer a truly multiscale approach interlinking dynamics occurring between different scales, including sub-cellular, cellular- and tissue scales, see Figure 1.
The extracellular matrix (ECM) is a highly complex structure that acts not only as a scaffold for cells and tissues, but also as a platform through which cells can communicate, and is a key structure in many biological processes, such as embryonic development, tumour formation, and fibrosis. The ECM is comprised of a variety of secreted proteins which can vary depending on the location in the body. One of the main components of the ECM is collagen, a fibrous protein which gives the ECM its structure and rigidity, with collagen type I the most abundant protein in the human body constituting around 90% of all proteins [13]. Alongside the rigid collagen fibres is elastin, a thin fibre that provides the ECM with elasticity and the ability to be reshaped. Elastin is a dominant component in tissues that require a high degree of flexibility, such as the lungs, bladder, and skin.
Cells interact chemically with the ECM through the secretion of enzymes, namely a family of matrix-degrading enzymes (MDEs) called matrix metalloproteinases (MMPs). Although prevalent during cancer invasion, the secretion of MMPs is an essential cellular process that occurs throughout normal development and aging. These enzymes are able to degrade components of the surrounding matrix, in particular collagen and elastin, with their breakdown resulting in the destabilization of cross-links between collagen and elastin fibres and ultimately the loosening of the ECM structure. Certain cells (fibroblasts) are also able to create new ECM by excreting collagen and fibronectin. Creating new ECM forms the basis for the important healthy process of wound healing as well as pathological processes such as fibrosis. Cellular remodelling of the ECM through degradation, regeneration and indeed re-orientation allow cells control over their environment. Invasive cancer cells in particular can initiate the remodeling and re-orientation of collagen fibres, providing tracks to facilitate the invasion process and thus favouring a more tumorigenic microenvironment [8].
Additionally, cells use the ECM as a means of mechanical communication or mechanotransduction. A cell can modify both its behaviour; such as its capacity for proliferation and migration, as well as its intracellular composition and chemical concentrations, in response to signals from its environment. In particular, fibronectin (FN), a matrix protein that mediates cell-ECM interactions, binds to integrin receptors on the cell membrane. This reaction causes the FN-induced phosphorylation of fibroblast growth factor receptor-1 (FGFR1) which then preferentially activates the protein kinase AKT, resulting in FN-induced endothelial cell migration [17].
Reflecting on the mechanotrasnduction and the structure of the ECM, the membrane bound mechanosensor Piezo1 is a stretch-activated ion channel that activates due to a change in the stiffness of the ECM. The activation of Piezo1 has been found to cause the cell to change the organisation of its cytoskeleton [3]. It has been further shown that the stiffening of the ECM and consequential activation of Piezo1 regulates cell numbers, showing that tissue stiffness is a key regulator of aging in cells [16]. Tumours are often fibrotic due to the presence of cancer associated fibroblasts (CAFs) which produce and deposit ECM. The classical puckering of breast cancer is caused by cancer invasion of the ligaments of Cooper (collagen fibres which define the shape of the breast). Stiff fibrous tumours create the perfect environment though cell-ECM interactions for cancer cell survival, invasion and metastasis leading to tumours which are particularly aggressive.
The open-source computational package PhysiCell [7], which implements a multiscale hybrid ABM (having both agent and continuum aspects) has hitherto been used to describe such processes as the invasion of cancer cells [12, 15], cancer-immune responses [9], and most recently the progression and spread of COVID-19 within the human body [6]. The underlying environment in which these cellular dynamics take place is typically modelled, in PhysiCell, as a distribution of some substrate of interest. The substrate can exist in the background of the tissue, potentially be secreted or taken up by cells and can then in-turn influence cellular behaviour. Often this influence is to cause cells to undergo some form of taxis, whereby the motility of cells is directed along the gradients of the substrate. Both haptotaxis (movement of cells up cellular-adhesion site gradients) [14] and durotaxis (movement of cells up gradients of matrix stiffness) [12] have been modelled in this way. Whilst such an approach is useful, it does not allow for fine-grained modelling of the specific extracellular matrix (ECM) components which also, importantly, interact mechanically with cellular agents.
In this paper we introduce a PhysiCell addon, PhysiMeSS (MicroEnvironment Structures Simulation) which allows the user to specify rod shaped microenvironment elements such as the matrix fibres (e.g. collagen) of the ECM. This allows the PhysiCell user the ability to investigate fine-grained processes between cellular and fibrous ECM agents. However, we note that the applications of PhysiMeSS stretch beyond those wanting to model the ECM as the new cylindrical/rod-shaped agents could be used to model blood vessel segments or indeed create obstacles within the domain. In Section 2 we describe the implementation of PhysiMeSS in 2D. Most of what we document here is also appropriate for 3D but some of the mechanical aspects are confined to 2D and so we focus on that for this article and the first release of PhysiMeSS which was included in version 1.13.0 of PhysiCell.
2 Methods
We choose to incorporate ECM agents as PhysiMeSS_Fibre, a derived class of the Cell class in PhysiCell in order to inherit all the properties of cells while adding new components specific to matrix fibres. This construct allows us to utilise the preexisting and future functionalities of PhysiCell. We also included PhysiMeSS_Cell, a new derived class of the Cell class to add new properties to the cells which are specific to their interaction with matrix fibres. Note that both of these new classes do not inherit directly from Cell, but indirectly through PhysiMeSS_Agent, which contains methods specific to the PhysiMeSS addon and common between PhysiMeSS_Fibre and PhysiMeSS_Cell. More details about the implementation of these new agents can be found in Appendix A. This new implementation can be found within the addons/PhysiMeSS directory of PhysiCell where you will also find additional documentation and user guidance.
PhysiMeSS comes with a dedicated sample project physimess-sample which can be built, as all other PhysiCell sample projects, by typing make physimess-sample; make from the PhysiCell root directory. Once built, PhysiMeSS loads its own specific config and custom_modules directories along with Makefile and main.cpp. The custom PhysiMeSS set-up is found within custom modules/custom.cpp and user examples are found within the config directory. We will first discuss fibre initialisation with simple examples provided in config/Fibre_Initialisation.
2.1 Initialising cylindrical matrix fibres
The first key component of the PhysiMeSS tool is to allow the user to distinguish (visually and practically) between cellular agents (typically circular in 2D or spherical in 3D) and the fibrous rods of the ECM. These new agents are cylindrical in shape, so designed to model matrix protein fibres (such as collagen), but could model any other cylindrical shaped component the user requires (e.g. blood vessel segments). In order for PhysiMeSS to identify agents as cylindrical matrix fibres the user must, for now, give the agent a name containing any of the following recognised strings: {ecm, fiber, fibre, matrix, rod} . The initialisation of cylindrical matrix fibres is incorporated in the setup_tissue function in custom.cpp. Using the typical centre-based approach, as implemented in PhysiCell, fibres are located within the domain using the position of their centre. The fibre centres, as per cell centres, can be read in from a .csv file or can be assigned randomly across the domain. The number of initial fibres can be controlled distinctly from the number of cells. Further to the fibre centre, fibres are described using a length (which may be normally distributed), radius (which may be normally distributed) and a orientation angle (which may be normally distributed). These are controlled by user parameters expressed in the .xml file and detailed in Table 1. For further details of fibre set-up, see Appendix B.
2.1.1 Visualising cylindrical matrix fibres
Visualising cylindrical agents is not a simple task. However, since matrix fibres are typically much longer than their girth (for example, collagen fibres average 75μm in length but only 2μm in radius) we make the choice to visualise the cylinders as lines. We added two functions in the PhysiMeSS addon: fibre_agent_SVG and fibre_agent_legend. These functions are replacing PhysiCell’ s default drawing function and instead draw ECM agents as lines in the outputted SVG plots and legend. In addition once fibre cross-links have been calculated (after at least one mechanics timestep) the function fibre_agent_SVG colours the fibres according to the number of cross-links, see Section 2.2.2.
In Figure 2 we display the results of three simple 2D fibre arrangements, which can be reproduced from Fibre_Initialisation/mymodel_initialisation.xml. In all three cases we attempt to initialise 2 000 fibres of length 75μm and radius 2μm randomly (there is no .csv file prescribing their centres) across an (800μm × 800μm domain). In the left panel fibres are placed isotropically (anisotropic_fibres is false) and so are given randomly assigned orientations. In the middle panel fibres are placed anisotropically (anisotropic_fibres is true) with a prescribed orientation angle of 0.2 radians and so all fibres are aligned at an angle of 0.2 radians from horizontal. In the right panel fibres are placed anisotropically with a prescribed orientation angle distributed around a mean of 0.2 radians with standard deviation of 0.15 radians. We note that during the fibre set-up, if a fibre is not contained wholly within the domain it is disregarded. If the fibrous mesh is isotropic we attempt to re-initialise such disregarded fibres, up to a maximum of ten times, by giving them a new orientation within the domain. If after which time the fibre still does not sit wholly within the domain, or the fibrous mesh is anisotropic (in which case changing the orientation will not be possible) it is permanently disregarded. This is why in all three cases shown in Figure 2 the actual number of initialised fibres is less than 2 000.
2.2 Fibre specific geometric considerations
When modelling fibres as cylinders there are certain geometrical aspects to overcome. These are discussed in the following Sections.
2.2.1 Determining neighbours of cylindrical agents
One immediate aspect to overcome in modelling cylindrical agents is how to determine neighbours. Finding neighbours is important in ensuring the efficiency and effectiveness of the code, for example, mechanical interactions only occur between neighbours. Currently cellular agents in PhysiCell belong to a single voxel and neighbours are found by checking for agents in the same or adjacent voxels. Fibres are typically much longer than a typical cell diameter (for example, collagen fibres 75μm in length; cells 10μm in diameter) and so is likely that they will extend across multiple voxels. Thus, in order to find neighbours of fibres we need to correctly find and register each voxel a fibre passes through. To achieve this, we implemented custom methods to find neighbors in PhysiMeSS. Since these methods are common to both cells and fibres in PhysiMeSS, they are defined in the PhysiMeSS_Agent’ s class. The method for finding and registering a fibre to its voxels is register_fibre_voxels, which is implemented differently for cells and fibres. We then build our own list of neighbors, by first finding all the voxels that an agent, cell or fibre, sits within as well as all adjacent voxels. Neighbours are then determined to be any agents which are registered to any of these voxels via the method find_agent_neighbors. After finding neighbours we de-register the fibre from all bar the voxel containing its centre using the method deregister_fibre_voxels. For further details of these processes, see Appendix C.
2.2.2 Determining fibre cross-links
A key aspect of the ECM is that fibres cross-link to form the matrix network. Within PhysiMeSS we consider, at a basic level, that two fibres cross-link at any point that they touch or intersect. Within the PhysiMeSS class we determine whether a pair of fibres cross-link using PhysiMeSS_Fibre’ s method check_fibre_crosslinks. This is primarily a geometrical problem and is explained in detail in Appendix C. It is only necessary to check cross-links for pairs of fibres which are in close proximity, thus PhysiMeSS_Fibre’ s method add_crosslinks determines cross-links between neighbouring fibres by calling the function check_fibre_crosslinks only if a pair of fibres are neighbours. Once fibre cross-links have been calculated we colour the fibres according to the number of cross-links. This colouring follows a gradient of blue, with non cross-linked fibres coloured light sky blue, fibres cross-linked once coloured steel blue, fibres cross-linked twice coloured blue and fibres crosslinked three or more times coloured dark blue. This is observed in Figure 3 where the initialised ECM fibres, as in Figure 2, are now coloured according to the number of cross-links.
2.2.3 Determining the nearest point on a fibre
A further geometrical problem is determining the nearest point on a fibre from any other given point, or more precisely, the displacement vector from a fibre to a point. This is calculated in PhysiMeSS_Fibre’ s method nearest_point_on_fibre and is used within the check_fibre_crosslinks method. It is also used to determine the the nearest point from a cell centre to a neighbouring fibre which we use to inform mechanical and chemical interactions between cells and fibres, see Section 2.3. Determining the nearest point on a fibre is discussed in more detail in Appendix C.
2.3 Fibre Specific Mechanics
The main purpose of introducing ECM agents as specific stand-alone agents rather than modelling them as a substrate or density is that we can more closely model the interaction between cells and ECM agents. For the purposes of this paper and associated release of PhysiMeSS we primarily mean mechanical interactions. Mechanical interactions are handled in PhysiMeSS (in an analogous way to PhysiCell) by potential functions which affect an agent’ s velocity. Thus, PhysiMeSS has a modified function physimess_update_cell_velocity which calls different potential functions as detailed in the following Section. We note that PhysiMeSS has been written with some basic simplified mechanical interactions as standard but the user is free to incorporate their own. Details of how the user can build in custom mechanical functions are included in Appendix D.
2.3.1 Potential Functions
There are four possible interactions to consider, namely, cell-cell interactions, cellfibre interactions fibre-cell interactions and fibre-fibre interactions, and so four different potential functions are considered. Cell-cell interactions are handled by PhysiCell as per the function add_potentials, we do not go into detail here, more details can be found in [7].
Cell-fibre interactions are cell interactions with neighbouring fibres which affect the velocity of the cell, i.e. describe how a fibre affects a cell. These interactions are contained within the method add_potentials_from_fibre of the PhysiMeSS_Cell class. Firstly, we include simple repulsion and adhesion between cells and fibres as per between cells, copying the behaviour in add_potentials. This prevents cells being able to go through fibres. Secondly, we introduce fibre-directed movement of cells as per [11] since cells are known to track along matrix fibres [4, 5]. We describe this briefly here, for more details please see [11]. We assume that cells move in response to a close neighbour fibre in two directions; an additional adhesive force, parallel to fibre orientation and an additional repulsive force orthogonal to the fibre (see, e.g., [2]) allowing the cell to track along the fibre.
The additional adhesive force takes the form It is directed along the normalised direction of the fibre, lf, and depends on the normalised scalar product between lf and v, the velocity of the cell. Moreover, the force depends on an adhesion coefficient, αfibre, and on a threshold velocity, vmax, which limits the pulling effect of fibres. In the PhysiMeSS code these parameters are called vel_adhesion and cell_velocity_max, respectively.
The additional repulsion force is modelled as friction exerted by the fibre and takes the form It is directed parallel to the cell’ s current velocity, v and is affected by the component of cell velocity orthogonal to the fibre. the strength of this force is dictated by, βfibre, a cell-fibre friction coefficient. In the PhysiMeSS code this parameter is called vel_contact. The additional cell-fibre interaction force is computed as the difference of these adhesion and repulsion terms, F = F∥ − F⊥.
Fibre-cell interactions are fibre interactions with neighbouring cells which affect the fibre. These interactions are contained within PhysiMeSS_Fibre’ s method add_potentials_from_cell. Any fibre-cell interaction can only take place if a fibre has no more than one cross-link with another fibre, otherwise we assume the fibre is fixed in place tethered by its cross-links.
A single fibre with no cross-links can be pushed and/or rotated by a motile cell. Whether pushing or rotation are turned on can be controlled by the user using the Boolean flags fibre_pushing and fibre_rotation. Cell-fibre pushing provides repulsion to the fibre, giving it speed and moving its center from its initial position. Cell-fibre rotation maintains the position of the fibre centre and modifies the coordinates of its extremities by changing the fibre orientation. The new fibre orientation is based on moment arm magnitude, impulse, and fibre length. The moment arm magnitude is determined using the Euclidean distance between the origin and the point of impact. The impulse is obtained by considering the the friction of the fibre (modified by the user with parameter fibre_sticky) and the speed of the interacting cell. The calculated impulse and fibre length are then used to determine the angular velocity, representing the rate of change of the fibre’ s orientation. Finally, the new orientation is obtained by rotating the old orientation vector using trigonometric functions. As a result, a cell impacting on a fibre end far from the centre will change the fibre’ s orientation faster than impacting closer to the centre. An example of fibre rotation is available in Cell_Fibre_Mechanics/fibre_rotating.xml, and can be visualized in Figure 4. The parameters controlling the fibre mechanics are defined as user parameter expressed in the .xml file and detailed in Table 2.
Fibre-fibre interactions are fibre interactions with neighbouring fibres. For this release we do not consider that there are fibre-fibre interactions. However, the method add_potentials_from_fibre is incorporated into the PhysiMeSS_Fibre class for future development.
2.3.2 Fibre Degradation
As discussed in the introduction to this paper, cellular remodelling of the ECM is a key process and an important interaction to consider between cells and matrix fibres. For the purpose of this release of PhysiMeSS we focus on matrix degradation. As well as degrading fibres, cells are responsible for creating new fibres and remodelling the ECM. The process of fibre generation by cells is not currently part of this release of PhysiMeSS but will be incorporated into a future release.
The degradation of the ECM plays a major role in tumor growth and invasion, for example. The key enzymes involved in this process are matrix metalloproteinases (MMPs). MMPs can be found both within the ECM, at the cell membrane level (MT-MMPs) or being secreted by the cell itself. Different MMPs have different ECM-component target but their main function is to cleave and degrade structural ECM proteins such as elastin and collagen [1].
Fibre degradation is modelled in PhysiMeSS as a simple process of removing fibres from the domain under certain conditions. Fibre degradation can be turned on or off by the user using the Boolean flag fibre_degradation, a user parameter in the .xml file. During cell-fibre interactions as controlled by add_potentials_from_fibre a fibre may be degraded if fibre degradation is turned on and further conditions are met, as detailed below. The fibre is then flagged for removal which, for simplicity, happens instantly.
The first condition which must be met in order for a fibre to be degraded relates to whether a cell is hindered by the presence of a fibre. This may either be because as a cell tries to migrate through the domain fibres are obstacles in the cell’ s path, or it may be because as cells proliferate they require additional space for the growing mass of cells. To target the first of these problems, the user can define a parameter fibre_stuck_time which determines how long a cell is stuck in a certain place before it will try to degrade/remove a fibre in its path. To determine whether a cell is stuck we check as part of the function physimess_update_cell_velocity whether the magnitude of a cell’ s velocity is below a given threshold defined by the parameter fibre_stuck_threshold. In order that cells only remove fibres in their path we consider the dot product of the cell’ s motility vector with the vector connecting the cell centre to the nearest point on the fibre, if this dot product is greater than zero a fibre is said to be in a cells path. A simple example of a cell migrating through the ECM and degrading cells along the way is available in Fibre_Degradation/mymodel_fibre_degradation.xml, and represented in Figure 5 To target the second issue, we defined a new class in custom.h, called PhysiMeSS_Fibre_Custom_Degrade, which is derived from the PhysiMeSS_Fibre class. This new class implements in custom.cpp a custom degradation function, as described in Appendix D. In this custom implementation, we check whether the pressure experienced by a cell is above a threshold fibre_pressure_threshold. In order to indicate the pressure experiences by a cell we have introduced an additional user Boolean flag which when set to true, colours the cells by the pressure they experience using color_cells_by_pressure. If either of the constraints outlined are satisfied and fibre degradation is turned on the the cell will degrade neighbouring fibres at a rate fibre_degradation_rate. The custom implementation is controlled by a Boolean parameter, fibre_custom_degradation.All the parameter describing the fibre degradation are controlled by user parameters expressed in the .xml file and detailed in Table 3.
3 Conclusions and planning for future releases
In this paper we have outlined the features and capabilities of the inaugural release of PhysiMeSS an add-on for PhysiCell. PhysiMeSS has been designed with explicitly modelling the ECM in mind by introducing new cylindrical/rod-shaped agents. As agents the components of the ECM can interact with and be affected by the cellular agents to permit detailed modelling of cell-fibre processes such as cell migration along and through the ECM network.
This release has naturally focused on laying the groundwork for introducing these new agents and tackling the geometrical and topological aspects which then permit cell-fibre interactions. We have introduced some basic mechanics which may be useful when modelling cell-fibre interactions but the user can add and expand to this using their own custom functions, see Appendix D.
For the next release of PhysiMeSS we will focus on two main aspects. Firstly, ensuring full 3D compatibility. At present, the potential inherent to the pushing and to the rotation of fibres is limited to 2 dimensions. PhysiCell/PhysiMeSS gives the user the possibility to switch between a 2D to a 3D representation, but does not take into account the modifications needed to rotate the fibres in 3D. Secondly, permitting fibrogenesis, i.e. the creation of new ECM fibres by cells.
Funding
This work was supported by the European Commission under the PerMedCoE project [H2020-ICT-951773] and by Inserm amorçage project. CKM gratefully acknowledges the support of her Rankin-Sneddon Fellowship at the University of Glasgow.
A New agents classes added with the PhysiMeSS addon
PhysiMeSS introduces new types of agents, derived from the Cell class that include more properties and behaviors. The first of them is PhysiMeSS_Agent, which directly inherits from Cell. The others are PhysiMeSS_Fibre and PhysiMeSS_Cell, which implements the fibres and the cells interacting with them, respectively, and directly inherits from PhysiMeSS_Agent (Figure 6).
PhysiMeSS_Agent adds two new properties : a list of voxels in which it is located, and a list of neighbors which can include both cells and fibres. The list of voxels will be built using the register_agent_voxels method, which is defined as virtual, meaning that its implementation can be different in the derived classes. Both PhysiMeSS_Cell and PhysiMeSS_Fibre are implementing it, with the difference that cells only span one voxel while fibres can span multiple voxels. The list of neighbors is then built using the find_agent_neighbors method using the find_agent_voxels method, both implemented in PhysiMeSS_Agent.
PhysiMeSS_Cell adds new components to PhysiMeSS_Agent related to their interaction with fibres, such as the potential function add_potentials_from_fibre which adds adhesion/repulsion forces. This method also calls the degrade_fibre method which can trigger the degradation of a fibre by the cell. Both of these methods are declared virtual, so that they can be overloaded if a user wants to modify their behavior. Another aspect added by PhysiMeSS_Cell concerns what to do if a cell becomes trapped in ECM. Two variables, stuck_counter and unstuck_counter, are used to quantify this and potentially trigger the force_updated_motility_vector method to force the movement of the cell.
Finally, the PhysiMeSS_Fibre adds components necessary to define the fibre, as well as components related to the interaction with cells and other fibres. To define the fibre, we need to defined its half length (variable mLength), its radius (variable mRadius). It’ s orientation is defined in the Cell variable orientation, which needs to be assigned via the assign_fibre_orientation method after the object is created. To deal with interaction with cells and fibres, we implemented the potential methods add_potentials_from_fibre and add_potentials_from_cell which adds forces from fibres or cells, respectively. Finally, to describe cross-links between fibres, we defined two variables fibres_crosslinkers and fibres_crosslink_points which are build using the method check_fibre_crosslinks.
B Adding cylindrical fibres to the tissue set-up
In order for PhysiMeSS to identify agents as cylindrical matrix fibres the user must give the cell definition a name containing any of the following recognised strings: {ecm, fiber, fibre, matrix, rod} . This will allow PhysiMeSS to properly recognized them using the isFibre function. Then in the function create_cell_types in custom.cpp, users must assign a function instantiating the proper class to the instantiate_cell function pointer in Cell_Functions. That will allow those cell types to be properly instantiated with the corresponding class. Note that the same should also be done with standard cell types, so that they can correctly interact with fibres. Fibres also need to have two specific function pointers assigned for correctly plotting them in the SVG : plot_agent_SVG and plot_agent_legend.
Fibres are initialised in the domain via the setup_tissue function in custom.cpp. If a .csv initial position file is provided, cells and fibres will be automatically created and isFibreFromFile will be turned to true. If there is no .csv file the number of fibres initialised is given by number_of_fibres and the number of cells by number_of_cells. User parameters which govern the length, radius and orientation angle of fibres are read from the .xml file (see Table 1). The length of fibres is normally distributed around a mean fibre_length with standard deviation length_normdist_sd. The radius of fibres is given by fibre_radius. The fibres will then have to be assigned an orientation via assign_fibre_orientation. Fibres can either be initialised isotropically or anisotropically within the domain controlled by the Boolean flag anisotropic_fibres. If anisotropic_fibres is false fibres are given a random orientation. If anisotropic_fibres is true the orientation of fibres is given as a angle from horizontal, this angle is normally distributed around a mean fibre_angle with standard deviation angle_normdist_sd and measured in radians. Finally, we need to check if fibres are out of bounds using check_out_of_bounds. Fibres which were determined to out of bounds will be removed via the call to remove_physimess_out_of_bounds_fibres.
C Geometrical Issues: fibre neighbours, fibre crosslinks and finding the nearest point on a fibre
Fibre Neighbours
Since long cylindrical agents may exist in multiple voxels we must be able to determine each such voxel in order to correctly identify possible agent neighbours and interactions. The PhysiMeSS_Agent method register_fibre_voxels determines each voxel which contains part of a fibre and registers the fibre to it. We start at one end of a fibre and sample voxels along the fibre at appropriate intervals no greater than the mechanics voxel size determined by PhysiCell. A fibre is registered a maximum of once to each unique voxel found in this way.
The PhysiMeSS_Agent method find_agent_voxels creates a unique list of all the voxels any agent has been registered to and all adjacent voxels, and stores it in the PhysiMeSS_Agent variable physimess_voxels. If the agent is a fibre this will be the multiple voxels determined by register_fibre_voxels and all voxels which are adjacent to any of those voxels. If the agent is a cell this will be the single voxel containing its centre and any adjacent voxels. In each case this function determines a unique list of voxels that could contain neighbour agents.
The PhysiMeSS_Agent method find_agent_neighbors determines if other agents sit within any of the voxels found in the list generated by find_agent_voxels. Any such agents are then declared neighbours of the the original agent and added to a list of neighbours defined in the PhysiMeSS_Agent variable physimess_neighbors.
The PhysiMeSS_Fibre method deregister_fibre_voxels takes all of the voxels a fibre has been registered to and de-registers it from all bar the voxel containing its centre.
Nearest Point on Fibre
The PhysiMeSS_Fibre method nearest_point_on_fibre determines for any given point and any given fibre the displacement vector connecting the point to the the nearest point on the fibre. This displacement vector can then be used to determine the shortest distance between a point and a fibre to compare with interaction distances or used alone to dictate the direction of forces between cells and fibres. The algorithm for determining the displacement vector from a fibre, f, to a point, p, is as follows:
Select one endpoint of the fibre, fe, and determine the vector which points from fe to p, i.e. .
Determine the dot product between the vector, and .
If the dot product is less than zero the nearest point on the fibre is the chosen endpoint and the displacement vector is .
If the dot product is greater than the square of the fibre length, , then the nearest point on the fibre in the other end of the fibre and the displacement vector is .
If the dot product is greater than zero but less than the square of the fibre length then the nearest point lies along the fibre. We calculate the distance, l along the fibre from the the original endpoint to this point by projecting through an angle θ which is the angle between and and is easily calculated from . Thus, and the displacement vector we require is .
Checking Fibre cross-links
The PhysiMeSS_Fibre method check_fibre_crosslinks checks if there are any intersections between two given fibres. If an intersection is detected, it will be added to the list of cross-linkers of both fibres. The function takes into account the spatial disposition of the two fibres verifying the intersection and proximity of the two fibres based on their geometric properties. Given a fibre fa and its neighboring fibre fb (Figure 7), the possible intersection is determined as follows:
Calculate fibre fa endpoints f1e, f2e and fiber fb endpoints f3e and f4e using their positions, lengths, and orientations.
Determine the vector that represents the direction from f1e to , f3e to , f1e to and finally the vector for the direction from center to center . These vectors are calculated by subtracting the corresponding coordinates of the endpoint positions i.e. .
Check if the fibres are co-planar and parallel by calculating the cross products of and , and then verifying that the dot product of with itself is zero, i.e. and .
Condition 1: if the vector is parallel or anti-parallel to the current fibre orientation and the center to center distance, i.e. , is less than or equal to a reference length (equal to half the length of fa and half the length of fb), then a cross-link is identified.
Check if the neighbour fibre, fb is stacked with fa so that fibres are non coplanar but parallel/anti-parallel. Check distances (D1 and D2) between fibre endpoints, f1e, f2e and the point on fibre fb which is nearest to fibre fa, taking advantage of the function nearest_point_on_fibre.
Condition 2: if either the distance D1 or D2 is less than a reference length (equal to the sum of the radii of the two fibres) but the vector is not parallel or anti-parallel to the current fibre orientation, then a cross-link is identified.
Check if the fibres are co-planar, skewed but intersect. This typically requires the scalar triple product to be zero. Since we also allow the case where the fibres are skewed but stacked non co-planar we compare the scalar triple product (between , and ) to a reference value equal to the sum of the radii. To determine if the skewed fibres intersect we determine line equations for each of the form La: f1e + t1(f1e − f2e); Lb: f3e + t2(f3e − f4e). Setting these equal to one another and resolving the t1 and t2 values.
Condition 3: if t1 and t2 both lie within [0, 1] allowing for a tolerance (equal to sum of the radii of the two fibres normalised by the sum of the two fibres half-lengths), then a cross-link is identified.
D User Customisation of PhysiMeSS
The user can modify much of what is documented and described in this paper simply by changing user parameters, see Tables 1, 2 and 3. However, they may also wish to include their own (mechanical) interactions between cells and fibres.
To do this, PhysiMeSS allows users to create a new class to implement new variations of the potential and degradation functions, derived from PhysiMeSS_Fibre and PhysiMeSS_Cell . The PhysiMeSS_Cell method add_potentials_from_fibre and the PhysiMeSS_Fibre methodsdegrade_fibre, add_potentials_from_cell, and add_potentials_from_fibre are all declared as virtual methods, allowing derived classes to overload them. Users then need to create functions instantiating these new derived classes and select them in the instantiate_cell function pointer of the desired cell definition.
To show such a possibility we added an example of a new degradation function which uses pressure exerted on cells to increase the probability of degradation, used in the example Fibre_Degradation/mymodel_matrix_degradation.xml. We start by declaring a new class PhysiMeSS_Cell_Custom_Degrade in custom.h which inherits from PhysiMeSS_Cell, and declaring one method degrade_fibre which will overload the one in PhysiMeSS_Cell.
Then in custom.cpp we define this new method :
Then we define a new function to instantiate this new object :
that we finally use in the instantiate_cell function pointer :
The same construct can be applied with potential functions, which will allow the advanced user to modify the mechanical interactions between cells and fibres.