diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000000000000000000000000000000000000..42d62190033f822d7cf5958b7ffb9d77681fcf5d
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,14 @@
+[flake8]
+doctests = True
+exclude = .git, .eggs, __pycache__, docs, dist, venv, .tox, env, envs
+ignore =
+    # line too long, we use black
+    E501,
+    # line break before binary operator
+    W503,
+    # wrong flake defaults: see https://github.com/psf/black/issues/315, https://github.com/psf/black/issues/43
+    E203,
+    W503,
+    W504
+per-file-ignores =
+    __init__.py:F401,E402
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8f4a5d31d4806e0190b48ce24da82366aa3063d4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,184 @@
+# requirements.txt is generated dynamically in this project (e.g. make requirements)
+requirements.txt
+
+# junit reports (generated by tox)
+report/
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+envs/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
+
+# pyc files:
+*.pyc 
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+
+# Flask instance folder
+instance/
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# IPython Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# dotenv
+.env
+
+# virtualenv
+venv/
+ENV/
+
+# Spyder project settings
+.spyderproject
+
+# vim files
+*.sw*
+
+# VisualStudioCode
+.vscode/*      # Maybe .vscode/**/* instead - see comments
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+**/.history
+
+# folder
+tmp/
+.idea
+docs/source/
+
+### Git ###
+*.orig
+
+### Linux ###
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Latex temp files (in case you include a documentation in latex e.g.)
+*.aux
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2daefcf8570e3ee6714c45b3af044e67569fb161
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,109 @@
+image: python:latest
+
+# Change pip's cache directory to be inside the project directory since we can
+# only cache local items.
+variables:
+  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
+
+# Pip's cache doesn't store the python packages
+# https://pip.pypa.io/en/stable/reference/pip_install/#caching
+#
+# If you want to also cache the installed packages, you have to install
+# them in a virtualenv and cache it as well.
+cache:
+  paths:
+    - .cache/pip
+    - venv/
+    - .cache/apt
+
+stages:
+  - build
+  - test
+  - deploy
+
+before_script:
+  - pip install virtualenv
+  - virtualenv venv
+  - source venv/bin/activate
+  - poetry install
+
+dist:
+  stage: build
+  script:
+    - mkdir -p .cache/apt
+    - apt-get update -yqq
+    - apt-get install -y gfortran libopenblas-dev liblapack-dev
+    - apt-get -o dir::cache::archives=".cache/apt" install -y -qq gfortran liblapack-dev libgmp-dev
+    - python setup.py bdist_wheel
+    # an alternative approach is to install and run:
+    - pip install dist/*
+    # run the command here
+  artifacts:
+    paths:
+      - dist/*.whl
+    expire_in: 1h
+  only:
+    - tags
+
+pages:
+  stage: build
+  script:
+    - poetry install --only docs
+    - cd docs
+    - make html
+    - cd ..
+    - mkdir -p public
+    - rm -rf public/*
+    - mv docs/_build/html/* public/  # add it to pages. Pages is exposing public/index.html
+  only:
+    - master
+  cache:
+    paths:
+      - public
+  artifacts:
+    paths:
+      - public
+      - docs
+
+lint:
+  stage: test
+  before_script:
+    - pip install -q flake8
+  script:
+    - flake8
+
+test:
+  stage: test
+  script:
+    - pip --version
+    - pip install tox  # you can also use tox
+    - tox
+  coverage: '/^TOTAL.+?(\d+\%)$/'
+  artifacts:
+    # paths:
+    # pa- report/unit
+    reports:
+      junit:
+        - report/junit.xml
+pypi:
+  image: docker.km3net.de/base/python:3
+  stage: deploy
+  cache: {}
+  before_script:
+    - echo "Starting upload to pypi"
+  script:
+    # Check if current_version is already uploaded
+    - VERSION=$((python -c "import configparser; config = configparser.ConfigParser(); config.read('setup.cfg'); print(config['bumpversion']['current_version'])") 2>&1)
+    - MODULE_NAME=$((python -c "import configparser; config = configparser.ConfigParser(); config.read('setup.cfg'); print(config['metadata']['name'])") 2>&1)
+    - PACKAGE_JSON_URL="https://pypi.org/pypi/$MODULE_NAME/json" 
+    - apt-get install -qq -y jq
+    - PYPI_VERSIONS=$(curl -s "$PACKAGE_JSON_URL" | jq  -r '.releases | keys | .[]' | sort -V)
+    - if [[ $PYPI_VERSIONS =~ $VERSION ]]; then echo "Version $VERSION is already uploaded!"; exit 1; fi
+    # Version not already uploaded so do it now.
+    - echo "Uploading version $VERSION"
+    - pip install -U twine
+    - python setup.py sdist
+    - twine upload dist/*
+  rules:
+    # for debuggin: git commit -am "deb" && git push && bumpversion patch && git tag -l --sort=-v:refname | head -n 1 | git push origin
+    - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/
\ No newline at end of file
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b6d2326ebedc61e8324b46226aabeefae75dce69
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,29 @@
+default_language_version:
+    python: python3
+repos:
+-   repo: https://github.com/ambv/black
+    rev: 22.3.0
+    hooks:
+    - id: black
+      language_version: python3.10
+-   repo: https://gitlab.com/pycqa/flake8
+    rev: 3.9.2
+    hooks:
+    - id: flake8
+-   repo: https://github.com/pre-commit/pre-commit-hooks 
+    rev: v4.0.1
+    hooks:
+    - id: check-json
+    - id: pretty-format-json
+      args: ['--indent', '4']
+    - id: check-merge-conflict
+    - id: check-toml
+    - id: check-yaml
+    - id: debug-statements
+    - id: detect-private-key
+    - id: end-of-file-fixer
+-   repo: https://github.com/asottile/blacken-docs
+    rev: v1.12.1
+    hooks:
+    - id: blacken-docs
+      additional_dependencies: [black==22.3.0]
diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1db793f37946026137fbe27e56e648887339190c
--- /dev/null
+++ b/.readthedocs.yml
@@ -0,0 +1,25 @@
+# .readthedocs.yml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+
+formats: all
+
+build:
+  image: latest
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+  configuration: docs/conf.py
+
+# Optionally set the version of Python and requirements required to build your docs
+python:
+  version: 3.7
+  install:
+    - method: pip
+      path: .
+      extra_requirements:
+        - docs
diff --git a/AUTHORS.rst b/AUTHORS.rst
new file mode 100644
index 0000000000000000000000000000000000000000..db7323ffb1f36e4403ea094afa0bd6d47c398fa3
--- /dev/null
+++ b/AUTHORS.rst
@@ -0,0 +1,17 @@
+=======
+Credits
+=======
+This package was created with Cookiecutter_ and the `dboe/dough`_ project template.
+
+.. _Cookiecutter: https://github.com/audreyr/cookiecutter
+.. _`dboe/dough`: https://gitlab.com/dboe/dough
+
+Development Lead
+----------------
+
+* Daniel Böckenhoff <dboe@ipp.mpg.de>
+
+Contributors
+------------
+
+None yet. Why not be the first?
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
new file mode 100644
index 0000000000000000000000000000000000000000..408c188f04c5bbb182aa8bcd920c2b0d60a339e1
--- /dev/null
+++ b/CONTRIBUTING.rst
@@ -0,0 +1,166 @@
+============
+Contributing
+============
+..
+    [contributing]
+
+.. highlight:: shell
+
+Contributions are welcome, and they are greatly appreciated! Every little bit
+helps, and credit will always be given.
+
+You can contribute in many ways:
+
+Types of Contributions
+----------------------
+
+Report Bugs
+~~~~~~~~~~~
+
+Report bugs at <https://gitlab.mpcdf.mpg.de/dboe/rna/-/issues/>_.
+
+If you are reporting a bug, please include:
+
+* Your operating system name and version.
+* Any details about your local setup that might be helpful in troubleshooting.
+* Detailed steps to reproduce the bug.
+
+If you want quick feedback, it is helpful to mention specific developers
+(@devloper_name) or @all. This will trigger a mail to the corresponding developer(s).
+
+Fix Bugs
+~~~~~~~~
+
+Look through the repository issues for bugs. Anything tagged with "bug" and "help
+wanted" is open to whoever wants to implement it.
+
+Implement Features
+~~~~~~~~~~~~~~~~~~
+
+Look through the remote issues for features. Anything tagged with "enhancement"
+and "help wanted" is open to whoever wants to implement it.
+
+Write Documentation
+~~~~~~~~~~~~~~~~~~~
+
+`rna` could always use more :ref name="Documentation":`documentation`, whether as part of the
+official `rna` docs, in docstrings, or even on the web in blog posts,
+articles, and such.
+
+Write pytest, unittests or doctests
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`rna` profits a lot from better :ref name="Testing":`testing`. We encourage you to add unittests 
+with the `pytest` module (`unittest` module is OK, too) in the `tests` directory or doctests (as part of docstrings or in the documentation).
+
+Submit Feedback
+~~~~~~~~~~~~~~~
+
+The best way to send feedback is to file an `Issue <https://gitlab.mpcdf.mpg.de/dboe/rna/-/issues/>`_.
+
+If you are proposing a feature:
+
+* Explain in detail how it would work.
+* Keep the scope as narrow as possible, to make it easier to implement.
+* Remember that this is a volunteer-driven project, and that contributions
+  are welcome
+
+Get Started!
+------------
+
+Ready to contribute? Here's how to set up `rna` for local development.
+
+1. Fork the `rna` repo.
+2. Clone your fork locally::
+
+    $ git clone git@gitlab.mpcdf.mpg.de:dboe/rna.git
+
+3. Set up your fork for local development::
+
+    $ cd rna/
+    $ pip install .[dev]
+
+4. Step 3. already installed `pre-commit <https://pre-commit.com/>`_. Initialize it by running::
+
+    $ pre-commit install
+
+5. Create a branch for local development::
+
+    $ git checkout -b name-of-your-bugfix-or-feature
+
+   Now you can make your changes locally.
+
+6. When you're done making changes, check that your changes pass flake8 and the
+   tests::
+
+    $ make test
+
+7. Commit your changes and push your branch to origin::
+
+    $ git add .
+    $ git commit -m "Your detailed description of your changes."
+    $ git push origin name-of-your-bugfix-or-feature
+
+8. Submit a pull request through the repository website.
+
+Pull Request Guidelines
+-----------------------
+
+Before you submit a pull request, check that it meets these guidelines:
+
+1. The pull request should include tests.
+2. If the pull request adds functionality, the docs should be updated. Put
+   your new functionality into a function with a docstring, and add the
+   feature to the list in README.rst.
+3. The pull request should work for Python 3.5, 3.6, 3.7 and 3.8, and for PyPy. Check
+   <https://gitlab.mpcdf.mpg.de/dboe/rna/-/merge_requests/>_
+   and make sure that the tests pass for all supported Python versions.
+
+Testing
+-------
+
+To run tests, use::
+
+    $ make test
+
+To run a subset of tests, you have the following options::
+
+    $ pytest tests/test_package.py
+
+    $ pytest tests/test_package.py::Test_rna::test_version_type
+
+    $ pytest --doctest-modules docs/usage.rst
+
+    $ pytest --doctest-modules rna/core.py -k "MyClass.funciton_with_doctest"
+
+Use the '--trace' option to directly jump into a pdb debugger on fails. Check out the coverage of your api with::
+
+    $ make coverage
+
+Documentation
+-------------
+To compile the documentation (including automatically generated module api docs), run::
+
+    $ make docs
+    
+To run an auto-updating server, use
+
+    $ make docs-serve
+
+Use doctests as much as possible in order to have tested examples in your documentation.
+
+Style guide
+-----------
+Please follow the `google style guide <https://google.github.io/styleguide/pyguide.html>`_ illustrated
+by `this example <https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html>`_.
+
+Deploying
+---------
+
+A reminder for the maintainers on how to deploy.
+Make sure all your changes are committed.
+Then run::
+
+    $ make publish
+
+The CI will then deploy to PyPI if tests pass.
\ No newline at end of file
diff --git a/LICENSE.rst b/LICENSE.rst
new file mode 100644
index 0000000000000000000000000000000000000000..2854fc17c17e5a4e5b16e10a40957009b2e9c0c8
--- /dev/null
+++ b/LICENSE.rst
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023, Daniel Böckenhoff
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..a3b3f26a1e81ddcf274e4bc0de81fe37590f526e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,86 @@
+include tools/Makefile.envs
+
+test: FORCE
+	flake8 rna tests
+	pylint rna tests
+	py.test
+
+coverage: env
+	# coverage run $(MODULE) test
+	py.test --cov=$(MODULE) || true
+	# coverage report
+	coverage html
+	python -m webbrowser htmlcov/index.html
+
+clean:
+	coverage erase
+	rm -rf htmlcov
+	rm -rf docs/_build
+	rm -rf docs/source
+	rm -rf dist
+	rm -rf build
+	rm -rf report
+	rm -rf .tox
+	rm -rf .pytest_cache
+	rm -rf *.egg-info
+	# pre-commit clean
+
+publish:
+	@echo $(GITSTATUS)
+	@if [ -z $(GITSTATUS) ]; then \
+	  	echo "Working directory clean."; \
+	else \
+		git status; \
+		printf $(_WARN) "WAIT" "Your Git status is not clean!" ; \
+	    if $(MAKE) -s confirm ; then \
+		    printf $(_INFO) "OK" "Continuing" ; \
+		else \
+		    printf $(_ERROR) "KO" "EXIT" ; \
+	        exit 1; \
+		fi \
+	fi
+	# call optional with argument: make part=minor publish
+	poetry version $(part)  # possible: major / minor / patch
+	git commit -m "release-$(poetry version --short)"
+	git tag "release-$(poetry version --short)"
+	git push
+	git push --tags
+
+untag:
+	# remove last tag. mostly, because publishing failed
+	git tag -d v$(VERSION)
+	git push origin :refs/tags/v$(VERSION)
+
+requirements: pyproject.toml
+	poetry export --without-hashes --format=requirements.txt > requirements.txt
+	
+docs-clean:
+	rm -rf docs/_build
+
+docs-serve:
+	${CONDA_RUN}poetry install --only docs
+	sphinx-autobuild docs docs/_build/ -j auto --watch my_project
+	
+docs-build: docs-clean
+	${CONDA_RUN}poetry install --only docs
+	sphinx-build -M html docs docs/_build/ -E -a -j auto -W --keep-going
+
+docs: docs-build
+	# open the html slides
+	${CONDA_RUN}python -m webbrowser docs/_build/html/index.html
+
+update:
+	# get up to date with the cookiecutter template 'dough'
+	# first check that no changes are existing
+	@echo $(GITSTATUS)
+	@if [ -z $(GITSTATUS) ]; then \
+	  	echo "Working directory clean."; \
+	else \
+		git status; \
+	  	echo "Your status is not clean! I can not update!"; \
+	    exit 1; \
+	fi
+	# Starting upgrade
+	cookiecutter_project_upgrader
+
+FORCE: ;
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000000000000000000000000000000000000..5821eb3b1fc4178795f1db6c1c618b5358d84336
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,73 @@
+=====================
+library documentation
+=====================
+
+..
+    [shields-start]
+
+
+.. pypi
+.. image:: https://img.shields.io/pypi/v/rna.svg
+    :target: https://pypi.python.org/pypi/rna
+.. ci
+    .. image:: https://img.shields.io/travis/dboe/rna.svg
+        :target: https://travis-ci.com/dboe/rna
+.. image:: https://gitlab.mpcdf.mpg.de/dboe/rna/badges/master/pipeline.svg
+    :target: https://gitlab.mpcdf.mpg.de/dboe/rna/commits/master
+
+.. coverage
+.. image:: https://gitlab.mpcdf.mpg.de/dboe/rna/badges/master/coverage.svg
+    :target: https://gitlab.mpcdf.mpg.de/dboe/rna/commits/master
+
+.. readthedocs
+.. image:: https://readthedocs.org/projects/rna/badge/?version=latest
+    :target: https://rna.readthedocs.io/en/latest/?badge=latest
+    :alt: Documentation Status
+
+.. pyup crosschecks your dependencies. Github is default, gitlab more complicated: https://pyup.readthedocs.io/en/latest/readme.html#run-your-first-update 
+    .. image:: https://pyup.io/repos/github/dboe/rna/shield.svg
+        :target: https://pyup.io/repos/github/dboe/rna/
+        :alt: Updates
+
+.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white
+   :target: https://github.com/pre-commit/pre-commit
+   :alt: pre-commit
+..
+    [shields-end]
+
+Overview
+========
+..
+    [overview-start]
+
+Basic and essential code building blocks of all pythons
+
+..
+    [overview-end]
+
+
+Licensed under the ``MIT License``
+
+Resources
+---------
+..
+    [resources-start]
+
+* Source code: https://gitlab.mpcdf.mpg.de/dboe/rna
+* Documentation: https://rna.readthedocs.io
+* Pypi: https://pypi.python.org/pypi/rna
+..
+    [resources-end]
+
+
+Features
+--------
+..
+    [features-start]
+
+The following features should be highlighted:
+
+* TODO
+
+..
+    [features-end]
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..8607fce7795fab193404dac8f276a887a9c90a15
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,25 @@
+# Minimal makefile for Sphinx documentation
+#
+MODULE_PATH := $(shell cd ..; pwd)
+MODULE := $(shell basename "$(MODULE_PATH)")
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = .
+BUILDDIR      = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+apidocs: $(MODULEPATH)/$(MODULE)/*.py apidoc-templates/*
+	 sphinx-apidoc -o source/ ../$(MODULE)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/_static/index.css b/docs/_static/index.css
new file mode 100644
index 0000000000000000000000000000000000000000..40f044c1fe244332b88af989894dd41a0c5a96b8
--- /dev/null
+++ b/docs/_static/index.css
@@ -0,0 +1,73 @@
+@font-face {
+	font-family: 'inter';
+	src: url('inter.ttf') format('truetype');
+}
+
+#landing-header {
+	width: 100%;
+	display: flex;
+	flex-wrap: wrap;
+	margin-left: auto;
+	margin-top: 1rem;
+	font-family: Inter;
+}
+
+#landing-header > img {
+	width: 75%;
+	margin: auto;
+}
+
+#landing-tagline {
+	width: 100%;
+	text-align: center;
+	font-size: xx-large;
+}
+
+
+#landing-overview {
+	width: 90%;
+	display: flex;
+	flex-wrap: wrap;
+	gap: 1rem;
+	margin-top: 4rem;
+	margin-left: auto;
+	margin-right: auto;
+	justify-content: space-around;
+}
+
+
+
+@media (min-width: 992px) {
+	#landing-overview > section {
+		width: 45% !important;
+	}
+}
+
+@media (min-width: 1400px) {
+	#landing-overview > section {
+		width: 30% !important;
+	}
+}
+
+#landing-overview > section {
+	font-size: medium;
+	background-color: var(--pst-color-on-background);
+	padding: .75rem;
+	border-radius: 5px;
+	text-align: justify;
+}
+
+
+
+#landing-overview > section  h2 {
+	margin-top: 0;
+	font-weight: bold;
+	font-size: medium;
+	text-transform: uppercase;
+	color: #edb641;
+}
+
+
+#landing-overview > section > p {
+	width: 100%;
+}
\ No newline at end of file
diff --git a/docs/_static/inter.ttf b/docs/_static/inter.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..ec3164efa8fe938310f74b6156d3ad33ccb2fef6
Binary files /dev/null and b/docs/_static/inter.ttf differ
diff --git a/docs/_static/style.css b/docs/_static/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..ca785ff3c5af458022c6a48edd3d319e3dfe51fb
--- /dev/null
+++ b/docs/_static/style.css
@@ -0,0 +1,93 @@
+.article-container p {
+	text-align: justify;
+}
+
+#version-warning {
+	top: 0;
+	position: sticky;
+	z-index: 60;
+	width: 100%;
+	height: 2.5rem;
+	display: flex;
+	column-gap: .5rem;
+	justify-content: center;
+	justify-items: center;
+	align-items: center;
+	background-color: #eee;
+	border-bottom: 2px solid #ae2828;
+}
+
+@media (prefers-color-scheme: dark) {
+	body:not([data-theme="light"]) #version-warning {
+		background-color: black;
+	}
+}
+
+
+table.docutils {
+	clear: left;
+	float: left;
+	margin: 0 1rem 1rem;
+}
+
+
+/* theme customization */
+
+html[data-theme="dark"] {
+	--color-background-primary: #1d2433;
+	--color-background-secondary: #0c101a;
+	--pst-color-on-background: #2e374a;
+	--pst-color-border: #2f2f2f;
+}
+
+html[data-theme="light"] {
+	--color-background-primary: #f8f9fb;
+	--color-background-secondary: #fff;
+}
+
+html[data-theme="light"], html[data-theme="dark"] {
+	--pst-color-background: var(--color-background-primary);
+	--pst-color-primary: #ffae57;
+}
+
+
+@media (min-width: 960px) {
+	.bd-page-width {
+		max-width: 100rem;
+	}
+}
+
+.bd-sidebar-primary {
+	display: block;
+	flex: 0 0 18%;
+}
+
+
+.bd-content, .bd-sidebar-secondary {
+	background-color: var(--color-background-secondary);
+}
+
+
+.sd-tab-content {
+	box-shadow: 0 -0.0625rem var(--sd-color-tabs-overline);
+}
+
+div.literal-block-wrapper, pre {
+	border: none;
+}
+
+.code-block-caption {
+	background-color: var(--pst-color-surface);
+}
+
+.navbar-persistent--mobile {
+	margin-left: unset;
+}
+
+.navbar-persistent--mobile:last-of-type {
+	padding-left: 1rem;
+}
+
+#navbar-icon-links a {
+	padding-top: .2rem;
+}
\ No newline at end of file
diff --git a/docs/_static/versioning.js b/docs/_static/versioning.js
new file mode 100644
index 0000000000000000000000000000000000000000..15f6c9b301978bd4e8583edc2d7696903bd0340c
--- /dev/null
+++ b/docs/_static/versioning.js
@@ -0,0 +1,114 @@
+const loadVersions = async () => {
+    const res = await fetch(DOCUMENTATION_OPTIONS.URL_ROOT + "versions.json")
+    if (res.status !== 200) {
+        return null
+    }
+    return await res.json()
+}
+
+
+const getCurrentVersion = (versions) => {
+    const baseURL = new URL(DOCUMENTATION_OPTIONS.URL_ROOT, window.location).href
+    const parts = window.location.href.replace(baseURL, "").split("/")
+    if (!parts.length) {
+        return null
+    }
+    const maybeVersion = parts[0]
+    if (maybeVersion === "lib") {
+        return versions.latest
+    }
+    if (versions.versions.includes(maybeVersion)) {
+        return maybeVersion
+    }
+    return null
+}
+
+
+const addVersionWarning = (currentVersion, latestVersion) => {
+    if (currentVersion === latestVersion) {
+        return
+    }
+
+    const navbarMain = document.getElementById("navbar-main")
+    if (!navbarMain) {
+        return
+    }
+
+    const container = document.createElement("div")
+    container.id = "version-warning"
+
+    const warningText = document.createElement("span")
+    warningText.textContent = `You are viewing the documentation for ${currentVersion === "dev" ? "a preview" : "an outdated"} version of this project.`
+    container.appendChild(warningText)
+
+    const latestLink = document.createElement("a")
+    latestLink.textContent = "Click here to go to the latest version"
+    latestLink.href = DOCUMENTATION_OPTIONS.URL_ROOT + "lib"
+    container.appendChild(latestLink)
+
+    navbarMain.before(container)
+}
+
+
+const formatVersionName = (version, isLatest) => version + (isLatest ? " (latest)" : "")
+
+
+const addVersionSelect = (currentVersion, versionSpec) => {
+    const navEnd = document.getElementById("navbar-end")
+    if (!navEnd) {
+        return
+    }
+
+    const container = document.createElement("div")
+    container.classList.add("navbar-nav")
+
+    const dropdown = document.createElement("div")
+    dropdown.classList.add("dropdown")
+    container.appendChild(dropdown)
+
+    const dropdownToggle = document.createElement("button")
+    dropdownToggle.classList.add("btn", "dropdown-toggle", "nav-item")
+    dropdownToggle.setAttribute("data-toggle", "dropdown")
+    dropdownToggle.setAttribute("type", "button")
+    dropdownToggle.textContent = `Version: ${formatVersionName(currentVersion, currentVersion === versionSpec.latest)}`
+    dropdown.appendChild(dropdownToggle)
+
+    const dropdownContent = document.createElement("div")
+    dropdownContent.classList.add("dropdown-menu")
+    dropdown.appendChild(dropdownContent)
+
+    for (const version of versionSpec.versions) {
+        const navItem = document.createElement("li")
+        navItem.classList.add("nav-item")
+
+        const navLink = document.createElement("a")
+        navLink.classList.add("nav-link", "nav-internal")
+        navLink.href = DOCUMENTATION_OPTIONS.URL_ROOT + version
+        navLink.textContent = formatVersionName(version, version === versionSpec.latest)
+        navItem.appendChild(navLink)
+
+        dropdownContent.appendChild(navItem)
+    }
+
+    navEnd.prepend(container)
+}
+
+
+const setupVersioning = (versions) => {
+    if (versions === null) {
+        return
+    }
+
+    const currentVersion = getCurrentVersion(versions)
+    if (currentVersion === null) {
+        return
+    }
+
+    addVersionWarning(currentVersion, versions.latest)
+    addVersionSelect(currentVersion, versions)
+}
+
+
+window.addEventListener("DOMContentLoaded", () => {
+    loadVersions().then(setupVersioning)
+})
diff --git a/docs/_templates/custom-class-template.rst b/docs/_templates/custom-class-template.rst
new file mode 100644
index 0000000000000000000000000000000000000000..f73eda50ec593f7393241c5d6aa4c143a66c805b
--- /dev/null
+++ b/docs/_templates/custom-class-template.rst
@@ -0,0 +1,34 @@
+{{ fullname | escape | underline}}
+
+.. currentmodule:: {{ module }}
+
+.. autoclass:: {{ objname }}
+   :members:
+   :show-inheritance:
+   :inherited-members:
+   :special-members: __call__, __add__, __mul__
+
+   {% block methods %}
+   {% if methods %}
+   .. rubric:: {{ _('Methods') }}
+
+   .. autosummary::
+      :nosignatures:
+   {% for item in methods %}
+      {%- if not item.startswith('_') %}
+      ~{{ name }}.{{ item }}
+      {%- endif -%}
+   {%- endfor %}
+   {% endif %}
+   {% endblock %}
+
+   {% block attributes %}
+   {% if attributes %}
+   .. rubric:: {{ _('Attributes') }}
+
+   .. autosummary::
+   {% for item in attributes %}
+      ~{{ name }}.{{ item }}
+   {%- endfor %}
+   {% endif %}
+   {% endblock %}
diff --git a/docs/_templates/custom-module-template.rst b/docs/_templates/custom-module-template.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d066d0e4dc2e34f399f55ea38d92ed4540787317
--- /dev/null
+++ b/docs/_templates/custom-module-template.rst
@@ -0,0 +1,66 @@
+{{ fullname | escape | underline}}
+
+.. automodule:: {{ fullname }}
+
+   {% block attributes %}
+   {% if attributes %}
+   .. rubric:: Module attributes
+
+   .. autosummary::
+      :toctree:
+   {% for item in attributes %}
+      {{ item }}
+   {%- endfor %}
+   {% endif %}
+   {% endblock %}
+
+   {% block functions %}
+   {% if functions %}
+   .. rubric:: {{ _('Functions') }}
+
+   .. autosummary::
+      :toctree:
+      :nosignatures:
+   {% for item in functions %}
+      {{ item }}
+   {%- endfor %}
+   {% endif %}
+   {% endblock %}
+
+   {% block classes %}
+   {% if classes %}
+   .. rubric:: {{ _('Classes') }}
+
+   .. autosummary::
+      :toctree:
+      :template: custom-class-template.rst
+      :nosignatures:
+   {% for item in classes %}
+      {{ item }}
+   {%- endfor %}
+   {% endif %}
+   {% endblock %}
+
+   {% block exceptions %}
+   {% if exceptions %}
+   .. rubric:: {{ _('Exceptions') }}
+
+   .. autosummary::
+      :toctree:
+   {% for item in exceptions %}
+      {{ item }}
+   {%- endfor %}
+   {% endif %}
+   {% endblock %}
+
+{% block modules %}
+{% if modules %}
+.. autosummary::
+   :toctree:
+   :template: custom-module-template.rst
+   :recursive:
+{% for item in modules %}
+   {{ item }}
+{%- endfor %}
+{% endif %}
+{% endblock %}
diff --git a/docs/_templates/navbar-nav.html b/docs/_templates/navbar-nav.html
new file mode 100644
index 0000000000000000000000000000000000000000..72ed846db9401cf32d433408b92160e437407451
--- /dev/null
+++ b/docs/_templates/navbar-nav.html
@@ -0,0 +1,32 @@
+{% macro nav_link(label, target) -%}
+    <li class="nav-item">
+        <a class="nav-link nav-internal" href="{{ target if target.startswith('http') else pathto(target) }}">{{ label }}</a>
+    </li>
+{%- endmacro %}
+
+
+<nav class="navbar-nav">
+    <p class="sidebar-header-items__title"
+       role="heading"
+       aria-level="1"
+       aria-label="{{ _('Site Navigation') }}">
+        {{ _("Site Navigation") }}
+    </p>
+    <ul id="navbar-main-elements" class="navbar-nav">
+        {% for label, item in navbar_items | items %}
+            {% if item is string %}
+                {{ nav_link(label, item) }}
+            {% else %}
+                <div class="nav-item dropdown">
+                    <button class="btn dropdown-toggle nav-item" type="button"
+                            data-toggle="dropdown">{{ label }}</button>
+                    <ul class="dropdown-menu">
+                        {% for child_label, child_item in item | items %}
+                            {{ nav_link(child_label, child_item) }}
+                        {% endfor %}
+                    </ul>
+                </div>
+            {% endif %}
+        {% endfor %}
+    </ul>
+</nav>
diff --git a/docs/about/index.rst b/docs/about/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..befeb16595a8379cde5ae67cac41e4f63c24ca18
--- /dev/null
+++ b/docs/about/index.rst
@@ -0,0 +1,5 @@
+=====
+ABOUT
+=====
+
+.. include:: ../../AUTHORS.rst
diff --git a/docs/community/index.rst b/docs/community/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..ac7b6bcf35e98139c791cb5c4b94f08849972d65
--- /dev/null
+++ b/docs/community/index.rst
@@ -0,0 +1 @@
+.. include:: ../../CONTRIBUTING.rst
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd93a5aaf6262dcdaf829fa8b6c1b7c998ea5576
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,106 @@
+import os
+import datetime
+try:
+    import tomllib
+except ModuleNotFoundError:
+    import tomli as tomllib
+
+__source_dir = "docs"
+with open(os.path.join(os.path.dirname(__file__), "../pyproject.toml"), "rb") as f:
+    __config = tomllib.load(f)
+
+project = __config["tool"]["poetry"]["name"]
+author = __config["tool"]["poetry"]["authors"][0]
+copyright = str(datetime.date.today().year) + ", " + author
+release = __config["tool"]["poetry"]["version"]
+
+extensions = [
+    "sphinx.ext.intersphinx",
+    "sphinx.ext.autosectionlabel",
+    "sphinx.ext.autodoc",
+    "sphinx.ext.napoleon",
+    "sphinx_design",
+    "sphinx_copybutton",
+    "sphinxcontrib.mermaid",
+    "sphinx.ext.viewcode",  # Add links to highlighted source code
+    "sphinx.ext.doctest",  # Test snippets in the documentation
+    "sphinx.ext.autosummary",
+    "sphinx_autodoc_typehints",  # Automatically parse type hints
+]
+autosummary_generate = True  # Turn on sphinx.ext.autosummary
+
+templates_path = ["_templates"]
+exclude_patterns = ["_build"]
+
+intersphinx_mapping = {
+    "python": ("https://docs.python.org/3", None),
+}
+
+napoleon_google_docstring = True
+napoleon_include_special_with_doc = True
+napoleon_use_admonition_for_examples = True
+napoleon_use_admonition_for_notes = True
+napoleon_use_admonition_for_references = False
+napoleon_attr_annotations = True
+
+autosummary_generate = True  # Turn on sphinx.ext.autosummary
+html_show_sourcelink = False  # Remove 'view source code' from top of page (for html, not python)
+autodoc_inherit_docstrings = True  # If no docstring, inherit from base class
+set_type_checking_flag = True  # Enable 'expensive' imports for sphinx_autodoc_typehints
+nbsphinx_allow_errors = True  # Continue through Jupyter errors
+#autodoc_typehints = "description" # Sphinx-native method. Not as good as sphinx_autodoc_typehints
+add_module_names = False # Remove namespaces from class/method signatures
+autoclass_content = "both"  # Both the class’ and the __init__ method’s docstring are concatenated
+autodoc_class_signature = "separated"
+autodoc_default_options = {
+    "special-members": "__init__",
+    "show-inheritance": True,
+}
+autodoc_member_order = "bysource"
+autodoc_typehints_format = "short"
+
+always_document_param_types = True
+typehints_defaults = "comma"
+
+auto_pytabs_min_version = (3, 7)
+auto_pytabs_max_version = (3, 11)
+
+autosectionlabel_prefix_document = True
+
+suppress_warnings = ["autosectionlabel.*"]
+
+html_theme = "pydata_sphinx_theme"
+html_static_path = ["_static"]
+html_css_files = ["style.css"]
+html_js_files = ["versioning.js"]
+html_favicon = "images/favicon.ico"
+html_logo = "images/logo.svg"
+html_show_sourcelink = False
+html_sidebars = {"about/*": []}
+html_title = f"{project} Framework"
+
+html_theme_options = {
+    "use_edit_page_button": False,
+    "show_toc_level": 4,
+    "navbar_align": "left",
+    "icon_links": [
+        {
+            "name": "Source",
+            "url": __config["tool"]["poetry"]["repository"],
+            "icon": f"fa-brands fa-{'github' if 'github' in __config['tool']['poetry']['repository'] else 'gitlab'}",
+            "type": "fontawesome",
+        },
+    ],
+    "navbar_end": ["navbar-icon-links"],
+    "navbar_persistent": ["search-button", "theme-switcher"],
+}
+
+html_context = {
+    "navbar_items": {
+        "Documentation": "lib/index",
+        "Community": {
+            "Contribution guide": "community/index",
+        },
+        "About": "about/index",
+    }
+}
diff --git a/docs/cookiecutter_input.json b/docs/cookiecutter_input.json
new file mode 100644
index 0000000000000000000000000000000000000000..6ba957deb75057490469eb920cc34cb4cca77974
--- /dev/null
+++ b/docs/cookiecutter_input.json
@@ -0,0 +1,20 @@
+{
+    "_output_dir": "/mnt/data/git/rna/.git/cookiecutter",
+    "_template": "https://gitlab.com/dboe/dough.git",
+    "author": "Daniel B\u00f6ckenhoff",
+    "continuous_integration": "y",
+    "copyright_holder": "Daniel B\u00f6ckenhoff",
+    "copyright_license": "MIT License",
+    "data_science": "n",
+    "distribution_name": "rna",
+    "email": "dboe@ipp.mpg.de",
+    "keywords": "plotting, matplotlib, pyqtgraph, backend, logging, path, argparse",
+    "package_name": "rna",
+    "package_version": "0.7.11",
+    "pypi_username": "dboe",
+    "remote_namespace": "dboe",
+    "remote_provider": "gitlab.mpcdf.mpg.de",
+    "remote_username": "dboe",
+    "summary": "Basic and essential code building blocks of all pythons"
+}
+
diff --git a/docs/images/favicon.ico b/docs/images/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..e0482a1bebb6c86187c50d00045e5ed9e1316b58
Binary files /dev/null and b/docs/images/favicon.ico differ
diff --git a/docs/images/logo.svg b/docs/images/logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8e8ae8a9db12740245deaac106eadb7037d78179
--- /dev/null
+++ b/docs/images/logo.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13 21v2.5l-3-2-3 2V21h-.5A3.5 3.5 0 0 1 3 17.5V5a3 3 0 0 1 3-3h14a1 1 0 0 1 1 1v17a1 1 0 0 1-1 1h-7zm-6-2v-2h6v2h6v-3H6.5a1.5 1.5 0 0 0 0 3H7zM7 5v2h2V5H7zm0 3v2h2V8H7zm0 3v2h2v-2H7z"/></svg>
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..26fc81f8d013d8062ebbdde2b80368c0b2d54a4c
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,74 @@
+.. div:: sd-text-center sd-text-primary sd-fs-1 sd-font-weight-bolder -sd-text-nowra
+   
+   rna
+
+.. card::
+   :text-align: center
+   :shadow: none
+   :class-card: sd-border-0
+
+   .. include:: ../README.rst
+      :start-after: [shields-start]
+      :end-before: [shields-end]
+      
+.. grid:: 1 1 2 2
+    :gutter: 1
+
+    .. grid-item::
+
+        .. grid:: 1 1 1 1
+            :gutter: 1
+
+            .. grid-item-card:: Overview
+               :link: lib/overview/index
+               :link-type: doc
+
+               .. include:: ../README.rst
+                  :start-after: [overview-start]
+                  :end-before: [overview-end]
+
+            .. grid-item-card:: Installation
+               :link: lib/installation/index
+               :link-type: doc
+
+               .. include:: lib/installation/index.rst
+                  :start-after: [essence-start]
+                  :end-before: [essence-end]
+
+    .. grid-item::
+
+        .. grid:: 1 1 1 1
+            :gutter: 1
+
+            .. grid-item-card:: Usage
+               :link: lib/usage/index
+               :link-type: doc
+
+               .. include:: lib/usage/index.rst
+                  :start-after: [essence-start]
+                  :end-before: [essence-end]
+
+            .. grid-item-card:: API reference
+               :link: lib/reference/index
+               :link-type: doc
+               :text-align: center
+
+               :octicon:`codescan;5em;sd-text-info`
+
+            .. grid-item-card:: API development
+               :link: community/index
+               :link-type: doc
+               
+               
+               .. code-block:: shell
+                  
+                  make install
+                  make test
+                  make publish
+
+.. toctree::
+   :hidden:
+
+   about/index
+   community/index
+   lib/index
diff --git a/docs/lib/index.rst b/docs/lib/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..a05b601dac2bcae281461632068a79db1cd7b321
--- /dev/null
+++ b/docs/lib/index.rst
@@ -0,0 +1,17 @@
+Library documentation
+=====================
+
+.. include:: overview/index.rst
+.. include:: installation/index.rst
+.. include:: usage/index.rst
+.. include:: reference/index.rst
+
+.. toctree::
+    :caption: Documentation
+    :hidden:
+    :maxdepth: 2
+
+    overview/index
+    installation/index
+    usage/index
+    reference/index
\ No newline at end of file
diff --git a/docs/lib/installation/index.rst b/docs/lib/installation/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d280c1004f6147fdeb854cf6ac128c1aad39a430
--- /dev/null
+++ b/docs/lib/installation/index.rst
@@ -0,0 +1,70 @@
+============
+Installation
+============
+..
+    How to get it and set it up?
+    [installation]
+
+To install rna, you have the following options:
+
+.. tab-set::
+
+    .. tab-item:: PyPi :octicon:`package`
+
+        The preferred method to install rna is to get the most recent stable release from PyPi:
+        
+        ..
+            [essence-start]
+
+        .. code-block:: shell
+       
+           pip install rna
+           
+        ..
+            [essence-end]
+
+        If you don't have `pip`_ installed, this `Python installation guide`_ can guide you through the process.
+        
+        .. _pip: https://pip.pypa.io
+        .. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/
+
+        .. dropdown:: Extras
+            :icon: star
+            
+            Install a special extra:
+                :code:`pip install rna[extra]`
+
+            All extras:
+                :code:`pip install rna[full]`
+
+    .. tab-item:: Source :octicon:`code`
+
+        First you have to retrieve the source code of rna.
+        You have the following options:
+        
+        .. tab-set::
+        
+            .. tab-item:: Git :octicon:`git-branch`
+
+                To clone the public repository run
+
+                .. code-block:: shell
+
+                    $ git clone git://gitlab.mpcdf.mpg.de/dboe/rna
+
+            .. tab-item:: Tarball :octicon:`gift`
+
+                Either download the tarball `here <https://gitlab.mpcdf.mpg.de/dboe/rna/tarball/master>`_ or run
+
+                .. code-block:: shell
+
+                    $ curl -OJL https://gitlab.mpcdf.mpg.de/dboe/rna/tarball/master
+
+                
+        Once you have a copy of the source, navigate inside and install it with:
+
+        .. code-block:: shell
+
+            $ poetry install
+
+
diff --git a/docs/lib/overview/index.rst b/docs/lib/overview/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..12114824fda68dc764ad18c14ccd04e4fce44c14
--- /dev/null
+++ b/docs/lib/overview/index.rst
@@ -0,0 +1,13 @@
+========
+Overview
+========
+..
+   What is it? Why should I use it?
+   [overview-start]
+
+.. include:: ../../../README.rst
+   :start-after: [overview-start]
+   :end-before: [overview-end]
+
+..
+   [overview-end]
diff --git a/docs/lib/reference/index.rst b/docs/lib/reference/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..ce3a9726d144e83b0c08a6bf70513810c0c24f1e
--- /dev/null
+++ b/docs/lib/reference/index.rst
@@ -0,0 +1,13 @@
+=============
+API reference
+=============
+..
+    How to dive deeper? Give me the api?
+    [reference]
+    
+.. autosummary::
+:toctree: _autosummary
+:template: custom-module-template.rst
+:recursive:
+
+.. automodule: rna
diff --git a/docs/lib/usage/index.rst b/docs/lib/usage/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..391c7386466d9e691f822bec13be2050827ff9d1
--- /dev/null
+++ b/docs/lib/usage/index.rst
@@ -0,0 +1,18 @@
+=====
+Usage
+=====
+..
+    How to use? Give me a primer.
+    [usage]
+    
+..
+    [essence-start]
+
+To use rna in a project use
+
+.. code-block:: python
+   
+   import rna
+    
+..
+    [essence-end]
diff --git a/environment.yml b/environment.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0234dc7c7b93212f16707b364bb26ddc316d1722
--- /dev/null
+++ b/environment.yml
@@ -0,0 +1,19 @@
+name: rna
+channels:
+  - conda-forge
+  # We want to have a reproducible setup, so we don't want default channels,
+  # which may be different for different users. All required channels should
+  # be listed explicitly here.
+  - nodefaults
+dependencies:
+  - python=3.10.*  # or don't specify the version and use the latest stable Python
+  - mamba
+  - pip >=21.2  # pip must be mentioned explicitly, or conda-lock will fail
+  - pip:
+    - "poetry>=1.2.0a2"
+    - "conda-lock"
+    # - "pyyaml"
+
+plugins:
+  poetry:
+    - "poetry_bumpversion"  # this is a field that is not defined by poetry but by dough
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..c5a72d7f892cc382b74eaca3b611e2dfae606ded
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,99 @@
+[tool.poetry]
+name = "rna"
+version = "0.7.11"
+description = "Basic and essential code building blocks of all pythons"
+authors = ["Daniel Böckenhoff <dboe@ipp.mpg.de>"]
+license = "MIT License"
+readme = "README.rst"
+repository = "https://gitlab.mpcdf.mpg.de/dboe/rna"
+documentation = "https://rna.readthedocs.io"
+classifiers = [
+    # find the full list of possible classifiers at https://pypi.org/classifiers/
+    "Development Status :: 3 - Alpha",
+    "License :: OSI Approved :: MIT License",
+    "Programming Language :: Python",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3.5",
+    "Programming Language :: Python :: 3.6",
+    "Programming Language :: Python :: 3.7",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+]
+keywords = ["plotting", " matplotlib", " pyqtgraph", " backend", " logging", " path", " argparse"]
+
+[tool.poetry.dependencies]
+python = "^3.7"
+pathlib = { version = "*", python = "<3.10" }
+
+[tool.poetry.group.docs]
+optional = true
+
+[tool.poetry.group.docs.dependencies]
+black = "^22.12.0"
+httpx = "^0.23.2"
+uvicorn = "^0.20.0"
+sphinx-autobuild = "^2021.3.14"
+"sphinx-autopackagesummary" = "^1.3"
+sphinx-design = "^0.3.0"
+sphinx = "^5.3.0"
+sphinx-toolbox = "^3.2.0"
+sphinx-copybutton = "^0.5.1"
+sphinxcontrib-mermaid = "^0.7.1"
+pydata-sphinx-theme = "^0.12.0"
+sphinx-autodoc-typehints = "^1.22"
+
+[tool.poetry.group.dev.dependencies]
+ensureconda = "*"  # is part of conda-lock either way
+conda-lock = "*"
+tomli = { version = ">=1.1.0", python = "<3.11" }
+pytest = "*"
+pytest-cov = "*"
+pytest-shutil = "*"
+pytest-virtualenv = "*"
+pytest-fixture-config = "*"
+pytest-xdist = "*"
+coverage = { version = "*", extras = ["toml"]}
+pylint = "*"
+flake8 = "*"
+ipdb = "*"
+mypy = "*"
+twine  = "*"  # for publishing
+pre-commit = "*"  # https://pre-commit.com/ for hook managment
+pre-commit-hooks = "*"
+sphinx = "*"  # for documentation
+cookiecutter_project_upgrader = "*"
+
+[tool.poetry.extras]
+config = ["hydra_core"]
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.coverage.report]
+show_missing = true
+exclude_lines = [
+    "pragma: no cover",
+    "if False",
+]
+
+[tool.poetry_bumpversion.file."your_package/__init__.py"]
+search = "__version__ = '{current_version}'"
+
+[tool.poetry_bumpversion.file."docs/cookiecutter_input.json"]
+search = "'package_version': '{current_version}'"
+
+[tool.pytest.ini_options]
+addopts = "--doctest-modules --ignore=env --ignore=envs --ignore=docs"
+junit_family = "xunit2"
+
+[tool.tox]
+isolated_build = true
+skip_missing_interpreters = true
+envlist = "py{35,36,37,38,39,310}"
+recreate = true
+
+[testenv]
+deps = ["pytest"]
+commands = ["pytest --import-mode importlib"]
diff --git a/rna/__init__.py b/rna/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b6b21b7cbfb628c6d3659f7ba346ed425daafac
--- /dev/null
+++ b/rna/__init__.py
@@ -0,0 +1,5 @@
+"""Top-level package of rna."""
+
+__author__ = """Daniel Böckenhoff"""
+__email__ = "dboe@ipp.mpg.de"
+__version__ = "0.7.11"
diff --git a/rna/__main__.py b/rna/__main__.py
new file mode 100644
index 0000000000000000000000000000000000000000..2acb97e947d01dfa561c192461beb9b2a4d8f642
--- /dev/null
+++ b/rna/__main__.py
@@ -0,0 +1,71 @@
+#!/user/bin/env python
+"""
+w7x option starter
+"""
+import sys
+import argparse
+import rna
+
+
+class SomeAction(argparse.Action):
+    """Some actions."""
+
+    def __init__(self, option_strings, dest, nargs=None, **kwargs):
+        if nargs is not None:
+            raise ValueError("nargs not allowed")
+        super().__init__(option_strings, dest, **kwargs)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        print(
+            f"Example action invoked by manage in namespace: {namespace} with values {values}"
+            " and option string {option_string}."
+        )
+        setattr(namespace, self.dest, values)
+
+    def showcase_dummy(self):
+        """
+        You can define a method to expose functionality of the class
+        """
+        print(self)
+
+
+def manage(args_):
+    """Example function."""
+    print("Managing!")
+    print(args_.x * args_.y)
+
+
+def parse_args(args_):
+    """Parse args."""
+    # create the top-level parser
+    parser = argparse.ArgumentParser(prog="rna app")
+    parser.add_argument(
+        "--version",
+        action="version",
+        version="v" + rna.__version__,
+        help="Show program's version number and exit",
+    )
+    parser = argparse.ArgumentParser(prog="rna app")
+
+    # subparsers
+    subparsers = parser.add_subparsers(help="sub-command help")
+
+    # create the parser for the "test" command
+    example_sub_parser = subparsers.add_parser("manage", help="manage something")
+    example_sub_parser.add_argument("-x", type=int, default=1)
+    example_sub_parser.add_argument("-y", type=float, default=42.0)
+    example_sub_parser.set_defaults(func=manage)
+
+    # If no arguments were used, print base-level help with possible commands.
+    if len(args_) == 0:
+        parser.print_help(file=sys.stderr)
+        sys.exit(1)
+
+    args_ = parser.parse_args(args_)
+    # let argparse do the job of calling the appropriate function after
+    # argument parsing is complete
+    return args_.func(args_)
+
+
+if __name__ == "__main__":
+    _ = parse_args(sys.argv[1:])
diff --git a/tests/.gitkeep b/tests/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..9fa65bb13a89d7cf3a41ffb6a7a95839bdf50164
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1 @@
+"""Unit test package for rna."""
diff --git a/tests/test_package.py b/tests/test_package.py
new file mode 100644
index 0000000000000000000000000000000000000000..f01fc7889744d44414388508dc463f20eabb5dc7
--- /dev/null
+++ b/tests/test_package.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+"""Tests for `rna` package."""
+
+import unittest
+import rna
+
+
+class TestPackage(unittest.TestCase):
+    """Tests for `rna` package."""
+
+    def setUp(self):
+        """Set up test fixtures, if any."""
+
+    def tearDown(self):
+        """Tear down test fixtures, if any."""
+
+    def test_version_type(self):
+        """Assure that version type is str."""
+
+        self.assertIsInstance(rna.__version__, str)
diff --git a/tools/Makefile.envs b/tools/Makefile.envs
new file mode 100644
index 0000000000000000000000000000000000000000..eff63f607b32289d155608cec8d4e079467ae897
--- /dev/null
+++ b/tools/Makefile.envs
@@ -0,0 +1,66 @@
+# Environment Management Makefile, adapted from https://github.com/hackalog/make_better_defaults
+#
+include tools/Makefile.include
+
+$(ENVLOCKFILE): environment.yml
+ifeq (conda, $(VIRTUALENV))
+	python -c "import tools; tools.env.create()"
+else
+	@printf $(_ERROR) "env" "Unsupported Environment `$(VIRTUALENV)`. Use conda." ;
+	@exit 1
+endif
+
+.PHONY: env_create
+## Set up virtual (conda) environment for this project
+env_create: $(ENVLOCKFILE)
+ifeq (conda,$(VIRTUALENV))
+	@rm -f $(ENVLOCKFILE)
+	@echo
+	@printf $(_INFO) "env" "New conda env created. Activate with:" ;
+	@echo ">>> conda activate $(ENVDIR)"
+	@echo ">>> make env_update"
+else
+	@printf $(_ERROR) "env" "Unsupported Environment `$(VIRTUALENV)`. Use conda." ;
+	@exit 1
+endif
+
+.PHONY: env_delete
+## Delete the virtual (conda) environment for this project
+env_delete:
+ifeq (conda,$(VIRTUALENV))
+	@printf $(_WARN) "env" "Deleting conda environment."
+	$(CONDA_EXE) env remove -p $(ENVDIR)
+	rm -f $(ENVLOCKFILE)
+else
+	@printf $(_ERROR) "env" "Unsupported Environment `$(VIRTUALENV)`. Use conda." ;
+	@exit 1
+endif
+
+.PHONY: env_update
+## Install or update Python Dependencies in the virtual (conda) environment
+env_update: env_enabled $(ENVLOCKFILE)
+
+.PHONY: env_enabled
+# Checktrues that the conda environment is active
+env_enabled:
+ifeq (conda,$(VIRTUALENV))
+ifneq (true,$(ENVACTIVE))
+	@printf $(_ERROR) "env" "Run `$(VIRTUALENV) activate $(ENVDIR)` before proceeding." ;
+	@exit 1
+endif
+else
+	@printf $(_ERROR) "env" "Unsupported Environment `$(VIRTUALENV)`. Use conda" ;
+	@exit 1
+endif
+
+.PHONY: check_lockfile
+# Test that an environment lockfile exists
+check_lockfile:
+ifeq (X,X$(wildcard $(ENVLOCKFILE)))
+	@printf $(_ERROR) "env" "Run `make env_update` before proceeding..." ;
+	@exit 1
+endif
+
+.PHONY: env
+## Check if environment is enabled and correctly configured
+env: env_enabled check_lockfile $(ENVLOCKFILE)
\ No newline at end of file
diff --git a/tools/Makefile.include b/tools/Makefile.include
new file mode 100644
index 0000000000000000000000000000000000000000..0dea8a8517dc0dc95a43688f1fbb84446e4c18ab
--- /dev/null
+++ b/tools/Makefile.include
@@ -0,0 +1,53 @@
+SHELL := /bin/bash# Use bash syntax
+CURRENT_PATH := $(shell pwd -P)
+MODULE := $(shell basename "$(CURRENT_PATH)")
+VERSION := $(shell python -c "import sys; import $(MODULE); sys.stdout.write($(MODULE).__version__)")
+SOURCES := $(shell find $(MODULE) -name '*.py')
+DOCUMENTATION := $(shell find . -name '*.rst')
+SPHINXSOURCEDIR = ./docs
+SPHINXBUILDDIR  = docs/_build
+GITSTATUS = $(shell git status --porcelain)
+DEBUG_FILE := debug.txt
+MODULE_NAME := my_project
+PROJECT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+PYTHON_INTERPRETER := python3
+ARCH := $(shell $(PYTHON_INTERPRETER) -c "import platform; print(platform.platform())")
+VIRTUALENV := conda
+ENVLOCKFILE := conda-linux-64.lock  # conda-$(ARCH).lock   ??? how to make compatible with conda-lock 
+ENVDIR  = $(CURRENT_PATH)/env
+ENVACTIVE = false
+ifeq (${CONDA_DEFAULT_ENV}, $(ENVDIR))
+	ENVACTIVE = true
+endif
+CONDA_EXE := $(shell which mamba)
+ifeq (,$(CONDA_EXE))
+	CONDA_EXE := $(shell which conda)
+endif
+CONDA_RUN := 
+ifneq (true,$(ENVACTIVE))
+    CONDA_RUN := conda run -p $(ENVDIR) 
+endif
+
+# OPTIONS
+part ?= patch
+
+# The CI environment variable can be set to a non-empty string,
+# it'll bypass this command that will "return true", as a "yes" answer.
+# To use the "confirm" target inside another target,
+# use the " if $(MAKE) -s confirm ; " syntax.
+confirm:
+	@if [[ -z "$(CI)" ]]; then \
+		REPLY="" ; \
+		read -p "⚠ Are you sure? [y/n] > " -r ; \
+		if [[ ! $$REPLY =~ ^[Yy]$$ ]]; then \
+			printf $(_ERROR) "KO" "Stopping" ; \
+			exit 1 ; \
+		else \
+			printf $(_INFO) "OK" "Continuing" ; \
+			exit 0; \
+		fi \
+	fi
+.PHONY: confirm
+_WARN := "\033[33m[%s]\033[0m %s\n"  # Yellow text for "printf"
+_INFO := "\033[32m[%s]\033[0m %s\n" # Green text for "printf"
+_ERROR := "\033[31m[%s]\033[0m %s\n" # Red text for "printf"
diff --git a/tools/__init__.py b/tools/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d8baba7c8a7f089bae6a6b86366d45c5ad4d0a2
--- /dev/null
+++ b/tools/__init__.py
@@ -0,0 +1,2 @@
+from . import process
+from . import env
diff --git a/tools/env.py b/tools/env.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c04446543c50946a5d1b2e2d9909a2c6923a851
--- /dev/null
+++ b/tools/env.py
@@ -0,0 +1,79 @@
+import shutil
+from .process import run_shell_command
+import tempfile
+import os
+from ensureconda.resolve import platform_subdir
+
+
+TMPDIR = tempfile.gettempdir()
+BOOTSTRAPDIR = os.path.join(TMPDIR, "bootstrap")
+PROJECT_DIR = os.path.abspath(os.path.join(__file__, "../.."))
+ENVIRONMENT_YAML = "environment.yml"
+ENVIRONMENT_YAML_PATH = os.path.join(PROJECT_DIR, ENVIRONMENT_YAML)
+POETRY_LOCK = "poetry.lock"
+CONDA_LOCK = f"conda-{platform_subdir()}.lock"
+
+
+def load():
+    import yaml
+    from yaml.loader import SafeLoader
+
+    # Open the file and load the file
+    with open(ENVIRONMENT_YAML_PATH) as f:
+        data = yaml.load(f, Loader=SafeLoader)
+    return data
+
+
+def install(conda_run=""):
+    run_shell_command(f"{conda_run}poetry install")
+    run_shell_command(f"{conda_run}pre-commit install")
+
+
+def update(conda_run=""):
+    # Re-generate Conda lock file(s) based on environment.yml
+    run_shell_command(f"{conda_run}conda-lock -k explicit --conda mamba")
+    # Update Conda packages based on re-generated lock file
+    run_shell_command(f"mamba update --file {CONDA_LOCK}")
+    # Update Poetry packages and re-generate poetry.lock
+    run_shell_command(f"{conda_run}poetry update")
+
+
+def create(name="env"):
+    """
+    This create routine was initially influenced by
+    https://stackoverflow.com/questions/70851048/does-it-make-sense-to-use-conda-poetry
+    """
+    env_dir = os.path.join(PROJECT_DIR, name)
+
+    if os.path.isfile(os.path.join(env_dir, POETRY_LOCK)):
+        run_shell_command(f"conda create -p {env_dir} --file {CONDA_LOCK}")
+        install()
+
+    requirements_here = ["poetry", "mamba", "conda-lock"]
+    requirements_not_satisfied = any(
+        [shutil.which(name) is None for name in requirements_here]
+    )
+
+    run = ""
+    if requirements_not_satisfied:
+        # Use (and if necessary create) a bootstrap env
+        if not os.path.exists(BOOTSTRAPDIR):
+            run_shell_command(
+                f"conda create --yes -p {BOOTSTRAPDIR} -c conda-forge "
+                + " ".join(requirements_here)
+            )
+        run = f"conda run -p {BOOTSTRAPDIR} "
+
+    # Create conda lock file(s) from environment.yml
+    run_shell_command(f"{run}conda-lock -k explicit --conda mamba")
+    # Add conda-lock (and other packages, as needed) to pyproject.toml and poetry.lock
+
+    run_shell_command(f"{run}mamba env create -f {ENVIRONMENT_YAML} -p {env_dir}")
+    run = f"conda run -p {env_dir} "
+
+    install(conda_run=run)
+
+    # Add conda and poetry lock files
+    run_shell_command("git add *.lock")
+
+    run_shell_command("git commit -m 'lock-files'")
diff --git a/tools/process.py b/tools/process.py
new file mode 100644
index 0000000000000000000000000000000000000000..d911e4a55aeb893b7e43be550086c18acc93db76
--- /dev/null
+++ b/tools/process.py
@@ -0,0 +1,6 @@
+import subprocess
+
+def run_shell_command(command_line, *args, **kwargs):
+    command_line_args = command_line.split(" ")
+    print(f"Run command '{command_line}'")
+    subprocess.call(command_line_args, *args, **kwargs)