From df433f8c31bd5bdc503ba4afdd3ac9d99d4561cd Mon Sep 17 00:00:00 2001
From: Okke van Eck <39912605+OkkeVanEck@users.noreply.github.com>
Date: Mon, 3 Oct 2022 16:44:39 +0200
Subject: [PATCH] Develop (#34)
* Rework readme (#6)
* Renamed actions and added badges to readme
* Switched slash for dash
* Fix import structure (#10)
* Fixed import structure
* Removed pull_request target as push also seems to trigger on pull request?
* Fix visualization helpers (#13)
* Fixed bugs
* Added pull_request again as trigger for workflow
* Update build_deploy.yml
* Fix compressing core and installed pre-commit (#15)
* Pre-commit test
* Added local hook for zipping core
* Added .zip and .tar.gz autozips into core_archives folder
* Zip test
* tar.gz test
* Compressing works, only really ugly workaround for moving files
* Refered to the archives in the README
* Fix datasets (#17)
* Release v0.2a1 (#14)
* Rework readme (#6)
* Renamed actions and added badges to readme
* Switched slash for dash
* Fix import structure (#10)
* Fixed import structure
* Removed pull_request target as push also seems to trigger on pull request?
* Fix visualization helpers (#13)
* Fixed bugs
* Added pull_request again as trigger for workflow
* Deleted old log file and changed setup version
* Restructured dataset files and added package_data to setup.py, also changed max-line-length for black to 79
* New setup for loading datasets
* Added dataset inclusion
* Added archiving for datasets
* Test for matrix include (#18)
* Test for matrix include
* Added runOns variable
* Changed to a custom action
* Added inputFile
* Copied literal line
* Changed strategy order
* Check only ubuntu
* Extended matrix with all OS and extra CIBW_BUILD ENV flag
* Added default of only python 3.6 builds for 64-bit if push is not to master
* Added enter to README
* Release v0.2a2 (#20)
* Release v0.2a1 (#14)
* Rework readme (#6)
* Renamed actions and added badges to readme
* Switched slash for dash
* Fix import structure (#10)
* Fixed import structure
* Removed pull_request target as push also seems to trigger on pull request?
* Fix visualization helpers (#13)
* Fixed bugs
* Added pull_request again as trigger for workflow
* Deleted old log file and changed setup version
* Changed master trigger to release trigger
* Moved wildcard
* Moved wildcard of JMESPath
* Added dot
* Trying starts_with
* Switched arguments
* Excluded python 2.7 pypy
* New jmespath filter test
* Changed version number
* Add PyTest to repo and CI (#21)
* Added first pytest script for protein class and a script for performing local tests.
* Added pytest in CI
* Forgot -r for file
* Version of pytest with pytest at end of pipeline
* New pytest CI where pip installs local package
* Fixed tabs and added caching of python/pip environment
* Removed dot and added removal of build dirs to manage clean command
* Added cache ignores for env setup and ids for the caches
* Fixed cache IDs
* Renamed cache because GitHub does not allow for clearing caches...
* Moved python setup to be before cache loading
* Run that will install the dependencies
* Uncommented the cache-hit detection for installing dependencies
* Updated pre-commit version in hope that runner will create new cache
* Added more tests and added flake8 incompatability
* Other flake8 config try
* Reset to .flake8 file
* Downgrade of pre-commit to force dep. installation in CI
* Different pre-commit version
* Added depth_first tests
* Added depth_first_bnb tests
* Push to try and install all dependencies correctly
* Added back cache check for installing dependencies. New way of calling flake8, added class dependencies on tests
* Removed ls
* Core change test
* Core change test - new correctly
* Core archiving works
* Fixed pytest ordering and upgraded pandas version to trigger new cache
* Upgraded pandas
* Changed pandas version to 1.1.0
* Removed caching of CI and moved code to new PR
* Add CI caching for python environments (#23)
* Added first pytest script for protein class and a script for performing local tests.
* Added pytest in CI
* Forgot -r for file
* Version of pytest with pytest at end of pipeline
* New pytest CI where pip installs local package
* Fixed tabs and added caching of python/pip environment
* Removed dot and added removal of build dirs to manage clean command
* Added cache ignores for env setup and ids for the caches
* Fixed cache IDs
* Renamed cache because GitHub does not allow for clearing caches...
* Moved python setup to be before cache loading
* Run that will install the dependencies
* Uncommented the cache-hit detection for installing dependencies
* Updated pre-commit version in hope that runner will create new cache
* Added more tests and added flake8 incompatability
* Other flake8 config try
* Reset to .flake8 file
* Downgrade of pre-commit to force dep. installation in CI
* Different pre-commit version
* Added depth_first tests
* Added depth_first_bnb tests
* Push to try and install all dependencies correctly
* Added back cache check for installing dependencies. New way of calling flake8, added class dependencies on tests
* Removed ls
* Core change test
* Core change test - new correctly
* Core archiving works
* Fixed pytest ordering and upgraded pandas version to trigger new cache
* Upgraded pandas
* Changed pandas version to 1.1.0
* Dependency check
* new flake8 installation
* Flake8 action
* Added pip update flag
* Cleaned up the flake8 action usage
* Trying to install new deps
* Removed caching, only using dependencies during pytest
* Add documentation to project (#24)
* Ran the sphinx quickstart, ignored mypy on docs
* First version of docs
* Added installation instructions for python
* Finished installation page and added quickstart info (not done yet)
* Finished v1 of the quickstart guide
* Removed heterogeneous setup page and added todo for creating example
* Added manpages for the datasets and algorithms
* Added helpers and visualize documentation
* Added placeholders for the Protein properties
* Added methods of Protein to the documentation
* Small changes
* Reworked the README
* Added whitespace for enter
* Added github star and filler-logo
* Starting on logo
* Added logo
* Removed github fork banner
* Logo test
* Changed logo loading
* New test
* Trying image tag
* Trying image tag 2.0
* Trying image tag 2.0
* Trying relative link
* New size
* New logo test
* New logo try
* New logo
* Reworked logo
* Downgraded matplotlib to alllow CI pipeline
* Added edittable logo, fixed small rst things, fixed compression of cores
* Added some figures, added reference to license, added license
* Started on AminoAcid class (#28)
* Started on AminoAcid class
* Added comments in core, still bugs to sort out
* Fixed more bugs in the core when adding AminoAcid class
* Moved part of bind
* Integrated AminoAcid class and fixed Protein tests
* Mid way testing for new depth-first approach
* Added local check script and depth_first works for HPPH
* Fixed depth_first search new version
* Fixed depth_first_bnb algorithm using new system
* Fixed small core bugs, working on new logo
* Mid-way of changing bond_value structure
* Cleaned up bugs from intermediate version. Bumped versions of requirements. Introduced max_weights string for keeping track of possible future scores. Merged bond_semetry model setup with the else model setup. Fixed bug with cur_len of protein always being 1. Fixed getting the weight of a amino bond
* Bumbed python version in github workflow for matplotlib version dependency
* Bumped workflow python version to 3.9 as numpy 1.23 requires so
* Removed h_idxs from prune function. Nothing has been tested
* Fixed Protein signature for pybind build
* Setup for debugging current protein issues
* Introduced core testing code
* Finished test script for amino acids
* Started on Protein core tests
* Fixed protein test compilation
* Fixed first couple protein generation checks
* Added more debug statements for core tests
* Fixed bugs with bond checks
* Fixed generation of weighted amino maps
* Finished all protein generation test
* Added debug options in script to run core tests with gdb
* Added removal of amino tests
* Updated some pytest asserts. Added pytest and core_test asserts for score updates
* Updated reference for black in pre-commit
* Try adding core build in github actions pipeline
* Fixed local algorithm core tests
* Fixed dfs_bnb
* Fixed pybind11 change to providing protein pointers
* Added special compilation case for MacOS
* Changed minimum Python version to 3.9 as 3.11 will release soon
* Changed always build to only build python 3.9 versions
* Changed CIwheel builds to be specific instead of exlcuding based
* Leaving documentation as is and adding issue for the future
* Added more licensing references
* Added config file for rtfd to set python version to 3.9
* Temp commit to switch branch
* Update core merge (#33)
* Started on AminoAcid class
* Added comments in core, still bugs to sort out
* Fixed more bugs in the core when adding AminoAcid class
* Moved part of bind
* Integrated AminoAcid class and fixed Protein tests
* Mid way testing for new depth-first approach
* Added local check script and depth_first works for HPPH
* Fixed depth_first search new version
* Fixed depth_first_bnb algorithm using new system
* Fixed small core bugs, working on new logo
* Mid-way of changing bond_value structure
* Cleaned up bugs from intermediate version. Bumped versions of requirements. Introduced max_weights string for keeping track of possible future scores. Merged bond_semetry model setup with the else model setup. Fixed bug with cur_len of protein always being 1. Fixed getting the weight of a amino bond
* Bumbed python version in github workflow for matplotlib version dependency
* Bumped workflow python version to 3.9 as numpy 1.23 requires so
* Removed h_idxs from prune function. Nothing has been tested
* Fixed Protein signature for pybind build
* Setup for debugging current protein issues
* Introduced core testing code
* Finished test script for amino acids
* Started on Protein core tests
* Fixed protein test compilation
* Fixed first couple protein generation checks
* Added more debug statements for core tests
* Fixed bugs with bond checks
* Fixed generation of weighted amino maps
* Finished all protein generation test
* Added debug options in scriptn to run core tests with gdb
* Fixed the last_pos indexing error from place_amino. Changed the 'changed' variable to 'solutions_found'-like variable
* Solved typing issues
* Finished protein movement tests
* Added removal of amino tests
* Updated some pytest asserts. Added pytest and core_test asserts for score updates
* Updated reference for black in pre-commit
* Fixed score generation of core_test
* Fixed score update through removal
* Try adding core build in github actions pipeline
* Started on algorithm code
* Changed signature of depth_first to use pointers. Added testing code for 2d and 3d depth_first tests
* Fixed local algorithm core tests
* Fixed dfs_bnb
* Fixed pybind11 change to providing protein pointers
* Added dynamic_lookup for linking python in case of undefined symbols
* New way of setting -undefined flag
* Updated the way of passing -undefined setting for macos
* Added special compilation case for MacOS
* Saving Furo update for issue
* Changed minimum Python version to 3.9 as 3.11 will release soon
* Updated versions for wheel deployment
* Changed always build to only build python 3.9 versions
* Changed CIwheel builds to be specific instead of exlcuding based
* Leaving documentation as is and adding issue for the future
* Added more licensing references
* Added config file for rtfd to set python version to 3.9
* Removed commented code
---
.flake8 | 2 +
.githooks/compress_files.sh | 5 +-
.github/workflows/build_deploy.yml | 87 +++--
.github/workflows/matrix_includes.json | 30 +-
.gitignore | 3 -
.pre-commit-config.yaml | 7 +-
.readthedocs.yaml | 10 +
COPYING.LESSER | 165 ++++++++
README.md | 46 ++-
archives/prospr_core.tar.gz | Bin 3371 -> 4982 bytes
archives/prospr_core.zip | Bin 5942 -> 8808 bytes
archives/prospr_data.tar.gz | Bin 306917 -> 306916 bytes
archives/prospr_data.zip | Bin 314293 -> 314293 bytes
docs/Makefile | 20 +
docs/gen_logo.py | 112 ++++++
docs/make.bat | 35 ++
docs/source/_static/gen_logo.png | Bin 0 -> 40705 bytes
docs/source/_static/prospr_logo.png | Bin 0 -> 959056 bytes
docs/source/_static/prospr_logo.xcf | Bin 0 -> 52177 bytes
.../_static/quickstart_example_fold.png | Bin 0 -> 18716 bytes
.../quickstart_example_fold_no_score.png | Bin 0 -> 15408 bytes
docs/source/api.rst | 322 ++++++++++++++++
docs/source/conf.py | 63 +++
docs/source/index.rst | 35 ++
docs/source/installation.rst | 65 ++++
docs/source/license.rst | 6 +
docs/source/quickstart.rst | 361 ++++++++++++++++++
manage.sh | 51 ++-
prospr/core/core_module.cpp | 46 ++-
prospr/core/src/amino_acid.cpp | 47 +++
prospr/core/src/amino_acid.hpp | 42 ++
prospr/core/src/depth_first.cpp | 185 ++++-----
prospr/core/src/depth_first.hpp | 5 +-
prospr/core/src/depth_first_bnb.cpp | 237 +++++-------
prospr/core/src/depth_first_bnb.hpp | 7 +-
prospr/core/src/protein.cpp | 278 ++++++++++----
prospr/core/src/protein.hpp | 79 +++-
prospr/core/tests/run_tests.sh | 119 ++++++
prospr/core/tests/test_algorithms.cpp | 69 ++++
prospr/core/tests/test_amino_acid.cpp | 43 +++
prospr/core/tests/test_protein.cpp | 179 +++++++++
prospr/datasets.py | 3 +
prospr/helpers.py | 23 +-
prospr/visualize.py | 108 ++++--
pyproject.toml | 5 +-
requirements.txt | 13 +-
setup.py | 5 +-
tests/core/test_depth_first.py | 37 ++
tests/core/test_depth_first_bnb.py | 37 ++
tests/core/test_protein.py | 90 +++++
50 files changed, 2621 insertions(+), 461 deletions(-)
create mode 100644 .flake8
create mode 100644 .readthedocs.yaml
create mode 100644 COPYING.LESSER
create mode 100644 docs/Makefile
create mode 100644 docs/gen_logo.py
create mode 100644 docs/make.bat
create mode 100644 docs/source/_static/gen_logo.png
create mode 100644 docs/source/_static/prospr_logo.png
create mode 100644 docs/source/_static/prospr_logo.xcf
create mode 100644 docs/source/_static/quickstart_example_fold.png
create mode 100644 docs/source/_static/quickstart_example_fold_no_score.png
create mode 100644 docs/source/api.rst
create mode 100644 docs/source/conf.py
create mode 100644 docs/source/index.rst
create mode 100644 docs/source/installation.rst
create mode 100644 docs/source/license.rst
create mode 100644 docs/source/quickstart.rst
create mode 100644 prospr/core/src/amino_acid.cpp
create mode 100644 prospr/core/src/amino_acid.hpp
create mode 100755 prospr/core/tests/run_tests.sh
create mode 100644 prospr/core/tests/test_algorithms.cpp
create mode 100644 prospr/core/tests/test_amino_acid.cpp
create mode 100644 prospr/core/tests/test_protein.cpp
create mode 100644 tests/core/test_depth_first.py
create mode 100644 tests/core/test_depth_first_bnb.py
create mode 100644 tests/core/test_protein.py
diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..41919e2
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+extend-ignore = E203, W503
diff --git a/.githooks/compress_files.sh b/.githooks/compress_files.sh
index a1c1cc1..158e74f 100755
--- a/.githooks/compress_files.sh
+++ b/.githooks/compress_files.sh
@@ -13,8 +13,11 @@ COREDIR=prospr/core/src
DATADIR=prospr/data
+# Move into the git root.
+cd $(git rev-parse --show-toplevel)
+
# Create .zip core archive.
-zip -jrq prospr_core.zip "${COREDIR}/"
+zip -jqr prospr_core.zip "${COREDIR}/"
mv prospr_core.zip "${ARCHIVEDIR}/prospr_core.zip"
# Create .tar.gz core archive.
diff --git a/.github/workflows/build_deploy.yml b/.github/workflows/build_deploy.yml
index 6346049..5b50d01 100644
--- a/.github/workflows/build_deploy.yml
+++ b/.github/workflows/build_deploy.yml
@@ -3,14 +3,51 @@ name: CI-CD
on: push
jobs:
+ matrix_prep:
+ name: Prepare Matrix
+ runs-on: ubuntu-latest
+ outputs:
+ matrix: ${{ steps.set-matrix.outputs.matrix }}
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: nelonoel/branch-name@v1.0.1
+
+ - id: set-matrix
+ uses: JoshuaTheMiller/conditional-build-matrix@0.0.1
+ with:
+ inputFile: '.github/workflows/matrix_includes.json'
+ filter: '[?starts_with(`${{ env.BRANCH_NAME }}`, runOn)] || [?runOn == `always`]'
+
syntax_check:
- name: Check for syntax errors.
+ name: Check for syntax errors
runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Flake8 - Error on syntax errors or undefined names
+ uses: py-actions/flake8@v1.1.0
+ with:
+ args: --count --select=E9,F63,F7,F82 --show-source --statistics
+ update-pip: "true"
+
+ - name: Flake8 - Warn on everything else
+ uses: py-actions/flake8@v1.1.0
+ with:
+ args: --count --exit-zero --max-complexity=10 --statistics
+ max-line-length: 127
+ update-pip: "true"
+
+ pytest:
+ name: Pytest
+ needs: syntax_check
strategy:
matrix:
- python-version: [3.6]
+ python-version: [3.9]
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
@@ -20,60 +57,42 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- python -m pip install flake8
-
- - name: Lint with flake8
- run: |
- # Stop the build if there are Python syntax errors or undefined names
- flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- # Exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
- flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
-
- matrix_prep:
- name: Prepare Matrix
- runs-on: ubuntu-latest
- outputs:
- matrix: ${{ steps.set-matrix.outputs.matrix }}
- steps:
- - uses: actions/checkout@v2
+ python -m pip install -r requirements.txt
+ ./manage.sh build
+ python -m pip install -e .
- - uses: nelonoel/branch-name@v1.0.1
-
- - id: set-matrix
- uses: JoshuaTheMiller/conditional-build-matrix@0.0.1
- with:
- inputFile: '.github/workflows/matrix_includes.json'
- filter: '[?starts_with(`${{ env.BRANCH_NAME }}`, runOn)] || [?runOn == `always`]'
+ - name: Test with pytest
+ run: pytest
build_wheels:
name: Build wheels
- needs: [syntax_check, matrix_prep]
+ needs: [pytest, matrix_prep]
strategy:
matrix: ${{ fromJson(needs.matrix_prep.outputs.matrix) }}
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v2
- name: Build wheels
- uses: joerick/cibuildwheel@v1.10.0
+ uses: pypa/cibuildwheel@v2.10.1
env:
CIBW_BUILD: ${{ matrix.cibw_build }}
CIBW_SKIP: ${{ matrix.cibw_skip }}
- CIBW_PROJECT_REQUIRES_PYTHON: ">=3.6"
+ CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9"
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
path: ./wheelhouse/*.whl
build_sdist:
name: Build source distribution
- needs: syntax_check
+ needs: pytest
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v2
@@ -87,7 +106,7 @@ jobs:
- name: Check metadata
run: twine check dist/*
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
path: dist/*.tar.gz
diff --git a/.github/workflows/matrix_includes.json b/.github/workflows/matrix_includes.json
index e35b895..06f5492 100644
--- a/.github/workflows/matrix_includes.json
+++ b/.github/workflows/matrix_includes.json
@@ -2,55 +2,55 @@
{
"runOn": "master",
"os": "ubuntu-latest",
- "cibw_skip": "cp27-* cp35-* *-win32 pp27-*",
- "cibw_build": ""
+ "cibw_skip": "",
+ "cibw_build": "cp39-* cp310-* cp311-* pp37-* pp38-* pp39-*"
},
{
"runOn": "master",
"os": "windows-latest",
- "cibw_skip": "cp27-* cp35-* *-win32 pp27-*",
- "cibw_build": ""
+ "cibw_skip": "",
+ "cibw_build": "cp39-* cp310-* cp311-* pp37-* pp38-* pp39-*"
},
{
"runOn": "master",
"os": "macos-latest",
- "cibw_skip": "cp27-* cp35-* *-win32 pp27-*",
- "cibw_build": ""
+ "cibw_skip": "",
+ "cibw_build": "cp39-* cp310-* cp311-* pp37-* pp38-* pp39-*"
},
{
"runOn": "release-",
"os": "ubuntu-latest",
- "cibw_skip": "cp27-* cp35-* *-win32 pp27-*",
- "cibw_build": ""
+ "cibw_skip": "",
+ "cibw_build": "cp39-* cp310-* cp311-* pp37-* pp38-* pp39-*"
},
{
"runOn": "release-",
"os": "windows-latest",
- "cibw_skip": "cp27-* cp35-* *-win32 pp27-*",
- "cibw_build": ""
+ "cibw_skip": "",
+ "cibw_build": "cp39-* cp310-* cp311-* pp37-* pp38-* pp39-*"
},
{
"runOn": "release-",
"os": "macos-latest",
- "cibw_skip": "cp27-* cp35-* *-win32 pp27-*",
- "cibw_build": ""
+ "cibw_skip": "",
+ "cibw_build": "cp39-* cp310-* cp311-* pp37-* pp38-* pp39-*"
},
{
"runOn": "always",
"os": "ubuntu-latest",
"cibw_skip": "",
- "cibw_build": "cp36-manylinux_x86_64"
+ "cibw_build": "cp39-manylinux_x86_64"
},
{
"runOn": "always",
"os": "windows-latest",
"cibw_skip": "",
- "cibw_build": "cp36-win_amd64"
+ "cibw_build": "cp39-win_amd64"
},
{
"runOn": "always",
"os": "macos-latest",
"cibw_skip": "",
- "cibw_build": "cp36-macosx_x86_64"
+ "cibw_build": "cp39-macosx_x86_64"
}
]
diff --git a/.gitignore b/.gitignore
index 2ddd649..23764d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,9 +3,6 @@
# ================
# PROJECT IGNORES.
# ================
-# Ignore test files.
-*test.py
-
# Ignore core compiled Python files.
prospr/core/**/*.py
!prospr/core/**/__init__.py
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 65573f4..c60fbab 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -10,6 +10,7 @@ repos:
rev: v3.2.0
hooks:
- id: trailing-whitespace
+ exclude: README.md
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
@@ -22,14 +23,16 @@ repos:
rev: v0.812
hooks:
- id: mypy
+ exclude: ^docs/
- repo: https://github.com/psf/black
- rev: 20.8b1
+ rev: 22.8.0
hooks:
- id: black
- language_version: python3.8
+ language_version: python3.10
- repo: local
hooks:
- id: compress-files
name: compress-files
+ pass_filenames: false
entry: ./.githooks/compress_files.sh
language: script
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..7e02fdf
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,10 @@
+version: 2
+
+build:
+ os: "ubuntu-20.04"
+ tools:
+ python: "3.10"
+
+# Build from the docs/ directory with Sphinx
+sphinx:
+ configuration: docs/source/conf.py
diff --git a/COPYING.LESSER b/COPYING.LESSER
new file mode 100644
index 0000000..0a04128
--- /dev/null
+++ b/COPYING.LESSER
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ +
+ ![GitHub](https://img.shields.io/github/license/OkkeVanEck/prospr) ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/OkkeVanEck/prospr?include_prereleases) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/OkkeVanEck/prospr/CI-CD/master) +[![Documentation Status](https://readthedocs.org/projects/prospr/badge/?version=latest)](https://prospr.readthedocs.io/en/latest/?badge=latest) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) **Creator:** Okke van Eck -This project is a universal toolbox for protein structure prediction within the HP-model. -It will contain a datastructure for creating own algorithms, pre-created algorithms, datasets and visualization functions. -Besides folding proteins, this package will also make it possible to determine the relative hardness of a protein for an algorithm. -This allows for a fair comparison across the different algorithms. +Prospr is a universal toolbox for protein structure prediction within the +HP-model. +At the core, Prospr offers an easy-to-use Protein data structure, which can be +used to simulate protein folding. +It also offers algorithms, datasets and visualization functions. +The Protein data structure tracks many properties when folding the protein. +This includes tracking the number of conformation changes, which makes it +possible to determine the relative hardness of a protein for a specific +algorithm. +This allows for a fair comparison between different algorithms. So far, only square lattices are supported in n-dimensions. -The amino acids can only be placed in the corners of the squares and have to be one unit away from the previously placed amino acid. +The amino acids can only be placed in the corners of the squares and have to be +one unit distance away from the previously placed amino acid. + +The Python package is based on a C++ core, which gives Prospr its high +performance. +The C++ core is made available as a separate zip file to facilitate +high-performance computing applications. +See the C++ core section below for direct links to the core. -## Installation guide +## Installation and documentation This package can simply be installed via pip by running: ```bash pip install prospr ``` +A quickstart and reference documentation can be found at +[prospr.readthedocs.io](https://prospr.readthedocs.io). +The PDF version of the complete documentation can be found +[here](https://prospr.readthedocs.io/_/downloads/en/latest/pdf/). ## Archives All the C++ core files and datasets are also available as compressed archives. @@ -33,15 +55,11 @@ The complete collection of datasets is available as a compressed archive in the `archives` folder. It is available as a [.zip](archives/prospr_data.zip) and a [.tar.tz](archives/prospr_data.tar.gz) archive. -## Example usage -*Work in progress* - ## Future work -This toolbox could be used for other protein folding problems within discrete models. -It would be a great extension to support different models by creating a modular amino acid. - -## Changelog -*Work in progress* +This toolbox could be used for other protein folding problems within discrete +models. +It would be a great extension to support different models by creating a modular +amino acid. ## License The used license is the GNU LESSER GENERAL PUBLIC LICENSE. diff --git a/archives/prospr_core.tar.gz b/archives/prospr_core.tar.gz index fa1537b598557b82f0412b69dc7aec86d00c96b1..e14ce6923d822855b7607877fed02f152998a2e4 100644 GIT binary patch literal 4982 zcmb7{)n5|;qlUo&qj7YHlrYC&5~D#$0SS>VX$0vU3P^Vjq(;Z+mXJCSI;J5txhYf8}C$O-`&@`B{Xo zK_T(o@mU5Fq1M-WJHrhMuU3P60as?8A5J|7&TYOxJP`EfKbTdExh$uA1MBjh9U#wt zTnO6>Xhh7+9)@N|ZM|*lj-wrorkVL`8e-?KRlE0k2eBsFAQP&5q?t$itO>neb0_+y zPK0htF*3qQ&xLM>t=@X#BOEjY+eX|j$a|QAe=$yQs5y$oKZu4i;&JY-Eb0j1s6sA^GZl}34>M9Vf zndyv8(~>M)42JX_&8=`YwEFnsFAdbO)9mB<{8vGiOdw8Z&KCf@vuG;^k*I2@^%tB6 z;}PSNc4oyQkk{Pq>^TEcV}$& wLUA%|n8)+UP?9fyqUF!~%^J(C)`BdnH~3C%(ni;# z;#2sJ0=NOlMhFdP3BfhFp^QH;;YZGKg^W-uQ?gJwZ{+P912mVE2-#vF?ueOXbS#}Z z>ql5;_ >AO~>f= p-cq*O 1w%)UlEM=vELL(7&TNGO4nAN zPdPP#m<7iBO05eu$H-#W^r{Ek@A~b2{Se^Jrp_@N{zqr?PL!XZeUv-Z#fl`CTd7C1 z&icMHr>UW$wS!nR67U8ZWRW!UiG;1QWlz%A`O62A*clAuCtT+UtJU{ >a z{Co#NCj|K8^|Bz?c4Xk`qEi<1gcb@{*n%8Pe>ofM-FIs1utz3iN-nhHXLd4h+KGEg z!SkZOUXl53s>w0LXZP>p5ki-8E?^yH8AV8pLG@yJ;K$!!OZ@@mtdMiEh<02)x;9=f zP+qu?+odn*NxzzfEw|}$J*l_otH+51GLZsrpwWiD#%LRD0ER4aW9I2NoejOF1YnDm z1H+_5*xAtw2l3u=FlUN<24Z(zzR>qXl(-wzKd{?_yR(iMG?$w$+e0!5!=^W@nJXtY zsORyTXbsOc{{0Kn^(K^d>Nbw!Poaz^G_$;vf)jE{d<7N9ZZa0c3%GKqO}k v+H$|8mIo=(M}l^bBoB zy=Wmf!nlkDAI8pS #qyxP+U)-(Egwx7};wu@N%(Fs$W}&25}? zb7Mv3PZ}w@7=-A_ y78di&L)DkID0y% zw(b&@TQaOGNAZNVbNI@~PEM`4E2Q}1Er&VG$~Oug&am~ be2%x=IQ8VAwETE*Xky5|KY>aNSs$*HmzW+|fN(erQqw&ujp=Ip?{CXJ`>T z@D9?xHWNS+^Ttw?l_gZjgxznT7Gk#~uErETqu<(mBlJ9^-XxQ?e%K!R-E+W25%c(z zbXOo@ZS|&sS(aDq`e8Wjaf`TorZ>0|Yl_Q3$leNZ>8GaxYjY`*AlM!sq*kofQNVxU z%MVzuB7(|El07U;FuGTpJGw1j{jMZB_ch+A2hCbBGqI+M6pXt>(>xjt5km1@>_m`Q z*v}2)n~d&3OxSSkV;Z==qYBhjVtU>6g=J-BTq%q+VyivvbhLMq4O1*Y1sfPZ)$=W# zPQF_A6L1x#k3WXK#|J*#;F#aBmT|X$NDoNMO~= SJ-Z3R9)e9xbsyRXzi-nGNv7JVVz*&(*Y53fu?=#8bJ!peOJEW#xn)VkQ@n#o^uz zl|UrmhX48rIT)0?wQ;_knRI Rv?;8b^nGXEvJ57Z`exLGkLSWz{)WAtjpffxV_QxlKQohbs)}8RS^#$cBFjcxy=~ z`4`_=^finCy0%81lLDXEWcl;(hu_UWFE|u|Twio1?pDR (7ZKw33Fv6h$qVie^s7=J&p*12!+8KI 1|ulPYI0WG?d}z z#|o4V_-qs@^e)(&RMkqLt%!QSa%aGD2DU_>;3d}Qgw}C5f`^6qdzakn@QI}9uAT92 zG(e8X o^6ze5-x2J?J zrlcA=qz4+(b`k*YR+bZig`GnQua+EI(c4{>APUO}Mlutb_w6|UA}pp2MfjVh_~et* zd5sJLoOpj}Tg$n63&N73sM?xIV_^uS(}!W(=p3h_C@dr=fL?VJM~aW%YC@53KGqF0 zTy&(xb+V)=FnXK$V6zYRo*{(y7O~9eVV^d|6Elh~msnMgw%kab_ZKn>667joC;KHN zeu0|S)EC^AD1($c`G~EwN`=mo0YzZ@x2_kJn7Ps4y9-a;N{Q|Gz_0)4z fcVl$q7w=j3#(d#O$E#fR;`}EJHJCarnKP{Qzq(pfgH2X zBd&{5@WqzD0!u$KdBQcN^YOFig$sy< @7jQy~*6neLead=`qkjya2VyuoMLd9FU#r~nX~;6A z3shJop3OOTNQXdB*c|O!jJ#@oetA#cgeJ%~iwQp=^xxXYw;%VUG+9_}TwbQ`^JZ<3 zg4TX<`-|=k3~4@AhAG$dn#CnfdyIqiUGzt2{&lI8v3a$6%r=Cb?%qNUK0CTtXj NkiPzwmA8-9FWMslIF|}- zo19?pG@~kFRrjVv|G{)j-j3SBV^r*s4OMND6bhku=Wo>8#pz?T)3&DUWQ0YN>xqSl z%@nkofogKou&0@-Nktc8a0 Kx_9utUmj1Y?)Z9w0Z66D?8; z@rpTIor%UhALT%@gXk|6(*`8%#=_2G?w!L1v zx?Wj>D5us>#6!T=A|cM;UAatb`FmQ7UL z0I<0VHl+CHaXYGqJ9-9F|D2`v_x1)<37mL-zzto+eM0C0q%T0C&3oJY6z0>=k%Skg z^9tsLx&y(BscfG!2{zxQuo1oF!4@aMhZ}U_S~R~h*=H%ixvkbQFXQHg7O+yq6IA5T zEoyKU7W5o7eb!^Q f*yG@b?)90d> z=7RQlauBZ>;76uvMyi&eBSg5+gvFqi2rR{$yf`MIo}hZdbh<1Q@Sm7L8Aq6mldlV~ zYV-`oLc>IC4;RVrjMy1ZlD3fBS^D>2SJ?^Dr7#0XY_lXkSZ@|bkS&*|4Z($>yJ61V z6S!BLX(atQY}To Jz^7 Wezp{w0*0(=1PelHYHlt4Ea@>Ml^ zAnTA;kBGqVJP=~v*NNsuaItFHa7};EYtM22@bkX^OO}QMr;<87)WMa?UmYYl&-6?U zcP%J<76To)!CdKzIDW(I3Oo9N{;*G$U{Ici&cUD4kx~jCXiund*tc87v|jJ%HW??n z 1n()I0~xmU9~8-Mz%Z9ibrAqP&8D3ONCvp~Jdk%ytWR?bJz4 zhr)h=v+7p`9C5I~Ykq)}3ucbt9$ARYpAxaZypk@H3O*4?)6-_{H rZSoBK5?zOAMOJ<$8?TOLJlPN5Vh zI62EX3d1Y81(zs(rDKxdz-%fo-TriG>6?qwp~O5-`ZED&$x}cfVjq4VB_uZZ1)Hbf ztm{Z{!KOPF%Ac04{)tvZaDh+YuWa6R?TN>6odu}fZa)|e%rY7upI3JsWAl|z^_`b0 zcFhO_64(cbDhulq2N-(e%8rKeCMop>>kCgY!B*L<>3IUWT{NDH|Ae*SqQ&u} eFnFfF_+#vxar%vlD4hpe;6!hXYBnyYOqh;Zop05lA*1q z EF$Q&}#l#V7ExMoN1q)evhAn$7b17ukp zM$fWzdk*%{m^dA0*JQ%1CXN%blf|#9U+?!6M!hbdYgfqVMZ|4vTmLj7QOtaa2!HRb z>#%lY-e2levQMl8`1F+v@cQ2u=^4A3C(exR3Qey?UkCDKJ!{2u=_zz6Zi>pA5?RbW z50K@*7b)X1`nh}LQcVp~T$W-b@jQD23;jNYjv%jL%Po{QZE2W(5GEK2KXK6@jv$1J z7ch)`faZuGt%w(cU4n`(HwSM}r_p<~74=hTg9jsvr=rkxp%`apLTGuNDDP7i`rH+% zmW?V^OgQofFTm8U*n%wd7J;dRE7;d*RqboIdJX9R6MhkkImj`}I8d*(+0X bL zCa7Y{OulJeCW6-iyiwwuqZ<$7aW0BrTnNd{-17OQwX&=Z8h`%O(!|>7J2Bm^AsOzQ zpGPI=aoaGzfJFqQe96d}IBsC` (088T(%7)~JBj5~%IA z{$x(vY!i^QVny;$InMM!*!~xKN|xO8wpx{PP>vGWrxc#jK6|u+5giIx;mSAG9Gd`- z_(wp=?>E%=OSIA?AVZwwjkI@=KTA*#kDP$Hj}-10CSri|H2{PyjS8ff_IeAfCcd3( zLE#^P3^a0wL)J~8SFeJy3DXaduLGhn vWY%XuF3;UUG9v1v}Mm(&XFepj=@Pv zC0M&$cogKVa~9iT=A$sk!I#UV+bpV-V$eq8->bv`vxm>)^~PU?57o3?9WTNFjumcL z&$iH@nxP?M&{^w>p~oK4&cNIVE?k;`9%bxH)ZJTD-cc&bP$%We=AzdI^tc8Xex3{X z%qcE>C~A?oaXW)TA{Plr^1uivSPSz@Tqmy(CoS=`rtL_8Hq84hJLJh+U=v$Yu-6No z#?GxNTNb8p>>+t>@N)Eh_B6}%Q!{jz*OnfBv?9Mmm|UfC!t;QM&T=sDRxh}g8m{>l zVIV<9^=U=fiHx6iynjA)kpN1WPHjhF^qMrTh>&}$C?$eGf4Z}m`6@@dU3>SB^yE=P z1rfm$X@1Ehc87n9Af$KP~dwe#=L#Yoo8 zLSOV%`0o{e ?ev 1mhM3%su)?Kpdiu*0I)oxY_1poPEwCaG$Pln^yPCk~4HK-!Y+C6?g) zD&jkmiO(v34-Y_N9N(+>n=41+`P<@e{y<{ObVzu(gW&)R4}ZwuFgeNx7+sA GH UO{n7&e{E 5>7c$ zIU=^Yrp~qkjsoTevKLvhNrfx1$|LKSYT3#a9sWU|1t-Bb#VM{X1(GmAXvBwq24=Y! z7{V}I(4ZNO)h??Af>G+LKxR~*D#xVnrGYSM4y@WfwE%{CTK^Rl=BN8c(#u47C>~=C zmJy(TwV{POb2keRwo~H%hZwctd7glTxBdvIX<3RdlcX>{(qL3CzQykm{)W^6Hy_Cy z6_3ogqunJaKWK=I&79G0ivR+@9#7QI2Cl|4h^o1396y*hqeg4c#cZQrDCR}iDW^gK zV^qez)0jcQOs5+M&f^JzJlDy#vr3&MJBQ#=Oa#)e_$cCRpX>p`HaRy8Ut|lHw2+$) zDSzHK$JRk}A9d{zTw$+`;ev001(rf`!$uvQk&p?X0!+g%(M}GWukk*g?;72y^=r;w zk6&-dkTGrk!1hOLfkr3YQQ77C6eKJ(!!G->D(sukX}FWJP?%pU&upYc7x-t1*$Y7c z_o)q`y}$`hd1N+O#_&_4(y`@k1oCvPbBB!qe zS_n?ag3?V)^j-mqah6mah%SY=?x=V>QhieOdY>L5H|@Mv&sE@Rq(+M^G6{1`Dy4{n zO+)3T&(m2a`JlvW`}&C7-p!Katx+QAV)3Y{h8Z<0HzA?Nj1nq%sNe^fav3hFQxO($ zIM8K+!lk}^m&j`bp**8X5dccpq!K**QiWcq>?O`*Xgii*9#?7+$2Xi;hbhhsQ^%em zplfi`&7GJ{3Ip4WO+Pvp%+V&+q*8lGNp5;6KMh~%OC0= *;b637+-ATd3^$pD%xJZGo$AnG~aqtf(n3NLqzu zo} ^5%08O#URg!|uAdY}#6PtA;dVJ-C>R8# ze8U*R%iPpxtE)ho^V4QS6Gb`y<*d~QhZH#jC&)O@>8J`qwmkxz+OU%&?;&eM&s&~K z;*ziMFxd2uqjYLRJeHooKRWT~hsUt-gPYY@@6Axq!W+Ac_HLkv%>^%MTz5OHI;or< z`Z=U92cRU5X#oT7{~fR-DwDWJo^(9U?2=V5^MXk9Cbg$kaOj<*3bBs5I`W$nVY5rE z>IquJ cOgkF}tFq$kv+^npF8J8v zx`%SO*LNElm;$9r&?|va;;$z>jLa Ih#IbZ-1#*o;o@ 6qU-tOu;M;7B!FQEtu{g7dY&YN8NVd{0`TkWJZ}o#b8(d5 z1i0xlb_XulA+CnxRqo5=lj+F@!8vf4c;Wz9*?g;@$1Y#USp|zYmmiDjqi2(j3L{Lv zlhrl4gwFo2;LCIdR3ze`4q@H9jru1&&GJ@VEjD#g4*aSmlS0v}@>gRthgH=N+h=fh zozpWi|0RZe#WO-Sgy)WyF-NUb%Y6XcRF5fsf!LFj` x(nj#aNHLN~?niE+*sbC1 zE|u-)wpp3~j-Z~z^wn&{veTt5d& ;9Go|0QX)DIWDtExvOnfE(@VhLHr%s zy%+|Em8TEWNXLdupES~F(1A21m{Q@d3!S%1c}gtL7`(h2|0~?S5)d-+ww(DgT_=;J z)Q+3w+FLk)_>Mi;-CR!DJX11;pU!MUmD6WYN>`?wnJzbdaj&2bvlDy=eu^&sw3$E$ z-7%j7Unwx~o_zXCowCP=?(D`i5mCYhB7z?4SXUq9rdMa}GYgFy&8jmbe}&l1$x1Pc zZM`N+n#Hhv7ZCRDoaoaS)gSp6ZAi43P;C2FMaELcju^-wpW=`|-+b0fCDP;9{lnOg z*?}UWX236+0yNxWFyb$h6P&$~2NQHMRr`~W1Kr!Zk;}+0K;;V8cNvfF+J%g$?Oc5r z#ylX$?9`${?W?YAe3!svHB^5vOZ!&9n(!5_l}eAKqSb^p*;qa*r?)<7l=!Zkm@Ws3 z#Rl(WY$e|jEHzLHwLyl4aTWRa?{Er7akP!pY2gM!Poy0%`)>^2mvKwK F(FI+g}JUOC3 z?#q}uRC`_9GhXlMP%OreV~V)8aF2@D;F!2M3md>@4Tl_9cw;xFH$U3re|v+wZel%u z#O4ZYzwUz}IaEd?I~0krRLxjwUZl(at3P;p@Xg+o1}SA+U~_#`t&kxsyxsygo$0>@ zWW71V{Ybtc(WFRy0Uc7b85T=)eWB>D2m)2Vq+kENwr?dP3i&jC%kJYJ zrtBAcr0We_t-tV6wG)`>yTFwEMVP40K!fXdaj*e{efTGoVUDdg$EaS5OIel?QUrKm zl9KQ xqGOQc*hu2 m3Y?WcFZtVt{65dIB(gE`0S1D0oM4TR^&_@aXDECI$i?#Pl2sCr za` sJO;(qFhP{%!A9245)-Lg^eqq$@Vge8G#(Dg>yMY@dRcY z40$CFaa(w(cb`vzJ&G9^B<4im0#0nvN_yV^1RB^?2mY%Iyj^yL(#u~8>^RIj(eZR( zDg!iMsmf`8(^2>#3NNXvm=zh $5w@Qz!6~86Bxyso!LOK+ z{+p`n55N7YhVNxuaVQy9^U*2Fe+9)%hUIHG-gPu%e^7fx3J?ooQv8`9S>eWemd-rp zv!V`qf7Aaq)?bPN{{HR81n;})Kg%T&7&)uFq1vxa!~uc6ZQ+%}tc;11lnhB!9MGVD zyS<4-&{rQi$(QK(CbM3jUvZNQAle4^?jUxS1O#)}E*ytu?kN(%cekHlm&_FgO2R7a z4FuIZ>1PLgGnJf6TCo9uLaF|M*3C86y0#01lwy?lZa9qqAn)J+@Ty$htXW+u^^qb* z@wZ?tAsu`^YVhWD25~7%4iEYsc>^acl{*7UGFa4Uf>|(*d2kG= PGhJ%|^RDHxC}0Pzw5Bt|-(Kxcay~ zkXQ#6_qVx7Y1$?wR RJkXS5x$h zDgVB)8NnM8GmL)@mJR*fVKVd;bxK@3;qL5)?$3>IsWV@*)$tvLjexHLz2~sRZrHJ3 z60wm}j%irKIB8JjoZtSs%c=6Ypg0dIQFXMbus;_zs2o|SR`gSqJxO`2@8W~Xf!r?W zCzTlBk6#c=Ie%}YG~Y}MflD6;ugb9mh3}h>g}Da}XEExex}cCqvyA^75RijirzU$L zd&RG&j+aQJSfP9_XH0Di8)Y;VBLq$g9G7pq98`hHE<`ZCO>0rsw8JW5Gfc5@UYU{) z|F+Zx+ecVyQoMB8z3iNOu`CiF -w1ggBYSI*fnlQy{u84{>Ir`n>91_eq=`l-p3h+aK2%OH? !(1 zz|XKONx$=7;3i{Yq012~>fRX@J*-C;5nYo|S_E>3+w%qce2vaJ=Vl~F|2FZ$M?o8) z*rS)gNR`AU3#Bw$KJdaRdvIGAaL)blTw@?v;UZ}(ANeKH4r6kyugG`|6h?E`nnk@` zxJQJP4N>@;B+RTBu~Cs-$z7M(0lAAvcZR*fRW{AnLIpk({ak()Xu{Msh`_tB<8u+T ze+kGp9a!cD`#`!g{;0B<#RMN+5>#Z?YLnSH27FF}gOUm5m}|o|7>H1jcWeZwCP_{L zV{rsc)U_O6@!P)p9^++A!eFJ$uRgpyS9G>)%VlQL&kXSR7Q FeCUQN3I?H7g*v1|BL7jBB%G7r2J>?SNY#Aa=h!Zho1U;ZbyIeS zt?i}{#)=h@2C5Cg_39q2{)rWkr*I kW~kCc)2T zd9MB7tFLb?WLqN{ON2vt&LOW!VPT{b4wDeOJ=!jos>36?ko_M#5Gp&Iu@p&wlb?jD zOlsLg$#{Ose^g*UUtJ1PLTDBEb3zuuFj(E%xezC-Qyt+kQ5k{Uk+jax3 vV7Tndi2T_`cx8~tO@F7rG(`-1B}Ny9S9v7D 45 zBTsO@znETO`Q})Kp;3wH20h%fWoAogWf8-3smilTHmz{ARji-TFXt6kpMGh75kbtr z4Uw!Y@$0#*k4?X& L%hJ~t*5_ I> zi+(*Ilf(4DnT52f3>NOv*RwmLAb9-sCxc)SYc=5IIPl3mxK$38dsQ$Kp8>Jc;pb{q zjnH}Pi=NpZInq>SDpA6Ebn@nOmo}&HvqF44>*|3rc=X`22A lP3}ocYN4b*$mp2 hngIJE2Vo78Jpwlw)#|a(xssBM zEWf6tHjVp|E9B!5AoLrFE*(Xqn{=Y{U d}v_*Cion+7@5dv*rx)qPx{<_A$2 zQkwVf^~=RV`*F#z!2z|TpULt&0(YDW2;`BE hh@gR z-`irdq^5L-LUnq`B-e{RaFe-xkq(7io-UlS@X!iO0Kg_;0TlYL14!uaXiqgYamV%@ zeBI%C!66G9JP}(A48XP8)L&7YRur(;2a dXTD*&hHbb@0qH*52;S_Y#Nm zr5~Eumer|zH0sXGH-5eMih(XlEgEdW;|-yWC6Oj?@rc_K6yD;@?mS{@5fwl~^m*{I zUMQY6*_m#fRB^Ja4}?6^#jLuZ^RY*RQGlsY7|pCukRwKc!lClyK){HC$^cet%R|7i zpseJ)37h2Lu<0)`#=VGd$?f>$car@8T+hNA5FST++W#pxec}RdvU&DH0!2h!u?4F= zF5|f6rcEFQq3uza--l KSLM9^!BW~Bi` z*7s=K*dR!Lt;2~m9To5DhHFHtDwj6r!_W7!>Nh^`R`a9)f13B@VJ8vH5?zYV_QTag zPsBCJN)6b_Qs1{StLF%@N5Q?t@@DNxLa6%jfz`E+_lw}^?5qP5k6$;gg>yB2sEqLy zd+P(b*A&IokKG1o6%AXo4PkLlnisB#t;;{Ce*ISW&id2p$2BUJ_@zDRbG%Q&eHh^< zf*}>^imL}+Ktojk4lIT%RA-&R%5jo&&qozK<>CMWJk_9@S%(F0%X5F9li2dI^Pb>A z@lF4E4Cw}<1M;~%Otfr9=7~teP|?KagqL4kuTCTCoko9BaNWN3A>ui9dB;%S+-;r- zpL(AKk9S^b2&um>OlxsN=%rL;03+RyBU#%S4@vOJ7GEVH7{2;I8z7Qbrg0CW&@^g` zIP4nK14JPQGRIK*bGt;|^yzz14`BP-iJor~4IL_ied-93-Pti6I@q`PolArgTPbKv zJ~Wo+Y}npZOt8Iap9cO>GL!|Vc|q1+_BihVA4`~~LaD haQ(G>uyQ z*#+2VybRM&H9FFk|H$^!i%N^^&m4-P`SS}1R!*oOsS|#T=xYpUACy=CSAAm?lS^tV zody25euMGsVAfY_6F?)nxL#c;x{FPbQeE#gfwelLGN({QCl~Wqe59Rb5KN8lhaVkO zs-k#+w_uNkS-wkP!vf61RWCQ+1_v^!GDztj0VX z$Te}XT4 LqP zuPb_S?`zCc_dQ*(w_wzADbwTT$6Pa!nMMAAo%TO9h2%6CLr(QCwpU^;ZyH7zfT*Sq ztoyqsCdpxyKGM=Wb9zOv1A;yjfwc6Ka8NaqRg7(7wX^&DxCOG@Wq|%NzI )^s6@K>~kjqACwClG@XgiIvbTvc8HX183l9J$}rWZ@=EO^3w zMU+BJF72bNVd4E+wP^~3!|}NOJ@-biAPUB>(s^Y*q^5)KgVml|c(#HeKu5+(zm%6@ zI0IrqQSOFYGoA(!3ZLJczm?ep7k8MU|D)y{*XgV9K_&Nka<< g{OBV zLWPNn-eI=Kjl7T-P~#Gs;NJ^l%k#0?DrC3%^Com`6UCI)xeNUV^S;aX-1MWh=ZTZu z4;4M4EVnOWGV56?9alD=+1wPxNPP78_i^qb=D>Z5upI(vyD#LkJ3ElbtU?v?t+;td zo7^nfNKG~oF8ic9+k+;vK0<&hgWmXToPF_G*(M6qmNI^`Pj*hxgw289&~Zd014V#l zet88`Ytkh5<@IYHr7DZ{d3ee%>QJA9sC7iCIPvM7r@UUbqUt)-X!QGEcQ|+rpNG_0 zpbe85$O? R_4s zmmHD&{_KO4&$$;~ii}f$nKQ&P=)k5TxnL*re~}wOJFKy8Tu`5cp7 HgQh 6L_FI*0x zm&rC|FmJkhQi^uCn)coz*h4gdjhjw8a2BqJKMveFR@W2 A4gAigU{^<$*M*f9!Q?;BvdDaoh^&V_nzooUeOZ_b1x z3)B0&DBWKT2MPC}BHX008%>%dZTi @$P;;uzo*0$ltA1oqN)rP)#?_aB&2tJo7P2uk2# zRNl1mB_vy O4_Qg&Nd^Zruxqz2PEd~>bww6OyxijD+Ei P>tG zsFE0`bF${n2!0rt&hj{Mjrg=8|91WN)i$`PVlt{<#;U26#w?68hEV&G7B&Sgsk+e6 zjjeKvJ0{%#oa5s6{bw%#sPUuLfTVM1SS7XSGf{uR@S+}xKsr^iEQ(Z~H#p)2i9ofr zd2eV4`aC<*6Wr 9;zgIsbvxkT>rqJ6q%ZC@t^P&`7kiC0DkS)n9k@+=m z6wq6G4fW^lNVkf&7gb8T$z-yO9yNXFgiiM *8 zTP>4GjRgkObyY62?Jl+Y{QrAP8<(w_)hlPd>Gc;c8(Ys@2+Il9nc`xjto1$O?CnP} zX-Ylu@47?5|Ki7GVz?C>yX{t8(0~E7azP~(kjOkcs*5PGWdRK`Lfv^^^VlN11chHY zUvR~+8e;H9@kSZf|E9mwK*UkOU%&0oA7-MZqd<@h*CWB|(f=`1Id=^W#mdF sN4D0J|d|4?3(xy1f(GT+P1%~> Q z*hJ8(DaOP|E-U7=^e4J;?d&w^_oy)2l*AZJ%P#PawrE@$c4pKW`njOQkAokrwY!8; zDE1|gtekAH1dd{de}&0IBFlEh*%FL}zm~$WWR6ECAQiAXjaL3m<(&*@pQsv+s6h@v zs5L4`WFONIr&D@lC)K9B9a{g`BWOi{`dWuRI4|Fj?PR41gx+iGJG`F57lEWLce^og z=Dno77PwW#ikH*FoAluln>k }Z2OrBEg`y03e(8w?_bvrilgluKHeJs0r8Y<9OjwEoo z;nVy-0K-5$zak@`DoTpBOeeHR+-MXDnM2Tysvtxc(PtUMk v0E^sm z7Q;{hO{UXBL(t8n+DsHsN0)ITnINJlvKFt2(yueuKz3SBHQMAe>1qh!-(BVtofDRZ zMOR%jD0xuzHvOUC2%+=?Q~<}pI&ypn`l7%WxiMi~>~?O-%RjIrA}Bon9)ec(@O2V8 zJ3Fo6WX8sS-psBarfK*PglcbX(!c{wd@%IQJ}2hP?adXe%z!$OKEOjZIpHTtjdqFe zu(wOdvo!>9b+l;rLyS%n7&S(dxX12B ztE6qG&MBljqM2p6<^2)f>K zvycUx!Hg*^ b!IPY#*%<^1W=BJ z&m<~8P)A^t&K!d9-h@0v7>nGTSq`2+MFNXQQw$!9zTSeZP5v_SX~S%{Fv@R|BzQbY z^ S>c~8Q(5Jm^`j;Lbg3xb*XmQd&+&pL3KXWVv zcf=8{AA;6*_ahnUiN+pSI#aQrFAVI^Jry5 luls~yN4OdO@l5M(u-3}{qvnoNX~D%?vJ;$Uj@@aXzrJp-dZN6EM+22i?x zX+5!CNGP`sK~)FR+3dXa&{0dpPxv&FFlci55Ok}{37u@NGRzv|p$`TV4#czB)53Mt z3tOZSrpy(S3UkP$)-RCY=gbVtVk-s(iYeU?7Q|mugbc?&nhH4~NOd5Mr1YO6 E2 z2-?+xjc65Cr)=^^LhvMGwktMNdk8wLsT{%}r6>F~vrhRyWVZ}Kchnq1&}pxG)A@`o zTn4;(`e1}Sz=lg$oS9*{tm1@1ASW91nm+P$;dYof`zXM0PlScpMmj?~M==I}6N89P zu@3)#U0=OxDRa6j|KkSd%oH%q!Yo0&4~xDFld92OidlMaF1ZxpMk3%Hz l%?zg*Ve#6kP78} z8pzBLgjFwWnhU@7=}?i=&`$4v$*<0M9{LD6P 8*tAb(_NM=Tn~wD9l&fOQ z5M&*1jjJ$O(;6cwp-Unxg7-N*#|%NMUJL3{6TAX3#9-g4sGI)XEd>>ZppCD4J9#Xs zj1R*G-GAnu-7MXnPlur0-joL~L_N6BVrQyIb!7p10ef4*dp-EI#W?{_E4Tu3GYdVg zW)`FnnnRFvqJfvX?4Zkk-9&-c@!2)T5#K8_R2@h< yd3D-(quoIHv;kl4eZ2!JzDT^WYTZRoO<*m(XOf)3ru@7-N8$(S5& zK^A~!s2KBlx$eZba_6NW3%u#CW`DX}W}o~46^EefZB{5k6K>>tkXcZZe*`+Bi9?5= z+b&L~z|iCRm)XdFNH&MjIU(&Hc<zn`B@)v3ZUj!Y&wRDaU?@ksLP!EpL5bB4&3w zh%DN)jy@(fiL6#U+Q0gKG=-2MpNM5}5g|C7M$6B#2(_c>KuI$H$ur%QpWICYCZd&P zL(ul7mEaC}Yf*)Qz?*w=;@PAtryYX$7WRxd2OqUBKNy{V8t4Au6ycr+3_-_lKfY#K zcg52w&4^D2A`d_;&|hFU{eB$+-=#eL#e|}f0;^1w4~3WzbP3*|9|LRYfDYwsj3Rwb z_ZnZz(jf?MVN)Z^1;ClPa0 x{N=uDs`M!3m8l~@d~LlC>ynf1y*6P%%* zQ-8`CZjZS;W3=Iw6T(Y$GNc)-ey}et37Sk7_%#IW_E-n8BJen~@FD0JDCkEyeU8)+ zbnrWDlTVZz#2K=d?&|Wx%vMfCZVo}`bdhi1p;knH98uWZPf(lS5x?o @h_%}$0AmU{X@i0)-k@D!Ti+yA}B(=A!x^4Vj$mGr%*MjYoG#1 z#4>`lPxd_UKJ{&4f`H- zMEJo3-6JgKuP1`LiG@oU*7#tzOh;eCR2+8q7 z&}GYY`~aipJSCL;)3t(vz)<=PLF|QX@oQ#(R5zO}6wpEDN-*sb9bOmKKq}oRsfjAm zPatkoPs9{WO?IO0;vGn&5~h?X4G{H+5D5&a#Deff7d(Q#ZV~k(ToeuI{R42wG9c>s z+BpRAJ_ESp$8+8vuXx-{%nUZ0 mX@anlePkbk#Z6F*xIqYYth_k{?JWIg#_(`| zr369E=Qb#l3Fd8PnIY(4HEe>_{AiRVhy*vHKuE_w;%!eJU8k4+gGsIzeL{EuPhskEkyI9}CJ+%0LU!&Pf{wT8)8wm0GZ`SE0iv4yJ=w{LYWNUzz5zIYVsDNk z9Bn+|h{;x?wT`U6hM)_sGe%5*6R9$aL3T$_H1w8#!y?^hKp=$xSJMIPt~1yOQ_{4g zzwS>}m1iUw8&b~1HXhk14*{(iCSMR?L(pQ~RHq>PV2YDlWQb+`A^tfJA3@)@asdx8 zrva|betI(p*uidO*Wh&Bs`Yh$GMCE9l`vBQ>rEQTB4UldTUw;|CZsI?G$wEovW1u< z;TbaVy7V1_yh1EFG6jJD5e4*#VT7{fM03s%gu$26 zK%*!^aH5s3d->>X9n#ZqD$hGd;3<77r&){{{Sl)@ooGlj{RQuI=`3zcNS >KUGHf!$DK3P`t}Y zL(pmU>kO;V+sBJSieh(Uk|sasj~HF5Uq_UX)#mvr4M1`?dwzK&ho_+17m1NW3K2r) zS;LSf_chvN9)(L^_m|HmoOhauM&J rC?1e9(9ci)MYPhlC+ybWCeYLd6b0&Ik}0zYhw8jgf) 2-6nvvA!uij>L&lle~?6@VW>HcxTm|dt5Fd8S_<|IkST^}7>?bA zg!KeJ`!xiis=WSx*Jko+J_pP^nUP$8vN%72*b93i=k%{smfEHe`7~)Ig!HuN#!ED! zBM)PsC*F6T+(%La93_0e?v>9bXpN#Fz#4D(Awwm7oYCTVe+auSZ`V=GGXx3sj_GdJ z2>i{IG8KlPFJ7 !S&=$;!b z5#COxCcjO8jGG9@ ?Cah>-gRqYB#yT~Xf!7lSlaw2QxF6#(>FfiT0~+@2@7Fe zpr6E%K|Epz`o7(C5blq8={mxT+Gr$xStJ`!x3Q*E`%`ISIP98)PaI;@4D|5tV^LL= zckAc*m`A28;dmoJ93z$m`jdh-zBeI6Ii-PuCjE$iiy2?a2s(yAAA%0O9BrQB>`FBr zXJr8H#wfwcY oGJp=eqLa_xH zZl)mWNVXzu#Iw*~CNwt{CK;pCqWxnn2I#n^%rZf{xooGLz)48T@d1W?L1XkehCGHD zhcSVFs~ZoTDcH `>7!zDg7JWAYGhFZr>B5gB6g#R6D*4 z^=&$OW@ 6h=P zSxgSKcL-9y31P&kq=crZTg0$wt|Y)AuRX4dI* c{lj#& zY%v7xNH>y43_;tpu-r&u91;;5a!UvCkSs(-^2+!!1ff2InC+>>!zy(;KY~T{nT1Vc z3PJidF|m{8G<{&qoS8rQVbT}o4?(ByoS2)XwqchDfwO<1YI)%YMMIFT83Z;R&N=B( zIi5&1jv7EXxFun4 so 1O zWiX&=gt^T><9`TZ_c~*(aBU *0;>-w%0&u62jsBtZ z6gmW5TERXi4h5}C4T4a(n@pq-gGEn4H~R63&68$-Ako6 E0ozzD@KWr5T0he-Zc!t0BeNCXw;s5Oms;<;i`2nvKMogD={O z;!Q>{9!c2ivM %KpH zgbi(`93U9!Lumq&3}3(jkBpCoAXIL#{9=-(xH8KylZY4qN;9p@4MWhEt7s-hOsa{m zj$Xv3O_n;2G|>>W`WwD~h5^Qhyj4~~ Ienqd`GZ_Q}Dus zL(p#T@zLJ~K )-#=fBJ`iTt1)Ae{6mE{D*(|=YReGKH2}|XH5P%j_vuqocqUrkDqlP zJO8q5%l6&&b=%Lse3tLFZGZW@&%e1Qf8*z0{`r6W{eS ;G!p|8D>P zqd))UKfnL^umA0TU;g?}|M1rrI}?nb*JAajUtjB4@LI8m;W<^H8cn2%T?=vh>#&-| zuTzV>+Uv5$ZLeF)D2LFGZpF0MvXG|F7K(g@M$7sZV_pl}jK?fHn $~G3