Repository: mpc-bioinformatics/ProtGraph (language: python)

Issue:
Export: JanusGraph
We currently only have exports to files and databases (redis and Postgres).

Those are not well suited to traverse and process graphs (postgres is actually very perfromant if the rec. depth is not large).

We need to use some dedicated graph processing algorithms/databases for such large graphs. Here JanusGraph is tested


Discussion / hints:
Export it via Gremlin? 


Fix patch:
diff --git a/.flake8 b/.flake8
index 6deafc2..8d51478 100644
--- a/.flake8
+++ b/.flake8
@@ -1,2 +1,3 @@
 [flake8]
 max-line-length = 120
+per-file-ignores = __init__.py:F401
\ No newline at end of file
diff --git a/.github/linters/.flake8 b/.github/linters/.flake8
new file mode 100644
index 0000000..8d51478
--- /dev/null
+++ b/.github/linters/.flake8
@@ -0,0 +1,3 @@
+[flake8]
+max-line-length = 120
+per-file-ignores = __init__.py:F401
\ No newline at end of file
diff --git a/.github/workflows/super_linter.yaml b/.github/workflows/super_linter.yaml
index dfd03d1..e540d0b 100644
--- a/.github/workflows/super_linter.yaml
+++ b/.github/workflows/super_linter.yaml
@@ -1,7 +1,5 @@
 name: Super-Linter
-
-# Run on every push
-on: push
+on: [push, pull_request]
 
 jobs:
   super-lint:
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a81c8ee
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,138 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# 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/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+#   For a library or package, you might want to ignore these files since the code is
+#   intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..cdc5cd7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+--------------------------------------------------------------------------------
+                                   ProtGraph
+--------------------------------------------------------------------------------
+Copyright 2021, Ruhr University Bochum, Medizinisches Proteom-Center
+
+This software is released under a three-clause BSD license:
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or
+  other materials provided with the distribution.
+
+* Neither the name of any author or any participating institution may be used to
+  endorse or promote products derived from this software without specific prior
+  written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Pipfile b/Pipfile
index f5076ab..ab8a0a5 100644
--- a/Pipfile
+++ b/Pipfile
@@ -13,6 +13,6 @@ biopython = "*"
 redis = "*"
 redisgraph = "*"
 psycopg2 = "*"
