This repository provides a library for development and simulation of PDE-based spatial tumor growth models, as well as implementations of specific tumor growth models. It is being developed as part of the 'Glioma Mass-Effect Simulator' (GlimS) project to investigate the role of tumor-induced mass-effect for tumor evolution and treatment.
GlimSLib aims to support implementation of new and extension of existing tumor growth models by providing a consistent simulation interface across model specifications. Various convenience functions are included in GlimSLib to facilitate model instantiation and analysis:
- Creation of simulation domains from segmented (medical) images
- Initialization of tissue-specific simulation parameters and boundary conditions on these domains.
- Storing, and plotting simulation results.
Inverse-problems can be adressed using the dolfin-adjoint library.
The following growth models have been implemented in GlimSLib and are included in this repository:
- mechanically-coupled reaction-diffusion model
These instructions will get you a copy of the project up and running on your local machine.
This version of GlimSLib has been developed against FEniCS 2017.2.0 (python 3.5) and the corresponding dolfinadjoint/libadjoint version.
First, clone this repository into <path_to_glimslib_dir> on your local machine. You need git-lfs to download images and meshed used in some of the examples.
git clone email@example.com:danielabler/glimslib.git
The easiest way to set up the project dependencies is by using the dockerfile description contained in this repository.
A docker file description of the development setup is located in /dockerfiles/2017.2.0_libadjoint. This file extends the official dolfin-adjoint images with additional python libraries needed for GlimSLib.
Get Docker for your system.
Build Docker image from dockerfile
cd dockerfiles/2017.2.0_libadjoint docker build -t glimslib_image .
Create Docker container from image
docker run --name glimslib -w /opt/project -v <path_to_glimslib_dir>:/opt/project -t glimslib_image:latest
- working directory in container: /opt/project
- share local (on host) directory <path_to_glimslib_dir> with container in /opt/project
You can stop / restart this container by
docker stop glimslib docker start glimslib
Connect to running container
docker exec -ti -u fenics glimslib /bin/bash -l
For more information about the dockerfile, see /dockerfiles/2017.2.0_libadjoint/README.md.
As the development of dolfinadjoint/libadjoint has been discontinued, we plan to update GlimSLib to be compatible with future versions of dolfinadjoint/pyadjoint (FENICS 2018.1.0, python 3.6, and later).
Alternative Installation Methods
Please see the dolfin-adjoint installation pages for alternative installation methods of FEniCS and dolfin-adjoint.
In addition, the python packages listed in dockerfiles/2017.2.0_libadjoint/requirements.txt are required.
pip install --trusted-host pypi.python.org -r dockerfiles/2017.2.0_libadjoint/requirements.txt
Running the Tests
We use unittest for simple function tests. Unittests for a class or function are located in the same directory where the class/function is defined. All unittest files are prefixed with 'test_unit_*' and can therefore be run by:
python3 -m unittest discover -p '*test_unit_*'
Tests can also be run using nose:
And to only show available tests:
nosetests -v --collect-only
Computationally more expensive tests and usage examples for specific model implementations are provided in script form in the directory test_cases/<model_name>.
For example, to run a forward simulation of the
simulation_tumor_growth model on a simple 2D domain with 2 subdomains, do:
and inspect the output in output/test_cases/simulation_tumor_growth/test_case_simulation_tumor_growth_2D_subdomains.
The documentation is based on sphinx. Compile by:
cd docs make html
Further Configuration Options
FEniCS and dolfin-adjoint support parallel execution via mpirun. Therefore any GlimSLib model can, in principle, be executed in parallel.
However, various support functions in GlimSLib do not currently support mpi. For example, GlimSLib does not ensure that results of distributed computations are correctly collected in the simulation.helper_classes.Results class. Therefore, plotting during and after computation (simulation.helper_classesPostprocess) may not be working correctly. Also, VTK output is not supported in mpi run mode.
Therefore execute the
run command with the following attributes:
sim.run(save_method='xdmf', plot=False, output_dir=output_path, clear_all=False)
For example, see test_cases/test_simulation_tumor_growth/test_case_simulation_tumor_growth_2D_uniform_mpi.py
mpirun -np 4 python3 test_cases/test_simulation_tumor_growth/test_case_simulation_tumor_growth_2D_uniform_mpi.py
Imported meshes need to be loaded from hdf5 in parallel execution. The following scripts illustrate how
2D from image grid
- an image is converted to a 2D FEniCS mesh and saved as hdf5
- this 2D mesh is loaded and used during parallel execution
mpirun -np 4 python3 test_cases/test_simulation_tumor_growth/test_case_simulation_tumor_growth_2D_atlas_mpi.py
3D from VTK mesh:
- an existing 3D vtk mesh (unstructured grid - VTU) is converted to a FEniCS mesh and saved as hdf5
- this 3D mesh is loaded and used during parallel execution
mpirun -np 4 python3 test_cases/test_simulation_tumor_growth/test_case_simulation_tumor_growth_3D_atlas_mpi.py
FENICS vs dolfin-adjoint
Dolfin-adjoint works by redefining some of the base FEniCS commands. Usage of dolfin-adjoint therefore typically requires:
from fenics import * from dolfin_adjoint import *
I found it preferable to import dolfin-adjoint only when it is actually needed, and work with standard FEniCS otherwise. At the same time, we need to make sure that all GlimSLib modules work either with standard FEniCS commands or with their dolfin-adjoint extended version. Mixing both imports results in internal errors.
GlimSLib uses the following mechanism for context-dependent global switching between these import options:
We define a pseudo module
fenics_local in the root of the project which imports either FEniCS,
or FEniCS and dolfin-adjoint simultaneously, depending on the variable
USE_ADJOINT in the config.py file.
Most GlimSLib modules and functions use
import config.py to identify path settings.
To activate dolfin-adjoint, include the following lines before importing any other GlimS modules.
import config config.USE_ADJOINT = True
Then to import FEniCS / FEniCS with dolfin-adjoint, simply do
from fenics_local import *
or a more fine-grained import statement. Such an import statement is also included in any other module that depends FEniCS / FEniCS with dolfin-adjoint packages.
For usage examples compare
- no adjoint: test_cases/test_simulation_tumor_growth/test_case_simulation_tumor_growth_2D_uniform.py
- with adjoint: test_cases/test_simulation_tumor_growth/test_case_simulation_tumor_growth_2D_uniform_adjoint.py
Matplotlib Settings & Backend
All project specific matplotlib settings are handled by the matplotlibrc file in the project root. For this file to be considered by matplotlib, the working directory needs to be set to the project root.
The easiest way to install and use this project is via docker containers, see the installation instructions above. However, interactive plotting from these containers is troublesome; a possible workaround is described in README file of the included dockerfile specifications.
To ensure that the local matplotlibrc is used regardless of the working directory, the environment
MATPLOTLIBRC must be set to point to the configuration file in the project directory:
The included dockerfile specification takes care of this.
To be able to switch globally between interactive and non-interactive plotting, change the plotting backend in matplotlibrc in the project root, e.g.
Aggfor raster graphics
Cairofor vector graphics
plt.show(), use the helper functions provided by the
import visualisation.helpers as vh # plot something vh.show_plot()
If an interactive backend is selected, this command behaves as
If a non-interactive backend is selected, it will save the generated image in a temporary folder output/tmp_plots and name it by the current date-time.
Development with PyCharm & Docker
PyCharm (Professional) can use a docker image (i.e. docker containers created from this image) as remote interpreter.
In the default configuration, PyCharm's working directory on the docker container is /opt/project. However, the "Run File in Console" command calls the remote python interpreter using the host project path by default. This fails for obvious reasons...
To fix this problem, map the local project path to the project's remote path, i.e. in Preferences -> Project -> Project Interpreter -> Path Mappings define the mapping /local/path/to/project -> /project/opt.
This project is licensed under the MIT License - see the LICENSE file for details