Repository: a-r-j/graphein (language: python)

Issue:
WIP: Add Dockerfile
#### Details

```
FROM pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime
```
I initially started from Ubuntu/Debian base images but quickly found that installing CUDA and the corresponding version of Pytorch can be troublesome, thus I opted to use the official Pytorch images as they come with CUDA, Pytorch and conda installed. 

```
RUN apt-get update \
    && apt-get -y install build-essential ffmpeg libsm6 libxext6 wget git \
    && rm -rf /var/lib/apt/lists/*
```
These dependencies are required prerequisites.

```
ENV CONDA_ALWAYS_YES=true
```
This is simply sets the `-y` flag by default when installing Conda libs.

```
SHELL ["conda", "run", "-n", "graphein", "/bin/bash", "-c"]
```
There appear to be a couple of ways to enable a Conda environment in a Dockerfile, for a complete explanation of this approach please see this [article](https://pythonspeed.com/articles/activate-conda-dockerfile/).

```
RUN python -m ipykernel install --user --name=graphein
```
This simply installs ipykernel and makes the graphein Conda environment available within Jupiter notebooks.

```
RUN export TORCH=1.7.1 \
    && export CUDA=cu110 \
    && pip install torch-scatter -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-sparse -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-cluster -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-spline-conv -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-geometric
```
TODO: I believe it would be preferable to install `torch-geommetric` using `RUN conda install pytorch-geometric -c rusty1s -c conda-forge -v` but I haven't been able to get it to work due to libc related errors.

```
ENTRYPOINT ["conda", "run", "-n", "graphein", "jupyter", "notebook", "--notebook-dir=/opt/notebooks",  "--ip='*'", "--NotebookApp.token=''", "--NotebookApp.password=''", "--port=8888",  "--no-browser", "--allow-root"]
```
Running this Docker image starts a Jupiter notebook server without a password at localhost:8888.

#### What testing did you do to verify the changes in this PR?

I have verified that most examples from the main Graphein docs work using this setup, however further testing is advised. Especially when it comes to using CUDA. 

WIP: Add Dockerfile
#### Details

```
FROM pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime
```
I initially started from Ubuntu/Debian base images but quickly found that installing CUDA and the corresponding version of Pytorch can be troublesome, thus I opted to use the official Pytorch images as they come with CUDA, Pytorch and conda installed. 

```
RUN apt-get update \
    && apt-get -y install build-essential ffmpeg libsm6 libxext6 wget git \
    && rm -rf /var/lib/apt/lists/*
```
These dependencies are required prerequisites.

```
ENV CONDA_ALWAYS_YES=true
```
This is simply sets the `-y` flag by default when installing Conda libs.

```
SHELL ["conda", "run", "-n", "graphein", "/bin/bash", "-c"]
```
There appear to be a couple of ways to enable a Conda environment in a Dockerfile, for a complete explanation of this approach please see this [article](https://pythonspeed.com/articles/activate-conda-dockerfile/).

```
RUN python -m ipykernel install --user --name=graphein
```
This simply installs ipykernel and makes the graphein Conda environment available within Jupiter notebooks.

```
RUN export TORCH=1.7.1 \
    && export CUDA=cu110 \
    && pip install torch-scatter -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-sparse -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-cluster -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-spline-conv -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html \
    && pip install torch-geometric
```
TODO: I believe it would be preferable to install `torch-geommetric` using `RUN conda install pytorch-geometric -c rusty1s -c conda-forge -v` but I haven't been able to get it to work due to libc related errors.

```
ENTRYPOINT ["conda", "run", "-n", "graphein", "jupyter", "notebook", "--notebook-dir=/opt/notebooks",  "--ip='*'", "--NotebookApp.token=''", "--NotebookApp.password=''", "--port=8888",  "--no-browser", "--allow-root"]
```
Running this Docker image starts a Jupiter notebook server without a password at localhost:8888.

#### What testing did you do to verify the changes in this PR?

I have verified that most examples from the main Graphein docs work using this setup, however further testing is advised. Especially when it comes to using CUDA. 

[INF] Introduce code style continuous integration checks
@a-r-j adding some code style continuous integration checks!

I'd recommend doing a squash merge rather than a direct merge commit. It'll keep the commit history a bit cleaner.


Discussion / hints:
Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; ![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=a-r-j_graphein&pullRequest=69&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=a-r-j_graphein&pullRequest=69&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=a-r-j_graphein&pullRequest=69&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=a-r-j_graphein&pullRequest=69) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=a-r-j_graphein&pullRequest=69&metric=duplicated_lines_density&view=list) No Duplication information


Hi @jadechip, have you tested/elaborated on this any? Do you think it's ready for a merge?
Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; ![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=a-r-j_graphein&pullRequest=69&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=a-r-j_graphein&pullRequest=69&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=a-r-j_graphein&pullRequest=69&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=a-r-j_graphein&pullRequest=69&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=a-r-j_graphein&pullRequest=69) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=a-r-j_graphein&pullRequest=69&metric=duplicated_lines_density&view=list) No Duplication information