-
-[requires]
-python_version = "3.8.6"
+networkx = "*"
+gremlinpython = "*"
+pytest = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
deleted file mode 100644
index 05e2e83..0000000
--- a/Pipfile.lock
+++ /dev/null
@@ -1,253 +0,0 @@
-{
-    "_meta": {
-        "hash": {
-            "sha256": "e57d497acdf3d2325b7db2a5aeba221a5d500c93aea86a943f0e129ac523d6b1"
-        },
-        "pipfile-spec": 6,
-        "requires": {
-            "python_version": "3.8.6"
-        },
-        "sources": [
-            {
-                "url": "https://pypi.python.org/simple",
-                "verify_ssl": true
-            }
-        ]
-    },
-    "default": {
-        "biopython": {
-            "hashes": [
-                "sha256:010142a8ec2549ff0649edd497658964ef1a18eefdb9fd942ec1e81b292ce2d9",
-                "sha256:0b9fbb0d3022dc22716da108b8a81b80d952cd97ac1f106de491dce850f92f62",
-                "sha256:0df5cddef2819c975e6508adf5d85aa046e449df5420d02b04871c7836b41273",
-                "sha256:194528eda6856a4c68f840ca0bcc9b544a5edee3548b97521084e7ac38c833ca",
-                "sha256:195f099c2c0c39518b6df921ab2b3cc43a601896018fc61909ac8385d5878866",
-                "sha256:1ee0a0b6c2376680fea6642d5080baa419fd73df104a62d58a8baf7a8bbe4564",
-                "sha256:2bd5a630be2a8e593094f7b1717fc962eda8931b68542b97fbf9bd8e2ac1e08d",
-                "sha256:4565c97fab16c5697d067b821b6a1da0ec3ef36a9c96cf103ac7b4a94eb9f9ba",
-                "sha256:48d424453a5512a1d1d41a4acabdfe5291da1f491a2d3606f2b0e4fbd63aeda6",
-                "sha256:5c0b369f91a76b8e5e36624d075585c3f0f088ea4a6e3d015c48f08e48ce0114",
-                "sha256:75b55000793f6b76334b8e80dc7e6d8cd2b019af917aa431cea6646e8e696c7f",
-                "sha256:ada611f12ee3b0bef7308ef41ee7b94898613b369ab44e0268d74bd1d6a06920",
-                "sha256:cc3b0b78022d14f11d508038a288a189d03c97c476d6636c7b6f98bd8bc8462b",
-                "sha256:e0af107cc62a905d13d35dd7b38f335a37752ede45e4617139e84409a6a88dc4",
-                "sha256:f1076653937947773768455556b1d24acad9575759e9089082f32636b09add54",
-                "sha256:f5021a398c898b9cf6815cc5171c146a601b935b55364c53e6516a2545ab740c"
-            ],
-            "version": "==1.78"
-        },
-        "numpy": {
-            "hashes": [
-                "sha256:0d28a54afcf46f1f9ebd163e49ad6b49087f22986fefd01a23ca0c1cdda25ca6",
-                "sha256:1264c66129f5ef63187649dd43f1ca59532e8c098723643336a85131c0dcce3f",
-                "sha256:1abc02e30e3efd81a4571e00f8e62bf42e343c76698e0a3e11d9c2b3ee0d77a7",
-                "sha256:2445a96fbae23a4109c61be0f0af0f3bc273905dc5687a710850c1dfde0fc994",
-                "sha256:2bf0e68c92ef077fe766e53f8937d8ac341bdbca68ec128ae049b7d5c34e3206",
-                "sha256:33edfc0eb229f86f539493917b34035054313a11afbed48404aaf9f86bf4b0f6",
-                "sha256:3d8233c03f116d068d5365fed4477f2947c7229582dad81e5953088989294cec",
-                "sha256:4d592264d2a4f368afbb4288b5ceb646d4cbaf559c0249c096fbb0a149806b90",
-                "sha256:5ae765dd29c71a555f8102281f6fb15a3f4dbd35f6e7daf36af9df6d9dd716a5",
-                "sha256:894aaee60043a98b03f0ad992c810f62e3a15f98a701e1c0f58a4f4a0df13429",
-                "sha256:89bd70c9ad540febe6c28451ba225eb4e49d27f64728357f512c808002325dfa",
-                "sha256:93c2abea7bb69f47029b84ceac30ab46dfcfdb99b671ad850a333ff794a765e4",
-                "sha256:abdfa075e293d73638ece434708aa60b510dc6e70d805f57f481a0f550b25a9e",
-                "sha256:afeee581b50df20ef07b736e62ca612858f1fcdba96651d26ab44e3d567a4e6e",
-                "sha256:b51b9ef0624f4b01b846c981034c10d2e30db33f9f8be71e992f3900741f6f77",
-                "sha256:b66a6c15d793eda7cdad986e737775aa31b9306d588c14dd0277d2dda5546150",
-                "sha256:cb257bb0c0a3176c32782a63cfab2eace7eabfa2a3b2dfd85a13700617ccaf28",
-                "sha256:cf5d9dcbdbe523fa665c5309cce5f144648d94a7fddbf5a40f8e0d5c9f5b596d",
-                "sha256:d1bc331e1706fd1809a1bc8a31205329e5b30cf5ba50461c624da267e99f6ae6",
-                "sha256:db5e69d08756a2fa75a42b4e433880b6187768fe1bc73d21819def893e5128c6",
-                "sha256:e3db646af9f6a145f0c57202f4b55d4a33f975e395e78fb7b394644c17c1a3a6",
-                "sha256:e9c5fd330d2fedf06051bafb996252de9b032fcb2ec03eefc9a543e56efa66d4",
-                "sha256:eee454d3aa3955d0c0069a0f265fea47f1e1384c35a110a95efed358eb6e1562",
-                "sha256:f1e9424e9aa3834ea27cc12f9c6ea8ace5da18ee60a720bb3a85b2f733f41782"
-            ],
-            "markers": "python_version >= '3.7'",
-            "version": "==1.20.0"
-        },
-        "prettytable": {
-            "hashes": [
-                "sha256:5dc7fcaca227f48deacd86958ae9d7b8c31a186fcb354bbb066763f20adf3eb9",
-                "sha256:e37acd91976fe6119172771520e58d1742c8479703489321dc1d9c85e7259922"
-            ],
-            "markers": "python_version >= '3.6'",
-            "version": "==2.0.0"
-        },
-        "psycopg2": {
-            "hashes": [
-                "sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301",
-                "sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725",
-                "sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821",
-                "sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3",
-                "sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051",
-                "sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5",
-                "sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84",
-                "sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a",
-                "sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e",
-                "sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad",
-                "sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5",
-                "sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7",
-                "sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3",
-                "sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d",
-                "sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543"
-            ],
-            "version": "==2.8.6"
-        },
-        "python-igraph": {
-            "hashes": [
-                "sha256:05626394df3459eb9a00364ca15af21daf5a10a800ad06dc897735d72c15dfa5",
-                "sha256:0d27f77bd00942ea22acbea97ea4c792b0b0126931e1723a9c8535acef59219a",
-                "sha256:1200984563df3ad57b02343fa526e7c79a1602a8e3040582e9fac17703e09a82",
-                "sha256:15ca37c91a93db0f03dcef211edcaaa3ccafdc18ff2a74359afb71e5f8dbe007",
-                "sha256:2d7dcdb1fd0b6d4c6a0f1901feae6b3cc3f7a81123b8ed8706213b7d98af4292",
-                "sha256:352d18a47e2c191b34534f79515344bc6727cfcf1196ca09fa1ca50a6a6a0497",
-                "sha256:38574aff86681fb75c70444b8aeedae010843321683d80f4c7511f73754ad63c",
-                "sha256:3edca294a68ac88dd1e5a6b363e495d64787b52aa0777ffb6a87a81dea263b8c",
-                "sha256:40cedaec28fa39997798311db7a6d0f47ad6644245cb5049f37864a644530f7b",
-                "sha256:46d89eba435ccdbf3aba0af16782e5ef45bdf7ef0e28fe9683c1a656bb9f240b",
-                "sha256:4efebee0ceeea457f9e18c26decba8047dd435a581fba780d19b7115da805cbd",
-                "sha256:52aba4fbc92cac1482aadb69a248b64ddbd594ef9b293e4119b428435cfd8cd2",
-                "sha256:54871369c8905d0df01a2d06db1e3a711156ded7e47da555e5366348b0690c91",
-                "sha256:6e2d42f7d7e37b20c701d5e09d4f871373b71c79b93578dca554eb158fb1a92b",
-                "sha256:71ee9467fb13f21465df53e8024dda12e3b170012039001b8f495c7bc8a3cb44",
-                "sha256:79c8b0d52497ac02c872a382491fc81214a01b694995520ed18abaab9d73c031",
-                "sha256:7ff11d0348aa220b61cf73e933df341c1d89a5b7312e8b9077737091cb650b9e",
-                "sha256:8004e5840db2d8aea489d9ee6a868f4475aa835fa761f85113305fd254ad9871",
-                "sha256:87191d10d16db2332dec69c814152a22535e5b42dcb9ce8c39e5024f1f576368",
-                "sha256:986076fa46f1f4eee500a270b7bb5bb0bcb68d9d775bedb98c898a678b3332a4",
-                "sha256:a36072566a5b5bbf6223f76b616c5a5fa95cb280626886de7ad6fc870f921880",
-                "sha256:ab063dbef3d3d442b9b351049961a81b4c281d0700d8e4f75f0a0c157e84864a",
-                "sha256:bc8b48a95b88cceab1fa918d2d63ef0ac04674c43db77984c5288e8ada524afc",
-                "sha256:c12ad84de1f0f6912bd0b5c52af5dbb9a96550ced521e7c1b9fcf2250d2e2b16",
-                "sha256:c290c4d0586cf2a4353b0b204cac365b02626bf96e7f7dba265a6265b24806c5",
-                "sha256:cf22509897b454538bb4cf2f84faef0351125fd2272ab09eec0aaf5005591d12",
-                "sha256:d906c30f478943d91f8acecbfbc4194b9dd5402a20373a4159220dec3b78ce55",
-                "sha256:e1045c64a4c346486a9b76ae888a8901dfc4555be4872ab81dd66e7a6860569b",
-                "sha256:e1f27622eddeb2bd5fdcbadb41ef048e884790bb050f9627c086dc609d0f1236",
-                "sha256:e7761befd224acad7bd1f14b2984f616bda520bf05622e39dbbdcd97a793672c",
-                "sha256:e814a8d4ebb9dd089e5ae98a3fe0b0b367467950e5bea7369779b570eb39c5fe",
-                "sha256:ecb6385cf70515a08fc31ce6ef4616a8ab96b983e16ed5bcaf2b5bb44d7c1dad",
-                "sha256:ede5f770df2fbe1cae45aae7f8fb110f01253d4a9ba2b919ccc2d76ab8d57e91",
-                "sha256:fa25cd51c1defd85ede46050f679b9c06179b68db01921d611f5eddab6910852",
-                "sha256:ff86acb8b33722994647c50cc2bbefe8174cd796b69a1523c5f8cdbc36438abc"
-            ],
-            "version": "==0.8.3"
-        },
-        "redis": {
-            "hashes": [
-                "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2",
-                "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"
-            ],
-            "version": "==3.5.3"
-        },
-        "redisgraph": {
-            "hashes": [
-                "sha256:af8b90170efa97fc471a377f5628ba9a69d04b939122ff70be5c179d3390f989"
-            ],
-            "version": "==2.2.4"
-        },
-        "texttable": {
-            "hashes": [
-                "sha256:ce0faf21aa77d806bbff22b107cc22cce68dc9438f97a2df32c93e9afa4ce436",
-                "sha256:f802f2ef8459058736264210f716c757cbf85007a30886d8541aa8c3404f1dda"
-            ],
-            "version": "==1.6.3"
-        },
-        "tqdm": {
-            "hashes": [
-                "sha256:4621f6823bab46a9cc33d48105753ccbea671b68bab2c50a9f0be23d4065cb5a",
-                "sha256:fe3d08dd00a526850568d542ff9de9bbc2a09a791da3c334f3213d8d0bbbca65"
-            ],
-            "version": "==4.56.0"
-        },
-        "wcwidth": {
-            "hashes": [
-                "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
-                "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
-            ],
-            "version": "==0.2.5"
-        }
-    },
-    "develop": {
-        "astroid": {
-            "hashes": [
-                "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703",
-                "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386"
-            ],
-            "markers": "python_version >= '3.5'",
-            "version": "==2.4.2"
-        },
-        "isort": {
-            "hashes": [
-                "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e",
-                "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"
-            ],
-            "markers": "python_version >= '3.6' and python_version < '4.0'",
-            "version": "==5.7.0"
-        },
-        "lazy-object-proxy": {
-            "hashes": [
-                "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
-                "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
-                "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
-                "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
-                "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
-                "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
-                "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
-                "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
-                "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
-                "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
-                "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
-                "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
-                "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
-                "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
-                "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
-                "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
-                "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
-                "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
-                "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
-                "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
-                "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
-            ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==1.4.3"
-        },
-        "mccabe": {
-            "hashes": [
-                "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
-                "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
-            ],
-            "version": "==0.6.1"
-        },
-        "pylint": {
-            "hashes": [
-                "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210",
-                "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f"
-            ],
-            "version": "==2.6.0"
-        },
-        "six": {
-            "hashes": [
-                "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
-                "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
-            ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==1.15.0"
-        },
-        "toml": {
-            "hashes": [
-                "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
-                "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
-            ],
-            "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==0.10.2"
-        },
-        "wrapt": {
-            "hashes": [
-                "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"
-            ],
-            "version": "==1.12.1"
-        }
-    }
-}
diff --git a/README.md b/README.md
index 2016137..c24e826 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,12 @@
 # [WIP] ProtGraph - A Graph-Generator for Proteins
 
-This project aims to efficiently generate graphs of proteins using text entries from [UniProt](https://www.uniprot.org/). These files either end via: `.dat` or `.txt`.
+This project aims to efficiently generate graphs of proteins using text entries from [UniProt](https://www.uniprot.org/). These text files usually end with the extension: `.dat` or `.txt`.
 
 We utilize the tools: [BioPython](https://biopython.org/) and [igraph](https://igraph.org/python/) to generate so called directed and acyclic graphs (DAGs) of proteins.
 
-In essence, this tool is doing the following:
+In essence, ProtGraph is doing the following:
 
-Lets assume that an entry has been saved from UniProt, containing following information:
+Lets assume that an entry has been exported as text from UniProt, containing the following content:
 
 ```txt
 ID   MY_CUSTOM_PROTEIN             Reviewed;         8 AA.
@@ -16,9 +16,9 @@ AC   QXXXXX
 
 FT   INIT_MET        1
 FT                   /note="Removed"
-FT                   /evidence="EXAMPLE Initiator Metheonine"
+FT                   /evidence="EXAMPLE Initiator Methionine"
 FT   SIGNAL          1..4
-FT                   /evidence="EXAMPLE Signal"
+FT                   /evidence="EXAMPLE Signal Peptide"
 FT   VARIANT         3
 FT                   /note="Missing (in Example)"
 FT                   /evidence="EXAMPLE Variant 1"
@@ -35,28 +35,33 @@ SQ   SEQUENCE   8 AA;  988 MW;  XXXXXXXXXXXXXXXX CRC64;
      MPROTEIN                   
 ```
 
-This entry contains the canonical sequence (in section `SQ`), which is used usually in fasta files and other tools. But this entry provides further information, which are usually not considered and left out. Especially in this example, a `SIGNAL` peptide is present, leading to a peptide, which may not be covered when cleaving e.g. via Trypsin.
-Additionally 3 `VARIANT`s are present in this entry, informing about substituted aminoacids, which again may yield peptides that are not covered by the canonical sequence or by digestion.
+This entry contains the canonical sequence (described in section `SQ`), which is usually exported in fasta files and then used by other tools. But such entries provide more information, which are usually not considered. Especially in this example, a `SIGNAL` peptide is present, which may lead to a peptide, which is not covered when cleaving (e.g. via the digestion enzyme Trypsin).
+Additionally, 3 `VARIANT`s are present in this entry, informing about substituted aminoacids, which again may yield peptides that are not covered by the canonical sequence or by digestion.
 
-With `ProtGraph`, a graph can be generated. It may look as follows:
+With `ProtGraph`, a graph can be generated. In this example, it would look like follows:
 ![Example Graph](resources/example_graph.png)
 
-With this graph, the earlier mentioned peptides are now considered and could be retrieved, by traversing from the dedicated `s`tart node to the dedicated `e`nd node. (These are internally denoted by: `__start__` and `__end__`).
-The `black drawn` edges (with the label `TRYPSIN`) indicate that this graph was additionally digested via Trypsin (default) leading to a compact DAGraph, allowing to compute all possible peptides and even more statistics!
+With such a graph representation, the earlier mentioned peptides, which might not be covered are now covered and could be retrieved, by traversing from the dedicated `s`tart node to the dedicated `e`nd node. (These start and end nodes are internally denoted by: `__start__` and `__end__`).
+The `black drawn` edges (with the label `TRYPSIN`) indicate that this graph was additionally digested via the enzyme Trypsin (default) leading to a compact directed and acyclic graph (in short DAG). From such DAGs, all possible peptides and further statistics can be retrieved.
 
-This tool will additionally generate a statistics file when generating a graph from an UniProt-entry, containing various information about the protein/entry which were retrieved during generation (partially on the fly).
+ProtGraph will generate a statistics file when generating a graph from an UniProt-entry, containing various information about the protein/entry which were retrieved during generation (partially on the fly).
 
-If executing via the flag `-cnp`, the number of possible paths between `s` and `e` are calculated. In this example, `48` paths are possible. With this, we now know that there are `48` peptides (some of them repeating) in such a (small) graph.
-It may be interesting to know how many (repeating) peptides with a certain number of miscleavages are present in a protein. To calculate this statistic, simply provide the flag `-cnpm`. In this example: `25` peptides with 0 miscleavages, `19` with 1 miscleavage and `4` with 2 miscleavages are present.
+Here are some examples, which can be retrieved from the statistics:
 
-By combining the flags `-cnph` and `-nm`, the distribution of the peptide lengths (counting aminoacids) over all possible peptides can be retrieved. For the example protein, we retrieved the following distribution:
+If executing via the flag `-cnp`, the total number of possible non-repeating paths between `s` and `e` are calculated. In this example, `43` paths are possible. With the number of possible paths, we know that the graph contains `43` peptides (some of them repeating).
+It may be interesting to know how many (repeating) peptides with a certain number of miscleavages are present in a protein. To calculate this statistic, simply provide the flag `-cnpm`. In this example: `21` peptides with 0 miscleavages, `18` with 1 miscleavage and `4` with 2 miscleavages are present.
+
+By combining multiple flags, it is possible to retrieve the number of  peptides having a specific length (counting aminoacids). With the flags `-cnph` and `-nm`, ProtGraph would write into the statistics file the needed information to retrieve the following:
 | Peptide Length | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 |----------------|---|---|---|---|---|---|---|---|
-| #Peptides      | 3 | 6 | 9 | 8 | 6 | 4 | 8 | 4 |
+| #Peptides      | 2 | 5 | 8 | 6 | 6 | 4 | 8 | 4 |
+
+
+Dividing this table by `43` would give us the distribution of the peptide lengths for the given protein.
 
-## Setting up
 
-To set up `ProtGraph` make sure you have `pipenv` and `pyenv` installed. (via `pacman` `apt` and alike)
+
+## Setting up ProtGraph
 
 First clone this project and enter its directory via:
 
@@ -65,60 +70,90 @@ git clone git@github.com:mpc-bioinformatics/ProtGraph.git
 cd ProtGraph/
 ```
 
-Now the dependencies (and possibly Python) need to be installed. This can be done with:
+Depending on how you want to use this project follow either the usage instructions for only using Protgraph or the development and tests instructions if you want to use it in a python project or even develop something in ProtGraph itself.
+
+### Installing via pip (for usage)
+
+If you only want to use ProtGraph from the command line, it is sufficient to simply execute: `pip install --user .`
+
+The "binary" `protgraph` should be available in your command line after it finished. You can now convert UniProt-entries into graphs!
+
+#### Troubleshooting
+
+ProtGraph has many dependencies which are mostly due to the export functionalities. For the dependency `psycopg2`, it may be neccessary to install PostgreSQL on your operating system, so that the wheel can be built. It should be sufficient to install it as follows `sudo pacman -S postgres` (adapt this for `apt` and alike).
+
+If the command `protgraph` cannot be found, make sure that you have included the python executables folder in your environment variable `PATH`. (If pip was executed with the flag `--user`, then the binaries should be available in the folder: `~/.local/bin`)
+
+### Installing via pipenv and pyenv (for development and tests)
+
+To set up ProtGraph make sure you have `pipenv` and `pyenv` installed. (via `pacman` `apt` and alike)
+
+
+The dependencies (and possibly Python) need to be installed first. This can be done with:
 > pipenv install
 
-After everything is set up activate the environment via:
+Afterwards execute to install the module ProtGraph:
+> pipenv run pip install -e .
+
+If both commands finished succesfully, activate the environment via:
 > pipenv shell
 
-That is everything, that needed to be done. You can now convert Uniprot-entries into graphs!
+You should be able to run `protgraph` now. Via the flag `-e` the code from the projects directory is used, so you can edit the files directly and test the changes via your debugger of choice or via the command `protgraph`.
 
-## Usage
 
-Currently, the entrypoint of this project is `main.py`. However, this may change in future.
+#### Testing
 
-To see an overview of possible parameters and options use: `python main.py --help`. The `help`-output contains brief descriptions for each flag.
+Make sure you are at the root folder of this project. Then execute `pytest .` to run the tests for ProtGraph.
+
+## Usage
+
+To see an overview of possible parameters and options use: `protgraph --help`. The `help`-output contains brief descriptions for each flag.
 
 ### Example calls
 
-Lets use the internal example from `e_coli.dat` located in `examples/e_coli.dat` (Or any other `.txt` or `.dat` file).
+Let's use the provided example `e_coli.dat` located in `examples/e_coli.dat` (Or any other `.txt` or `.dat` file).
 
-The graph generation can be executed via: `python main.py examples/e_coli.txt`. This will generate graphs and the additional statistics file. After it has finished (should only take up to 3 minutes), you can inspect the statistics file.
+The graph generation can be executed via: `protgraph examples/e_coli.dat`. This will generate the graphs and the additional statistics file. You can inspect the statistics file after it has finished. This should only take a few seconds/minutes.
 
 ---
 
-But why does it not show information when it will end?
+During execution it could be seen that now information was provided, when ProtGraph finishes.
+
+Sadly, `Biopython` does not provide information of how many entries are available in a `.txt` or `.dat` file. Therefore this information needs to be provided via another parameter: `protgraph --num_of_entries 9434 examples/e_coli.dat` (you can also use `-n`).
 
-Sadly, `Biopython` does not provide information of how many entries are available in a `.txt` or `.dat` file. Therefor this information needs to be provided via another parameter: `python main.py --num_of_entries 9434 e_coli.txt` (you can also use `-n`).
-To retrieve the number of entries beforehand you could e.g. use a simple command as follows `cat /examples/e_coli.dat | grep "^//" | wc -l`. It is also possible to add multiple files. The number of entries for each file then need to be summed: `python main.py -n 18868 examples/e_coli.txt examples/e_coli.txt`
+To retrieve the number of entries beforehand, you could e.g. use `cat examples/e_coli.dat | grep "^//" | wc -l`. It is also possible to add multiple files. The number of entries for each file then need to be summed: `protgraph -n 18868 examples/e_coli.dat examples/e_coli.dat`
 
 ---
 
-If to many (or to few) processes are executed, then it can be adjusted via `--num_of_processes` or `-np`. E.G. `python main.py --num_of_processes 3 --num_of_entries 9434 examples/e_coli.txt` will use 4 (`3` + 1 reading process) processes.
+If to many (or to few) processes are executed, then it can be adjusted via the parameter `--num_of_processes` or `-np`. E.G. `protgraph --num_of_processes 3 --num_of_entries 9434 examples/e_coli.dat` will use 4 (`3` + 1 reading process) processes.
 
 ---
 
-To fully annotate the graphs with weights and to retrieve all statistics, use the following: `python main.py -amwe -aawe -cnp -cnpm -cnph -n 9434 examples/e_coli.dat`
+To fully annotate the graphs with weights and to retrieve currently all available statistics, use the following: `protgraph -amwe -aawe -cnp -cnpm -cnph -n 9434 examples/e_coli.dat`
 
 ## Exporting graphs
 
-But where are the graphs after executing this tool?
+While executing ProtGraph, generated graphs are not saved.
 
-The default behaviour of `ProtGraph` is to exclude the generated graphs, since those can explode in size and disk space may be limited. Currently a few export functionalities are available and it is planned to extend this functionality.
+This is the default behaviour of `protgraph`. It excludes the generated graphs, since those can explode in size and the disk space on machines  may also be limited. Currently a few export functionalities are available and it is planned to extend this functionality.
 
 ### File Exports
 
-To export each protein graph into a folder, simply set the flags `-edot`, `-egraphml` and/or `-egml`, which will create the corresponding dot, GraphML or GML files into a output folder.
-Exporting to GraphML is recommended since this is the only export method able to serialize all properties in a file which have been set in this project on a graph.
+To export each protein graph into a file, simply set the flags `-edot`, `-egraphml` and/or `-egml`, which will create the corresponding dot, GraphML or GML files into a output folder.
+Exporting to GraphML is recommended since this is the only export method able to serialize all properties in a file which can be set in the graph.
 
 ### Database Exporters
 
-The database exporters are currently under development. But two exports are already available. `ProtGraph` allows to export the generated graphs into PostgreSQL as well as into RedisGraph. For configuration such export, please look into the `--help` output.
+The database exporters are currently under development. Two exports are currently available. `protgraph` allows to export the generated graphs into PostgreSQL as well as into RedisGraph. For configuring such export, please look into the `--help` output.
+
+Furthermore an export (experimental) via gremlin is provided as well as an peptide export into PostgreSQL (NOTE: Peptide exports may generate unmanagable amounts of peptides).
+
+Note: In PostgreSQL a database should be created with no tables to ensure that ProtGraph can generate the tables itself without errors.
 
-Note: In Postgresql a database should be created where the tables `nodes` and `edges` are NOT present.
+Note: Currently no peptide export is available, but it is planned to be added into ProtGraph. However, using the peptide export to PostgreSQL, some can easily script a peptide export from the database and the corresponding graph files by iterating over each entry.
 
-Note: For RedisGraph, a version with a custom set `YY_BUFFER_SIZE` buffer length needs to be compiled manually. This is due to some issues regarding the buffer length in Redisgraph.
 
 ## Missing Functionalities
 
-* Other Export functionalities!
+* Other export functionalities
+* Peptide export scripts/possibility for ProtGraph
diff --git a/examples/F1SN05.txt b/examples/F1SN05.txt
new file mode 100644
index 0000000..4f9feee
--- /dev/null
+++ b/examples/F1SN05.txt
@@ -0,0 +1,141 @@
+ID   F1SN05_PIG              Unreviewed;       248 AA.
+AC   F1SN05;
+DT   03-MAY-2011, integrated into UniProtKB/TrEMBL.
+DT   22-NOV-2017, sequence version 2.
+DT   02-DEC-2020, entry version 69.
+DE   RecName: Full=Eukaryotic translation initiation factor 3 subunit J {ECO:0000256|HAMAP-Rule:MF_03009};
+DE            Short=eIF3j {ECO:0000256|HAMAP-Rule:MF_03009};
+DE   AltName: Full=Eukaryotic translation initiation factor 3 subunit 1 {ECO:0000256|HAMAP-Rule:MF_03009};
+DE   AltName: Full=eIF-3-alpha {ECO:0000256|HAMAP-Rule:MF_03009};
+DE   AltName: Full=eIF3 p35 {ECO:0000256|HAMAP-Rule:MF_03009};
+GN   Name=EIF3J {ECO:0000256|HAMAP-Rule:MF_03009,
+GN   ECO:0000313|Ensembl:ENSSSCP00000005055, ECO:0000313|VGNC:VGNC:87621};
+GN   Synonyms=EIF3S1 {ECO:0000256|HAMAP-Rule:MF_03009};
+OS   Sus scrofa (Pig).
+OC   Eukaryota; Metazoa; Chordata; Craniata; Vertebrata; Euteleostomi; Mammalia;
+OC   Eutheria; Laurasiatheria; Artiodactyla; Suina; Suidae; Sus.
+OX   NCBI_TaxID=9823 {ECO:0000313|Ensembl:ENSSSCP00000005055, ECO:0000313|Proteomes:UP000008227};
+RN   [1] {ECO:0000313|Ensembl:ENSSSCP00000005055, ECO:0000313|Proteomes:UP000008227}
+RP   NUCLEOTIDE SEQUENCE [LARGE SCALE GENOMIC DNA].
+RC   STRAIN=Duroc {ECO:0000313|Ensembl:ENSSSCP00000005055,
+RC   ECO:0000313|Proteomes:UP000008227};
+RG   Porcine genome sequencing project;
+RL   Submitted (NOV-2009) to the EMBL/GenBank/DDBJ databases.
+RN   [2] {ECO:0000313|Ensembl:ENSSSCP00000005055}
+RP   IDENTIFICATION.
+RG   Ensembl;
+RL   Submitted (JUL-2011) to UniProtKB.
+CC   -!- FUNCTION: Component of the eukaryotic translation initiation factor 3
+CC       (eIF-3) complex, which is required for several steps in the initiation
+CC       of protein synthesis. The eIF-3 complex associates with the 40S
+CC       ribosome and facilitates the recruitment of eIF-1, eIF-1A, eIF-
+CC       2:GTP:methionyl-tRNAi and eIF-5 to form the 43S pre-initiation complex
+CC       (43S PIC). The eIF-3 complex stimulates mRNA recruitment to the 43S PIC
+CC       and scanning of the mRNA for AUG recognition. The eIF-3 complex is also
+CC       required for disassembly and recycling of post-termination ribosomal
+CC       complexes and subsequently prevents premature joining of the 40S and
+CC       60S ribosomal subunits prior to initiation. The eIF-3 complex
+CC       specifically targets and initiates translation of a subset of mRNAs
+CC       involved in cell proliferation, including cell cycling, differentiation
+CC       and apoptosis, and uses different modes of RNA stem-loop binding to
+CC       exert either translational activation or repression. This subunit binds
+CC       directly within the mRNA entry channel of the 40S ribosome to the
+CC       aminoacyl (A) site. It may regulate the interaction between the 43S PIC
+CC       and mRNA. {ECO:0000256|HAMAP-Rule:MF_03009}.
+CC   -!- SUBUNIT: Component of the eukaryotic translation initiation factor 3
+CC       (eIF-3) complex, which is composed of 13 subunits: EIF3A, EIF3B, EIF3C,
+CC       EIF3D, EIF3E, EIF3F, EIF3G, EIF3H, EIF3I, EIF3J, EIF3K, EIF3L and
+CC       EIF3M. The eIF-3 complex appears to include 3 stable modules: module A
+CC       is composed of EIF3A, EIF3B, EIF3G and EIF3I; module B is composed of
+CC       EIF3F, EIF3H, and EIF3M; and module C is composed of EIF3C, EIF3D,
+CC       EIF3E, EIF3K and EIF3L. EIF3C of module C binds EIF3B of module A and
+CC       EIF3H of module B, thereby linking the three modules. EIF3J is a labile
+CC       subunit that binds to the eIF-3 complex via EIF3B. The eIF-3 complex
+CC       interacts with RPS6KB1 under conditions of nutrient depletion.
+CC       Mitogenic stimulation leads to binding and activation of a complex
+CC       composed of MTOR and RPTOR, leading to phosphorylation and release of
+CC       RPS6KB1 and binding of EIF4B to eIF-3. {ECO:0000256|HAMAP-
+CC       Rule:MF_03009}.
+CC   -!- SUBCELLULAR LOCATION: Cytoplasm {ECO:0000256|HAMAP-Rule:MF_03009}.
+CC   -!- PTM: Phosphorylated. Phosphorylation is enhanced upon serum
+CC       stimulation. {ECO:0000256|HAMAP-Rule:MF_03009}.
+CC   -!- SIMILARITY: Belongs to the eIF-3 subunit J family. {ECO:0000256|HAMAP-
+CC       Rule:MF_03009}.
+CC   -!- CAUTION: Lacks conserved residue(s) required for the propagation of
+CC       feature annotation. {ECO:0000256|HAMAP-Rule:MF_03009}.
+CC   ---------------------------------------------------------------------------
+CC   Copyrighted by the UniProt Consortium, see https://www.uniprot.org/terms
+CC   Distributed under the Creative Commons Attribution (CC BY 4.0) License
+CC   ---------------------------------------------------------------------------
+DR   EMBL; AEMK02000004; -; NOT_ANNOTATED_CDS; Genomic_DNA.
+DR   STRING; 9823.ENSSSCP00000005055; -.
+DR   PaxDb; F1SN05; -.
+DR   PeptideAtlas; F1SN05; -.
+DR   PRIDE; F1SN05; -.
+DR   Ensembl; ENSSSCT00000005181; ENSSSCP00000005055; ENSSSCG00000004691.
+DR   VGNC; VGNC:87621; EIF3J.
+DR   eggNOG; KOG4813; Eukaryota.
+DR   GeneTree; ENSGT00390000018400; -.
+DR   HOGENOM; CLU_085806_2_1_1; -.
+DR   InParanoid; F1SN05; -.
+DR   OMA; MPPKKWD; -.
+DR   TreeFam; TF101514; -.
+DR   Reactome; R-SSC-156827; L13a-mediated translational silencing of Ceruloplasmin expression.
+DR   Reactome; R-SSC-72649; Translation initiation complex formation.
+DR   Reactome; R-SSC-72689; Formation of a pool of free 40S subunits.
+DR   Reactome; R-SSC-72702; Ribosomal scanning and start codon recognition.
+DR   Proteomes; UP000008227; Chromosome 1.
+DR   Bgee; ENSSSCG00000004691; Expressed in longissimus thoracis muscle and 38 other tissues.
+DR   ExpressionAtlas; F1SN05; baseline.
+DR   GO; GO:0016282; C:eukaryotic 43S preinitiation complex; IEA:UniProtKB-UniRule.
+DR   GO; GO:0033290; C:eukaryotic 48S preinitiation complex; IEA:UniProtKB-UniRule.
+DR   GO; GO:0005852; C:eukaryotic translation initiation factor 3 complex; IBA:GO_Central.
+DR   GO; GO:0003743; F:translation initiation factor activity; IEA:UniProtKB-UniRule.
+DR   GO; GO:0001732; P:formation of cytoplasmic translation initiation complex; IEA:UniProtKB-UniRule.
+DR   Gene3D; 1.10.246.60; -; 1.
+DR   HAMAP; MF_03009; eIF3j; 1.
+DR   InterPro; IPR023194; eIF3-like_dom_sf.
+DR   InterPro; IPR013906; eIF3j.
+DR   PANTHER; PTHR21681; PTHR21681; 1.
+DR   Pfam; PF08597; eIF3_subunit; 1.
+PE   1: Evidence at protein level;
+KW   Coiled coil {ECO:0000256|SAM:Coils};
+KW   Cytoplasm {ECO:0000256|ARBA:ARBA00022490, ECO:0000256|HAMAP-Rule:MF_03009};
+KW   Initiation factor {ECO:0000256|HAMAP-Rule:MF_03009};
+KW   Phosphoprotein {ECO:0000256|HAMAP-Rule:MF_03009};
+KW   Protein biosynthesis {ECO:0000256|HAMAP-Rule:MF_03009};
+KW   Proteomics identification {ECO:0000213|PeptideAtlas:F1SN05};
+KW   Reference proteome {ECO:0000313|Proteomes:UP000008227}.
+FT   INIT_MET        1
+FT                   /note="Removed"
+FT                   /evidence="ECO:0000256|HAMAP-Rule:MF_03009"
+FT   REGION          1..53
+FT                   /note="Disordered"
+FT                   /evidence="ECO:0000256|SAM:MobiDB-lite"
+FT   REGION          71..98
+FT                   /note="Disordered"
+FT                   /evidence="ECO:0000256|SAM:MobiDB-lite"
+FT   REGION          207..236
+FT                   /note="Disordered"
+FT                   /evidence="ECO:0000256|SAM:MobiDB-lite"
+FT   REGION          233..248
+FT                   /note="Promotes stable association with the 40S ribosome"
+FT                   /evidence="ECO:0000256|HAMAP-Rule:MF_03009"
+FT   COILED          105..125
+FT                   /evidence="ECO:0000256|SAM:Coils"
+FT   MOD_RES         18
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000256|HAMAP-Rule:MF_03009"
+FT   MOD_RES         25
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000256|HAMAP-Rule:MF_03009"
+FT   MOD_RES         99
+FT                   /note="Phosphothreonine"
+FT                   /evidence="ECO:0000256|HAMAP-Rule:MF_03009"
+SQ   SEQUENCE   248 AA;  27746 MW;  25F67F1B71415651 CRC64;
+     RREMAAAAAA AAAGDSDSWD ADTFSVDDPV RKVGGGGTAG GDRWEGEDED EDVKVGAEVK
+     ISEKKKIAEK IKEKERQQKK RQEEIKKRLE EPEEPKVLTP EEQLADKLRL KKLQEESDLE
+     LAKETFGVNN TIYGIDAMNP SSRDDFTEFG KLLKDKITQY EKSLYYASFL EALVRDVCIS
+     LEIDDLKKIT NSLTVLCSEK QKQEKQSKAK KKKKGVVPGG GLKATMKDDL ADYGGYDGGY
+     VQDYEDFM
+//
diff --git a/examples/Q9QXS1.txt b/examples/Q9QXS1.txt
new file mode 100644
index 0000000..ab8cb41
--- /dev/null
+++ b/examples/Q9QXS1.txt
@@ -0,0 +1,962 @@
+ID   PLEC_MOUSE              Reviewed;        4691 AA.
+AC   Q9QXS1; E9QN87; Q6S384; Q6S389; Q6S394; Q9CS65; Q9QUT2; Q9QXQ8; Q9QXQ9;
+AC   Q9QXR0; Q9QXR1; Q9QXR2; Q9QXR3; Q9QXR4; Q9QXR5; Q9QXR6; Q9QXR7; Q9QXR8;
+AC   Q9QXR9; Q9QXS0; Q9QXS2; Q9QXS3;
+DT   01-JUN-2001, integrated into UniProtKB/Swiss-Prot.
+DT   16-APR-2014, sequence version 3.
+DT   02-DEC-2020, entry version 195.
+DE   RecName: Full=Plectin;
+DE            Short=PCN;
+DE            Short=PLTN;
+DE   AltName: Full=Plectin-1;
+DE   AltName: Full=Plectin-6;
+GN   Name=Plec; Synonyms=Plec1;
+OS   Mus musculus (Mouse).
+OC   Eukaryota; Metazoa; Chordata; Craniata; Vertebrata; Euteleostomi; Mammalia;
+OC   Eutheria; Euarchontoglires; Glires; Rodentia; Myomorpha; Muroidea; Muridae;
+OC   Murinae; Mus; Mus.
+OX   NCBI_TaxID=10090;
+RN   [1]
+RP   NUCLEOTIDE SEQUENCE [MRNA], AND ALTERNATIVE SPLICING.
+RX   PubMed=14672974; DOI=10.1101/gr.1225204;
+RA   Zhang T., Haws P., Wu Q.;
+RT   "Multiple variable first exons: a mechanism for cell- and tissue-specific
+RT   gene regulation.";
+RL   Genome Res. 14:79-89(2004).
+RN   [2]
+RP   NUCLEOTIDE SEQUENCE [LARGE SCALE GENOMIC DNA].
+RC   STRAIN=C57BL/6J;
+RX   PubMed=19468303; DOI=10.1371/journal.pbio.1000112;
+RA   Church D.M., Goodstadt L., Hillier L.W., Zody M.C., Goldstein S., She X.,
+RA   Bult C.J., Agarwala R., Cherry J.L., DiCuccio M., Hlavina W., Kapustin Y.,
+RA   Meric P., Maglott D., Birtle Z., Marques A.C., Graves T., Zhou S.,
+RA   Teague B., Potamousis K., Churas C., Place M., Herschleb J., Runnheim R.,
+RA   Forrest D., Amos-Landgraf J., Schwartz D.C., Cheng Z., Lindblad-Toh K.,
+RA   Eichler E.E., Ponting C.P.;
+RT   "Lineage-specific biology revealed by a finished genome assembly of the
+RT   mouse.";
+RL   PLoS Biol. 7:E1000112-E1000112(2009).
+RN   [3]
+RP   NUCLEOTIDE SEQUENCE [MRNA] OF 1-964, ALTERNATIVE SPLICING, AND TISSUE
+RP   SPECIFICITY.
+RC   TISSUE=Brain, Embryo, Heart, Kidney, Skeletal muscle, and Testis;
+RX   PubMed=10556294; DOI=10.1093/hmg/8.13.2461;
+RA   Fuchs P., Zoerer M., Rezniczek G.A., Spazierer D., Oehler S.,
+RA   Castanon M.J., Hauptmann R., Wiche G.;
+RT   "Unusual 5' transcript complexity of plectin isoforms: novel tissue-
+RT   specific exons modulate actin binding activity.";
+RL   Hum. Mol. Genet. 8:2461-2472(1999).
+RN   [4]
+RP   NUCLEOTIDE SEQUENCE [LARGE SCALE MRNA] OF 181-812.
+RC   STRAIN=C57BL/6J; TISSUE=Embryo;
+RX   PubMed=16141072; DOI=10.1126/science.1112014;
+RA   Carninci P., Kasukawa T., Katayama S., Gough J., Frith M.C., Maeda N.,
+RA   Oyama R., Ravasi T., Lenhard B., Wells C., Kodzius R., Shimokawa K.,
+RA   Bajic V.B., Brenner S.E., Batalov S., Forrest A.R., Zavolan M., Davis M.J.,
+RA   Wilming L.G., Aidinis V., Allen J.E., Ambesi-Impiombato A., Apweiler R.,
+RA   Aturaliya R.N., Bailey T.L., Bansal M., Baxter L., Beisel K.W., Bersano T.,
+RA   Bono H., Chalk A.M., Chiu K.P., Choudhary V., Christoffels A.,
+RA   Clutterbuck D.R., Crowe M.L., Dalla E., Dalrymple B.P., de Bono B.,
+RA   Della Gatta G., di Bernardo D., Down T., Engstrom P., Fagiolini M.,
+RA   Faulkner G., Fletcher C.F., Fukushima T., Furuno M., Futaki S.,
+RA   Gariboldi M., Georgii-Hemming P., Gingeras T.R., Gojobori T., Green R.E.,
+RA   Gustincich S., Harbers M., Hayashi Y., Hensch T.K., Hirokawa N., Hill D.,
+RA   Huminiecki L., Iacono M., Ikeo K., Iwama A., Ishikawa T., Jakt M.,
+RA   Kanapin A., Katoh M., Kawasawa Y., Kelso J., Kitamura H., Kitano H.,
+RA   Kollias G., Krishnan S.P., Kruger A., Kummerfeld S.K., Kurochkin I.V.,
+RA   Lareau L.F., Lazarevic D., Lipovich L., Liu J., Liuni S., McWilliam S.,
+RA   Madan Babu M., Madera M., Marchionni L., Matsuda H., Matsuzawa S., Miki H.,
+RA   Mignone F., Miyake S., Morris K., Mottagui-Tabar S., Mulder N., Nakano N.,
+RA   Nakauchi H., Ng P., Nilsson R., Nishiguchi S., Nishikawa S., Nori F.,
+RA   Ohara O., Okazaki Y., Orlando V., Pang K.C., Pavan W.J., Pavesi G.,
+RA   Pesole G., Petrovsky N., Piazza S., Reed J., Reid J.F., Ring B.Z.,
+RA   Ringwald M., Rost B., Ruan Y., Salzberg S.L., Sandelin A., Schneider C.,
+RA   Schoenbach C., Sekiguchi K., Semple C.A., Seno S., Sessa L., Sheng Y.,
+RA   Shibata Y., Shimada H., Shimada K., Silva D., Sinclair B., Sperling S.,
+RA   Stupka E., Sugiura K., Sultana R., Takenaka Y., Taki K., Tammoja K.,
+RA   Tan S.L., Tang S., Taylor M.S., Tegner J., Teichmann S.A., Ueda H.R.,
+RA   van Nimwegen E., Verardo R., Wei C.L., Yagi K., Yamanishi H.,
+RA   Zabarovsky E., Zhu S., Zimmer A., Hide W., Bult C., Grimmond S.M.,
+RA   Teasdale R.D., Liu E.T., Brusic V., Quackenbush J., Wahlestedt C.,
+RA   Mattick J.S., Hume D.A., Kai C., Sasaki D., Tomaru Y., Fukuda S.,
+RA   Kanamori-Katayama M., Suzuki M., Aoki J., Arakawa T., Iida J., Imamura K.,
+RA   Itoh M., Kato T., Kawaji H., Kawagashira N., Kawashima T., Kojima M.,
+RA   Kondo S., Konno H., Nakano K., Ninomiya N., Nishio T., Okada M., Plessy C.,
+RA   Shibata K., Shiraki T., Suzuki S., Tagami M., Waki K., Watahiki A.,
+RA   Okamura-Oho Y., Suzuki H., Kawai J., Hayashizaki Y.;
+RT   "The transcriptional landscape of the mammalian genome.";
+RL   Science 309:1559-1563(2005).
+RN   [5]
+RP   PROTEIN SEQUENCE OF 629-633, AND IDENTIFICATION BY MASS SPECTROMETRY.
+RC   STRAIN=OF1; TISSUE=Hippocampus;
+RA   Lubec G., Sunyer B., Chen W.-Q.;
+RL   Submitted (JAN-2009) to UniProtKB.
+RN   [6]
+RP   INTERACTION WITH FER.
+RX   PubMed=12200133; DOI=10.1016/s0006-291x(02)02007-7;
+RA   Lunter P.C., Wiche G.;
+RT   "Direct binding of plectin to Fer kinase and negative regulation of its
+RT   catalytic activity.";
+RL   Biochem. Biophys. Res. Commun. 296:904-910(2002).
+RN   [7]
+RP   INTERACTION WITH SYNE3.
+RX   PubMed=16330710; DOI=10.1083/jcb.200506083;
+RA   Wilhelmsen K., Litjens S.H.M., Kuikman I., Tshimbalanga N., Janssen H.,
+RA   van den Bout I., Raymond K., Sonnenberg A.;
+RT   "Nesprin-3, a novel outer nuclear membrane protein, associates with the
+RT   cytoskeletal linker protein plectin.";
+RL   J. Cell Biol. 171:799-810(2005).
+RN   [8]
+RP   IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RX   PubMed=15592455; DOI=10.1038/nbt1046;
+RA   Rush J., Moritz A., Lee K.A., Guo A., Goss V.L., Spek E.J., Zhang H.,
+RA   Zha X.-M., Polakiewicz R.D., Comb M.J.;
+RT   "Immunoaffinity profiling of tyrosine phosphorylation in cancer cells.";
+RL   Nat. Biotechnol. 23:94-101(2005).
+RN   [9]
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT SER-728, AND IDENTIFICATION BY
+RP   MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Brain;
+RX   PubMed=16452087; DOI=10.1074/mcp.t500041-mcp200;
+RA   Trinidad J.C., Specht C.G., Thalhammer A., Schoepfer R., Burlingame A.L.;
+RT   "Comprehensive identification of phosphorylation sites in postsynaptic
+RT   density preparations.";
+RL   Mol. Cell. Proteomics 5:914-922(2006).
+RN   [10]
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT TYR-2788; TYR-3040; TYR-3369;
+RP   TYR-3797 AND TYR-4622, PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT TYR-26
+RP   (ISOFORM PLEC-1A), AND IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE
+RP   ANALYSIS].
+RC   TISSUE=Mast cell;
+RX   PubMed=17947660; DOI=10.4049/jimmunol.179.9.5864;
+RA   Cao L., Yu K., Banh C., Nguyen V., Ritz A., Raphael B.J., Kawakami Y.,
+RA   Kawakami T., Salomon A.R.;
+RT   "Quantitative time-resolved phosphoproteomic analysis of mast cell
+RT   signaling.";
+RL   J. Immunol. 179:5864-5876(2007).
+RN   [11]
+RP   IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Brain cortex;
+RX   PubMed=17114649; DOI=10.1074/mcp.m600046-mcp200;
+RA   Munton R.P., Tweedie-Cullen R., Livingstone-Zatchej M., Weinandy F.,
+RA   Waidelich M., Longo D., Gehrig P., Potthast F., Rutishauser D., Gerrits B.,
+RA   Panse C., Schlapbach R., Mansuy I.M.;
+RT   "Qualitative and quantitative analyses of protein phosphorylation in naive
+RT   and stimulated mouse synaptosomal preparations.";
+RL   Mol. Cell. Proteomics 6:283-293(2007).
+RN   [12]
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT THR-823, AND IDENTIFICATION BY
+RP   MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Liver;
+RX   PubMed=17208939; DOI=10.1074/mcp.m600218-mcp200;
+RA   Lee J., Xu Y., Chen Y., Sprung R., Kim S.C., Xie S., Zhao Y.;
+RT   "Mitochondrial phosphoproteome revealed by an improved IMAC method and
+RT   MS/MS/MS.";
+RL   Mol. Cell. Proteomics 6:669-676(2007).
+RN   [13]
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT SER-4633, AND IDENTIFICATION BY
+RP   MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Liver;
+RX   PubMed=17242355; DOI=10.1073/pnas.0609836104;
+RA   Villen J., Beausoleil S.A., Gerber S.A., Gygi S.P.;
+RT   "Large-scale phosphorylation analysis of mouse liver.";
+RL   Proc. Natl. Acad. Sci. U.S.A. 104:1488-1493(2007).
+RN   [14]
+RP   INTERACTION WITH TOR1A.
+RX   PubMed=18827015; DOI=10.1242/jcs.029454;
+RA   Nery F.C., Zeng J., Niland B.P., Hewett J., Farley J., Irimia D., Li Y.,
+RA   Wiche G., Sonnenberg A., Breakefield X.O.;
+RT   "TorsinA binds the KASH domain of nesprins and participates in linkage
+RT   between nuclear envelope and cytoskeleton.";
+RL   J. Cell Sci. 121:3476-3486(2008).
+RN   [15]
+RP   IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Liver;
+RX   PubMed=18630941; DOI=10.1021/pr800223m;
+RA   Zhou H., Ye M., Dong J., Han G., Jiang X., Wu R., Zou H.;
+RT   "Specific phosphopeptide enrichment with immobilized titanium ion affinity
+RT   chromatography adsorbent for phosphoproteome analysis.";
+RL   J. Proteome Res. 7:3957-3967(2008).
+RN   [16]
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT SER-4393 AND SER-4396,
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT SER-21 (ISOFORM PLEC-1A), AND
+RP   IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RX   PubMed=19144319; DOI=10.1016/j.immuni.2008.11.006;
+RA   Trost M., English L., Lemieux S., Courcelles M., Desjardins M.,
+RA   Thibault P.;
+RT   "The phagosomal proteome in interferon-gamma-activated macrophages.";
+RL   Immunity 30:143-154(2009).
+RN   [17]
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT SER-4389 AND SER-4393,
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT SER-21 (ISOFORM PLEC-1A), AND
+RP   IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Embryonic fibroblast;
+RX   PubMed=19131326; DOI=10.1074/mcp.m800451-mcp200;
+RA   Sweet S.M., Bailey C.M., Cunningham D.L., Heath J.K., Cooper H.J.;
+RT   "Large scale localization of protein phosphorylation by use of electron
+RT   capture dissociation mass spectrometry.";
+RL   Mol. Cell. Proteomics 8:904-912(2009).
+RN   [18]
+RP   PHOSPHORYLATION [LARGE SCALE ANALYSIS] AT SER-728; SER-1055; THR-4037;
+RP   SER-4389; SER-4391; SER-4392; SER-4393; SER-4396; SER-4620; SER-4625;
+RP   SER-4629; THR-4630; SER-4633 AND SER-4649, PHOSPHORYLATION [LARGE SCALE
+RP   ANALYSIS] AT SER-21 (ISOFORM PLEC-1A), AND IDENTIFICATION BY MASS
+RP   SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Brain, Brown adipose tissue, Heart, Kidney, Liver, Lung, Pancreas,
+RC   Spleen, and Testis;
+RX   PubMed=21183079; DOI=10.1016/j.cell.2010.12.001;
+RA   Huttlin E.L., Jedrychowski M.P., Elias J.E., Goswami T., Rad R.,
+RA   Beausoleil S.A., Villen J., Haas W., Sowa M.E., Gygi S.P.;
+RT   "A tissue-specific atlas of mouse protein phosphorylation and expression.";
+RL   Cell 143:1174-1189(2010).
+RN   [19]
+RP   INTERACTION WITH DST.
+RX   PubMed=19932097; DOI=10.1016/j.yexcr.2009.11.010;
+RA   Steiner-Champliaud M.F., Schneider Y., Favre B., Paulhe F.,
+RA   Praetzel-Wunder S., Faulkner G., Konieczny P., Raith M., Wiche G.,
+RA   Adebola A., Liem R.K., Langbein L., Sonnenberg A., Fontao L., Borradori L.;
+RT   "BPAG1 isoform-b: complex distribution pattern in striated and heart muscle
+RT   and association with plectin and alpha-actinin.";
+RL   Exp. Cell Res. 316:297-313(2010).
+RN   [20]
+RP   TISSUE SPECIFICITY, AND IDENTIFICATION IN A COMPLEX WITH EZR; AHNAK; BFSP1;
+RP   BFSP2; ANK2; PRX; VIM AND SPECTRIN.
+RX   PubMed=21745462; DOI=10.1016/j.ydbio.2011.06.036;
+RA   Maddala R., Skiba N.P., Lalane R. III, Sherman D.L., Brophy P.J., Rao P.V.;
+RT   "Periaxin is required for hexagonal geometry and membrane organization of
+RT   mature lens fibers.";
+RL   Dev. Biol. 357:179-190(2011).
+RN   [21]
+RP   ACETYLATION [LARGE SCALE ANALYSIS] AT LYS-1733; LYS-2644 AND LYS-3060, AND
+RP   IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Embryonic fibroblast;
+RX   PubMed=23806337; DOI=10.1016/j.molcel.2013.06.001;
+RA   Park J., Chen Y., Tishkoff D.X., Peng C., Tan M., Dai L., Xie Z., Zhang Y.,
+RA   Zwaans B.M., Skinner M.E., Lombard D.B., Zhao Y.;
+RT   "SIRT5-mediated lysine desuccinylation impacts diverse metabolic
+RT   pathways.";
+RL   Mol. Cell 50:919-930(2013).
+RN   [22]
+RP   METHYLATION [LARGE SCALE ANALYSIS] AT ARG-4634 AND ARG-4647, AND
+RP   IDENTIFICATION BY MASS SPECTROMETRY [LARGE SCALE ANALYSIS].
+RC   TISSUE=Brain;
+RX   PubMed=24129315; DOI=10.1074/mcp.o113.027870;
+RA   Guo A., Gu H., Zhou J., Mulhern D., Wang Y., Lee K.A., Yang V., Aguiar M.,
+RA   Kornhauser J., Jia X., Ren J., Beausoleil S.A., Silva J.C., Vemulapalli V.,
+RA   Bedford M.T., Comb M.J.;
+RT   "Immunoaffinity enrichment and mass spectrometry analysis of protein
+RT   methylation.";
+RL   Mol. Cell. Proteomics 13:372-387(2014).
+RN   [23]
+RP   X-RAY CRYSTALLOGRAPHY (2.00 ANGSTROMS) OF 181-417, AND INTERACTION WITH
+RP   VIM.
+RX   PubMed=15128297; DOI=10.1111/j.1432-1033.2004.04095.x;
+RA   Sevcik J., Urbanikova L., Kost'an J., Janda L., Wiche G.;
+RT   "Actin-binding domain of mouse plectin. Crystal structure and binding to
+RT   vimentin.";
+RL   Eur. J. Biochem. 271:1873-1884(2004).
+CC   -!- FUNCTION: Interlinks intermediate filaments with microtubules and
+CC       microfilaments and anchors intermediate filaments to desmosomes or
+CC       hemidesmosomes. May be involved not only in the cross-linking and
+CC       stabilization of cytoskeletal intermediate filaments network, but also
+CC       in the regulation of their dynamics.
+CC   -!- SUBUNIT: Homodimer or homotetramer (By similarity). Interacts (via
+CC       actin-binding domain) with SYNE3 (PubMed:16330710). Interacts (via
+CC       calponin-homology (CH) 1 domain) with VIM (via rod region)
+CC       (PubMed:15128297). Interacts (via N-terminus) with DST isoform 2 (via
+CC       N-terminus) (PubMed:19932097). Interacts with FER (PubMed:12200133).
+CC       Interacts with TOR1A (PubMed:18827015). Interacts with ANK3 (By
+CC       similarity). Identified in complexes that contain VIM, EZR, AHNAK,
+CC       BFSP1, BFSP2, ANK2, PLEC, PRX and spectrin (PubMed:21745462).
+CC       {ECO:0000250, ECO:0000250|UniProtKB:P30427,
+CC       ECO:0000269|PubMed:12200133, ECO:0000269|PubMed:15128297,
+CC       ECO:0000269|PubMed:16330710, ECO:0000269|PubMed:18827015,
+CC       ECO:0000269|PubMed:19932097, ECO:0000269|PubMed:21745462}.
+CC   -!- INTERACTION:
+CC       Q9QXS1; Q9D2G2: Dlst; NbExp=2; IntAct=EBI-774583, EBI-773210;
+CC       Q9QXS1; P35486: Pdha1; NbExp=2; IntAct=EBI-774583, EBI-773613;
+CC       Q9QXS1-3; P0DP25: CALM3; Xeno; NbExp=11; IntAct=EBI-16145475, EBI-397435;
+CC       Q9QXS1-3; P16144: ITGB4; Xeno; NbExp=4; IntAct=EBI-16145475, EBI-948678;
+CC   -!- SUBCELLULAR LOCATION: Cytoplasm, cytoskeleton. Cell junction,
+CC       hemidesmosome {ECO:0000250}.
+CC   -!- ALTERNATIVE PRODUCTS:
+CC       Event=Alternative splicing; Named isoforms=16;
+CC       Name=PLEC-1,2A;
+CC         IsoId=Q9QXS1-1; Sequence=Displayed;
+CC       Name=PLEC-1;
+CC         IsoId=Q9QXS1-2; Sequence=VSP_005048;
+CC       Name=PLEC-1A;
+CC         IsoId=Q9QXS1-3; Sequence=VSP_005036, VSP_005045, VSP_005048;
+CC       Name=PLEC-1B,2A;
+CC         IsoId=Q9QXS1-4; Sequence=VSP_005037, VSP_005045;
+CC       Name=PLEC-1B;
+CC         IsoId=Q9QXS1-5; Sequence=VSP_005037, VSP_005045, VSP_005048;
+CC       Name=PLEC-0,1C;
+CC         IsoId=Q9QXS1-6; Sequence=VSP_005039, VSP_005047, VSP_005048;
+CC       Name=PLEC-0,1C,2A;
+CC         IsoId=Q9QXS1-7; Sequence=VSP_005039, VSP_005047;
+CC       Name=PLEC-0,1C,2A,3A;
+CC         IsoId=Q9QXS1-8; Sequence=VSP_005039, VSP_005047, VSP_005049;
+CC       Name=PLEC-1D,2A;
+CC         IsoId=Q9QXS1-9; Sequence=VSP_005032, VSP_005041;
+CC       Name=PLEC-1D;
+CC         IsoId=Q9QXS1-10; Sequence=VSP_005032, VSP_005041, VSP_005048;
+CC       Name=PLEC-1E,2A;
+CC         IsoId=Q9QXS1-11; Sequence=VSP_005033, VSP_005042;
+CC       Name=PLEC-1E;
+CC         IsoId=Q9QXS1-12; Sequence=VSP_005033, VSP_005042, VSP_005048;
+CC       Name=PLEC-1F;
+CC         IsoId=Q9QXS1-13; Sequence=VSP_005034, VSP_005043, VSP_005048;
+CC       Name=PLEC-1G;
+CC         IsoId=Q9QXS1-14; Sequence=VSP_005038, VSP_005046, VSP_005048;
+CC       Name=PLEC-1H;
+CC         IsoId=Q9QXS1-15; Sequence=VSP_005040;
+CC       Name=PLEC-1I;
+CC         IsoId=Q9QXS1-16; Sequence=VSP_005035, VSP_005044;
+CC   -!- TISSUE SPECIFICITY: Detected in eye lens fiber cells (at protein level)
+CC       (PubMed:21745462). Expressed at high levels in lung, brain, small
+CC       intestine, muscle, heart and skin with lower levels found in kidney,
+CC       liver, uterus, spleen and salivary gland (PubMed:10556294).
+CC       {ECO:0000269|PubMed:10556294, ECO:0000269|PubMed:21745462}.
+CC   -!- DOMAIN: The N-terminus interacts with actin, the C-terminus with
+CC       vimentin, desmin, GFAP, cytokeratins, lamin B; whereas both the N- and
+CC       the C-terminus can bind integrin beta-4.
+CC   -!- PTM: Phosphorylated by CDK1; regulates dissociation from intermediate
+CC       filaments during mitosis. Isoform PLEC-1A is phosphorylated on Ser-21.
+CC       Isoform PLEC-1A is phosphorylated on Tyr-26.
+CC   -!- SIMILARITY: Belongs to the plakin or cytolinker family. {ECO:0000305}.
+CC   ---------------------------------------------------------------------------
+CC   Copyrighted by the UniProt Consortium, see https://www.uniprot.org/terms
+CC   Distributed under the Creative Commons Attribution (CC BY 4.0) License
+CC   ---------------------------------------------------------------------------
+DR   EMBL; AY480033; AAR95666.1; -; mRNA.
+DR   EMBL; AY480038; AAR95671.1; -; mRNA.
+DR   EMBL; AY480043; AAR95676.1; -; mRNA.
+DR   EMBL; AC110211; -; NOT_ANNOTATED_CDS; Genomic_DNA.
+DR   EMBL; AF188006; AAF18066.1; -; mRNA.
+DR   EMBL; AF188007; AAF18067.1; -; mRNA.
+DR   EMBL; AF188008; AAF18068.1; -; mRNA.
+DR   EMBL; AF188009; AAF18069.1; -; mRNA.
+DR   EMBL; AF188010; AAF18070.1; -; mRNA.
+DR   EMBL; AF188011; AAF18071.1; -; mRNA.
+DR   EMBL; AF188012; AAF18072.1; -; mRNA.
+DR   EMBL; AF188013; AAF18073.1; -; mRNA.
+DR   EMBL; AF188014; AAF18074.1; -; mRNA.
+DR   EMBL; AF188015; AAF18075.1; -; mRNA.
+DR   EMBL; AF188016; AAF18076.1; -; mRNA.
+DR   EMBL; AF188017; AAF18077.1; -; mRNA.
+DR   EMBL; AF188018; AAF18078.1; -; mRNA.
+DR   EMBL; AF188019; AAF18079.1; -; mRNA.
+DR   EMBL; AF188020; AAF18080.1; -; mRNA.
+DR   EMBL; AF188021; AAF18081.1; -; mRNA.
+DR   EMBL; AF188022; AAF18082.1; -; mRNA.
+DR   EMBL; AF188023; AAF18083.1; -; mRNA.
+DR   EMBL; AK017743; -; NOT_ANNOTATED_CDS; mRNA.
+DR   CCDS; CCDS37113.1; -. [Q9QXS1-13]
+DR   CCDS; CCDS37114.1; -. [Q9QXS1-2]
+DR   CCDS; CCDS37115.1; -. [Q9QXS1-14]
+DR   CCDS; CCDS37116.1; -. [Q9QXS1-3]
+DR   CCDS; CCDS49644.1; -. [Q9QXS1-5]
+DR   CCDS; CCDS49645.1; -. [Q9QXS1-4]
+DR   CCDS; CCDS49646.1; -. [Q9QXS1-10]
+DR   CCDS; CCDS49647.1; -. [Q9QXS1-1]
+DR   CCDS; CCDS49648.1; -. [Q9QXS1-12]
+DR   CCDS; CCDS49649.1; -. [Q9QXS1-8]
+DR   PIR; D59404; D59404.
+DR   RefSeq; NP_001157012.1; NM_001163540.1. [Q9QXS1-1]
+DR   RefSeq; NP_001157014.1; NM_001163542.1. [Q9QXS1-8]
+DR   RefSeq; NP_001157021.1; NM_001163549.1. [Q9QXS1-4]
+DR   RefSeq; NP_001157675.1; NM_001164203.1.
+DR   RefSeq; NP_035247.2; NM_011117.2. [Q9QXS1-6]
+DR   RefSeq; NP_958791.2; NM_201389.2. [Q9QXS1-2]
+DR   RefSeq; NP_958796.2; NM_201394.2. [Q9QXS1-3]
+DR   PDB; 1SH5; X-ray; 2.00 A; A/B=181-417.
+DR   PDB; 1SH6; X-ray; 2.00 A; A=181-417.
+DR   PDB; 4Q57; X-ray; 1.80 A; B=181-411.
+DR   PDBsum; 1SH5; -.
+DR   PDBsum; 1SH6; -.
+DR   PDBsum; 4Q57; -.
+DR   SMR; Q9QXS1; -.
+DR   BioGRID; 202243; 24.
+DR   CORUM; Q9QXS1; -.
+DR   DIP; DIP-32004N; -.
+DR   IntAct; Q9QXS1; 16.
+DR   MINT; Q9QXS1; -.
+DR   STRING; 10090.ENSMUSP00000075772; -.
+DR   iPTMnet; Q9QXS1; -.
+DR   PhosphoSitePlus; Q9QXS1; -.
+DR   SwissPalm; Q9QXS1; -.
+DR   jPOST; Q9QXS1; -.
+DR   PaxDb; Q9QXS1; -.
+DR   PeptideAtlas; Q9QXS1; -.
+DR   PRIDE; Q9QXS1; -.
+DR   Antibodypedia; 3549; 191 antibodies.
+DR   Ensembl; ENSMUST00000023226; ENSMUSP00000023226; ENSMUSG00000022565. [Q9QXS1-3]
+DR   Ensembl; ENSMUST00000054449; ENSMUSP00000057158; ENSMUSG00000022565. [Q9QXS1-4]
+DR   Ensembl; ENSMUST00000071869; ENSMUSP00000071765; ENSMUSG00000022565. [Q9QXS1-12]
+DR   Ensembl; ENSMUST00000072692; ENSMUSP00000072478; ENSMUSG00000022565. [Q9QXS1-14]
+DR   Ensembl; ENSMUST00000073418; ENSMUSP00000073124; ENSMUSG00000022565. [Q9QXS1-1]
+DR   Ensembl; ENSMUST00000074834; ENSMUSP00000074383; ENSMUSG00000022565. [Q9QXS1-13]
+DR   Ensembl; ENSMUST00000076442; ENSMUSP00000075772; ENSMUSG00000022565. [Q9QXS1-2]
+DR   Ensembl; ENSMUST00000089610; ENSMUSP00000087037; ENSMUSG00000022565. [Q9QXS1-8]
+DR   Ensembl; ENSMUST00000169108; ENSMUSP00000126068; ENSMUSG00000022565. [Q9QXS1-10]
+DR   Ensembl; ENSMUST00000169714; ENSMUSP00000126526; ENSMUSG00000022565. [Q9QXS1-5]
+DR   GeneID; 18810; -.
+DR   KEGG; mmu:18810; -.
+DR   UCSC; uc007wir.2; mouse. [Q9QXS1-3]
+DR   UCSC; uc007wis.2; mouse. [Q9QXS1-14]
+DR   UCSC; uc007wit.2; mouse. [Q9QXS1-1]
+DR   UCSC; uc007wiu.2; mouse. [Q9QXS1-5]
+DR   UCSC; uc007wiv.2; mouse. [Q9QXS1-10]
+DR   UCSC; uc007wiw.2; mouse. [Q9QXS1-2]
+DR   UCSC; uc007wiz.2; mouse. [Q9QXS1-12]
+DR   UCSC; uc007wja.2; mouse. [Q9QXS1-13]
+DR   UCSC; uc007wjb.2; mouse. [Q9QXS1-6]
+DR   UCSC; uc007wjd.2; mouse. [Q9QXS1-4]
+DR   UCSC; uc011zuq.1; mouse. [Q9QXS1-8]
+DR   CTD; 5339; -.
+DR   MGI; MGI:1277961; Plec.
+DR   eggNOG; KOG0516; Eukaryota.
+DR   eggNOG; KOG3344; Eukaryota.
+DR   GeneTree; ENSGT00940000159045; -.
+DR   HOGENOM; CLU_000132_0_0_1; -.
+DR   InParanoid; Q9QXS1; -.
+DR   OrthoDB; 2464at2759; -.
+DR   Reactome; R-MMU-2022090; Assembly of collagen fibrils and other multimeric structures.
+DR   Reactome; R-MMU-264870; Caspase-mediated cleavage of cytoskeletal proteins.
+DR   Reactome; R-MMU-446107; Type I hemidesmosome assembly.
+DR   BioGRID-ORCS; 18810; 4 hits in 19 CRISPR screens.
+DR   ChiTaRS; Plec; mouse.
+DR   EvolutionaryTrace; Q9QXS1; -.
+DR   PRO; PR:Q9QXS1; -.
+DR   Proteomes; UP000000589; Chromosome 15.
+DR   RNAct; Q9QXS1; protein.
+DR   Bgee; ENSMUSG00000022565; Expressed in skeletal muscle tissue and 292 other tissues.
+DR   ExpressionAtlas; Q9QXS1; baseline and differential.
+DR   Genevisible; Q9QXS1; MM.
+DR   GO; GO:0016324; C:apical plasma membrane; ISO:MGI.
+DR   GO; GO:0009925; C:basal plasma membrane; ISO:MGI.
+DR   GO; GO:0005903; C:brush border; IDA:UniProtKB.
+DR   GO; GO:0043292; C:contractile fiber; IDA:MGI.
+DR   GO; GO:0005737; C:cytoplasm; IBA:GO_Central.
+DR   GO; GO:0005829; C:cytosol; ISO:MGI.
+DR   GO; GO:0005925; C:focal adhesion; ISO:MGI.
+DR   GO; GO:0030056; C:hemidesmosome; ISS:UniProtKB.
+DR   GO; GO:0045111; C:intermediate filament cytoskeleton; ISO:MGI.
+DR   GO; GO:0016020; C:membrane; IBA:GO_Central.
+DR   GO; GO:0048471; C:perinuclear region of cytoplasm; ISO:MGI.
+DR   GO; GO:0042383; C:sarcolemma; ISS:UniProtKB.
+DR   GO; GO:0016528; C:sarcoplasm; ISO:MGI.
+DR   GO; GO:0003779; F:actin binding; IEA:UniProtKB-KW.
+DR   GO; GO:0030506; F:ankyrin binding; ISO:MGI.
+DR   GO; GO:0008092; F:cytoskeletal protein binding; ISO:MGI.
+DR   GO; GO:0047485; F:protein N-terminus binding; ISO:MGI.
+DR   GO; GO:0005200; F:structural constituent of cytoskeleton; ISO:MGI.
+DR   GO; GO:0008307; F:structural constituent of muscle; ISO:MGI.
+DR   GO; GO:0005198; F:structural molecule activity; IBA:GO_Central.
+DR   GO; GO:0031581; P:hemidesmosome assembly; ISS:UniProtKB.
+DR   GO; GO:0045104; P:intermediate filament cytoskeleton organization; IBA:GO_Central.
+DR   GO; GO:0007584; P:response to nutrient; ISO:MGI.
+DR   GO; GO:0042060; P:wound healing; IBA:GO_Central.
+DR   CDD; cd00014; CH; 2.
+DR   Gene3D; 1.10.10.10; -; 1.
+DR   Gene3D; 1.10.418.10; -; 2.
+DR   Gene3D; 3.90.1290.10; -; 6.
+DR   InterPro; IPR001589; Actinin_actin-bd_CS.
+DR   InterPro; IPR001715; CH-domain.
+DR   InterPro; IPR036872; CH_dom_sf.
+DR   InterPro; IPR041615; Desmoplakin_SH3.
+DR   InterPro; IPR041573; Desmoplakin_Spectrin-like.
+DR   InterPro; IPR043197; Plakin.
+DR   InterPro; IPR035915; Plakin_repeat_sf.
+DR   InterPro; IPR030269; Plectin.
+DR   InterPro; IPR001101; Plectin_repeat.
+DR   InterPro; IPR005326; S10_plectin_N.
+DR   InterPro; IPR001452; SH3_domain.
+DR   InterPro; IPR018159; Spectrin/alpha-actinin.
+DR   InterPro; IPR036388; WH-like_DNA-bd_sf.
+DR   PANTHER; PTHR23169; PTHR23169; 3.
+DR   PANTHER; PTHR23169:SF20; PTHR23169:SF20; 3.
+DR   Pfam; PF00307; CH; 2.
+DR   Pfam; PF00681; Plectin; 18.
+DR   Pfam; PF03501; S10_plectin; 1.
+DR   Pfam; PF17902; SH3_10; 1.
+DR   Pfam; PF18373; Spectrin_like; 1.
+DR   SMART; SM00033; CH; 2.
+DR   SMART; SM00250; PLEC; 35.
+DR   SMART; SM00150; SPEC; 6.
+DR   SUPFAM; SSF47576; SSF47576; 1.
+DR   SUPFAM; SSF75399; SSF75399; 7.
+DR   PROSITE; PS00019; ACTININ_1; 1.
+DR   PROSITE; PS00020; ACTININ_2; 1.
+DR   PROSITE; PS50021; CH; 2.
+DR   PROSITE; PS50002; SH3; 1.
+PE   1: Evidence at protein level;
+KW   3D-structure; Acetylation; Actin-binding; Alternative splicing;
+KW   Cell junction; Coiled coil; Cytoplasm; Cytoskeleton;
+KW   Direct protein sequencing; Methylation; Phosphoprotein; Reference proteome;
+KW   Repeat; SH3 domain.
+FT   CHAIN           1..4691
+FT                   /note="Plectin"
+FT                   /id="PRO_0000078136"
+FT   DOMAIN          185..293
+FT                   /note="Calponin-homology (CH) 1"
+FT                   /evidence="ECO:0000255|PROSITE-ProRule:PRU00044"
+FT   DOMAIN          306..411
+FT                   /note="Calponin-homology (CH) 2"
+FT                   /evidence="ECO:0000255|PROSITE-ProRule:PRU00044"
+FT   REPEAT          653..727
+FT                   /note="Spectrin 1"
+FT   REPEAT          748..832
+FT                   /note="Spectrin 2"
+FT   REPEAT          845..938
+FT                   /note="Spectrin 3"
+FT   DOMAIN          949..1006
+FT                   /note="SH3"
+FT                   /evidence="ECO:0000255|PROSITE-ProRule:PRU00192"
+FT   REPEAT          1323..1423
+FT                   /note="Spectrin 4"
+FT   REPEAT          2795..2832
+FT                   /note="Plectin 1"
+FT   REPEAT          2833..2870
+FT                   /note="Plectin 2"
+FT   REPEAT          2871..2908
+FT                   /note="Plectin 3"
+FT   REPEAT          2909..2946
+FT                   /note="Plectin 4"
+FT   REPEAT          2947..2984
+FT                   /note="Plectin 5"
+FT   REPEAT          2988..3022
+FT                   /note="Plectin 6"
+FT   REPEAT          3123..3160
+FT                   /note="Plectin 7"
+FT   REPEAT          3161..3198
+FT                   /note="Plectin 8"
+FT   REPEAT          3199..3236
+FT                   /note="Plectin 9"
+FT   REPEAT          3237..3274
+FT                   /note="Plectin 10"
+FT   REPEAT          3275..3312
+FT                   /note="Plectin 11"
+FT   REPEAT          3315..3350
+FT                   /note="Plectin 12"
+FT   REPEAT          3492..3529
+FT                   /note="Plectin 13"
+FT   REPEAT          3530..3567
+FT                   /note="Plectin 14"
+FT   REPEAT          3568..3605
+FT                   /note="Plectin 15"
+FT   REPEAT          3606..3643
+FT                   /note="Plectin 16"
+FT   REPEAT          3647..3681
+FT                   /note="Plectin 17"
+FT   REPEAT          3827..3864
+FT                   /note="Plectin 18"
+FT   REPEAT          3865..3902
+FT                   /note="Plectin 19"
+FT   REPEAT          3903..3940
+FT                   /note="Plectin 20"
+FT   REPEAT          3941..3978
+FT                   /note="Plectin 21"
+FT   REPEAT          3982..4015
+FT                   /note="Plectin 22"
+FT   REPEAT          4070..4107
+FT                   /note="Plectin 23"
+FT   REPEAT          4108..4145
+FT                   /note="Plectin 24"
+FT   REPEAT          4146..4183
+FT                   /note="Plectin 25"
+FT   REPEAT          4184..4221
+FT                   /note="Plectin 26"
+FT   REPEAT          4225..4259
+FT                   /note="Plectin 27"
+FT   REPEAT          4272..4312
+FT                   /note="Plectin 28"
+FT   REPEAT          4415..4452
+FT                   /note="Plectin 29"
+FT   REPEAT          4453..4490
+FT                   /note="Plectin 30"
+FT   REPEAT          4491..4528
+FT                   /note="Plectin 31"
+FT   REPEAT          4529..4566
+FT                   /note="Plectin 32"
+FT   REPEAT          4567..4604
+FT                   /note="Plectin 33"
+FT   REGION          1..1478
+FT                   /note="Globular 1"
+FT                   /evidence="ECO:0000250"
+FT   REGION          181..411
+FT                   /note="Actin-binding"
+FT   REGION          1479..2762
+FT                   /note="Central fibrous rod domain"
+FT                   /evidence="ECO:0000250"
+FT   REGION          2763..4691
+FT                   /note="Globular 2"
+FT                   /evidence="ECO:0000250"
+FT   REGION          4257..4307
+FT                   /note="Binding to intermediate filaments"
+FT                   /evidence="ECO:0000250"
+FT   REGION          4632..4647
+FT                   /note="4 X 4 AA tandem repeats of G-S-R-X"
+FT   COILED          1477..1697
+FT                   /evidence="ECO:0000255"
+FT   COILED          1729..2764
+FT                   /evidence="ECO:0000255"
+FT   MOD_RES         728
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:16452087,
+FT                   ECO:0000244|PubMed:21183079"
+FT   MOD_RES         823
+FT                   /note="Phosphothreonine"
+FT                   /evidence="ECO:0000244|PubMed:17208939"
+FT   MOD_RES         1055
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         1443
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         1729
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         1733
+FT                   /note="N6-acetyllysine"
+FT                   /evidence="ECO:0000244|PubMed:23806337"
+FT   MOD_RES         2639
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         2644
+FT                   /note="N6-acetyllysine"
+FT                   /evidence="ECO:0000244|PubMed:23806337"
+FT   MOD_RES         2781
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:P30427"
+FT   MOD_RES         2788
+FT                   /note="Phosphotyrosine"
+FT                   /evidence="ECO:0000244|PubMed:17947660"
+FT   MOD_RES         2809
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         2893
+FT                   /note="Phosphothreonine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         3040
+FT                   /note="Phosphotyrosine"
+FT                   /evidence="ECO:0000244|PubMed:17947660"
+FT   MOD_RES         3060
+FT                   /note="N6-acetyllysine"
+FT                   /evidence="ECO:0000244|PubMed:23806337"
+FT   MOD_RES         3098
+FT                   /note="N6-acetyllysine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         3369
+FT                   /note="Phosphotyrosine"
+FT                   /evidence="ECO:0000244|PubMed:17947660"
+FT   MOD_RES         3427
+FT                   /note="N6-acetyllysine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         3792
+FT                   /note="Phosphothreonine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         3797
+FT                   /note="Phosphotyrosine"
+FT                   /evidence="ECO:0000244|PubMed:17947660"
+FT   MOD_RES         4037
+FT                   /note="Phosphothreonine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4061
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4389
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:19131326,
+FT                   ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4391
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4392
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4393
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:19131326,
+FT                   ECO:0000244|PubMed:19144319, ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4396
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:19144319,
+FT                   ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4397
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4398
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4399
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4400
+FT                   /note="Phosphotyrosine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4403
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4413
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:P30427"
+FT   MOD_RES         4418
+FT                   /note="Phosphothreonine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4546
+FT                   /note="Phosphothreonine; by CDK1"
+FT                   /evidence="ECO:0000250|UniProtKB:Q9JI55"
+FT   MOD_RES         4614
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4620
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4622
+FT                   /note="Phosphotyrosine"
+FT                   /evidence="ECO:0000244|PubMed:17947660"
+FT   MOD_RES         4623
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   MOD_RES         4625
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4629
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4630
+FT                   /note="Phosphothreonine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4633
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:17242355,
+FT                   ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4634
+FT                   /note="Omega-N-methylarginine"
+FT                   /evidence="ECO:0000244|PubMed:24129315"
+FT   MOD_RES         4647
+FT                   /note="Omega-N-methylarginine"
+FT                   /evidence="ECO:0000244|PubMed:24129315"
+FT   MOD_RES         4649
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:21183079"
+FT   MOD_RES         4682
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000250|UniProtKB:Q15149"
+FT   VAR_SEQ         1..242
+FT                   /note="Missing (in isoform PLEC-1H)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005040"
+FT   VAR_SEQ         1..66
+FT                   /note="MVAGMLMPLDRLRAIYEVLFREGVMVAKKDRRPRSLHPHVPGVTNLQVMRAM
+FT                   ASLKARGLVRETFA -> MSGEDSEVRPVAVAEGSSNGSSGSPSPGDTLPWNLGKTQRS
+FT                   RRSGGGSVGNGSVLDPAERAVIRIA (in isoform PLEC-0,1C, isoform
+FT                   PLEC-0,1C,2A,3A and isoform PLEC-0,1C,2A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005039"
+FT   VAR_SEQ         1..44
+FT                   /note="MVAGMLMPLDRLRAIYEVLFREGVMVAKKDRRPRSLHPHVPGVT -> MAGT
+FT                   WAAKGVFTSQREVLLERPCWLDGGCEQVRRGYLYGQLCCV (in isoform PLEC-
+FT                   1G)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005038"
+FT   VAR_SEQ         1..37
+FT                   /note="MVAGMLMPLDRLRAIYEVLFREGVMVAKKDRRPRSLH -> MSQHRLRVPEP
+FT                   EGLGSKRTSSEDNLYLAVLRASEGKK (in isoform PLEC-1A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005036"
+FT   VAR_SEQ         1..37
+FT                   /note="MVAGMLMPLDRLRAIYEVLFREGVMVAKKDRRPRSLH -> MEPSGSLFPSL
+FT                   VVVGHVVTLAAVWHWRKGHRQAKDEQ (in isoform PLEC-1B and isoform
+FT                   PLEC-1B,2A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005037"
+FT   VAR_SEQ         1..33
+FT                   /note="MVAGMLMPLDRLRAIYEVLFREGVMVAKKDRRP -> MNETVCRRKLSPSGS
+FT                   TNTLSRLRGTSVTCTKTS (in isoform PLEC-1I)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005035"
+FT   VAR_SEQ         1..28
+FT                   /note="MVAGMLMPLDRLRAIYEVLFREGVMVAK -> MAHLLTSGPPPDEQDFIQAY
+FT                   EEVREKYK (in isoform PLEC-1F)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005034"
+FT   VAR_SEQ         1..15
+FT                   /note="MVAGMLMPLDRLRAI -> MDPSRAIQHEISSLK (in isoform PLEC-
+FT                   1E and isoform PLEC-1E,2A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005033"
+FT   VAR_SEQ         1..5
+FT                   /note="MVAGM -> MKIVP (in isoform PLEC-1D and isoform PLEC-
+FT                   1D,2A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005032"
+FT   VAR_SEQ         6..180
+FT                   /note="Missing (in isoform PLEC-1D and isoform PLEC-1D,2A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005041"
+FT   VAR_SEQ         16..180
+FT                   /note="Missing (in isoform PLEC-1E and isoform PLEC-1E,2A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005042"
+FT   VAR_SEQ         29..180
+FT                   /note="Missing (in isoform PLEC-1F)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005043"
+FT   VAR_SEQ         34..180
+FT                   /note="Missing (in isoform PLEC-1I)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005044"
+FT   VAR_SEQ         38..180
+FT                   /note="Missing (in isoform PLEC-1A, isoform PLEC-1B and
+FT                   isoform PLEC-1B,2A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005045"
+FT   VAR_SEQ         45..180
+FT                   /note="Missing (in isoform PLEC-1G)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005046"
+FT   VAR_SEQ         67..180
+FT                   /note="Missing (in isoform PLEC-0,1C, isoform PLEC-0,1C,2A
+FT                   and isoform PLEC-0,1C,2A,3A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005047"
+FT   VAR_SEQ         202..206
+FT                   /note="Missing (in isoform PLEC-1, isoform PLEC-1A, isoform
+FT                   PLEC-1B, isoform PLEC-1D, isoform PLEC-1E, isoform PLEC-1G,
+FT                   isoform PLEC-1F and isoform PLEC-0,1C)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005048"
+FT   VAR_SEQ         239
+FT                   /note="E -> ERDVIRSVRLPRE (in isoform PLEC-0,1C,2A,3A)"
+FT                   /evidence="ECO:0000305"
+FT                   /id="VSP_005049"
+FT   CONFLICT        2535
+FT                   /note="A -> V (in Ref. 1; AAR95666/AAR95671/AAR95676)"
+FT                   /evidence="ECO:0000305"
+FT   HELIX           181..199
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           205..207
+FT                   /evidence="ECO:0000244|PDB:1SH5"
+FT   TURN            214..220
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           222..232
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           244..260
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           270..274
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           278..292
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           294..296
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           308..319
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   TURN            320..322
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           333..335
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           339..348
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           350..352
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           355..360
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           363..378
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           386..389
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   STRAND          390..393
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   HELIX           396..408
+FT                   /evidence="ECO:0000244|PDB:4Q57"
+FT   MOD_RES         Q9QXS1-3:21
+FT                   /note="Phosphoserine"
+FT                   /evidence="ECO:0000244|PubMed:19131326,
+FT                   ECO:0000244|PubMed:19144319, ECO:0000244|PubMed:21183079"
+FT   MOD_RES         Q9QXS1-3:26
+FT                   /note="Phosphotyrosine"
+FT                   /evidence="ECO:0000244|PubMed:17947660"
+SQ   SEQUENCE   4691 AA;  534188 MW;  91A09EC8181137D1 CRC64;
+     MVAGMLMPLD RLRAIYEVLF REGVMVAKKD RRPRSLHPHV PGVTNLQVMR AMASLKARGL
+     VRETFAWCHF YWYLTNEGID HLRQYLHLPP EIVPASLQRV RRPVAMVIPA RRRSPHVQTM
+     QGPLGCPPKR GPLPAEDPAR EERQVYRRKE REEGAPETPV VSATTVGTLA RPGPEPAPAT
+     DERDRVQKKT FTKWVNKHLI KHWRAEAQRH ISDLYEDLRD GHNLISLLEV LSGDSLPREK
+     GRMRFHKLQN VQIALDYLRH RQVKLVNIRN DDIADGNPKL TLGLIWTIIL HFQISDIQVS
+     GQSEDMTAKE KLLLWSQRMV EGYQGLRCDN FTTSWRDGRL FNAIIHRHKP MLIDMNKVYR
+     QTNLENLDQA FSVAERDLGV TRLLDPEDVD VPQPDEKSII TYVSSLYDAM PRVPGAQDGV
+     RANELQLRWQ EYRELVLLLL QWIRHHTAAF EERKFPSSFE EIEILWCQFL KFKETELPAK
+     EADKNRSKVI YQSLEGAVQA GQLKIPPGYH PLDVEKEWGK LHVAILEREK QLRSEFERLE
+     CLQRIVSKLQ MEAGLCEEQL NQADALLQSD IRLLASGKVA QRAGEVERDL DKADGMIRLL
+     FNDVQTLKDG RHPQGEQMYR RVYRLHERLV AIRTEYNLRL KAGVGAPVTQ VTLQSTQRRP
+     ELEDSTLRYL QDLLAWVEEN QRRIDSAEWG VDLPSVEAQL GSHRGMHQSI EEFRAKIERA
+     RNDESQLSPA TRGAYRDCLG RLDLQYAKLL NSSKARLRSL ESLHGFVAAA TKELMWLNEK
+     EEEEVGFDWS DRNTNMAAKK ESYSALMREL EMKEKKIKEI QNTGDRLLRE DHPARPTVES
+     FQAALQTQWS WMLQLCCCIE AHLKENTAYF QFFSDVREAE EQLQKLQETL RRKYSCDRTI
+     TVTRLEDLLQ DAQDEKEQLN EYKGHLSGLA KRAKAIVQLK PRNPAHPVRG HVPLIAVCDY
+     KQVEVTVHKG DQCQLVGPAQ PSHWKVLSGS SSEAAVPSVC FLVPPPNQEA QEAVARLEAQ
+     HQALVTLWHQ LHVDMKSLLA WQSLSRDIQL IRSWSLVTFR TLKPEEQRQA LRNLELHYQA
+     FLRDSQDAGG FGPEDRLVAE REYGSCSRHY QQLLQSLEQG EQEESRCQRC ISELKDIRLQ
+     LEACETRTVH RLRLPLDKDP ARECAQRIAE QQKAQAEVEG LGKGVARLSA EAEKVLALPE
+     PSPAAPTLRS ELELTLGKLE QVRSLSAIYL EKLKTISLVI RSTQGAEEVL KTHEEQLKEA
+     QAVPATLQEL EATKASLKKL RAQAEAQQPV FNTLRDELRG AQEVGERLQQ RHGERDVEVE
+     RWRERVTQLL ERWQAVLAQT DVRQRELEQL GRQLRYYRES ADPLSAWLQD AKRRQEQIQA
+     VPIANCQAAR EQLRQEKALL EEIERHGEKV EECQKFAKQY INAIKDYELQ LITYKAQLEP
+     VASPAKKPKV QSGSESVIQE YVDLRTRYSE LTTLTSQYIK FISETLRRME EEERLAEQQR
+     AEERERLAEV EAALEKQRQL AEAHAQAKAQ AELEAQELQR RMQEEVARRE EAAVDAQQQK
+     RSIQEELQHL RQSSEAEIQA KAQQVEAAER SRMRIEEEIR VVRLQLETTE RQRGGAEGEL
+     QALRARAEEA EAQKRQAQEE AERLRRQVQD ESQRKRQAEA ELALRVKAEA EAAREKQRAL
+     QALDELRLQA EEAERRLRQA EAERARQVQV ALETAQRSAE VELQSKRASF AEKTAQLERT
+     LQEEHVTVAQ LREEAERRAQ QQAEAERARE EAERELERWQ LKANEALRLR LQAEEVAQQK
+     SLAQADAEKQ KEEAEREARR RGKAEEQAVR QRELAEQELE KQRQLAEGTA QQRLAAEQEL
+     IRLRAETEQG EQQRQLLEEE LARLQHEATA ATQKRQELEA ELAKVRAEME VLLASKARAE
+     EESRSTSEKS KQRLEAEAGR FRELAEEAAR LRALAEEAKR QRQLAEEDAA RQRAEAERVL
+     TEKLAAISEA TRLKTEAEIA LKEKEAENER LRRLAEDEAF QRRRLEEQAA LHKADIEERL
+     AQLRKASESE LERQKGLVED TLRQRRQVEE EIMALKVSFE KAAAGKAELE LELGRIRSNA
+     EDTMRSKEQA ELEAARQRQL AAEEEQRRRE AEERVQRSLA AEEEAARQRK VALEEVERLK
+     AKVEEARRLR ERAEQESARQ LQLAQEAAQK RLQAEEKAHA FVVQQREEEL QQTLQQEQNM
+     LDRLRSEAEA ARRAAEEAEE AREQAEREAA QSRKQVEEAE RLKQSAEEQA QAQAQAQAAA
+     EKLRKEAEQE AARRAQAEQA ALKQKQAADA EMEKHKKFAE QTLRQKAQVE QELTTLRLQL
+     EETDHQKSIL DEELQRLKAE VTEAARQRSQ VEEELFSVRV QMEELGKLKA RIEAENRALI
+     LRDKDNTQRF LEEEAEKMKQ VAEEAARLSV AAQEAARLRQ LAEEDLAQQR ALAEKMLKEK
+     MQAVQEATRL KAEAELLQQQ KELAQEQARR LQEDKEQMAQ QLVEETQGFQ RTLEAERQRQ
+     LEMSAEAERL KLRMAEMSRA QARAEEDAQR FRKQAEEIGE KLHRTELATQ EKVTLVQTLE
+     IQRQQSDHDA ERLREAIAEL EREKEKLKQE AKLLQLKSEE MQTVQQEQIL QETQALQKSF
+     LSEKDSLLQR ERFIEQEKAK LEQLFQDEVA KAKQLREEQQ RQQQQMEQEK QELMASMEEA
+     RRRQREAEEG VRRKQEELQH LEQQRQQQEK LLAEENQRLR ERLQRLEEEH RAALAHSEIA
+     TTQAASTKAL PNGRDAPDGP SVEAEPEYTF EGLRQKVPAQ QLQEAGILSQ EELQRLAQGH
+     TTVAELTQRE DVYRYLKGRS SIAGLLLKPT NEKLSVYTAL QRQLLSPGTA LILLEAQAAS
+     GFLLDPVRNR RLTVNEAVKE GVVGPELHHK LLSAERAVTG YKDPYTGEQI SLFQAMKKDL
+     IVRDHGVRLL EAQIATGGII DPVHSHRVPV DVAYKRGYFD EEMNRILSDP SDDTKGFFDP
+     NTHENLTYLQ LLERCVEDPE TGLRLLPLTD KAAKGGELVY TDTEARDVFE KATVSAPFGK
+     FQGRTVTIWE IINSEYFTAE QRRDLLQQFR TGHITVEKII KIVITVVEEH ERKGQLCFEG
+     LRALVPAAEL LDSGVISHEL YQQLQRGERS VREVAEADSV RQALRGTNVI AGVWLEEAGQ
+     KLSIYEALKK DLLQPEVAVA LLEAQAGTGH IIDPATSARL TVDEAVRAGL VGPELHEKLL
+     SAEKAVTGYR DPYSGQSVSL FQALKKGLIP REQGLRLLDA QLSTGGIVDP SKSHRVPLDV
+     AYARGYLDKE TNRALTSPRD DARVYHDPST QEPVTYSQLQ QRCRSDQLTG LSLLPLSEKA
+     VRARQEEVYS ELQARETLEQ AKVEVPVGSF KGRAMTVWEL ISSEYFTEEQ RQELLRQFRT
+     GKVTVEKVIK IVITIVEEVE TRRQERLSFS GLRAPVPASE LLDAKILSRA QFDQLKDGKT
+     SVKELSEVGS VRTLLQGSGC LAGIYLEDSK EKVTIYEAMR RGLLRPSTAT LLLEAQAATG
+     FLVDPVRNQR LYVHEAVKAG VVGPELHEKL LSAEKAVTGY KDPYSGNTIS LFQAMKKGLV
+     LRDHAIRLLE AQVATGGIID PVHSHRLPVD VAYQRGYFDE EMNRVLADPS DDTKGFFDPN
+     THENLTYLQL LERCVEDPET GLRLLPLKGA EKTEVVETTQ VYTEEETRRA FEETQIDIPG
+     GGSHGGSSMS LWEVMQSNMI PEDQRARLMA DFQAGRVTKE RMIIIIIEII EKTEIIRQQN
+     LASYDYVRRR LTAEDLYEAR IISLETYNLF REGTKNLREV LEMESAWRYL YGTGAVAGVY
+     LPGSRQTLTI YQALKKGLLS AEVARLLLEA QAATGFLLDP VKGERLTVDE AVRKGLVGPE
+     LHDRLLSAER AVTGYRDPYT EQTISLFQAM KKELIPAEEA LRLLDAQLAT GGIVDPRLGF
+     HLPLEVAYQR GYLNKDTHDQ LSEPSEVRSY VDPSTDERLS YTQLLKRCRR DDPSGQMLLL
+     LSDARKLTFR GLRKQITVEE LVRSQVMDEA TALQLQEGLT SIEEVTKNLQ KFLEGTSCIA
+     GVFVDATKER LSVYQAMKKG IIRPGTAFEL LEAQAATGYV IDPIKGLKLT VEEAVRMGIV
+     GPEFKDKLLS AERAVTGYKD PYSGKLISLF QAMKKGLILK DHGIRLLEAQ IATGGIIDPE
+     ESHRLPVEVA YKRGLFDEEM NEILTDPSDD TKGFFDPNTE ENLTYLQLME RCITDPQTGL
+     CLLPLKEKKR ERKTSSKSSV RKRRVVIVDP ETGKEMSVYE AYRKGLIDHQ TYLELSEQEC
+     EWEEITISSS DGVVKSMIID RRSGRQYDID DAITKNLIDR SALDQYRAGT LSITEFADML
+     SGNAGGFRSR SSSVGSSSSY PISSAGPRTQ LASWSDPTEE TGPVAGILDT ETLEKVSITE
+     AMHRNLVDNI TGQRLLEAQA CTGGIIDPST GERFPVTEAV NKGLVDKIMV DRINLAQKAF
+     CGFEDPRTKT KMSAAQALKK GWLYYEAGQR FLEVQYLTGG LIEPDTPGRV SLDEALQRGT
+     VDARTAQKLR DVSAYSKYLT CPKTKLKISY KDALDRSMVE EGTGLRLLEA AAQSSKGYYS
+     PYSVSGSGST AGSRTGSRTG SRAGSRRGSF DATGSGFSMT FSSSSYSSSG YGRRYASGPS
+     ASLGGPESAV A
+//
diff --git a/protgraph/__init__.py b/protgraph/__init__.py
new file mode 100644
index 0000000..b72404d
--- /dev/null
+++ b/protgraph/__init__.py
@@ -0,0 +1,1 @@
+from protgraph.protgraph import main, parse_args, prot_graph  # pyflakes.ignore
diff --git a/aa_masses_annotation.py b/protgraph/aa_masses_annotation.py
similarity index 100%
rename from aa_masses_annotation.py
rename to protgraph/aa_masses_annotation.py
diff --git a/digestion.py b/protgraph/digestion.py
similarity index 88%
rename from digestion.py
rename to protgraph/digestion.py
index edd6f61..14c7dad 100644
--- a/digestion.py
+++ b/protgraph/digestion.py
@@ -63,14 +63,23 @@ def _digest_via_trypsin(graph):
     # Digest the graph into smaller parts
     # Explicitly we add ->
     trypsin_in = [
-        (__start_node__, k.target) for k in k_s_edges_remaining + r_s_edges_remaining
+        (__start_node__.index, k.target) for k in k_s_edges_remaining + r_s_edges_remaining
     ]  # edges for Nodes which should have an edge to __start__
     trypsin_out = [
-        (k.source, __end_node__) for k in k_s_edges_remaining + r_s_edges_remaining
+        (k.source, __end_node__.index) for k in k_s_edges_remaining + r_s_edges_remaining
     ]  # edges for Nodes which should have an edge to __end__
 
+    # Check if edge already exists, if so skip it:
+    remaining_edges = []
+    for x in set(trypsin_out).union(set(trypsin_in)):
+        try:
+            # Skip if found
+            graph.es.find(_between=((x[0],), (x[1],)))
+        except ValueError:
+            remaining_edges.append(x)
+
     # Add the newly created edges to the graph
-    graph.add_edges(trypsin_in + trypsin_out)
+    graph.add_edges(remaining_edges)
 
     # Return the number of cleaved edges
     return len(cleaved_idcs)
diff --git a/export/__init__.py b/protgraph/export/__init__.py
similarity index 100%
rename from export/__init__.py
rename to protgraph/export/__init__.py
diff --git a/export/abstract_exporter.py b/protgraph/export/abstract_exporter.py
similarity index 100%
rename from export/abstract_exporter.py
rename to protgraph/export/abstract_exporter.py
diff --git a/export/dot.py b/protgraph/export/dot.py
similarity index 94%
rename from export/dot.py
rename to protgraph/export/dot.py
index bad1270..1a639a0 100644
--- a/export/dot.py
+++ b/protgraph/export/dot.py
@@ -1,6 +1,6 @@
 import os
 
-from export.abstract_exporter import AExporter
+from protgraph.export.abstract_exporter import AExporter
 
 
 class Dot(AExporter):
diff --git a/export/exporters.py b/protgraph/export/exporters.py
similarity index 74%
rename from export/exporters.py
rename to protgraph/export/exporters.py
index 0765a1e..2c1ad75 100644
--- a/export/exporters.py
+++ b/protgraph/export/exporters.py
@@ -1,12 +1,13 @@
 from contextlib import ContextDecorator
 
-from export.dot import Dot
-from export.gml import GML
-from export.graphml import GraphML
-from export.pickle import Pickle
-from export.postgres import Postgres
-from export.postgres_trypper_peptides import PostgresTrypperPeptides
-from export.redisgraph import RedisGraph
+from protgraph.export.dot import Dot
+from protgraph.export.gml import GML
+from protgraph.export.graphml import GraphML
+from protgraph.export.gremlin import Gremlin
+from protgraph.export.pickle import Pickle
+from protgraph.export.postgres import Postgres
+from protgraph.export.postgres_trypper_peptides import PostgresTrypperPeptides
+from protgraph.export.redisgraph import RedisGraph
 
 
 class Exporters(ContextDecorator):
@@ -31,6 +32,8 @@ def __init__(self, **kwargs):
             self.export_classes.append(RedisGraph())
         if kwargs["export_postgres"]:
             self.export_classes.append(Postgres())
+        if kwargs["export_gremlin"]:
+            self.export_classes.append(Gremlin())
         if kwargs["export_postgres_trypper"]:
             self.export_classes.append(PostgresTrypperPeptides())
 
diff --git a/export/gml.py b/protgraph/export/gml.py
similarity index 94%
rename from export/gml.py
rename to protgraph/export/gml.py
index b6f9673..2d5a73e 100644
--- a/export/gml.py
+++ b/protgraph/export/gml.py
@@ -1,6 +1,6 @@
 import os
 
-from export.abstract_exporter import AExporter
+from protgraph.export.abstract_exporter import AExporter
 
 
 class GML(AExporter):
diff --git a/export/graphml.py b/protgraph/export/graphml.py
similarity index 95%
rename from export/graphml.py
rename to protgraph/export/graphml.py
index 81c2124..b29443f 100644
--- a/export/graphml.py
+++ b/protgraph/export/graphml.py
@@ -1,6 +1,6 @@
 import os
 
-from export.abstract_exporter import AExporter
+from protgraph.export.abstract_exporter import AExporter
 
 
 class GraphML(AExporter):
diff --git a/protgraph/export/gremlin.py b/protgraph/export/gremlin.py
new file mode 100644
index 0000000..c5ca5bd
--- /dev/null
+++ b/protgraph/export/gremlin.py
@@ -0,0 +1,84 @@
+import random
+from time import sleep
+
+from gremlin_python.driver.driver_remote_connection import \
+    DriverRemoteConnection
+from gremlin_python.process.anonymous_traversal import traversal
+from gremlin_python.statics import FloatType, LongType
+
+from protgraph.export.abstract_exporter import AExporter
+
+
+class Gremlin(AExporter):
+    """
+    A Gremlin exporter (to various databases)
+
+    NOTE: This exporter is not finisehd and may not be further developed.
+    """
+
+    def start_up(self, **kwargs):
+        # it can cause exceptions when starting all at once!
+        # This solves it currently... ( TODO why does it not allow multiple connections consistently?)
+        sleep(random.randint(1, 15))
+
+        # This generates a connection to the gremlin server
+        self.conn = DriverRemoteConnection(kwargs["gremlin_url"], kwargs["gremlin_traversal_source"], pool_size=1)
+        self.remote_graph = traversal().withRemote(self.conn)
+
+    def export(self, prot_graph):
+        try:
+            # Non Bulk approach
+            nodes = [
+                self._set_properties(self.remote_graph.addV(), list(x.attributes().items())).next()
+                for x in prot_graph.vs[:]
+            ]
+            _ = [
+                self._set_properties(
+                    self.remote_graph.addE("e").from_(nodes[x.source]).to(nodes[x.target]),
+                    list(x.attributes().items())
+                ).next()
+                for x in prot_graph.es[:]
+            ]
+
+        except Exception as e:
+            raise e
+
+        # Bulk approach, which works only partially (due to high processing time on server side!)
+        # try:
+        #     rg = self.remote_graph
+        #     for k in prot_graph.vs:
+        #         rg = self._set_properties(rg.addV(), list(k.attributes().items())).as_(str(k.index))
+        #     for k in prot_graph.es:
+        #         rg = self._set_properties(
+        #             rg.addE("e").from_(str(k.source)).to(str(k.target)),
+        #             list(k.attributes().items())
+        #         )
+        #     rg.next()
+        # except Exception as e:
+        #     raise e
+
+    def _set_properties(self, rg, prot_graph_attrs):
+        """ set the properties of nodes or edges recursively """
+        if len(prot_graph_attrs) == 0:
+            return rg
+        key, value = prot_graph_attrs.pop()
+        if key == "position" and value is None:
+            return self._set_properties(rg, prot_graph_attrs).property(key, -1)
+        if (key == "isoform_position" or key == "isoform_accession" or key == "cleaved" or key == "qualifiers") \
+           and value is None:
+            return self._set_properties(rg, prot_graph_attrs).property(key, "")
+        if key == "qualifiers":
+            # Special case, do a json dump to string
+            return self._set_properties(rg, prot_graph_attrs).property(key, "")
+        if(key == "avrg_weight" or key == "mono_weight" or key == "avrg_weight_to_end" or key == "mono_weight_to_end"):
+            # Special case for weights
+            if type(value) == int:
+                return self._set_properties(rg, prot_graph_attrs).property(key, LongType(value))
+            return self._set_properties(rg, prot_graph_attrs).property(key, FloatType(value))
+
+        return self._set_properties(rg, prot_graph_attrs).property(key, value)
+
+    def tear_down(self):
+        # Close the connection to the gremlin server
+        self.conn.close()
+        pass
diff --git a/export/pickle.py b/protgraph/export/pickle.py
similarity index 94%
rename from export/pickle.py
rename to protgraph/export/pickle.py
index 9382fad..a744d36 100644
--- a/export/pickle.py
+++ b/protgraph/export/pickle.py
@@ -1,6 +1,6 @@
 import os
 
-from export.abstract_exporter import AExporter
+from protgraph.export.abstract_exporter import AExporter
 
 
 class Pickle(AExporter):
diff --git a/export/postgres.py b/protgraph/export/postgres.py
similarity index 99%
rename from export/postgres.py
rename to protgraph/export/postgres.py
index 3bd14f5..aed626a 100644
--- a/export/postgres.py
+++ b/protgraph/export/postgres.py
@@ -4,7 +4,7 @@
 import psycopg2
 from Bio.SwissProt import FeatureLocation, FeatureTable
 
-from export.abstract_exporter import AExporter
+from protgraph.export.abstract_exporter import AExporter
 
 
 class Postgres(AExporter):
diff --git a/export/postgres_trypper_peptides.py b/protgraph/export/postgres_trypper_peptides.py
similarity index 51%
rename from export/postgres_trypper_peptides.py
rename to protgraph/export/postgres_trypper_peptides.py
index def7850..dc60112 100644
--- a/export/postgres_trypper_peptides.py
+++ b/protgraph/export/postgres_trypper_peptides.py
@@ -1,6 +1,7 @@
+import networkx
 import psycopg2
 
-from export.abstract_exporter import AExporter
+from protgraph.export.abstract_exporter import AExporter
 
 
 class PostgresTrypperPeptides(AExporter):
@@ -27,10 +28,22 @@ def start_up(self, **kwargs):
         # OFFSET +1 since we have dedicated start and end nodes!
         # The number of hops is also equal to the number of results generated by
         # the dynamic programming approach, counting the hops!
-        self.peptide_length = kwargs["postgres_trypper_hops"] + 1  # Number of hops. E.G. 2: s -> h_1 -> h_2 -> e
+        self.peptide_length = (
+            kwargs["postgres_trypper_hops"] + 1
+            if kwargs["postgres_trypper_hops"] is not None
+            else None
+        )  # Number of hops. E.G. 2: s -> h_1 -> h_2 -> e
+        if self.peptide_length is None:
+            if kwargs["postgres_use_igraph"]:
+                self.peptide_length = -1
+
         self.miscleavages = kwargs["postgres_trypper_miscleavages"]  # A filter criterion how many miscleavages?
         self.peptide_min_length = kwargs["postgres_trypper_min_pep_length"]  # Peptide minimum length
 
+        self.postgres_skip_x = kwargs["postgres_skip_x"]
+        self.postgres_no_duplicates = kwargs["postgres_no_duplicates"]
+        self.use_igraph = kwargs["postgres_use_igraph"]
+
         # Initialize connection
         try:
             self.conn = psycopg2.connect(
@@ -72,10 +85,8 @@ def _create_tables(self, **kwargs):
             cur = self.conn.cursor()
             cur.execute("""
             CREATE TABLE  if not exists peptides (
-                id BIGSERIAL,
-                accession_id INT references accessions(id),
+                id BIGSERIAL UNIQUE,
                 weight {0} NOT NULL,
-                path INT[] NOT NULL,
                 a_count SMALLINT NOT NULL,
                 b_count SMALLINT NOT NULL,
                 c_count SMALLINT NOT NULL,
@@ -99,52 +110,80 @@ def _create_tables(self, **kwargs):
                 u_count SMALLINT NOT NULL,
                 v_count SMALLINT NOT NULL,
                 w_count SMALLINT NOT NULL,
-                -- x_count SMALLINT NOT NULL,  -- SKipping X since TrypperDB does not need it
+                x_count SMALLINT NOT NULL,  -- NOT SKIPPED
                 y_count SMALLINT NOT NULL,
                 z_count SMALLINT NOT NULL,
                 n_terminus character(1) NOT NULL,
                 c_terminus character(1) NOT NULL,
-                PRIMARY KEY (id, weight)
-            );""".format("BIGINT" if kwargs["mass_dict_type"] is int else "DOUBLE PRECISION"))
+                PRIMARY KEY ({1}));""".format(
+                "BIGINT" if kwargs["mass_dict_type"] is int else "DOUBLE PRECISION",
+                """ weight, a_count, b_count, c_count, d_count, e_count, f_count, g_count,
+                h_count, i_count, j_count, k_count, l_count, m_count, n_count, o_count,
+                p_count, q_count, r_count, s_count, t_count, u_count, v_count, w_count,
+                x_count, y_count, z_count, n_terminus, c_terminus""" if self.postgres_no_duplicates else "id"
+                ))
         except Exception as e:
             print("Error createing peptides table. Continuing... (Reason: {})".format(str(e)))
         finally:
             self.conn.commit()
             cur.close()
             self.peptides_keys = [
-                "accession_id",
                 "weight",
+                "a_count", "b_count", "c_count", "d_count", "e_count", "f_count", "g_count", "h_count",
+                "i_count", "j_count", "k_count", "l_count", "m_count", "n_count", "o_count", "p_count",
+                "q_count", "r_count", "s_count", "t_count", "u_count", "v_count", "w_count", "x_count",
+                "y_count", "z_count", "n_terminus", "c_terminus"
+            ]
+        try:
+            # Create the peptides meta information (can also be extremely large)
+            cur = self.conn.cursor()
+            cur.execute("""
+            CREATE TABLE  if not exists peptides_meta (
+                id BIGSERIAL,
+                peptides_id BIGINT references peptides(id),
+                accession_id INT references accessions(id),
+                path INT[] NOT NULL,
+                miscleavages INT NOT NULL,
+                PRIMARY KEY (id)
+            );""")
+        except Exception as e:
+            print("Error createing peptides_meta table. Continuing... (Reason: {})".format(str(e)))
+        finally:
+            self.conn.commit()
+            cur.close()
+            self.peptides_meta_keys = [
+                "peptides_id",
+                "accession_id",
                 "path",
-                "a_count",
-                "b_count",
-                "c_count",
-                "d_count",
-                "e_count",
-                "f_count",
-                "g_count",
-                "h_count",
-                "i_count",
-                "j_count",
-                "k_count",
-                "l_count",
-                "m_count",
-                "n_count",
-                "o_count",
-                "p_count",
-                "q_count",
-                "r_count",
-                "s_count",
-                "t_count",
-                "u_count",
-                "v_count",
-                "w_count",
-                # "x_count",
-                "y_count",
-                "z_count",
-                "n_terminus",
-                "c_terminus"
+                "miscleavages"
             ]
 
+        # Set insert statement for peptides
+        self.statement_accession = "INSERT INTO accessions(accession) VALUES (%s) RETURNING id;"
+
+        if self.postgres_no_duplicates:
+            # Set statement, where we LOCK the table to exclude duplicates
+            self.statement_peptides = " LOCK TABLE peptides IN SHARE ROW EXCLUSIVE MODE; INSERT INTO peptides (" \
+                + ",".join(self.peptides_keys) \
+                + ") VALUES (" \
+                + ",".join(["%s"]*len(self.peptides_keys)) \
+                + ") ON CONFLICT (" \
+                + ",".join(self.peptides_keys) \
+                + ") do update set {0} = EXCLUDED.{0} ".format(self.peptides_keys[0]) \
+                + "RETURNING id;"
+        else:
+            self.statement_peptides = "INSERT INTO peptides (" \
+                + ",".join(self.peptides_keys) \
+                + ") VALUES (" \
+                + ",".join(["%s"]*len(self.peptides_keys)) \
+                + ") returning id"
+
+        self.statement_meta_peptides = "INSERT INTO peptides_meta (" \
+            + ",".join(self.peptides_meta_keys) \
+            + ") VALUES (" \
+            + ",".join(["%s"]*len(self.peptides_meta_keys)) \
+            + ")"
+
     def export(self, prot_graph):
         # Export the protein
         self._export(prot_graph)
@@ -157,11 +196,32 @@ def tear_down(self):
         except Exception as e:
             print("Connection to PostgreSQL (Trypper) could not be closed. (Reason: {})".format(str(e)))
 
+    def _get_peps(self, prot_graph, s, e):
+        """ Get peptides depending on selected method """
+        if self.use_igraph:
+            # This can consume lots of memory
+            results = prot_graph.get_all_simple_paths(
+                s.index,
+                to=e.index,
+                cutoff=self.peptide_length
+            )
+            for r in results:
+                yield r
+        else:
+            # This is a generator approach but is also considerably slower
+            netx = prot_graph.to_networkx()
+            yield from networkx.algorithms.simple_paths.all_simple_paths(
+                netx,
+                s.index,
+                e.index,
+                cutoff=self.peptide_length
+            )
+
     def _export(self, prot_graph):
         # First insert accession into accession table and retrieve its id:
         accession = prot_graph.vs[0]["accession"]
         self.cursor.execute(
-            "INSERT INTO accessions(accession) VALUES (%s) RETURNING id;",
+            self.statement_accession,
             (accession,)
         )
         accession_id = self.cursor.fetchone()[0]
@@ -170,26 +230,14 @@ def _export(self, prot_graph):
         [__start_node__] = prot_graph.vs.select(aminoacid="__start__")
         [__stop_node__] = prot_graph.vs.select(aminoacid="__end__")
 
-        # Get all simple paths (depending on how long we want them)
-        peptides = prot_graph.get_all_simple_paths(
-            __start_node__,
-            to=__stop_node__,
-            cutoff=self.peptide_length
-        )
-
-        # Now Filter and insert wanted peptides
-        statement = "INSERT INTO peptides (" \
-            + ",".join(self.peptides_keys) \
-            + ") VALUES (" \
-            + ",".join(["%s"]*len(self.peptides_keys)) \
-            + ")"
-        for pep in peptides:
+        # Iterate over all peptides
+        for pep in self._get_peps(prot_graph, __start_node__, __stop_node__):
             # Get the actual Peptide (aas)
             aas = "".join(prot_graph.vs[pep[1:-1]]["aminoacid"])
 
             # TrypperDB specific: Filter out peptides which contain 'X'
-            if "X" in aas:
-                continue  # TODO should we make this as a option?
+            if self.postgres_skip_x and "X" in aas:
+                continue  # Skip Peptides, which contain an X
 
             # Filter by Peptide Length
             if len(aas) < self.peptide_min_length:
@@ -202,29 +250,41 @@ def _export(self, prot_graph):
             else:
                 weight = -1
 
+            if "cleaved" in prot_graph.es[edge_ids[0]].attributes():
+                cleaved = sum(filter(None, prot_graph.es[edge_ids]["cleaved"]))
+            else:
+                cleaved = -1
+
             # Filter by Miscleavages
-            if self.miscleavages != -1 and "cleaved" in prot_graph.es[edge_ids[0]].attributes():
-                miscleaves = sum(filter(None, prot_graph.es[edge_ids]["cleaved"]))
-                if miscleaves > self.miscleavages:
+            if self.miscleavages != -1:
+                if cleaved > self.miscleavages:
                     continue  # Skip this entry
 
+            peptides_tup = (
+                weight,
+                # Counts of Aminoacids
+                aas.count("A"), aas.count("B"), aas.count("C"), aas.count("D"), aas.count("E"), aas.count("F"),
+                aas.count("G"), aas.count("H"), aas.count("I"), aas.count("J"), aas.count("K"), aas.count("L"),
+                aas.count("M"), aas.count("N"), aas.count("O"), aas.count("P"), aas.count("Q"), aas.count("R"),
+                aas.count("S"), aas.count("T"), aas.count("U"), aas.count("V"), aas.count("W"), aas.count("X"),
+                aas.count("Y"), aas.count("Z"),
+                # N and C Terminus
+                aas[0], aas[-1]
+            )
+
             # Insert new entry into database:
-            self.cursor.execute(
-                statement,
-                (
-                    accession_id,
-                    weight,
-                    pep,
-                    # Counts of Aminoacids
-                    aas.count("A"), aas.count("B"), aas.count("C"), aas.count("D"), aas.count("E"), aas.count("F"),
-                    aas.count("G"), aas.count("H"), aas.count("I"), aas.count("J"), aas.count("K"), aas.count("L"),
-                    aas.count("M"), aas.count("N"), aas.count("O"), aas.count("P"), aas.count("Q"), aas.count("R"),
-                    aas.count("S"), aas.count("T"), aas.count("U"), aas.count("V"), aas.count("W"),  # aas.count("X"),
-                    aas.count("Y"), aas.count("Z"),
-                    # N and C Terminus
-                    aas[0], aas[-1]
-                )  # TODO we could easily add other information (like "#of Miscleavages" or similar!)
+            self.cursor.execute(self.statement_peptides, peptides_tup)
+            peptides_id_fetched = self.cursor.fetchone()
+            peptides_id = peptides_id_fetched[0]
+
+            # Inster meta data
+            peptides_meta_tup = (
+                peptides_id,
+                accession_id,
+                pep,
+                cleaved
             )
+            self.cursor.execute(self.statement_meta_peptides, peptides_meta_tup)
 
         # Commit conenction
         self.conn.commit()
diff --git a/export/redisgraph.py b/protgraph/export/redisgraph.py
similarity index 98%
rename from export/redisgraph.py
rename to protgraph/export/redisgraph.py
index 6bcaf16..6fc1f2c 100644
--- a/export/redisgraph.py
+++ b/protgraph/export/redisgraph.py
@@ -2,7 +2,7 @@
 from Bio.SwissProt import FeatureLocation, FeatureTable
 from redisgraph import Edge, Graph, Node
 
-from export.abstract_exporter import AExporter
+from protgraph.export.abstract_exporter import AExporter
 
 
 class RedisGraph(AExporter):
diff --git a/ft_execution/__init__.py b/protgraph/ft_execution/__init__.py
similarity index 100%
rename from ft_execution/__init__.py
rename to protgraph/ft_execution/__init__.py
diff --git a/ft_execution/init_met.py b/protgraph/ft_execution/init_met.py
similarity index 72%
rename from ft_execution/init_met.py
rename to protgraph/ft_execution/init_met.py
index 333583b..df630ed 100644
--- a/ft_execution/init_met.py
+++ b/protgraph/ft_execution/init_met.py
@@ -1,9 +1,9 @@
-from unexpected_exception import UnexpectedException
+from protgraph.unexpected_exception import UnexpectedException
 
 
 def execute_init_met(graph, init_met_feature):
     """
-    This function adds ONLY edges to skip the initiator metheonine.
+    This function adds ONLY edges to skip the initiator methionine.
 
     NOTE: This transforms the graph without returning it!
 
@@ -19,7 +19,7 @@ def execute_init_met(graph, init_met_feature):
 
     # Filtering is important, since we may skip an aminoacid of an already cleaved protein
     # Depending on the set reference we need to distinguish between multiple INIT_METs for one protein
-    met_aas = _get_metheonines(graph, pos_first_aas, init_met_feature)
+    met_aas = _get_methionines(graph, pos_first_aas, init_met_feature)
 
     # Get possible features of remaining nodes
     features = [_get_qualifiers(graph, start, x) for x in met_aas]
@@ -54,12 +54,13 @@ def _get_qualifiers(graph, source_node: int, target_node: int):
         return [[]]
 
 
-def _get_metheonines(graph, pos_first_aas, init_met_feature):
-    """ Wrapper function to retrieve the metheonines, depending on reference and isoforms """
+def _get_methionines(graph, pos_first_aas, init_met_feature):
+    """ Wrapper function to retrieve the methionines, depending on reference and isoforms """
     # Check if graph has isoforms
     has_isoforms = True if "isoform_accession" in graph.vs[0].attributes() and \
         "isoform_position" in graph.vs[0].attributes() else False
 
+    _aas_set = True  # Bool to check if we were able to retrieve aminoacids from the graph
     if init_met_feature.ref is None:
         # Canonical M
         if not has_isoforms:
@@ -86,20 +87,29 @@ def _get_metheonines(graph, pos_first_aas, init_met_feature):
             graph.vs[x]["isoform_accession"] == init_met_feature.ref
         ]
     else:
-        # Unknown case
-        raise UnexpectedException(
-            accession=graph.vs[0]["accession"],
-            position=1,
-            message="Unknown Case for the feature INIT_MET. No Aminoacid found to be skipped",
-            additional_info=str(init_met_feature)
-        )
+        if init_met_feature.ref is not None and not has_isoforms:
+            print(
+                "Warning, INIT_MET could not applied on isoform {} (isoform is missing in graph)"
+                .format(init_met_feature.ref)
+            )
+            met_aas = []
+            _aas_set = False
+
+        else:
+            # Unknown case
+            raise UnexpectedException(
+                accession=graph.vs[0]["accession"],
+                position=1,
+                message="Unknown Case for the feature INIT_MET. No Aminoacid found to be skipped",
+                additional_info=str(init_met_feature)
+            )
 
     # Check if we found a M to skip, if not print a Warning, since this may be the case for
     # unreviewed entries...
-    if len(met_aas) == 0:
+    if _aas_set and len(met_aas) == 0:
         print(
-            "WARNING: Protein '{}' does not have Metheonine at the beginning, while "
-            "trying to skip it via the feature 'INIT_MET'. Skipping ..."
+            "WARNING: Protein '{}' does not have Methionine at the beginning, while "
+            "trying to skip it via the feature 'INIT_MET'. Skipping ...".format(graph.vs[0]["accession"])
         )
 
     return met_aas
diff --git a/ft_execution/signal.py b/protgraph/ft_execution/signal.py
similarity index 100%
rename from ft_execution/signal.py
rename to protgraph/ft_execution/signal.py
diff --git a/ft_execution/var_seq.py b/protgraph/ft_execution/var_seq.py
similarity index 100%
rename from ft_execution/var_seq.py
rename to protgraph/ft_execution/var_seq.py
diff --git a/ft_execution/variant.py b/protgraph/ft_execution/variant.py
similarity index 100%
rename from ft_execution/variant.py
rename to protgraph/ft_execution/variant.py
diff --git a/graph_generator.py b/protgraph/graph_generator.py
similarity index 89%
rename from graph_generator.py
rename to protgraph/graph_generator.py
index c450d34..7df7a65 100644
--- a/graph_generator.py
+++ b/protgraph/graph_generator.py
@@ -1,14 +1,16 @@
 import igraph
 
-from aa_masses_annotation import annotate_weights
-from digestion import digest
-from export.exporters import Exporters
-from ft_execution.init_met import execute_init_met
-from ft_execution.signal import execute_signal
-from ft_execution.var_seq import _get_isoforms_of_entry, execute_var_seq
-from ft_execution.variant import execute_variant
-from graph_statistics import get_statistics
-from merge_aminoacids import merge_aminoacids
+from protgraph.aa_masses_annotation import annotate_weights
+from protgraph.digestion import digest
+from protgraph.export.exporters import Exporters
+from protgraph.ft_execution.init_met import execute_init_met
+from protgraph.ft_execution.signal import execute_signal
+from protgraph.ft_execution.var_seq import (_get_isoforms_of_entry,
+                                            execute_var_seq)
+from protgraph.ft_execution.variant import execute_variant
+from protgraph.graph_statistics import get_statistics
+from protgraph.merge_aminoacids import merge_aminoacids
+from protgraph.verify_graphs import verify_graph
 
 
 def _generate_canonical_graph(sequence: str, acc: str):
@@ -123,6 +125,10 @@ def generate_graph_consumer(entry_queue, graph_queue, **kwargs):
         # Calculate statistics on the graph:
         num_nodes, num_edges, num_paths, num_paths_miscleavages, num_paths_hops = get_statistics(graph, **kwargs)
 
+        # Verify graphs if wanted:
+        if kwargs["verify_graph"]:
+            verify_graph(graph)
+
         # Persist or export graphs with speicified exporters
         graph_exporters.export_graph(graph)
 
diff --git a/graph_statistics.py b/protgraph/graph_statistics.py
similarity index 100%
rename from graph_statistics.py
rename to protgraph/graph_statistics.py
diff --git a/merge_aminoacids.py b/protgraph/merge_aminoacids.py
similarity index 100%
rename from merge_aminoacids.py
rename to protgraph/merge_aminoacids.py
diff --git a/main.py b/protgraph/protgraph.py
similarity index 83%
rename from main.py
rename to protgraph/protgraph.py
index c6c2daa..13fdf87 100644
--- a/main.py
+++ b/protgraph/protgraph.py
@@ -7,36 +7,39 @@
 
 from tqdm import tqdm
 
-from graph_generator import generate_graph_consumer
-from read_embl import read_embl
+from protgraph.graph_generator import generate_graph_consumer
+from protgraph.read_embl import read_embl
 
 
 def main():
-    """ MAIN DESCRIPTION TODO """
+    ARGS = parse_args()
+    prot_graph(ARGS)
+
 
-    graph_gen_args = parse_args()
+def prot_graph(prot_graph_args):
+    """ MAIN DESCRIPTION TODO """
 
     entry_queue = Queue(1000)  # TODO limit? or not limit
     statistics_queue = Queue()
 
     number_of_procs = \
-        cpu_count() - 1 if graph_gen_args["num_of_processes"] is None else graph_gen_args["num_of_processes"]
+        cpu_count() - 1 if prot_graph_args["num_of_processes"] is None else prot_graph_args["num_of_processes"]
 
     # Create Processes
     entry_reader = Process(
         target=read_embl,
         args=(
-            graph_gen_args["files"], graph_gen_args["num_of_entries"],
-            graph_gen_args["exclude_accessions"], entry_queue,
+            prot_graph_args["files"], prot_graph_args["num_of_entries"],
+            prot_graph_args["exclude_accessions"], entry_queue,
         )
     )
     graph_gen = [
-        Process(target=generate_graph_consumer, args=(entry_queue, statistics_queue), kwargs=graph_gen_args)
+        Process(target=generate_graph_consumer, args=(entry_queue, statistics_queue), kwargs=prot_graph_args)
         for _ in range(number_of_procs)
     ]
     main_write_thread = Thread(
         target=write_output_csv_thread,
-        args=(statistics_queue, graph_gen_args["output_csv"], graph_gen_args["num_of_entries"],)
+        args=(statistics_queue, prot_graph_args["output_csv"], prot_graph_args["num_of_entries"],)
     )
 
     # Start Processes/threads in reverse!
@@ -80,7 +83,7 @@ def check_if_file_exists(s: str):
         raise Exception("File '{}' does not exists".format(s))
 
 
-def parse_args():
+def parse_args(args=None):
     # Arguments for Parser
     parser = argparse.ArgumentParser(
         description="Graph-Generator for Proteins/Peptides and Exporter to various formats"
@@ -108,6 +111,13 @@ def parse_args():
         "The default value is 'cores - 1', since one process is reserved for reading entries"
     )
 
+    # Flag to check if generated graphs are correctly generated
+    parser.add_argument(
+        "--verify_graph", "--verify", default=False, action="store_true",
+        help="Set this flag to perform a check whether the graph was generated correctly. Here we explicitly check "
+        "for parallel edges, for DAG and other properties."
+    )
+
     # Arguments for graph generation
     parser.add_argument(
         "--skip_isoforms", "-si", default=False, action="store_true",
@@ -202,18 +212,18 @@ def parse_args():
     )
 
     parser.add_argument(
-        "--output_csv", "-o", default=os.path.join(os.path.dirname(__file__), "protein_graph_statistics.csv"),
+        "--output_csv", "-o", default=os.path.join(os.getcwd(), "protein_graph_statistics.csv"),
         type=str,
         help="Set the output file, which will contain information about the ProteinGaph (in csv) NOTE: "
         "It will write to 'protein_graph_statistics.csv' and overwrite if such a file exists. Default is "
-        "set to write it in this projects folder"
+        "set to the current working directory"
     )
 
     # Arguments for exporting
     parser.add_argument(
-        "--export_output_folder", "-eo", default=os.path.join(os.path.dirname(__file__), "exported_graphs"), type=str,
+        "--export_output_folder", "-eo", default=os.path.join(os.getcwd(), "exported_graphs"), type=str,
         help="Set the output folder to specify the dirctory of exported graphs (dot, graphml, gml) NOTE: It will "
-        "overwrite exisiting files. Default is set to export in this projects folder"
+        "overwrite exisiting files. Default is set the current working directory"
     )
     parser.add_argument(
         "--export_in_directories", "-edirs", default=False, action="store_true",
@@ -239,10 +249,7 @@ def parse_args():
     )
     parser.add_argument(
         "--export_redisgraph", "-eredisg", default=False, action="store_true",
-        help="Set this flag to export to a redis-server having the module RedisGraph."
-        "NOTE: Currently the YY_BUFFER_SIZE is set to 1MB max large queries, you "
-        "may encounter errors while adding graphs. To resolve this, you may need to build RedisGraph yourself"
-        # TODO check on https://github.com/RedisGraph/RedisGraph/issues/1486
+        help="Set this flag to export to a redis-server having the module RedisGraph loaded."
     )
     parser.add_argument(
         "--redisgraph_host", type=str, default="localhost",
@@ -310,11 +317,10 @@ def parse_args():
         help="Set the database which will be used for the postgresql server. Default: proteins"
     )
     parser.add_argument(
-        "--postgres_trypper_hops", type=int, default=9,
+        "--postgres_trypper_hops", type=int, default=None,
         help="Set the number of hops (max length of path) which should be used to get paths "
         "from a graph. NOTE: the larger the number the more memory may be needed. This depends on "
-        "the protein which currently is processed. Defaul is set to '9', since this value generates "
-        "reasonable and not too exploding numbers."
+        "the protein which currently is processed. Defaul is set to 'None', so all lengths are considered."
     )
     parser.add_argument(
         "--postgres_trypper_miscleavages", type=int, default=-1,
@@ -323,13 +329,47 @@ def parse_args():
         "those paths/peptides. If setting (default) to '-1', all results are considered. However you can limit the "
         "number of miscleavages, if needed."
     )
+    parser.add_argument(
+        "--postgres_skip_x",  default=False, action="store_true",
+        help="Set this flag to skip to skip all entries, which contain an X"
+    )
+    parser.add_argument(
+        "--postgres_no_duplicates",  default=False, action="store_true",
+        help="Set this flag to not insert duplicates into the database. "
+        "NOTE: Setting this value decreases the performance drastically"
+    )
+    parser.add_argument(
+        "--postgres_use_igraph",  default=False, action="store_true",
+        help="Set this flag to use igraph instead of netx. "
+        "NOTE: If setting this flag, the peptide generation will be considerably faster "
+        "but also consumes much more memory. Also, the igraph implementation DOES NOT go "
+        "over each single edge, so some (repeating results) may never be discovered when using "
+        "this flag."  # TODO see issue: https://github.com/igraph/python-igraph/issues/366
+    )
     parser.add_argument(
         "--postgres_trypper_min_pep_length", type=int, default=0,
         help="Set the minimum peptide length to filter out smaller existing path/peptides. "
         "Here, the actual number of aminoacid for a peptide is referenced. Default: 0"
     )
+    parser.add_argument(
+        "--export_gremlin", "-egremlin", default=False, action="store_true",
+        help="Set this flag to export the graphs via gremlin to a gremlin server."
+        "NOTE: The export is very slow, since it executes each node as a single query "
+        "(tested on JanusGraph and Apache Gremlin Server). This exporter is not well implemented and may not work. "
+        "This is due to difficulties implementing such an exporter in a global manner. "
+        "To reduce the number of errors: Try to have a stable connection to the gremlin-server and also allocate "
+        "enough resource for it, so that it can process the queries quick enough."
+    )
+    parser.add_argument(
+        "--gremlin_url", type=str, default="ws://localhost:8182/gremlin",
+        help="Set the url to the gremlin URL (no authentication). Default: 'ws://localhost:8182/gremlin'"
+    )
+    parser.add_argument(
+        "--gremlin_traversal_source", type=str, default="g",
+        help="Set the traversal source for remote. Default 'g'"
+    )
 
-    args = parser.parse_args()
+    args = parser.parse_args(args)
 
     # Graph generation arguments in dict:
     graph_gen_args = dict(
@@ -338,6 +378,8 @@ def parse_args():
         exclude_accessions=args.exclude_accessions,
         # num of parallel processes
         num_of_processes=args.num_of_processes,
+        # verify graph flag
+        verify_graph=args.verify_graph,
         # skip FTs?
         skip_isoforms=args.skip_isoforms,
         skip_variants=args.skip_variants,
@@ -386,7 +428,14 @@ def parse_args():
         postgres_trypper_database=args.postgres_trypper_database,
         postgres_trypper_hops=args.postgres_trypper_hops,
         postgres_trypper_miscleavages=args.postgres_trypper_miscleavages,
+        postgres_skip_x=args.postgres_skip_x,
+        postgres_no_duplicates=args.postgres_no_duplicates,
+        postgres_use_igraph=args.postgres_use_igraph,
         postgres_trypper_min_pep_length=args.postgres_trypper_min_pep_length,
+        # Export Gremlin (partially finished)
+        export_gremlin=args.export_gremlin,
+        gremlin_url=args.gremlin_url,
+        gremlin_traversal_source=args.gremlin_traversal_source,
     )
 
     return graph_gen_args
diff --git a/read_embl.py b/protgraph/read_embl.py
similarity index 92%
rename from read_embl.py
rename to protgraph/read_embl.py
index 8030563..6eefca9 100644
--- a/read_embl.py
+++ b/protgraph/read_embl.py
@@ -22,7 +22,7 @@ def read_embl(path_to_embls: list, num_of_entries: int, exclude_csv: str, queue)
         with open(exclude_csv) as in_f:
             # Read the contents of the csv
             csv_reader = csv.reader(in_f)
-            exclude_list = [x[0] for x in list(csv_reader)]
+            exclude_set = set(x[0] for x in list(csv_reader))
 
             for input_f in path_to_embls:
                 # For each entry: try to read it and
@@ -30,7 +30,7 @@ def read_embl(path_to_embls: list, num_of_entries: int, exclude_csv: str, queue)
                 try:
                     entries = SwissProt.parse(input_f)
                     for entry in entries:
-                        if entry.accessions[0] in exclude_list:
+                        if entry.accessions[0] in exclude_set:
                             # This effectively skips an entry at the cost to check whether to skip in EACH entry!
                             continue
                         queue.put(entry)
diff --git a/unexpected_exception.py b/protgraph/unexpected_exception.py
similarity index 100%
rename from unexpected_exception.py
rename to protgraph/unexpected_exception.py
diff --git a/protgraph/verify_graphs.py b/protgraph/verify_graphs.py
new file mode 100644
index 0000000..7a56aa8
--- /dev/null
+++ b/protgraph/verify_graphs.py
@@ -0,0 +1,24 @@
+def verify_graph(graph):
+
+    _check_dag(graph)
+
+    _check_parallel_edges(graph)
+
+
+def _check_dag(graph):
+    if not graph.is_dag:
+        print("Protein {} is not a DAG!".format(graph.vs[0]["accession"]))
+
+
+def _check_parallel_edges(graph):
+    for x in range(0, graph.vcount()):
+        k = graph.neighbors(x)
+        k_set = set(k)
+        if len(k) != len(k_set):
+            print(
+                "Protein '{}' has {} parallel edges (on Node {})".format(
+                    graph.vs[0]["accession"],
+                    len(k) - len(k_set),
+                    x
+                )
+            )
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..14c8500
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,47 @@
+from setuptools import find_packages, setup
+
+# Get Packages from Pipfile by parsing them
+lines = []
+with open("Pipfile", "r") as pipfile:
+    lines = pipfile.readlines()
+c = [idx for idx, x in enumerate(lines) if x[0] == "["]
+
+# dev packages index range
+dev_packages_sec = [x for x in c if "[dev-packages]" in lines[x]][0]
+if c.index(dev_packages_sec) + 1 == len(c):
+    dev_packages_end = len(lines)
+else:
+    dev_packages_end = c[c.index(dev_packages_sec)+1]
+
+# packages index range
+packages_sec = [x for x in c if "[packages]" in lines[x]][0]
+if c.index(packages_sec) + 1 == len(c):
+    packages_end = len(lines)
+else:
+    packages_end = c[c.index(packages_sec)+1]
+
+# retrieve the packages (except itself)
+packages = []
+for i in range(dev_packages_sec+1, dev_packages_end):
+    if lines[i] == "\n":
+        continue
+    package = lines[i].split("=")[0].strip()
+    if package != "protgraph":
+        packages.append(package)
+for i in range(packages_sec+1, packages_end):
+    if lines[i] == "\n":
+        continue
+    package = lines[i].split("=")[0].strip()
+    if package != "protgraph":
+        packages.append(package)
+
+
+setup(
+    name='protgraph',
+    version='0.0.1a0',
+    description="ProtGraph, a graph generator for proteins.",
+    python_requires=">=3.6",
+    entry_points=dict(console_scripts=['protgraph=protgraph.protgraph:main']),
+    packages=find_packages(),
+    install_requires=packages
+)
diff --git a/utilities/README.md b/utilities/README.md
new file mode 100644
index 0000000..269978c
--- /dev/null
+++ b/utilities/README.md
@@ -0,0 +1,3 @@
+# Python-Utilities
+
+This folder contains utilities, which may help to analyze the generated statistic csv, etc... TBD.
\ No newline at end of file
diff --git a/utilities/generate_exclude_csvs_by_paths.py b/utilities/generate_exclude_csvs_by_paths.py
new file mode 100644
index 0000000..c96dc30
--- /dev/null
+++ b/utilities/generate_exclude_csvs_by_paths.py
@@ -0,0 +1,100 @@
+import argparse
+import csv
+import os
+import sys
+
+import tqdm
+
+csv.field_size_limit(sys.maxsize)
+
+
+def _check_if_file_exists(s: str):
+    """ checks if a file exists. If not: raise Exception """
+    # TODO copied from prot_graph.py
+    if os.path.isfile(s):
+        return s
+    else:
+        raise Exception("File '{}' does not exists".format(s))
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Graph-Generator for Proteins/Peptides and Exporter to various formats"
+    )
+
+    # Statistics file
+    parser.add_argument(
+        "input_csv", type=_check_if_file_exists, nargs=1,
+        help="File containing the statistics output from ProtGraph (generated via '-cnp')"
+    )
+
+    # Output folder
+    parser.add_argument(
+        "--output_folder", "-o", type=str, default=os.getcwd(),
+        help="Output path for the lower and upper csv. (Default: current working directory)"
+    )
+    # threshould
+    parser.add_argument(
+        "--threhshold", "-t", type=int, default=10000000,
+        help="Threshold to distinguish entries which are lower or higher. (Default 10 000 000)"
+    )
+
+    # Number of entries in csv
+    parser.add_argument(
+        "--num_entries", "-n", type=int, default=None,
+        help="Number of entries in csv. If provided, an estimate of needed time can be reported. Default None"
+    )
+
+    return parser.parse_args()
+
+
+if __name__ == "__main__":
+    args = parse_args()
+
+    # Parameters
+    base_path = args.output_folder
+    statistics_file = args.input_csv[0]
+    amount = args.threhshold
+    num_entries = args.num_entries
+
+    # Static parameter, always the 0th and 9th entry in statistics
+    accession_entry = 0
+    paths_entry = 9
+
+    # Output files
+    lower_file = os.path.join(base_path, "lower_by_paths.csv")
+    upper_file = os.path.join(base_path, "upper_by_paths.csv")
+
+    # Open al files and sort them accordingly
+    with open(lower_file, "w") as l_in, open(upper_file, "w") as u_in, open(statistics_file, "r") as in_file:
+        # Initialize CSV writer/reader
+        l_csv_in, u_csv_in = csv.writer(l_in), csv.writer(u_in)
+        csv_in = csv.reader(in_file)
+
+        # Write header
+        l_csv_in.writerow(["Accession"])
+        u_csv_in.writerow(["Accession"])
+
+        # Skip Header
+        k = next(csv_in)
+
+        paths_sum_lower = 0
+        paths_sum_upper = 0
+        prot_count_lower = 0
+        prot_count_upper = 0
+        for row in tqdm.tqdm(csv_in, unit="rows", total=num_entries):
+            e = int(row[paths_entry])
+            if e <= amount:
+                l_csv_in.writerow([row[accession_entry]])
+                paths_sum_lower += e
+                prot_count_lower += 1
+                continue
+
+            u_csv_in.writerow([row[accession_entry]])
+            paths_sum_upper += e
+            prot_count_upper += 1
+
+        print("Sum of paths which are lower  then {} (in total {} proteins):\n\t{}"
+              .format(amount, prot_count_lower, paths_sum_lower))
+        print("Sum of paths which are higher then {} (in total {} proteins):\n\t{}"
+              .format(amount, prot_count_upper, paths_sum_upper))


Test patch:
diff --git a/.github/workflows/functional_tests.yaml b/.github/workflows/functional_tests.yaml
new file mode 100644
index 0000000..e2844fa
--- /dev/null
+++ b/.github/workflows/functional_tests.yaml
@@ -0,0 +1,35 @@
+name: Python Tests on Version 3.8
+on: [push, pull_request]
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version:
+        - '3.6' 
+        - '3.7' 
+        - '3.8' 
+        - '3.9' 
+
+    steps:
+      - name: Check out Repository
+        uses: actions/checkout@v2
+
+      - name: Setup Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: ${{ matrix.python-version }}
+
+      - name: Install pipenv
+        run: |
+          python -m pip install --upgrade pipenv wheel
+
+      - name: Install dependencies
+        run: |
+          pipenv install
+          pipenv run pip install -e .
+
+      - name: Run Complete tests
+        run: |
+          pipenv run pytest
diff --git a/tests/functional_test.py b/tests/functional_test.py
new file mode 100644
index 0000000..8f27e1b
--- /dev/null
+++ b/tests/functional_test.py
@@ -0,0 +1,93 @@
+import os
+import unittest
+
+import protgraph
+
+
+class FunctionalTest(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """ Set base Example Folder """
+        main_file_path = os.path.dirname(os.path.abspath(protgraph.__file__))
+        cls.examples_path = os.path.join(main_file_path, "..", "examples")
+        cls.example_files = [
+            os.path.abspath(os.path.join(cls.examples_path, "e_coli.dat")),
+            os.path.abspath(os.path.join(cls.examples_path, "p53_human.txt"))
+        ]
+
+    def test_minimal(self):
+        args = protgraph.parse_args([] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_skip_isoforms(self):
+        args = protgraph.parse_args(["-si"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_skip_variants(self):
+        args = protgraph.parse_args(["-sv"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_skip_met(self):
+        args = protgraph.parse_args(["-sm"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_skip_signal(self):
+        args = protgraph.parse_args(["-ss"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_digestion_skip(self):
+        args = protgraph.parse_args(["-d", "skip"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_digestion_trypsin(self):
+        args = protgraph.parse_args(["-d", "trypsin"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_digestion_full(self):
+        args = protgraph.parse_args(["-d", "full"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_no_merge(self):
+        args = protgraph.parse_args(["-nm"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_annotate_weights(self):
+        args = protgraph.parse_args(["-aawe", "-amwe"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_statistics_possibilites(self):
+        args = protgraph.parse_args(["-cnp"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_statistics_miscleavages(self):
+        args = protgraph.parse_args(["-cnpm"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_statistics_hops(self):
+        args = protgraph.parse_args(["-cnph"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_export_dot(self):
+        args = protgraph.parse_args(["-edot"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_export_graphml(self):
+        args = protgraph.parse_args(["-egraphml"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_export_gml(self):
+        args = protgraph.parse_args(["-epickle"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_export_pickel(self):
+        args = protgraph.parse_args(["-egml"] + self.example_files)
+        protgraph.prot_graph(args)
+
+    def test_issue8(self):
+        args = protgraph.parse_args(["-n", "1", os.path.join(self.examples_path, "Q9QXS1.txt")])
+        protgraph.prot_graph(args)
+
+    def test_issue13(self):
+        args = protgraph.parse_args(["-n", "1", os.path.join(self.examples_path, "F1SN05.txt")])
+        protgraph.prot_graph(args)