diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000000000000000000000000000000000000..47db81d63d258bb791cfc8dbd7176492fd9c496f
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,6 @@
+[flake8]
+max-line-length=120
+exclude=pystencils/jupytersetup.py,
+        pystencils/plot2d.py
+        pystencils/session.py
+ignore = W293 W503 W291
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..73c1ace7cf8cf1d79984375aa3f6db811804a3be
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+__pycache__
+.ipynb_checkpoints
+.coverage
+*.pyc
+*.vti
+/build
+/dist
+/*.egg-info
+.cache
+_build
+/.idea
+.cache
+_local_tmp
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..dcb0ef62e71da29674eb056d1782bc62ecc15aa9
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,133 @@
+stages:
+  - test
+  - deploy
+
+
+# --------------------------  Tests ------------------------------------------------------------------------------------
+
+# Normal test - runs on every commit all but "long run" tests
+tests-and-coverage:
+  stage: test
+  except:
+    variables:
+      - $ENABLE_NIGHTLY_BUILDS
+  image: i10git.cs.fau.de:5005/software/pystencils/full
+  script:
+    - export NUM_CORES=$(nproc --all)
+    - mkdir -p ~/.config/matplotlib
+    - echo "backend:template" > ~/.config/matplotlib/matplotlibrc
+    - mkdir public
+    - py.test -v -n $NUM_CORES --cov-report html --cov-report term --cov=. -m "not longrun"
+  tags:
+    - docker
+    - cuda
+    - AVX
+  artifacts:
+    when: always
+    paths:
+      - coverage_report
+
+# Nightly test  - runs "long run" jobs only
+test-longrun:
+  stage: test
+  only:
+    variables:
+      - $ENABLE_NIGHTLY_BUILDS
+  image: i10git.cs.fau.de:5005/software/pystencils/full
+  script:
+    - export NUM_CORES=$(nproc --all)
+    - mkdir -p ~/.config/matplotlib
+    - echo "backend:template" > ~/.config/matplotlib/matplotlibrc
+    - py.test -v -n $NUM_CORES --cov-report html --cov-report term --cov=.
+  tags:
+    - docker
+    - cuda
+    - AVX
+  artifacts:
+    paths:
+      - coverage_report
+
+# Minimal tests in windows environment
+minimal-windows:
+  stage: test
+  except:
+    variables:
+      - $ENABLE_NIGHTLY_BUILDS
+  tags:
+    - win
+  script:
+    - source /cygdrive/c/Users/build/Miniconda3/Scripts/activate
+    - source activate pystencils_dev
+    - env
+    - conda env list
+    - python -c "import numpy"
+    - python setup.py quicktest
+
+minimal-ubuntu:
+  stage: test
+  except:
+    variables:
+      - $ENABLE_NIGHTLY_BUILDS
+  image: i10git.cs.fau.de:5005/software/pystencils/minimal_ubuntu
+  script:
+    - python3 setup.py quicktest
+  tags:
+    - docker
+
+minimal-conda:
+  stage: test
+  except:
+    variables:
+      - $ENABLE_NIGHTLY_BUILDS
+  image: i10git.cs.fau.de:5005/software/pystencils/minimal_conda
+  script:
+    - python setup.py quicktest
+  tags:
+    - docker
+
+
+# -------------------- Linter & Documentation --------------------------------------------------------------------------
+
+
+flake8-lint:
+  stage: test
+  except:
+    variables:
+      - $ENABLE_NIGHTLY_BUILDS
+  image: i10git.cs.fau.de:5005/software/pystencils/full
+  script:
+    - flake8 pystencils
+  tags:
+    - docker
+    - cuda
+
+
+build-documentation:
+  stage: test
+  image: i10git.cs.fau.de:5005/software/pystencils/full
+  script:
+    - export PYTHONPATH=`pwd`
+    - mkdir html_doc
+    - sphinx-build -W -b html doc  html_doc
+  tags:
+    - docker
+    - cuda
+  artifacts:
+    paths:
+      - html_doc
+
+
+pages:
+  image: i10git.cs.fau.de:5005/software/pystencils/full
+  stage: deploy
+  script:
+    - ls -l
+    - mv coverage_report html_doc
+    - mv html_doc public  # folder has to be named "public" for gitlab to publish it
+  artifacts:
+    paths:
+      - public
+  tags:
+    - docker
+  only:
+    - master@software/pystencils
diff --git a/conftest.py b/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..5a7ce065a9888d02faf36c9d9f3c3c279dce865d
--- /dev/null
+++ b/conftest.py
@@ -0,0 +1,129 @@
+import os
+import pytest
+import tempfile
+import runpy
+import sys
+# Trigger config file reading / creation once - to avoid race conditions when multiple instances are creating it
+# at the same time
+from pystencils.cpu import cpujit
+
+# trigger cython imports - there seems to be a problem when multiple processes try to compile the same cython file
+# at the same time
+try:
+    import pyximport
+    pyximport.install(language_level=3)
+except ImportError:
+    pass
+from pystencils.boundaries.createindexlistcython import *  # NOQA
+
+
+SCRIPT_FOLDER = os.path.dirname(os.path.realpath(__file__))
+sys.path.insert(0, os.path.abspath('pystencils'))
+
+
+def add_path_to_ignore(path):
+    if not os.path.exists(path):
+        return
+    global collect_ignore
+    collect_ignore += [os.path.join(SCRIPT_FOLDER, path, f) for f in os.listdir(os.path.join(SCRIPT_FOLDER, path))]
+
+
+collect_ignore = [os.path.join(SCRIPT_FOLDER, "doc", "conf.py")]
+add_path_to_ignore('pystencils_tests/benchmark')
+add_path_to_ignore('_local_tmp')
+
+
+try:
+    import pycuda
+except ImportError:
+    collect_ignore += [os.path.join(SCRIPT_FOLDER, "pystencils/pystencils_tests/test_cudagpu.py")]
+    add_path_to_ignore('pystencils/gpucuda')
+
+try:
+    import llvmlite
+except ImportError:
+    collect_ignore += [os.path.join(SCRIPT_FOLDER, 'pystencils_tests/backends/llvm.py')]
+    add_path_to_ignore('pystencils/llvm')
+
+try:
+    import kerncraft
+except ImportError:
+    collect_ignore += [os.path.join(SCRIPT_FOLDER, "pystencils_tests/test_kerncraft_coupling.py")]
+    add_path_to_ignore('pystencils/kerncraft_coupling')
+
+try:
+    import blitzdb
+except ImportError:
+    add_path_to_ignore('pystencils/runhelper')
+
+
+collect_ignore += [os.path.join(SCRIPT_FOLDER, 'setup.py')]
+
+for root, sub_dirs, files in os.walk('.'):
+    for f in files:
+        if f.endswith(".ipynb") and not any(f.startswith(k) for k in ['demo', 'tutorial', 'test', 'doc']):
+            collect_ignore.append(f)
+
+
+import nbformat
+from nbconvert import PythonExporter
+
+
+class IPythonMockup:
+    def run_line_magic(self, *args, **kwargs):
+        pass
+
+    def run_cell_magic(self, *args, **kwargs):
+        pass
+
+    def magic(self, *args, **kwargs):
+        pass
+
+    def __bool__(self):
+        return False
+
+
+class IPyNbTest(pytest.Item):
+    def __init__(self, name, parent, code):
+        super(IPyNbTest, self).__init__(name, parent)
+        self.code = code
+        self.add_marker('notebook')
+
+    def runtest(self):
+        global_dict = {'get_ipython': lambda: IPythonMockup(),
+                       'is_test_run': True}
+
+        # disable matplotlib output
+        exec("import matplotlib.pyplot as p; "
+             "p.switch_backend('Template')", global_dict)
+
+        # in notebooks there is an implicit plt.show() - if this is not called a warning is shown when the next
+        # plot is created. This warning is suppressed here
+        exec("import warnings;"
+             "warnings.filterwarnings('ignore', 'Adding an axes using the same arguments as a previous.*')",
+             global_dict)
+        with tempfile.NamedTemporaryFile() as f:
+            f.write(self.code.encode())
+            f.flush()
+            runpy.run_path(f.name, init_globals=global_dict, run_name=self.name)
+
+
+class IPyNbFile(pytest.File):
+    def collect(self):
+        exporter = PythonExporter()
+        exporter.exclude_markdown = True
+        exporter.exclude_input_prompt = True
+
+        notebook_contents = self.fspath.open()
+        notebook = nbformat.read(notebook_contents, 4)
+        code, _ = exporter.from_notebook_node(notebook)
+        yield IPyNbTest(self.name, self, code)
+
+    def teardown(self):
+        pass
+
+
+def pytest_collect_file(path, parent):
+    glob_exprs = ["*demo*.ipynb", "*tutorial*.ipynb", "test_*.ipynb"]
+    if any(path.fnmatch(g) for g in glob_exprs):
+        return IPyNbFile(path, parent)
diff --git a/doc/conf.py b/doc/conf.py
index a71c41e781d07c70990ce446042ee2947f25b114..de898facf492671b8290c1d0ff3e9ffb2ca605e0 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -1,12 +1,59 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 #
+import datetime
+import sphinx_rtd_theme
 import os
 import sys
 
-sys.path.insert(0, os.path.abspath('..'))
-sys.path.insert(0, os.path.abspath('../..'))
-from sphinx_doc_conf import *
+sys.path.insert(0, os.path.abspath('.'))
+from version_from_git import version_number_from_git
+
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.doctest',
+    'sphinx.ext.intersphinx',
+    'sphinx.ext.mathjax',
+    'sphinx.ext.napoleon',
+    'nbsphinx',
+    'sphinxcontrib.bibtex',
+    'sphinx_autodoc_typehints',
+]
+
+add_module_names = False
+templates_path = ['_templates']
+source_suffix = '.rst'
+master_doc = 'index'
+
+copyright = '{}, Martin Bauer'.format(datetime.datetime.now().year)
+author = 'Martin Bauer'
+version = version_number_from_git()
+release = version_number_from_git()
+language = None
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '**.ipynb_checkpoints']
+default_role = 'any'
+pygments_style = 'sphinx'
+todo_include_todos = False
+
+# Options for HTML output
+
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+html_theme = 'sphinx_rtd_theme'
+htmlhelp_basename = 'pystencilsdoc'
+html_sidebars = {'**': ['globaltoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html']}
+
+# NbSphinx configuration
+nbsphinx_execute = 'never'
+nbsphinx_codecell_lexer = 'python3'
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'python': ('https://docs.python.org/3.6', None),
+                       'numpy': ('https://docs.scipy.org/doc/numpy/', None),
+                       'matplotlib': ('https://matplotlib.org/', None),
+                       'sympy': ('https://docs.sympy.org/latest/', None),
+                       }
+
+autodoc_member_order = 'bysource'
 
 project = 'pystencils'
 html_logo = "img/logo.png"
diff --git a/doc/version_from_git.py b/doc/version_from_git.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b7d0713b901466d178c6d8eaf71dd59f1c6bb77
--- /dev/null
+++ b/doc/version_from_git.py
@@ -0,0 +1,31 @@
+import subprocess
+
+def version_number_from_git(tag_prefix='release/', sha_length=10, version_format="{version}.dev{commits}+{sha}"):
+
+    def get_released_versions():
+        tags = sorted(subprocess.getoutput('git tag').split('\n'))
+        versions = [t[len(tag_prefix):] for t in tags if t.startswith(tag_prefix)]
+        return versions
+
+    def tag_from_version(v):
+        return tag_prefix + v
+
+    def increment_version(v):
+        parsed_version = [int(i) for i in v.split('.')]
+        parsed_version[-1] += 1
+        return '.'.join(str(i) for i in parsed_version)
+
+    latest_release = get_released_versions()[-1]
+    commits_since_tag = subprocess.getoutput('git rev-list {}..HEAD --count'.format(tag_from_version(latest_release)))
+    sha = subprocess.getoutput('git rev-parse HEAD')[:sha_length]
+    is_dirty = len(subprocess.getoutput("git status --untracked-files=no -s")) > 0
+
+    if int(commits_since_tag) == 0:
+        version_string = latest_release
+    else:
+        next_version = increment_version(latest_release)
+        version_string = version_format.format(version=next_version, commits=commits_since_tag, sha=sha)
+
+    if is_dirty:
+        version_string += ".dirty"
+    return version_string
diff --git a/pystencils_tests/test_datahandling.py b/pystencils_tests/test_datahandling.py
index 0710fb249f71bdc0684da069922a0c7ce4601c6f..887c855dbb1c0be11847f0d3a34f849edea08ce9 100644
--- a/pystencils_tests/test_datahandling.py
+++ b/pystencils_tests/test_datahandling.py
@@ -1,7 +1,6 @@
 import numpy as np
 import os
 from tempfile import TemporaryDirectory
-
 import pystencils as ps
 from pystencils import create_kernel, create_data_handling
 
@@ -196,11 +195,15 @@ def test_kernel():
     for domain_shape in [(4, 5), (3, 4, 5)]:
         dh = create_data_handling(domain_size=domain_shape, periodicity=True)
         kernel_execution_jacobi(dh, test_gpu=True)
-
-        dh = create_data_handling(domain_size=domain_shape, periodicity=True)
-        kernel_execution_jacobi(dh, test_gpu=False)
         reduction(dh)
 
+        try:
+            import pycuda
+            dh = create_data_handling(domain_size=domain_shape, periodicity=True)
+            kernel_execution_jacobi(dh, test_gpu=False)
+        except ImportError:
+            pass
+
 
 def test_vtk_output():
     for domain_shape in [(4, 5), (3, 4, 5)]:
diff --git a/pystencils_tests/test_fd_derivation.ipynb b/pystencils_tests/test_fd_derivation.ipynb
index 144bf19487056c2e9e363b6ec0baf828fa158227..50ff9e1015b8c3e1983185b3be8f007383dfcabe 100644
--- a/pystencils_tests/test_fd_derivation.ipynb
+++ b/pystencils_tests/test_fd_derivation.ipynb
@@ -2,13 +2,11 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": 11,
    "metadata": {},
    "outputs": [],
    "source": [
-    "from lbmpy.session import *\n",
-    "from lbmpy.phasefield.scenarios import *\n",
-    "import pystencils as ps\n",
+    "from pystencils.session import *\n",
     "from pystencils.fd.derivation import *"
    ]
   },
@@ -21,7 +19,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -36,7 +34,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 13,
    "metadata": {},
    "outputs": [
     {
@@ -45,7 +43,7 @@
        "Finite difference stencil of accuracy 2, isotropic error: False"
       ]
      },
-     "execution_count": 16,
+     "execution_count": 13,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -58,12 +56,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 14,
    "metadata": {},
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGkAAABLCAMAAABEOFk1AAAAPFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo1xBWAAAAE3RSTlMAMquZdlQQQOkwRIlmzd0i77ts7uXj/QAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAkpJREFUWAntmduagyAMhBGU7YrH5f3fdQW2mkmrpqv2oh9etIDj/JJGi1EVPm5aXbV1CaBU4U05bdVVINUEe+0DqbgMshg3QLLGNU6AFepAhqR2iqDt+uVEVlpCHciA1AzB2bUr/vOwUIcyII0x/SpvZ8/nDaEOZUDykVT7vSwU6lBGSdabMIfal8+nch8V6piMknrvglmRvu6+j99CHZMhKc5JQBLp+hSiux0lsek+TuZvRKhjMkpS6SeshBmxq0M7II1jOOtmP8tlOrQDUrrUjPDK3dWhHZBUF+5Gw/6NT6gDGZKsm+7u+yAl1IEMSavpdsKOTDoSxBy9HD2MQM4IjIfqjRlHwW0yHsajVw17S7CFZsNSyvl6GXloETsgWW307t/g4qbjSQ1xObqMLi20A9IkKl8gDV1w1VvPD8TuCKmNZ/UOUopTtxWFk+YUSfXmOvRMUrf50PpPkm27eWv/LiMTl7Mpjk8+Genr9j2LyK55bKNRboNoKv/c8Dn3NVIVQP3GMySxO5LlqogzKq8n9Z1zzuh4/a5EeHVORg++1c3KYXy4TQWNdRLY8ehxt/P6mXQkljl6OXoYgc/PCCgy4uShJ9SBDKMHRUbwxo5QBzIgYZERzWlPqEMZkLDISL2xLdShDEhYZER32hPqUEZJrExGvaEt1DEZJbEiI7jTjlDHZEiKK5B7kZGaQ5sVI2Ef6TAZJbHpkoOwKdQxGSXlmqXKNcupkIxPAJhlZ/Yy6Ug0Pzd673pzbMOL3bLcqjQd+YGmdzIJoH4B+tMpKpuC5nwAAAAASUVORK5CYII=\n",
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGkAAABLCAMAAABEOFk1AAAAPFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo1xBWAAAAE3RSTlMAMquZdlQiEEDpMESJZs3d77ts6LWnRAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAj9JREFUWAntmV17gyAMRlFQ1olf4///1wl0kpc+Qlba3QxvBnKas6TUaio6649evOtYg0CIzkp1HMO7RGJ24XvrTOPbJDHwgCajZtPF1csRk6MYmpajgnotZ8jkAAPTvLkkzHKZyn2BySEGpt1vv8HqgorJIQYm602TLe1CJocYNWkrXTKTVfmcmFyCUdNojVN0JROTSzA0+Zy6ILzOawy5l7gEo6Yk3UsVk0swahLhLRyYO6LIYTgw7bvLYy7vch6H4cCEH7XL6gkmhxiYxOquRlv5wsfkAEOTNsfVvSwSTA4wNF0XrH6lmWpq2KrXqocVaDsC6yG0lPvOuEz6l6XVG7bSLVi0aXcrZewUzzyMSDgw6d70xa/BGE36f2rzt6PxbBxhODAdUPkLN0baVjfuc88PJFyNafH59zbzTr3IFLJbc/V+pWnK3h2+0rRmH1qfNOmFHPc3R/rb3rhLklFi+rh9ngBZOs9lBiovolv564bPub8zDU40Zp4hSbiaXS46/2yinjOp3J5NyjiuxhjZ+89vsvQzJeEwJ9lvdpHzD1f4u4SGxrUJwqGpELpquZlqyteq16qHFfgHO4I2GTF5nDE5imH1oMmIsWHG5AADE7YqIDZMmBxiYMImIwSHCZNDDEzYZITgMGFyiFFT0iaD4HTC5BKMmpImIw0OYyaXYGhqPctSb7P1LGHTnRNoRp5nHwaA0b13dEZbz/KhXLkTWL0cWbvWTDUVDNX7q1+OtfthV6lcp6kmmaNFFATiG+4bKVe2WSLVAAAAAElFTkSuQmCC\n",
       "text/latex": [
        "$$\\left[\\begin{matrix}0 & 0 & 0\\\\1 & -2 & 1\\\\0 & 0 & 0\\end{matrix}\\right]$$"
       ],
@@ -75,7 +73,7 @@
        "⎣0  0   0⎦"
       ]
      },
-     "execution_count": 17,
+     "execution_count": 14,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -95,7 +93,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [
     {
@@ -104,13 +102,13 @@
        "Finite difference stencil of accuracy 2, isotropic error: True"
       ]
      },
-     "execution_count": 19,
+     "execution_count": 15,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "stencil = get_stencil(\"D2Q9\")\n",
+    "stencil = [(i, j) for i in (-1, 0, 1) for j in (-1, 0, 1)]\n",
     "isotropic_2d_00 = FiniteDifferenceStencilDerivation((0,0), stencil)\n",
     "isotropic_2d_00_res = isotropic_2d_00.get_stencil(isotropic=True)\n",
     "assert isotropic_2d_00_res.is_isotropic\n",
@@ -120,12 +118,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 16,
    "metadata": {},
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAIIAAABNCAMAAABdY0yuAAAAXVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADXQA/SAAAAHnRSTlMAMquZdlQQQOkwRM3d7yKJu2aF48P7apvf8VzR02ydbYKKAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADz0lEQVRoBe2a6XbbIBCF0VpXq92kbdJF7/+YAUlIwNyBIUtPc475YUto5s5nhIERUiosRR/WiM5lbhKroioHUUjfSObGWBXLWspDsnkNglIyN9dq2CIrVSxVrUvz7xFuJm65GITiiL4euKD+leiZzI1Y3e4IulnvrWD6Fm6FMdrtuIuNyI1YAYSpGpay5uKw9TI3YAUQ2CAfdOHzIrT9cJQ+GNhyG8tvhW3Idj7lcocT63JY2IPd0kdg3T/yAkHYp/O5ulZtZuB5rm9xFygeINjpfJ6UKjMXLn2npujIwIgHCHbSHzRCsegPean1eqNNDCfbLBmIcwidUtOiP+RlPNcbrNOO4IszCEakWbI6w9LUdar7nGsFRzyCMCRa1f+t01Ip1SVWfCeCI84jzFoyo7SLuRGJe3cguOIswi2PYI++xP+VFsET5xC6WTdr1sjbm+iyVvDFKcJYlMX07aFpmmtWd/xxKaafD/Fb1yDxAMFM5496DP++juNxveBqp12eotCMeIBgZLumiCoFoe2pzA1YIYSsEckSqE7kBqwQgs6tUmPMEfg86ERuwAogTPrn3K6ntvBI5gasAIIJmTlFWUqZW2AFEErdGdvEH9zGdL5lbsAKIIx6jp7ypihDInMDVgBh1q3gjuHOL40dytyAFUBQ81zp4Tm7yNyoFULIDv42h8+L8N6pzJfLV6cpbaKhH7/kFJkbsvp7Ac+ackK/3Rb2hXROggLPdWUGnlQh4gghmZPAKJVeNVXpqYWKAwRJTgIgzFhi1OIFiAMESU7CxEm3AhAHCJKcBCO0Y3LBC8QpgigngQh1n0x+kDhFEOUkEEHQHZE4RdhygUROwiBMa0rFXFyr13WILw4QJDkJjbL2g8kXp1YKiAOE7lr0TebjDR1smIq+HlNjExAHCMXj0/MrVtC/fv95LpMPRYA4QLBPWkAzxqts0pppdUcwDXZvhXsr2D8O7gvRh6jWlXyT/RZiYSqIFUAAGydQK6iUuQErgBBIf/jp50V471Tm3LM+Mg17IL8L1oNfwB4W9mAX/x9vBNw4kTUGSVKIGxQPWoHZOCFaqIImKYEVIx4g2LVCsHESaMFTkKQQu21FEYhzCP7GCdECFSBJIVY7gi/OIBhnZ+OEaIEKkKQQq3Nd5YhHEJyNE6JFK1CSQqxOBEecR8h86IaSFB7BFWcRvI0TogUqQJJCrGwreOIcgr9xQrRABUhSiNWO4ItvCOuQub1atU3nOpnJ3ZXp9OONVAYUih+vVrXmBae6NvsJdjofVyjyK6IVt2qOZ0BUfH21qq7VC3XOS/my1/oRAAAAAElFTkSuQmCC\n",
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAIIAAABNCAMAAABdY0yuAAAAYFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACACGXEAAAAH3RSTlMAMquZdlQiEEDpMES73YnNZu+F48P7apvf1/Fc0cls39hR/gAAAAlwSFlzAAAOxAAADsQBlSsOGwAAA8dJREFUaAXtmumW2yAMhcFrU6/pdJ0ufv+3LNjGBnQBkcn0NOfEPxIbpMsXGQMyEcI/ZO+XsK55bhwrWZYDq0nXiOcWsJLLehSHZHcLghA8N9tq2FoWQi5lpY763yPMut1i0QjN0fp6YoO6NdErnhuxqp8IKqzPKOi+BaNQ3/ZQ8tyIFUBoymEpqmjfR5U8N2AFEJD+e5Y9LkI7WYd8W4zcKGxDtvXJFz+cgi6HhTnZLV2EoPt7VhCEfTofy75sMxsex2qOu0BxD8FM56OauIoprufXTp1orn6hfR0Q9xDMpD8oBDKB2nL0vFLrjTYxnGyzpCceQuiEaBb1wT+u53oj6LQjuOIBBC1SL1mdYamrKtV9zrWCJR5BGBJRdX9rs4zmLroV9tWJYImHEcbSdk6et+ttS9y7A8EWDyLMeQRCbAjxp9IgOOIhhE6HNWvknXTrvCi44gShHmQhm08vdV33Wd3x60U2317iNwyKewh6Ov+sxvAv6zge1/NqO+XyPQodEPcQtGxXy6iS17S55LkBK4SQ1QUMAbPngP6FEFRulRpjjobPk47lBqwAQqPGzzk/t+a5ASuAoH9Y5hRlYsFz86wAgr4J21hnlFnfPDdgBRCuaqJu8qYozchzA1YAYVRRsMdwVgyUC8sNWAEEMY6lGp6zD54btUII2Y2/zeFxEe6dyny4fLRCaRIN9fol5+C5Ias/l5vHoRzAmC3sC+mcBEmOVVkwplgijhCSOQkCEKVaNZXpqYWKAwROTgIg9FgyJzsQEAcInJwEIOiidBSAOEDg5CQYob0mVztAnCKwchKIUE3J5AeJUwRWTgIRGDcCiVMEVk4SQGiWVG4LEh6AwMlJKMLaD5olnk0JAcQBQtfLvs58vaGQhkb28zU1NgFxgCD7H683rKB//vr9Wni7CjRYQBwgpHN0qryWmKQ1UL0XE6sngo7MMwrPKOxPCO4LZOPEWMe/eW7ECnRHsHESb3qr5bkBK4DAae+eNo+LcO9U5nzlcGQa5oQfcOMRXsAeFuZkF/8fbwTcOOEFgyQpxA2Ke1EIbJwQLVRAkxTPKiDuIZi1grdx4mnBS5CkELttreCJhxDcjROiBQpAkkKsdgRXPICgna2NE6IFCkCSQqzOFZMlHkGwNk6IFi1ASQqxOhEs8TBC5ks3lKSEEWzxIIKzcUK0QAFIUoiViYIjHkJwN06IFigASQqx2hFc8Q1hHTK3v1Zt07mcsndlOvV6I5UB+eLHX6ta/QenqlKPijDT+XWFIr8iWlCXYzwDouLrX6uqSvwFDr5NBGUlpz0AAAAASUVORK5CYII=\n",
       "text/latex": [
        "$$\\left[\\begin{matrix}\\frac{1}{12} & - \\frac{1}{6} & \\frac{1}{12}\\\\\\frac{5}{6} & - \\frac{5}{3} & \\frac{5}{6}\\\\\\frac{1}{12} & - \\frac{1}{6} & \\frac{1}{12}\\end{matrix}\\right]$$"
       ],
@@ -137,7 +135,7 @@
        "⎣1/12  -1/6  1/12⎦"
       ]
      },
-     "execution_count": 20,
+     "execution_count": 16,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -148,17 +146,19 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 17,
    "metadata": {},
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKQAAACaCAYAAAAnxeOcAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvIxREBQAAE+FJREFUeJztnXtwXNV5wH9nd7UPrWTJ8soWsh6uATPBIQ/KKzEloSngdcOAE9M0E6cUApmUuJPAJI1pnLSJA2RqbEKGkjKEAs0wDiUYOoAX8iyEDEljYGyS1ji2gm1JfuhaWkkrrR6rPf1jtbZkr/Z1X+de3d+MZ6x9nPt9+n66j71nvyOklHh4qILP7gA8PGYSsGpDIqHVARcBUUBU8FYJpIBdMh4bMSM2IxAJbQHwp0AtleVXiCxwBNgt47Gs3tjMQiS0ZcB5QE2Fb53iVH6zDtHCikO2SGg3AF8HgjqGGQe+IeOxp42JyjhEQvs08BUqL0wpeoCbZTz2jsHj6kIktBBwP3ClzqEOAjfJeKwn/4Dph2yR0JqBb6JPRoAQsFkktJj+qIxDJLR2YBPGywiwFNhswrh6+TT6ZQToBP5p5gNWnEP+mYHb8QOrDBrLKK4wefyLREKrNXkblfIhA8daJRKaP/+DFUI2GDxeo8Hj6cXo/E7HB9SbvI1KMTLnALnrCsAaIfWe4Js9nhNQLWfT4rH/Y5/hAR+f/3AHazvOZf9uveeZzsKtuevIy34hw9Esm5/s4ZKrh+0OxXLcmruOvOwXsiYITUum7A7DFtyau4687BfSw2MGnpAeSuEJ6aEUlt3LLsrGtUs5uDdMb1eQa9Yn+ejNQ3aHZBluzb3KvNQQ8tvP9JR+kUtxa+5V5uUdsj2UQo09pBu5Y3U7e1+PFHzu3Peluf8nhy2OyBHYI+Sa5hUVvX5n3z6TIjGPbS+WFq7Y78FpORtUU3uEfHLffjaubaO3K8SW5w5yznsn2PNqmIe/vphAjWThkgx3fv8INe65m1aQnX372PWzCD/ctohsVnDtLQNc+fGU3WFVhUE1teccstCtpZZlk2x5/jD3vXSYJR2TvPJsnS2xWcl4WrDjwSbu3tHNtsRhx8oIhtXUHiEL3Vpa3DZFuDY3fd3vlwgXXm9JCb1dZ5Psy00y3vNqhGA4y6Yb2vjaJ1rRev0lRlAXg2qqXtW7D9Tw5stRLr82xehwHccOdTIyVIcbvh2ZTkWR0sfIcCNSQv9xP8cOBfnWU92sXj/IY3cpNRu+JJmMn6S2iKOHOslOze3SzJqWQK2r7FTSx723tfDlB48QDEF2KsPkRIhk31kMapJowwDjo/XgrLqdJDXYhJQCgSSdqqOuIct5F6YJhuDiq0Z56oEmu0Msi6TWSGailfF0FCkFPn8G4Sv8ZbTTa1oCdfaQmUm46+az+NSXTrDs/EkAQpEx/IFJpBRksz5SySae2HKfEMLsWdrGk5kMMDkeBkBKH6nkQlZemqb7QBCZhbffCNHSMWlzlCURQnyefW+sYmy0LvfHJST1jf2IAnN2C9W0BPbtIU+/teTzw4E9YbZvXcT2rYuI35jkqk8OU7/wBIPaEqQUSCloWvJbwHnzB1ODDUh5qmoT4xGaWnxctjrF7fF2fALueOCojRGWywvAd5k5azy6YBAov6ZFsE/IQreW1tx45v3O2vphBrXFCAFSCk4cvcyK8Aynti4FUpAabEIISbShH38gw7oNSdZtSNodXgUsRspTR9ZI3RA+f+4Ev9yaFkGdQ/Zc+HySBU0akbpBWjq6ph+dEsJhl+HB8DiNzRoA4egwjbETBQ9zCiOEuAT4Df7ABC0dXQTDo9Qv7DdyG1YUNa17hPqFSZqWHCcQzHD95zZMP6qKlGMWbEP/71AnJ2UEjYs+8l8EghkWt3VTEzTivHc8/x8rCrrL0NGWr3yR3BfMQQ0pXzd5/P0yHhs0eRtFmSmjlLIZY3N+S8Zj1gkp47E/ADsMGu5pGY8dkFIeQhEpZTy2G0iYNHwG2GrS2GVRQEaAHwC9Bgw/Adw3a3sW9fbxAR+c/ldHdc2mfgW8NrP5khCig1x/GAC/lNKWxkzTnRcuBz5AqWZT27duonnpbv7ir58rMuQUcBR4ScZjfzQy1kqYQ8bccwmtAVhN9c2meoEXZTx2aNa4Tu8PqYqU5SKEkMBjUsqb7I6lGMVkNBO7z790o9Lh2y3YJSO4QEjwpDQSO2UElwgJnpRGYLeM4CIhwZNSDyrICC4TEjwpq0EVGcGFQoInZSWoJCO4VEjwpCwH1WQEFwsJnpTFUFFGcLmQ4ElZCFVlhHkgJHhSzkRlGWGeCAmelKC+jDCPhIT5LaUTZIR5JiTMTymdIiPMQyFhfknpJBlhngoJ80NKp8kI81hIcLeUTpQR5rmQ4E4pnSojeEIC7pLSyTKCJ+RJ3CCl02UET8hZOFlKN8gInpBn4EQp3SIjeEIWxElSuklG8IScEydI6TYZwROyKCpL6UYZwROyJCpK6VYZwROyLFSS0s0ygidk2aggpdtlBBs76E43aCrWpGhSxmNVrUpvFlLKQ0KITnK9hKaEELN6CYmEJoAgxZpN1YTAH/CLhBYusqmsjMcmZj7gBBlFQgsy905OAhMyHivaTMryZlMioV0L3Equa1Yp3gYelvFYsU5hlnN6gyt29q0A/gG4lFJ/5N37VxCpG2JRS6l+4v3A88C/sKb5/Sgq4/Qf1kYgDjSWePkE8Cpwt4zHCi69Z+lhRyS0VcAWypOR6ddtEQntA+ZFVTmzDt/h6BRSPg6swtgjThPwNxzc+z0UlXGazcAnKS0j5I4efw48Pn2EPAOrz4Ouo7LekEy//joTYtHFSSnf80HoOXCJKQs7jafDTE58Br9fSRlFQosA11Tx1qXARYWesFrI9irf12ZoFAYhpTzErZv/EYCeAysMlXI8Haavp4PauimeO3q+cQMbSjNQejWkwhSsqdVCVrs9tVYcm8nSswdp6cytDmGUlHkZfb4pWpcfAFRdA1GPPwVzsr/QPV0Bbr+mk7azc1eVmx7vPWMRR9UJ1GRo6ezi6MHl9BxYwdKz95W15Eeh3KMLak6T0VnorKf9QgK866I039huRBN1+6hWypm5n7lndCY66qnGB+P73ozwxavbeeirMdRuEV6cvJRQ/uE7n/v37mzheLfzZQRd9bRfyObWKR7Z1cV9Lx5mUPPzi6edvXB7JVLmc//2M30MHFvAmy9nHS+jznraL2QwLKmtyy3uveqjKbreqvaqTR3KlTIYlvj9IbQjHVx4ZZbjhwYsjNIcdNbTfiFTyVMxvPVahNblyi/RWxblSNl/LHLynPGd/0u6Ined9bT/ouaN/46wfWuMUCTL4rZJbvmGZndIhlHoQifPeDrMazvbee4RCNdOsLgt4IrcddbTfiGvuH6EK64fmfN5KaH3j21CNP+K3L33D1oXnAGcLiVAdspPX08H7//QFH95k+POGYUQFwA/5ewLfsrWRJBg6NREkFL1LIH9Qs7F5EQNqcFGRocb6PrdcnKxjkzPtlGHh3/dxJL20r/HWOshtN4OAMbTUXy+LIvbDpKZKP3ex+9pE2seUOnc+kIgSir5V/R1+/EHJqhrHKCuoaK1sQuhrpADx1qYGI8AkJ3Kn5dEgXfsCqkgzz4E1332zMfvvQ32vVn4PWe/B77ykI+jh5aXtY2f/+dvdURoHpLcESwzGSLZ1+IOIdc0r5jzuSf/cIxUsgmfT5C7ABuUUjZZFlsZiIR2G/CFM574zo9n/5z/0Hsmny0yiWln36nzzSd+/yEZj5WarmYZQoirgWcRQiBEiGBkhPrG3CcExeo5M6c5sF/InX372PWzCD/ctohsVnDtLQNc+fHUyefrGwcJRd4htzpqrV1h6mLmHZhs1k+4dpix0XrufQH+7c4x/AGJzy/Z+PARmpc64bZpF7CXWGuCls5P4A+cirlUPUtgv5DjacGOB5u4e0c3wTlOk5qWDEgpb7Q2MIM4/XZg9/4VCJ+kpbOL7NRyvvS9MO3n7uOFRxfwwqMN/O2mfrtDLoWUcj9woUhoy4B1s54sp55FsP9zyD2vRgiGs2y6oY2vfaIVrVfVmS2VU+zedKAmQ+vyLny+3OeUo8M+Ot81McdIzkFnPe0Xsv+4n2OHgnzrqW5Wrx/ksbtidodkCOVMlAjUZBjq7+buz0DiPxaz4v1jFkdpPDrrab+QdQ1ZzrswTTAEF181Svf+oN0h6aaSWTvnXzLKd3/axXW3wg/uWW7KzHMr0VlP+4VceWma7gNBZBbefiNES4ezb59VIuPEWG5+WqAmQ3PbEYJh42eeW43Oetp/UdPYnOWy1Sluj7fjE3DHA8p8vFExlc5n3LsrxL9vbsbng5pQltvvP0hmsrOi+ZSqobOe9gsJsG5DknUbknaHoYtqJte+5/IxvvPS7K+DZiYrn+SrGjrqaf8h2w0YOdO7mkm+LsJqITNVvk/d88rfvdZu+NcOTpcyqan6YbmeuAq6YLWQXVW+T8kZMUKIS9i+daMpXzvIS5lKwvqVx1XoulaAY0C1M3sKumB1kj+i8r3dJPC0CbHo4mSvnd//WqN1+cumbCRQk6Gx+Ztks6BIK8CZTPcfqqY2/wvsLvSEpRc1Mh7bLRLaLcCNwEpKNJsCfg88KuOxt6yIr1xmNX4aH2sWCa0V+DvgA+Tut899JTI8ADBOrnfPXGSBI8ALtHQ+BjzCHA2uFOAe4Di53j5LKN5sahj4JfCvczWdsrzZlNPR24VMCCGBx6SUN1X4vlkNrhST0jCUOgSojp0t8VToT2kFrkzKDFTozzgfpHRdQmaggox53C6lq5IxA5VkzONmKV2TiBmoKGMet0rpiiTMQGUZ87hRSscnYAZOkDGP26R0dPBm4CQZ87hJSscGbgZOlDGPW6R0ZNBm4GQZ87hBSscFbAZukDGP06V0VLBm4CYZ8zhZSscEagZulDGPU6V0RJBm4GYZ8zhRSuUDNIP5IGMep0mpdHBmMJ9kzOMkKZUNzAzmo4x5nCKlkkGZwXyWMY8TpFQuIDPwZDyF6lIqFYwZeDKeicpSKhOIGXgyzo2qUioRhBl4MpZGRSltD8AMPBnLRzUpXSekJ2PlqCSlq4T0ZKweVaR0jZCejPpRQUpXCOnJaBx2S+l4IT0ZjcdOKS1pNiUSWgi4DlgFVLTC/DQp4FfAs9Mt4HLjKiKjSGgR4Hpy3c+iRV/80hM3s6jlD1z0kV8WeZUEeoEXZDz2G8MCrZBiDa5EQusEPgacR/EudoXIAj3A8zIe2zVrmxYJ+QhwuQFDvSLjsVtBKRn9wOPAxWW9oXv/CiJ1QyxqKbcZ/FdlPPajauPTSyEpRUI7B9gOLNA5vAS+LOOx5/IPmL4rFgntvRgjI8AVIqG9WxUZp7mYcmWsjttMHLskcxy+16NfRsj10fzczAesODe4wNDRXv/5WtSREeDdJo+/VCQ0W1fAPV1KpDSypudMn/IA1gipf2WuZF+Mvp42xkYjvPzMN1FHRjAiPzW2UZRZUv7Pjz/GeDrEkXf+hIkxIxaWP3kOqv5VdnbKx8jQQibGImi97fj9owrJWD7pkVr6eltz/08t4MSRs8hmHbUIzSwp+3o6mcrUMDRg6N7bfiGHB3x8/sMdrO04l/27z9wTpIZy5ypS5ooXqT8shDDir9JaJsdDjI+e+oQhPVLPUH+gaO5q0oQQp9pJj4/WMZWZveJrqZoWwX4hw9Esm5/s4ZKrh894TkpIJZtOyiiEJJ1qQ5UVyCohumCIXH/xHKHICNEFk3Pmri4rAWblkhpsmPWKYjUtgf1C1gShaUnhBXjGRqJkpwIIIQnUTNDYfJTP3f0FKWW1a6PYhz8wRTA8CuSKWdc4UDR3RZFSPsEFq35OdMEAQmSRwMhg06wVx3TkpfaeRogs4doU9Qv7CUXya0k7qoCzqG/sZzwdRfiyhGtH7Q6naiLRMSJRjQWLTjA6XM/YSB1Sill7zSpRW8hwNE04mrY7DMMI1abxBzLU1icduajm6fh8krqGIeoahowaUm0h3YYQcNayapfXmxeoIeTGtUs5uDdMb1eQa9Yn+ejNhv3FKY9bc68yLzWE/PYzPXaHYBtuzb3KvOy/yvbwmIEae0g3csfqdva+Hin43LnvS3P/Tw5bHJEjsEfINc0rKnr9zr59JkViHtteLC1csd+D03I2qKb2CPnkvv1sXNtGb1eILc8d5Jz3TrDn1TAPf30xgRrJwiUZ7vz+EWqccjetSnb27WPXzyL8cNsislnBtbcMcOXHU3aHVRUG1dSec8hCt5Zalk2y5fnD3PfSYZZ0TPLKs9XMLHcW42nBjgebuHtHN9sShx0rIxhWU3v2kIVuLS1uO/Wz3y+xv4mC+ex5NUIwnGXTDW2EIlm+cN8xYq3OvBNlUE3Vq3r3gRrefDnK5dc6d29RLv3H/Rw7FORbT3Wzev0gj90VszskU6igpmoJmUr6uPe2Fr784BGCzpthVjF1DVnOuzBNMAQXXzVK9373nTRXWFN1hMxMwl03n8WnvnSCZedP2h2OJay8NE33gSAyC2+/EaKlw115V1FT+z6HPP3Wks8PB/aE2b51Edu3LiJ+Y5KrPumkeYKV09ic5bLVKW6Pt+MTcMcD5X4TUU0MqKl9Qha6tbTmRnfcx62EdRuSrNuQtDsMQzCgplYcsrOlX2LreHox/4vt6uVsdDwnf4dWCHlC8fH0YnY8GUC1I4eROaeBk5OVrRDyZWDcoLHGgWItSOzgF5g7i/0VGY+NlX6ZpfzEwLF+IeOxk78/04WU8dgQ8PfAcZ1DHQM2TI+nDDIe6wO+CGgmDL8L2GTCuHp5EngCmCj1wiJI4DXgn2c+aElvHwCR0ARwDtU3m9ov4zFrgq0CkdB85PIr3myqPLLAURmPHTNgLNMQCa0OWEZ1zaZ6p/+YZ49plZAeHuWgzgfjHh54Qnoohiekh1J4Qnooxf8DQobOZydRBWoAAAAASUVORK5CYII=\n",
+      "image/png": "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\n",
       "text/plain": [
        "<Figure size 144x144 with 1 Axes>"
       ]
      },
-     "metadata": {},
+     "metadata": {
+      "needs_background": "light"
+     },
      "output_type": "display_data"
     }
    ],
@@ -169,7 +169,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 18,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -186,12 +186,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 23,
+   "execution_count": 19,
    "metadata": {},
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHoAAABNCAMAAABe+IDDAAAAV1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcPecEAAAAHHRSTlMAMquZdlQQQOkwRM3d7yKJZrvh0Xzfvadc0/FsqyZmNQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAA5lJREFUaAXtmtmanCAQhVHQmbh2Z7LH93/OsAxanBapyjhJ50t7oXRTdX7B7YAqRZeqp79K5VlfdVsK2uqPxCtdD1tksTRPStXsfd0Rrxa/1J7USNCDRVeLXTGXKD4EokvWxi7Nb6A7pabFrphLRF8cr14cutpSY+32T6HULPyDnYhf3oweTGHfSPW56FkT6VLxVPRFQlZnortZqY6cKYVmF9BjIZ1WV33TNFfBaUbF4TSb9LDU/PNm9Ncn3ZmjMogD+ijz7LoHWqlwa7VrXufKwjH6njp8ns2F12YXNRtd868tlYhjq/tOTfTiO94LbfdSX49jSG0qDmhjH9ot/7rW9mbmFHgLiAN6DA9tnlSI4rcaxAG9NMZIzJbto5F9CwfxFD0t9kHUSSyS6dmHB8VTdLu4Dhc4HhvN7nAUT9GBugiuLufNuOeHb9ImDujeUdmt9sd52sTCeZddgzigu4/6en3JJmOFM8NmfApO3MzGXmsHC4gDev6k5898dGVpX76GUcPFcpvg5TN4EAe01NN7SLA9g7Pjh8YYxBEt9PQbuvVmHu4aafPdzpEBA6BdrMTTb+gw/hlKFwcR30FLPD1FuydYMZcE3KJFnp6i3ahvLNzbqPgNWubpN3Q41oVbQiKOaKGn39CqfIarVBzQUk8f0N5bGPvkOb6uQRzQMk/vwauxn/V8/LwFcUB7sT+0+nfQbT+sS8+2J/vd6Fr99PzhtRJd+n5O8u+aEgtJLf0RA6KN/PkMcyk0+H3LeKyFnj7uHC8tjQK00NNHMi8NohAt8vSRrHhDAYgCtBNjW8yV7Au8NBJ1ixZ4esrmpdGoG7TA01MyLy2JukH/zQ4XeHrabGYaGTCkrRZ6+ojmpWFUilbDVPVm5M8TvL4FCEOBUhqIA/rby/cfNX9qPb4FcEOBchqIA9oaDckQF0x9PADZbSL+RnRq6rPIWHEi2kkSUx8J2e3JaGLqs8hYcS6amvpIyG5PRSemPouMFWeiU1MfCdltAc2fK7TW6vEWINvNmYqbW0om7h3+vhs0uvRCW2XhGH03rbatTCbqC61+vAUodpCd0kxfMcCxPpxy21cnpn4/YP0XxAENE/VrVr5ATX0+yteAeIrGifqClq1OTP1xOIqnaJyoP9YKtewOR/EU/X+9BfD3ODeN3tlXdQ378xo7YnBvAUrWPx62TXz9JKZ1H6gY46bS1aU07xZ1/JZn/deUVdx/EmOM+gXcoENgExPFVQAAAABJRU5ErkJggg==\n",
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHoAAABNCAMAAABe+IDDAAAAVFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwjqETAAAAG3RSTlMAMquZdlQiEEDpMES73Ylmze/h0WzfvadcyfFyvev/AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADhklEQVRoBe2a2XqlIBCE8YCajHuSWX3/9xyWg9LlQvfEzPLN8cKNpn5B0AJVKl2KNj3K7fe61XUuaE0/Ey+07tbI7F5fKXUbs2H3gB3xYvbLzUc0EnRn0cVsV8wlineB6DJrY5fyF9CNUtVsV8wlogfHu81w3TGVKaZUOfNvNhEv343uDPsq1bXoXvPJ16IHCflSdNMr1RTscp9XeCnpXMVYlmXLb2ZEHJpZpbv5xm83k++f3EKDOKC5KlfEPdBKhUerXfMqVBaO0X9Thfe9GXhldlG90Td+31JEHEs9Nqqa2Ghtr1LzvQUVB7SxL+2a36+1fZgNzIahFIgDegovbXaxbSC/1CAO6Lk0RmK2bB1N7Ec4iFN0NbvXgeQpbkb27UFxiq692RE4HkmFozhFq4AW9C7nzbjtA8QBPToqu9T+Plcz90pBHNDNi27bV3YDd2Z4mJ5Czza9sS3lZAFxQPdvuv/MRxeW9uVrGDUMllsGL3+AB3FASz29h4Qu0Tk7fmqMQRzRQk+/ouvZ9W94avjkZeUuLhkwANqFSTy9l/WlDuOfLtfkEvEdtMTTp2j3BsvmTQK2aJGnT9Fu1Ddlnm2p+AYt8/QrOtzrzCOBiCNa6OlXtMq3cEXFAS319B4djL2xQ6Dzfg3igJZ5eg9ejL3p0zvp0+gKxAFNYz/26N9B12OysO3Jfu25Uj89f7onokvfz0POLlniDklND2JAtJFvzzCXkgZ/7D7ea6GnjxfHy0ajAC309JHMywZRiBZ5+khWvKEARAHaifE9/YLmZ0vEt2iBp0/RvGxp1AYt8PQpmZeNRG3Qf7LCBZ4+LTYzWzJgoKUWevqI5mXDKIpWXVW0w8SfJ7h/BQhDgVw2EAf0t9fvP278qfX4FcANBfLZQBzQwiEumPp4Aw63ZPz8TjQ19YfImHAh2kkmpj4SDrcXoxNTf4iMCdeiM1YwQsP2UjQx9ZSzc3Qlmpr6HRg9dY4mE/U04/YITP02AM4Qcehci5+HPAeHYOoPouJpEAd0jPod2wf68RWA2c6oqc9menwFsK88Mtw7nXLbr8/E1O8HLGdBHNAwUb/kOt5JTf1xlE8BcYrGifqMlk0mpv48HMUpGifqz7VCKrvCUZyi/6+vAH6aw02jN3ZCv2T/XmNHDO4rQM76x9u2ii+/xNTuBxVj3FS6KnUv+M7Fs/4RvYr7X2KMUT8Bqn5A97SBuwoAAAAASUVORK5CYII=\n",
       "text/latex": [
        "$$\\left[\\begin{matrix}\\frac{1}{6} & \\frac{2}{3} & \\frac{1}{6}\\\\\\frac{2}{3} & - \\frac{10}{3} & \\frac{2}{3}\\\\\\frac{1}{6} & \\frac{2}{3} & \\frac{1}{6}\\end{matrix}\\right]$$"
       ],
@@ -203,7 +203,7 @@
        "⎣1/6   2/3   1/6⎦"
       ]
      },
-     "execution_count": 23,
+     "execution_count": 19,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -217,7 +217,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 24,
+   "execution_count": 20,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -242,7 +242,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.6.7"
+   "version": "3.6.8"
   }
  },
  "nbformat": 4,
diff --git a/pystencils_tests/test_field_equality.ipynb b/pystencils_tests/test_field_equality.ipynb
index 03837702b4d4ea4b1667ea6bbe724f717a69a182..8de31e83b5e496cd57e7e1f7d91a1847588108d8 100644
--- a/pystencils_tests/test_field_equality.ipynb
+++ b/pystencils_tests/test_field_equality.ipynb
@@ -164,13 +164,13 @@
      "output_type": "stream",
      "text": [
       "Field Accesses:\n",
-      "   - f[0], hash 2177071761647211096, offsets (0,), index (), (('f_C', ('commutative', True)), ((0,), (fshape_f[0],), (fstride_f[0],), -2638709558778433189, <FieldType.GENERIC: 0>, 'f'), 0)\n",
-      "   - f[0], hash -219035921004479174, offsets (0,), index (), (('f_C', ('commutative', True)), ((0,), (fshape_f[0],), (fstride_f[0],), 1379426851108887372, <FieldType.GENERIC: 0>, 'f'), 0)\n",
+      "   - f[0], hash -3276894289571194847, offsets (0,), index (), (('f_C', ('commutative', True)), ((0,), (_size_f_0,), (_stride_f_0,), 3146377891102027609, <FieldType.GENERIC: 0>, 'f', None), 0)\n",
+      "   - f[0], hash -1516451775709390846, offsets (0,), index (), (('f_C', ('commutative', True)), ((0,), (_size_f_0,), (_stride_f_0,), -1421177580377734245, <FieldType.GENERIC: 0>, 'f', None), 0)\n",
       "\n",
       "   -> 0,1  f[0] == f[0]: False\n",
       "Fields\n",
-      "  - f, 139911303819560, shape (fshape_f[0],), strides (fstride_f[0],), double, FieldType.GENERIC, layout (0,)\n",
-      "  - f, 139911303820008, shape (fshape_f[0],), strides (fstride_f[0],), float, FieldType.GENERIC, layout (0,)\n",
+      "  - f, 140548694371968, shape (_size_f_0,), strides (_stride_f_0,), double, FieldType.GENERIC, layout (0,)\n",
+      "  - f, 140548693963104, shape (_size_f_0,), strides (_stride_f_0,), float, FieldType.GENERIC, layout (0,)\n",
       "\n",
       "  - f == f: False, ids equal False, hash equal False\n"
      ]
@@ -179,52 +179,6 @@
    "source": [
     "print_field_accesses_debug(f1.center * f2.center)"
    ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Custom fields"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 10,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "from lbmpy.sparse.update_rule_sparse import *"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 13,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEcAAAAgBAMAAACyb3jOAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEJl2IquJVETdZu8yu83OyatpAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABN0lEQVQ4EcWQsUoDQRCGJ6A5CcFAsNDqLGJhF3yC4AukEITgE9iIICmCRV4hjZVIAr6AkDoQ8gByTao0aWwPLZR0OjO7MzdLbkErr7j5d75v93YOwD2vvm6V+lpbi57GMNRPRkVjUMQwJf8jNc86UHonAnKny+FtuUTAS5XNIVjpTsZj4KXkHbv3QgBUYpC8MKmOAM7HF2qpRGDn9LONpHb1cKwCBZEC0CDVPCKBBd25MTCqZMGQnFovY/Umzx/z/I0zgm/XBbjmvLtmgC89CUEq0pJzieSA2zuNSQ6wVNlEJA9Y2vuISB6wVMW7pVmymk14WVzcAR67v49QhyDvwMkCaKKnI+wFknMUkPTcikgC9N+kmfxxf4yU8ReoZLNwqSphw2bhVM3YccluiJ70Zyn4dLD7t4sf071mgtNBAg8AAAAASUVORK5CYII=\n",
-      "text/latex": [
-       "$${{f}_{\\mathbf{{l}_{1}^{1}}}^{1}} + {{f}_{\\mathbf{{l}_{1}}}^{1}}$$"
-      ],
-      "text/plain": [
-       "f_000035D373 + f_000035D373"
-      ]
-     },
-     "execution_count": 13,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "list_field = create_symbolic_list('l', 10, 2, np.float64)\n",
-    "normal_field = ps.fields(\"f: [2D]\")\n",
-    "normal_field.field_type = ps.FieldType.CUSTOM\n",
-    "\n",
-    "t1 = normal_field.absolute_access( (list_field[1](0),), (1,))\n",
-    "t2 = normal_field.absolute_access( (list_field[1](1),), (1,))\n",
-    "t1 + t2"
-   ]
   }
  ],
  "metadata": {
@@ -243,7 +197,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.6.6"
+   "version": "3.6.8"
   }
  },
  "nbformat": 4,
diff --git a/pystencils_tests/test_finite_differences.py b/pystencils_tests/test_finite_differences.py
index dcf9fa2b735c8512424918052c63348b51355cd7..f8784d0e34cb66198639f2d66b6f6d7f98ff0467 100644
--- a/pystencils_tests/test_finite_differences.py
+++ b/pystencils_tests/test_finite_differences.py
@@ -25,6 +25,7 @@ def test_spatial_2d_unit_sum():
             _, coefficients = stencil_coefficients(discretized)
             assert sum(coefficients) == 0
 
+
 def test_spatial_1d_unit_sum():
     f = ps.fields("f: double[1D]")
     h = sp.symbols("h")
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000000000000000000000000000000000000..88de625d43f2fefe3558748698f6746d89ebacc5
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,42 @@
+[pytest]
+python_files = test_*.py *_test.py scenario_*.py
+norecursedirs = *.egg-info .git .cache .ipynb_checkpoints htmlcov
+addopts = --doctest-modules --durations=20  --cov-config pytest.ini
+
+[run]
+branch = True
+source = pystencils
+         pystencils_tests
+
+omit = doc/*
+       pystencils_tests/*
+       setup.py
+       conftest.py
+       pystencils/jupytersetup.py
+       pystencils/cpu/msvc_detection.py
+       pystencils/sympy_gmpy_bug_workaround.py
+       pystencils/cache.py
+       pystencils/pacxx/benchmark.py
+
+[report]
+exclude_lines =
+       # Have to re-enable the standard pragma
+       pragma: no cover
+
+       def __repr__
+
+       # Don't complain if tests don't hit defensive assertion code:
+       raise AssertionError
+       raise NotImplementedError
+       #raise ValueError
+
+       # Don't complain if non-runnable code isn't run:
+       if 0:
+       if False:
+       if __name__ == .__main__.:
+
+skip_covered = True
+fail_under = 74
+
+[html]
+directory = coverage_report
diff --git a/setup.py b/setup.py
index 1694c1545f383499ae0d6e6c92571632a22b7b95..a24dafccb0b2afa60cb454a09c3e08c2c5bc3269 100644
--- a/setup.py
+++ b/setup.py
@@ -1,12 +1,55 @@
 import os
 import sys
+import io
 from setuptools import setup, find_packages
-sys.path.insert(0, os.path.abspath('..'))
-from custom_pypi_index.pypi_index import get_current_dev_version_from_git
+import distutils
+from contextlib import redirect_stdout
+from importlib import import_module
+sys.path.insert(0, os.path.abspath('doc'))
+from version_from_git import version_number_from_git
+
+
+quick_tests = [
+    'test_datahandling.test_kernel',
+    'test_blocking_staggered.test_blocking_staggered',
+    'test_blocking_staggered.test_blocking_staggered',
+    'test_vectorization.test_vectorization_variable_size',
+]
+
+
+class SimpleTestRunner(distutils.cmd.Command):
+    """A custom command to run selected tests"""
+
+    description = 'run some quick tests'
+    user_options = []
+
+    @staticmethod
+    def _run_tests_in_module(test):
+        """Short test runner function - to work also if py.test is not installed."""
+        test = 'pystencils_tests.' + test
+        mod, function_name = test.rsplit('.', 1)
+        if isinstance(mod, str):
+            mod = import_module(mod)
+
+        func = getattr(mod, function_name)
+        print("   -> %s in %s" % (function_name, mod.__name__))
+        with redirect_stdout(io.StringIO()):
+            func()
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        """Run command."""
+        for test in quick_tests:
+            self._run_tests_in_module(test)
 
 
 setup(name='pystencils',
-      version=get_current_dev_version_from_git(),
+      version=version_number_from_git(),
       description='Python Stencil Compiler based on sympy as numpy',
       author='Martin Bauer',
       license='AGPLv3',
@@ -14,6 +57,7 @@ setup(name='pystencils',
       url='https://i10git.cs.fau.de/software/pystencils/',
       packages=['pystencils'] + ['pystencils.' + s for s in find_packages('pystencils')],
       install_requires=['sympy>=1.1', 'numpy', 'appdirs', 'joblib'],
+      package_data={'pystencils': ['include/*.h']},
       classifiers=[
           'Development Status :: 4 - Beta',
           'Framework :: Jupyter',
@@ -31,6 +75,9 @@ setup(name='pystencils',
           'doc': ['sphinx', 'sphinx_rtd_theme', 'nbsphinx',
                   'sphinxcontrib-bibtex', 'sphinx_autodoc_typehints', 'pandoc'],
       },
-      tests_require=['pytest', 'pytest-cov', 'pytest-xdist', 'flake8'],
+      tests_require=['pytest', 'pytest-cov', 'pytest-xdist', 'flake8', 'nbformat', 'nbconvert', 'ipython'],
       python_requires=">=3.6",
+      cmdclass={
+          'quicktest': SimpleTestRunner
+      }
       )