Hi @jadechip, have you tested/elaborated on this any? Do you think it's ready for a merge?
LGTM

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 059c30bc..e095ca3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
+### 1.0.12 - UNRELEASED
+
+* [Packaging] - #100 adds docker support.
+
 ### 1.0.11 - 01/02/2022
+
 * [Improvement] - #79 Replaces `Literal` references with `typing_extensions.Literal` for Python 3.7 support.
 
 #### 1.0.10 - 23/12/2021
 
-* [Bug] Adds a fix for #74. Adding a disulfide bond to a protein with no disulphide bonds would fail. This was fixed by adding a check for the presence of a minimum of two CYS residues.
\ No newline at end of file
+* [Bug] Adds a fix for #74. Adding a disulfide bond to a protein with no disulphide bonds would fail. This was fixed by adding a check for the presence of a minimum of two CYS residues.
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index a2500a36..c47c4ab6 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -1,12 +1,14 @@
 # Contributing to Graphein
+
 Contribution is always welcomed. A good starting place is the roadmap issue, where you can find our current milestones. All contributions must go through pull requests and be reviewed by the committers. See our contribution guide for more details.
 
 Once your contribution is accepted and merged, congratulations, you are now a contributor to the Graphein project. We will put your name in the list below.
 
-##Contributors
+## Contributors
+
 Arian Jamasb: [@a-r-j](https://github.com/a-r-j)
 
-Eric J. Ma: [@ericmjl](https://github.com/ericmjl) 
+Eric J. Ma: [@ericmjl](https://github.com/ericmjl)
 
 Ramon Vinas: [@rvinas](https://github.com/rvinas)
 
@@ -16,4 +18,6 @@ Dominic Hall: [@dhall1995](https://github.com/dhall1995)
 
 Kexin Huang: [@kexinhuang12345](https://github.com/kexinhuang12345)
 
-Sean Aubi: [@Seanny123](https://github.com/Seanny123)
+Sean Aubin: [@Seanny123](https://github.com/Seanny123)
+
+Ryan Greenhalgh: [@rg314](https://github.com/rg314)
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..4f7cd11d
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,56 @@
+FROM pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime
+
+
+RUN apt-get update \
+    && apt-get -y install build-essential ffmpeg libsm6 libxext6 wget git \
+    && rm -rf /var/lib/apt/lists/*
+
+# get iputils-ping for tests
+RUN apt-get update && apt-get install -y iputils-ping && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+ENV CONDA_ALWAYS_YES=true
+
+
+RUN mkdir -p graphein/requirements
+WORKDIR /graphein
+
+
+COPY .requirements /graphein/requirements
+RUN echo "$(cat requirements/base.in)" >> requirements.txt \
+    && echo "$(cat requirements/dev.in)" >> requirements.txt \
+    && echo "$(cat requirements/extras.in)" >> requirements.txt
+
+RUN pip install -r requirements.txt --no-cache-dir
+
+RUN conda install -c conda-forge libgcc-ng
+RUN conda install scipy scikit-learn matplotlib pandas cython ipykernel
+RUN pip install ticc==0.1.4 --no-cache-dir
+
+# # Set up vmd-python library
+RUN conda install -c conda-forge vmd-python
+# RUN conda install -c https://conda.anaconda.org/rbetz vmd-python
+
+# Set up getcontacts library
+RUN git clone https://github.com/getcontacts/getcontacts.git
+ENV PATH /getcontacts:$PATH
+
+RUN conda install -c fvcore -c iopath -c conda-forge fvcore iopath
+RUN conda install -c pytorch3d pytorch3d
+RUN conda install -c dglteam dgl
+
+ARG CUDA TORCH
+# gcc error with version 2.0.9. Therefore, using 2.0.8
+# install torch-geometric components separately in case of fail
+RUN pip install torch-scatter==2.0.7 -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html --no-cache-dir
+RUN pip install torch-sparse -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html --no-cache-dir
+RUN pip install torch-cluster -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html --no-cache-dir
+RUN pip install torch-spline-conv -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html --no-cache-dir
+RUN pip install torch-geometric --no-cache-dir
+
+
+# Testing
+# docker-compose -f docker-compose.cpu.yml up -d --build
+# docker exec -it $(docker-compose ps -q) bash -c 'pip install -e .'
+# docker exec -it $(docker-compose ps -q) bash -c 'pytest .'
+# docker exec -it $(docker-compose ps -q) bash -c 'grep -l smoke_test notebooks/*.ipynb | pytest --nbval-lax --current-env'
diff --git a/README.md b/README.md
index 2d4484e7..24e776c5 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ Protein & Interactomic Graph Library
 This package provides functionality for producing geometric representations of protein and RNA structures, and biological interaction networks. We provide compatibility with standard PyData formats, as well as graph objects designed for ease of use with popular deep learning libraries.
 
 ## What's New?
+
 * [Protein Graph Creation from AlphaFold2!](http://graphein.ai/notebooks/alphafold_protein_graph_tutorial.html)
 * [Protein Graph Visualisation!](http://graphein.ai/notebooks/protein_mesh_tutorial.html)
 * [RNA Graph Construction from Dotbracket notation](http://graphein.ai/modules/graphein.rna.html)
@@ -31,7 +32,9 @@ This package provides functionality for producing geometric representations of p
 * [High and Low-level API for massive flexibility - create your own bespoke workflows!](http://graphein.ai/notebooks/residue_graphs.html)
 
 ## Example usage
+
 ### Creating a Protein Graph
+
 [Tutorial (Residue-level)](http://graphein.ai/notebooks/residue_graphs.html) [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/a-r-j/graphein/blob/master/notebooks/residue_graphs.ipynb) | [Tutorial - Atomic](http://graphein.ai/notebooks/atom_graph_tutorial.html) [![Open In Colab(https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/a-r-j/graphein/blob/master/notebooks/atom_graph_tutorial.ipynb) | [Docs](http://graphein.ai/modules/graphein.protein.html#module-graphein.protein.graphs)
 
 ```python
@@ -43,7 +46,9 @@ g = construct_graph(config=config, pdb_code="3eiy")
 ```
 
 ### Creating a Protein Graph from the AlphaFold Protein Structure Database
+
  [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/a-r-j/graphein/blob/master/notebooks/residue_graphs.ipynb) [Tutorial](http://graphein.ai/notebooks/alphafold_protein_graph_tutorial.html) | [Docs](http://graphein.ai/modules/graphein.protein.html#module-graphein.protein.graphs)
+
 ```python
 from graphein.protein.config import ProteinGraphConfig
 from graphein.protein.graphs import construct_graph
@@ -55,15 +60,20 @@ g = construct_graph(config=config, pdb_path=fp)
 ```
 
 ### Creating a Protein Mesh
+
 [Tutorial](http://graphein.ai/notebooks/protein_mesh_tutorial.html) | [Docs](http://graphein.ai/modules/graphein.protein.html#module-graphein.protein.meshes)
+
 ```python
 from graphein.protein.config import ProteinMeshConfig
 from graphein.protein.meshes import create_mesh
 
 verts, faces, aux = create_mesh(pdb_code="3eiy", config=config)
 ```
+
 ### Creating an RNA Graph
+
 Tutorial | [Docs](http://graphein.ai/modules/graphein.rna.html)
+
 ```python
 from graphein.rna.graphs import construct_rna_graph
 # Build the graph from a dotbracket & optional sequence
@@ -72,7 +82,9 @@ rna = construct_rna_graph(dotbracket='..(((((..(((...)))..)))))...',
 ```
 
 ### Creating a Protein-Protein Interaction Graph
+
 [Tutorial](http://graphein.ai/notebooks/ppi_tutorial.html) | [Docs](http://graphein.ai/modules/graphein.ppi.html)
+
 ```python
 from graphein.ppi.config import PPIGraphConfig
 from graphein.ppi.graphs import compute_ppi_graph
@@ -88,7 +100,9 @@ g = compute_ppi_graph(config=config,
 ```
 
 ### Creating a Gene Regulatory Network Graph
+
 [Tutorial](http://graphein.ai/notebooks/grn_tutorial.html) | [Docs](http://graphein.ai/modules/graphein.grn.html)
+
 ```python
 from graphein.grn.config import GRNGraphConfig
 from graphein.grn.graphs import compute_grn_graph
@@ -107,8 +121,11 @@ g = compute_grn_graph(
 ```
 
 ## Installation
+
 ### Pip
+
 The simplest install is via pip. *N.B this does not install ML/DL libraries which are required for conversion to their data formats and for generating protein structure meshes with PyTorch 3D.* [Further details]
+
 ```bash
 pip install graphein # For base install
 pip install graphein[extras] # For additional featurisation dependencies
@@ -139,7 +156,9 @@ get_dynamic_contacts.py --topology 5xnd_topology.pdb \
 ```
 
 ### Conda environment
+
 The dev environment includes GPU Builds (CUDA 11.1) for each of the deep learning libraries integrated into graphein.
+
 ```bash
 git clone https://www.github.com/a-r-j/graphein
 cd graphein
@@ -157,7 +176,15 @@ pip install -e .
 ```
 
 ### Dockerfile
-We also provide a [Dockerfile](https://github.com/a-r-j/graphein/pull/69)
+
+We provide two `docker-compose` files for CPU (`docker-compose.cpu.yml`) and GPU usage (`docker-compose.yml`) locally. For GPU usage please ensure that you have [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html) installed. Ensure that you install the locally mounted volume after entering the container (`pip install -e .`). This will also setup the dev environment locally.
+
+To build (GPU) run:
+
+```
+docker-compose up -d --build # start the container
+docker-compose down # stop the container
+```
 
 ## Citing Graphein
 
@@ -165,16 +192,16 @@ Please consider citing graphein if it proves useful in your work.
 
 ```bibtex
 @article {Jamasb2020.07.15.204701,
-	author = {Jamasb, Arian R. and Vi{\~n}as, Ramon and Ma, Eric J. and Harris, Charlie and Huang, Kexin and Hall, Dominic and Li{\'o}, Pietro and Blundell, Tom L.},
-	title = {Graphein - a Python Library for Geometric Deep Learning and Network Analysis on Protein Structures and Interaction Networks},
-	elocation-id = {2020.07.15.204701},
-	year = {2021},
-	doi = {10.1101/2020.07.15.204701},
-	publisher = {Cold Spring Harbor Laboratory},
-	abstract = {Geometric deep learning has well-motivated applications in the context of biology, a domain where relational structure in datasets can be meaningfully leveraged. Currently, efforts in both geometric deep learning and, more broadly, deep learning applied to biomolecular tasks have been hampered by a scarcity of appropriate datasets accessible to domain specialists and machine learning researchers alike. However, there has been little exploration of how to best to integrate and construct geometric representations of these datatypes. To address this, we introduce Graphein as a turn-key tool for transforming raw data from widely-used bioinformatics databases into machine learning-ready datasets in a high-throughput and flexible manner. Graphein is a Python library for constructing graph and surface-mesh representations of protein structures and biological interaction networks for computational analysis. Graphein provides utilities for data retrieval from widely-used bioinformatics databases for structural data, including the Protein Data Bank, the recently-released AlphaFold Structure Database, and for biomolecular interaction networks from STRINGdb, BioGrid, TRRUST and RegNetwork. The library interfaces with popular geometric deep learning libraries: DGL, PyTorch Geometric and PyTorch3D though remains framework agnostic as it is built on top of the PyData ecosystem to enable inter-operability with scientific computing tools and libraries. Graphein is designed to be highly flexible, allowing the user to specify each step of the data preparation, scalable to facilitate working with large protein complexes and interaction graphs, and contains useful pre-processing tools for preparing experimental files. Graphein facilitates network-based, graph-theoretic and topological analyses of structural and interaction datasets in a high-throughput manner. As example workflows, we make available two new protein structure-related datasets, previously unused by the geometric deep learning community. We envision that Graphein will facilitate developments in computational biology, graph representation learning and drug discovery.Availability and implementation Graphein is written in Python. Source code, example usage and tutorials, datasets, and documentation are made freely available under the MIT License at the following URL: graphein.aiCompeting Interest StatementThe authors have declared no competing interest.},
-	URL = {https://www.biorxiv.org/content/early/2021/10/12/2020.07.15.204701},
-	eprint = {https://www.biorxiv.org/content/early/2021/10/12/2020.07.15.204701.full.pdf},
-	journal = {bioRxiv}
+ author = {Jamasb, Arian R. and Vi{\~n}as, Ramon and Ma, Eric J. and Harris, Charlie and Huang, Kexin and Hall, Dominic and Li{\'o}, Pietro and Blundell, Tom L.},
+ title = {Graphein - a Python Library for Geometric Deep Learning and Network Analysis on Protein Structures and Interaction Networks},
+ elocation-id = {2020.07.15.204701},
+ year = {2021},
+ doi = {10.1101/2020.07.15.204701},
+ publisher = {Cold Spring Harbor Laboratory},
+ abstract = {Geometric deep learning has well-motivated applications in the context of biology, a domain where relational structure in datasets can be meaningfully leveraged. Currently, efforts in both geometric deep learning and, more broadly, deep learning applied to biomolecular tasks have been hampered by a scarcity of appropriate datasets accessible to domain specialists and machine learning researchers alike. However, there has been little exploration of how to best to integrate and construct geometric representations of these datatypes. To address this, we introduce Graphein as a turn-key tool for transforming raw data from widely-used bioinformatics databases into machine learning-ready datasets in a high-throughput and flexible manner. Graphein is a Python library for constructing graph and surface-mesh representations of protein structures and biological interaction networks for computational analysis. Graphein provides utilities for data retrieval from widely-used bioinformatics databases for structural data, including the Protein Data Bank, the recently-released AlphaFold Structure Database, and for biomolecular interaction networks from STRINGdb, BioGrid, TRRUST and RegNetwork. The library interfaces with popular geometric deep learning libraries: DGL, PyTorch Geometric and PyTorch3D though remains framework agnostic as it is built on top of the PyData ecosystem to enable inter-operability with scientific computing tools and libraries. Graphein is designed to be highly flexible, allowing the user to specify each step of the data preparation, scalable to facilitate working with large protein complexes and interaction graphs, and contains useful pre-processing tools for preparing experimental files. Graphein facilitates network-based, graph-theoretic and topological analyses of structural and interaction datasets in a high-throughput manner. As example workflows, we make available two new protein structure-related datasets, previously unused by the geometric deep learning community. We envision that Graphein will facilitate developments in computational biology, graph representation learning and drug discovery.Availability and implementation Graphein is written in Python. Source code, example usage and tutorials, datasets, and documentation are made freely available under the MIT License at the following URL: graphein.aiCompeting Interest StatementThe authors have declared no competing interest.},
+ URL = {https://www.biorxiv.org/content/early/2021/10/12/2020.07.15.204701},
+ eprint = {https://www.biorxiv.org/content/early/2021/10/12/2020.07.15.204701.full.pdf},
+ journal = {bioRxiv}
 }
 
 ```
diff --git a/docker-compose.cpu.yml b/docker-compose.cpu.yml
new file mode 100644
index 00000000..6bf3d560
--- /dev/null
+++ b/docker-compose.cpu.yml
@@ -0,0 +1,14 @@
+version: "3.3"
+
+services:
+    graphein-cpu:
+        image: 'graphein-cpu:latest'
+        build:
+            context: ./
+            dockerfile: Dockerfile
+            args:
+                CUDA: cpu
+                TORCH: '1.7.1'
+        volumes:
+            - ./:/graphein
+        command: tail -f /dev/null
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..34eaf5cf
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,21 @@
+version: "3.3"
+
+services:
+  graphein-gpu:
+    image: 'graphein-gpu:latest'
+    build:
+      context: ./
+      dockerfile: Dockerfile
+      args:
+        CUDA: cpu
+        TORCH: '1.7.1'
+    volumes:
+      - ./:/graphein
+    command: tail -f /dev/null
+    ipc: host
+    deploy:
+      resources:
+        reservations:
+          devices:
+            - capabilities: [ gpu ]
+              driver: nvidia


Test patch:
diff --git a/.github/workflows/code-tests-docker.yaml b/.github/workflows/code-tests-docker.yaml
new file mode 100644
index 00000000..a57cc4c1
--- /dev/null
+++ b/.github/workflows/code-tests-docker.yaml
@@ -0,0 +1,51 @@
+name: Code tests (docker)
+
+on: [pull_request]
+
+jobs:
+  code-tests-docker:
+    name: Run code tests (docker)
+    runs-on: "ubuntu-18.04"
+
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v2
+
+      # See: https://github.com/marketplace/actions/setup-conda
+      - name: Setup anaconda
+        uses: s-weigand/setup-conda@v1
+        with:
+          python-version: 3.8
+          conda-channels: "conda-forge"
+
+      # # Build cache of environment
+      # - name: Cache conda environment
+      #   id: cache-environment
+      #   uses: actions/cache@v2
+      #   # Conda environment build step depends on two files,
+      #   # so we ensure that the hash key contains both their hashes.
+      #   with:
+      #     path: |
+      #       /usr/share/miniconda/envs/graphein-dev/
+      #     key: ${{ runner.os }}-env.${{ hashFiles('environment-dev.yml') }}
+
+      - name: Build Docker container
+        # if: steps.cache-environment.outputs.cache-hit != 'true'
+        run: |
+          docker-compose -f docker-compose.cpu.yml up -d --build
+
+      - name: Install Graphein (Docker)
+        run: |
+          docker exec $(docker ps -q) bash -c 'pip install -e .'
+
+      - name: Run tests (Docker)
+        run: |
+          docker exec $(docker ps -q) bash -c 'pytest .'
+
+      - name: Run example notebooks (Docker)
+        run: |
+          docker exec $(docker ps -q) bash -c 'grep -l smoke_test notebooks/*.ipynb | pytest --nbval-lax --current-env'
+
+      - name: Upload code coverage
+        run: |
+          bash <(curl -s https://codecov.io/bash)