From ece8b0f7883dcbb31d0eccb94d8ac7fb735ec49c Mon Sep 17 00:00:00 2001 From: Okke van Eck <39912605+OkkeVanEck@users.noreply.github.com> Date: Fri, 21 May 2021 12:40:28 +0200 Subject: [PATCH] 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 --- .githooks/compress_files.sh | 3 + .pre-commit-config.yaml | 2 + README.md | 46 ++- archives/prospr_core.tar.gz | Bin 3381 -> 3390 bytes archives/prospr_core.zip | Bin 5942 -> 5955 bytes docs/Makefile | 20 + docs/gen_logo.py | 100 +++++ docs/make.bat | 35 ++ docs/source/_static/gen_logo.png | Bin 0 -> 23408 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 | 348 ++++++++++++++++++ prospr/core/core_module.cpp | 6 +- prospr/core/src/protein.hpp | 1 + requirements.txt | 1 + setup.py | 2 +- 23 files changed, 1037 insertions(+), 18 deletions(-) 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 diff --git a/.githooks/compress_files.sh b/.githooks/compress_files.sh index 35efb96..158e74f 100755 --- a/.githooks/compress_files.sh +++ b/.githooks/compress_files.sh @@ -13,6 +13,9 @@ COREDIR=prospr/core/src DATADIR=prospr/data +# Move into the git root. +cd $(git rev-parse --show-toplevel) + # Create .zip core archive. zip -jqr prospr_core.zip "${COREDIR}/" mv prospr_core.zip "${ARCHIVEDIR}/prospr_core.zip" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c1623af..56a2d4e 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,6 +23,7 @@ repos: rev: v0.812 hooks: - id: mypy + exclude: ^docs/ - repo: https://github.com/psf/black rev: 20.8b1 hooks: diff --git a/README.md b/README.md index ff80515..5d82976 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,45 @@ ## Prospr: The Protein Structure Prediction Toolbox +

+ Prospr's logo +

+ ![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 728aa739411178a232abf816661cd51c8bd66288..86506e8b86f9ed626ad4bb6af8b456f0af9370bb 100644 GIT binary patch delta 3236 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 W4JVTy4FwFp5BwLF-ws9qcmMzxKW3`{ delta 3228 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 Ofd2uN=LJ6icmM!Pq+dn= diff --git a/archives/prospr_core.zip b/archives/prospr_core.zip index f72d431764ca3f790121d664d9a90be0ec363e19..16c625849f1bffc17a9b146e849d89f3a71fb7a0 100644 GIT binary patch delta 575 zcmV-F0>J&YF2gRcKnxAnVy04Vk%r^y0RRA1lT8d419roclV=Pdf07kh0_^CfxvU$q z!7z@0|gE{;{;o*gR8D73b*zP}8Mxt5-kq%pAskQSV5*oWl-_J z=g!M4>)65J?*_HN1(5b2se1VI;rSfo9Yg%t2CRum;P36 zmDR4!2oO$uJw`6BVmIJwo{~o)&bKx+hPxaZE|a`bS$}ZD$X5JO%I-?;*}tI447H?! z{RgvH4%r6{*J7qpZjpxL>Hz=%Rg*pzB?ETDlas&|Ad`j`8UbaKp%zdB5flKEAruyq N3Ku2@FBJd)001oQ45k18 delta 561 zcmV-10?z%zF19YPKnx9Kf1Of=zkDv;0RR9TlT8d41g*P@V3Tnb6O(%k41eMkSpw|n zrn#&wvda<-y&H-|$J}JelVrEUuz#Oq$EocYsZSR9NIpK2>pOTRg((ca${LTPR|SJR zctj^GRi2FQKs)3TE#x5za$|w_creGGC_KE9FT%?g2)o1Q(nwURkZH}>f^sb}hr^Hk z%hR{-*^Vv3lQa%20i=bhC4a)kc}x1VDz*b#$*bYB2?dSaGRB1B&cWeK3s*A$HCzYMUw4bFM(y zXQgRI>DrQAUz-5jz9TE+J_PcTv`Ma9A(Y|>XGl0<>})@x;QE9gmwzlWl5Zo}(HI5f zvf_`lCW-kd%>8YEXbefP=+Gy#)=U^3maF8E^jzwOE0S&MsNXb4rMSSe7CmO!#d^!d zuLp1IVbFRFFZ;)R3SZlvA+NQFmBAaR9k#oC85VFK7UEcYTuqrr_oVEUTBqt+^>=RZ z?-l7(_*-%p+!a}FlvKP@Eov6M*Q1Z{)-@6!=gLKH-JMu!xW{yM?faF#MXTL_2_RhR zW{O;1#csh>e3(26aXy)`F`U=fa2d!AX8qlaBU|w&CA($6Xa9mG3)GTw_8+rl4%r6{ zWq+Mgg};0*-2ngq9Ft2HB?GOyij&P1Ad{088Ua|7t`<-M1e5<3J_aHc00000ZioxH diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/gen_logo.py b/docs/gen_logo.py new file mode 100644 index 0000000..0bd600a --- /dev/null +++ b/docs/gen_logo.py @@ -0,0 +1,100 @@ +import seaborn as sns +import pandas as pd +from prospr import Protein +from prospr.helpers import get_ordered_positions, get_scoring_pairs +from matplotlib import pyplot as plt +from matplotlib.path import Path +import matplotlib.patches as patches + + +if __name__ == "__main__": + protein = Protein("HPPHP") + protein.set_hash([1, -2, -1, -2]) + + fig = plt.figure(figsize=(8, 5)) + sns.set_style("whitegrid") + ax = fig.gca() + + df = pd.DataFrame( + get_ordered_positions(protein), columns=["x", "y", "Type"] + ) + df = df.astype({"x": "int32", "y": "int32"}) + + # Plot straight lines and add last amino acid. + line_width = 8 + alpha_val = 0.85 + ax.plot( + df["x"], + df["y"], + color="black", + alpha=alpha_val, + zorder=1, + lw=line_width, + ) + last_amino = {"x": 3.5, "y": -0.75, "Type": "H"} + df = df.append(last_amino, ignore_index=True) + + # Plot curvy line. + verts = [ + (df.iloc[-2]["x"], df.iloc[-2]["y"]), + (1.375, -0.5), + (last_amino["x"], last_amino["y"]), + ] + codes = [ + Path.MOVETO, + Path.CURVE3, + Path.CURVE3, + ] + path = Path(verts, codes) + patch = patches.PathPatch( + path, + facecolor="none", + edgecolor="black", + lw=line_width, + alpha=alpha_val, + zorder=1, + ) + ax.add_patch(patch) + + # Add amino acids. + sns.scatterplot( + x="x", + y="y", + data=df, + hue="Type", + hue_order=["H", "P"], + style="Type", + markers={"H": "o", "P": "s"}, + palette={"H": "royalblue", "P": "orange"}, + s=280, + linewidth=0, + zorder=2, + ax=ax, + ) + + # Plot dotted lines between the aminos that increase the stability. + pairs = get_scoring_pairs(protein) + + for pos1, pos2 in pairs: + ax.plot( + [pos1[0], pos2[0]], + [pos1[1], pos2[1]], + linestyle="dashed", + color="indianred", + alpha=1, + zorder=1, + lw=line_width, + ) + + # Plot text. + ax.text(0.73, -1.88, "rospr", fontsize=121, fontstyle="italic") + + # Remove axis and legend. + ax.get_xaxis().set_visible(False) + ax.get_yaxis().set_visible(False) + ax.get_legend().remove() + + fig.savefig( + "source/_static/gen_logo.png", bbox_inches="tight", pad_inches=0 + ) + plt.show() diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..6247f7e --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/gen_logo.png b/docs/source/_static/gen_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f1a7b02e35e6f08236498606efc9b469f4e53e7a GIT binary patch literal 23408 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 H0i*vPz02V& literal 0 HcmV?d00001 diff --git a/docs/source/_static/prospr_logo.xcf b/docs/source/_static/prospr_logo.xcf new file mode 100644 index 0000000000000000000000000000000000000000..81e19945786be6f4bebfb5e3624acb6c26629538 GIT binary patch literal 52177 zcmeHQ34Bb~_a8(M60sMp#?m`8*(Q+)k{}WL9<;XDLPSaugj!lgYo}CgEsAP|pQUKj zn$pw~OVqBGqM{;#h?r!O$-H;Z|9js|BK7OP%kS6zO3mc+@;&Fg`?h=UyXT&J&b==( zDteU5gdxLR-tzMHR;g4a-&Cne=s}3zGHjKwl_-IKRj`$9d6e#m4Rlp(cGyZ{t6q$* z2GLpY&XG8^M^yCS$Ow6i5lw?6*FXbM4UJx zcG$4Eh_Nn8`eL+&{CQ$=&sB>(M|8y4!9xd+9W3N{mJ%6(Eha>dba^XcOk7lKOf$8& zrzJsBn6ZP$;<@TI_x_DjcaK16juUBLM_%J*ej|PFCkNo;sdmK}D_QjBh)V7}YD{e0 zs4)Xa#zw|^j*5vCX~c^ne)ibJi$mDz3cAHq{Kw0MO~}RZ<*YP7Rj(NRaxvPW80}Jw zE?gmgMppzau2=Xg143L|oc}c|4Nx@@G~oxVUyLsP@CYvdGWJb zV!@QPR{X+>d#!lHg5rNsUV^rtZjo15VZ~DxbRJ~EDm|g8c_raL_Ib zMmkwA`V$L|8*agOtobypxrLuA$`-%Hy)3xGn*VFlEqweM3x2^YxYfmi+YeZ9$Hx}j zUD|^CgciZ?V1@;gg+{^e*ftBQRC?8AlB5Usj7`Xxv3f+i;NX`1XPx#T`SI+KvcY`F zMK9uKdX^8CLq6di#80+$3Z@0_#M3)E2h$c;;(Sb{VBY?=mgsnuV47OX;6yaBN-z)7 z)MSptjUiQo$xD!QzFIK(Dbx;7{tER4sDP(rMd^wTE_Ot;H%@ zZz#UD!MX4zJqvGq71up^93L{?vpnX2*=L&I(KGKE^(C4R$qx5PZb&3Kd`HrYhIL4( z2lAtb`KSk(33FqjqTbYhdIj|$ckPI>QGEIh)PpM%%16m>ektm~r5L9uT9110V6<}- z?HBc6VWlV@n}K?8p-L1jSL(siDp5SrO%yNBA5k@mf|QcJRxOG;E7T!Sy%p*JsD4k$ ziqaJwjKVKGB}j3dP)j`!*B+)*>Va}YyOnxixk=Om%Z(?9dQkW{s0R-%k2!Vi71RUy zQC7ZE56lkVkQwD~bO<&;X9s0HR*&Z(3wYQfz~sr*&}YJsszDy1v6Afrku|DlmmxN@~ridCq5P)ilc z0BVOqJqES!DcO^B)?-odg(n0luCm%v2gH>x2Pt(xxt;q;9kARY>VWmGbwy9&Q~Uw( zwBn&{H2^ihSw;GiQ>lePUowf|zeCV(^VVZ@hKi&^Yy7)6gT6#-B11Xm`w#uEFX2TM z<8{BZ86anWU=!(|I?q2f*DTMaGUhMZp5KfSRsK)jG%yHW+)ecYKf5S*+wSDuDShthZpLIy#KQd(L9Gal&9oTvfAo26dH?qfe^`ysr*!#0yTfjK zI$I9da^P9c0byG_x5km}#-Gn&5L>zZspa-(j}M6Ry}088HXGSCMxc^@=NN(PaFb-K z?GNhr+Q83ax{}{XDc|f*E~P{g7^M9(2DL$4#T#QcekXY&6k(Q#tmu30e;iryJBAWW z4lBu|6p=#xQIq+3N?$6hM1MQQ!*4M54<9x>Dr$J-(1Bq_luz#J;fQz`cIkf{@n9>T z;`OIwnAAV&&B3LtMKof~p&wFHe>}NuvQk9y-5X_7`LXQ(X*7b;cW??4j`0#xnf{k3 z^ah?~3+CCpH{>S$THwI5dDqYKT|FHpP{jXA$icJxJkRF6JsnU`#Q#cg!V5o!pfAx3 zk)Q!273_F}H6{7}691B{G09iPx!SQth}|4khBYKvKG3@y^CH>&WykW&lVsy(L5|Fw ziItcwbA#+Q%agm8`XoM=mOvYafp&IFY^f@ov@( zwvX3Zv)DdfZOvr+_}8r2Y#(3WmeC@7=I4M%*$e{EWIlJmX{1EU+c{ZS2)FHH4$g-MMk?#~00y{;>mkXb2G4aCVFi^Ex@ zkcC(HOC;Z276Qh9`dKiNIdPb#Hj{iNB}+K@gJsRYc#itoR14=D?^X*}ib%)-WB#gF zZ6^0y|FAad=+eMiOm4gK&MU;nAyQb&lS0}UK;DWyH^;u;yXYQRIs!?OAgk(B8ud6$A zATz(dHbUpYxL;TqlCt-_9puJL>h^DantY$z;dG}yd_&{P%&kYSI+23}w>OOR(K2(; z$d8X?mnZ6=VP^lxB}w<4sR1j{gwEKL&a09OGrRZu;E5$)w=- z4&)*tyW5h>TwnSfTOQf+=+CJ~;(aUWkN4;Ct@DQxJSivl#?kF7=1d&kr+rhc9kixV z$~gCR{DSd=+BbBDsxHU~cpL&?ll5e_^^x5=b?cBAj z44JaO``5GqL255nf(nf1zL*`}yfKr9hp6?c0w(*k?C!;K8h43!`~6S0>_2(!fw?3x zW^@nfJ8IVIohN@XIngW3sA)Oq?ZunEy`05sK=0*ybR0f&-NBn?7plneeY=nPV9SZS zvKlW;LC~;y+s|d|s1z#*7(8?HnVd!>y}Lf;k-l7@?eU)P(i0W5#AeFllF68pn=hep zy-|>ze&a&Q!9Cm7f3kS))bY_n`*rWqv3={1pymNh8u@s6xN6F>`&th#-zEVqLfUlb z9QxU!_u|64xAfKOOHN}+ZobXihV~s2{g!^tqLuMmckln^(2-*&PMtY_@$wHhZvJ#9 zL<43;Tzb`y)+Tza=4xPW5@mSKA_qE;A@69Kr{F3PY>%GGU z4T&B-Xlwxhpp9J%06GL2atf47#9hgGT8W ze!4yB%pJ26c`;+tE<-0RT)+Q(hGa)gp=td?BPTBw!;V?I61Htw|H-1+`mrMh_v#$t zuk&QilqDPQ-@1J2@ZK#e=e;vBtYd)NE6jx+b7R`YBRk`l&KMW*dMlkX^PpUAxPJ7@ zl`~@dgm~D)?#}1gSC4F4J}p|AwiP8qtg7E3%M*Ab9c=j-mm}I72ok{h{d%h z*|4ZXnP5I(PgSs`i66%VT|PduGB`Wp`$8PyUbH$wAuv~VIDH(Sv8nFzDi-za8$)$ zimwC)k7J0f5X?h1h=(gpvb3RXIXun*3=l*SzHT*;Di%Zo6DquDKgWm5Jh0k6O$10w&z@#gDAzdTfMa6rY?~SgsdG zR7BEzYq@F%SBj#I)^crMIf}n|TVy$7nxU8`8*eGsz^YMvlx!)W4w!L!+d{qp@|cC} z2l9Z0>t#2 zvhoVcRnELsCY7fdtmSIFT|Sj(NS1P?94G8DSE2&tbGxo258SNZua4#I_GoTDkvupUNoh$AdRo;|T5#+&&be`mOpc*cmzOanjEMj!ZD zJ(j46-wdnFc+^h}=UL$aVXGtvFLZ-PM*DuAkS@|f8hR1Z>)j#sSSdj&uN7(g--Pte zKuCQyb4YoDIBoPjNVB3r1?KIOO6^QThMl#nm z9Qt6JBcs6%SO{f05`~;cKWPRe@0St9_V24a{K85O`chMD1^J8@L6JnN&?a69+?T5^Ghd>p)NeE6xlB;TH- zt%j!Pt*fBZ^{$|G)6+oTo8|`EchN)84`z9QZnh>Dbk_Si(Cxk`0Bv0A4Z3Hd3|jgk z5On|JydLqxovWc8I$j?uR1Jaf^}`U#8Iv?snH>6!pmP`LKzB+Mw6xJ5bo*U0X#Qs<(_Yd=$QVBGXsR6`84j{}YUtcUM%^&2!a`t8{tZ8`KqP6IOE-26^2-)f8kUnR-7YfM0G_A=tF4#axZL3oFp^Ld-P z3?WwqYy9dX`23kW5sF&xltkwK`uMZ?{wN-^YnN%eANWyOCUt&4MS6v3t790gwu45I z{3abT*CL8WANeyoXdLPX4rU0Y*gackQJ(5FJ^dl|H9;@K*!j>X;@#HzxxidHS`Cl(OrA=4NE4Z? zni}B*LOqv8#Dm4uaa444Il(J-PI*O3mlwQZ<&;CzVXWE_wep!c2_EU!d}{x!eK}IG z&K2G>shsFpy)1^=(XX=NS600K@(Z=Bku7ij|GNIi^Ts;W(_r&cJU;`B!prnW$_ot$ zhs#bm=4GttyP%LkADk~_gV{$*slGwW(+o?+PlP)oEtFxB*bzS_CW-Nt8sXO9Inj2)t8t@!X-taYiQe{DHkwNx zl!bGH8zRaH-^NcJ9S}dyziV6`E)Krktpa9`ae2Oz@NgJMDjtrzp%od;b%P%yz=?6) zZcuwXLAAar7BF9iVX1*)Df9d|P*cpH9`wSPm}V^k`1q9|B=r6khaB++6?_#`f)-To zOmXl^95T)XN}dktV{t@&EcSZtMY`-TP=Oaf-R%S_Gy~KREkH#ZL7nskHD3m`*BwJ| zn)UF-#G_NqJrW_~3$WMsJ5c8Fpn|S}G7bUNS)3&sH^}=x29? z)cc@34|x#H2jP9vQ;a}*pVDE95BECdB?cnBPI+UZ5BK`6A--2&t1Y(LVyi8-w&gEq zTQGW1g7|&m4<7Xxac=!EGPSEL8p}X9d_6XDXS7xgAxpI<`N(=#H1+MTR3`cnB45O) z$_vyua-tDk<(&}qM-Xe~AV|Ct5Wb5xkY*#s^;`=`y4|c!G#HW{C84u0=Y&raF^-KL znfV6M2``-4C-EhCK_Kwvl&piG)6JShiI_pvk1mM>V=%@<3mus}BNNI=)_%%s6AeS# zxw$V|;HJl+mjiHxK44x?2Xp@ws5Mg^qNLi4yKiwJT2_OZHA`5F^L2?vR%d3vLo^_> z9#L>LW)8lIVFb{R;Hm0x7jC0u_>bCVs)<&@e-wBd*5zo#1$e=2PMDlVJK-tM(Ntpe zo-0ub9P%BY4rwi(Omo_eXuLC{X;31aaN~a2P!svcJ)s=vEF{hIL9B;h4Ya^y+;Bq! zi0)7yGoilC?jWv1a0%GMlV}TYE$}@&tolBPUU*LI;IbEpMG#y=inG83r0|kJ%*KuZ zI->r-1wd#&Iso}CB)kXQ4L%TZs33|2h65J?n*#S^|6QcJ3)~OhAM(Y(2;gww2f*gQ zMC{K*x;wyw;G00c92gFa0nP`u0`9?`K89MQpOEkv&<{IS0|x=)fOCQEfjg1Vr~#2$ z#a1tE_0m=^ZSAG4y+m{Pd)iB3S<0r5bTy#>$f&p6}IFb4L#Q_Y_`lLsshHiEmPF1i6>;e&$ zG4lbG>L$36n(pj*39)aE6*vl()CDzEXD1^hgFtv)192F;ghk0ip_m3khwj53x0@i)NuYVaix30| zb^8_sYoTr*xIt+)$%AAKBp*XZ^?<+=ks)*wf^iTm2A%*4CDj@zwCMZ5c;IQ^n>Zjq zd??H;dP@@_Nx`0Nz~#VOz*xwIz7_f~x=%O+QEdV-8YzWF6}r9) zFc3Hdh`Xh?u)hEYP6j>(P6uWH=K)iJ9|Fa_&j$)kJ{yQg6h`APBq$Jyq7xeS4nS|ZSU;|XFfc5KHjXtF@S{HHMN$r2BXb-(B{ zadY>PgR;=H{UJdIfYt;1V2@5H^<)S{9?QsMx&*-&z}^t#Gy|~{0^|_yB%?Qxgv?K@ zY^yxB%44fMwwC8_XnBO{g4LGT`ZWfHl08a|STugLxds6Ue7#o7gpD@W4M3CKu{;JX z@W4lDX5U^OenO6diYi5E15*UC2y z?dxH*w=2nSIpcLj1BD*6Z_%-u4hf!yk!t0sE~&*gfabb(z#^+F|oc zutJB{N9^YK0|nLbgcDw4a^rW;f{gcMOzyfq2W4=*zZ%mB7G{Fn*;e!;79lgG?OoIi zLE6cq+#6usLFv)P!LD^haBJ3%asG9%P>FQ)^AUcvSbeNc_WkOip4GA1nUw$S*9h@*A5BuQ0t`M)-zJUB&7q zbXff7Jg79h#}uvnpQQYcQU3QXjoY%-B3mu8)goJ4^!K+#LaU)^p9G`mF_Z(>HhuW4Fd(VOsPNFfTMSO&t39RrHt%OTaUJRluyn$joE*T!hya?;*g!jmtg`mEE z=(&sYeFr|6=pp8`Drfv0{=^aVs8cD%M>Ir;g>v2ra4Ie>7+}ZDWIpkJNEyq?yWp}( zXhrQvK0U1wMpMQ8nuMV-!=Aw*YTVGNq~#*#adovlD@W4)P$uqsV|7*@?X9@yDWZ|5 zp4Bnh$|X~ii6>rs0I?#3H1 zD;L4J_!R`53P8+(_S2q)_8W+&nhAA?X}sL`5d=R$upEND5Cn*U(FMo{406&?sL+Nv zAP@>f(|{N*u^lj_AEpl=b7hzW0Nz)W@&mhoHpaLtYb8}Eq8bi8{O!nHes zJ?#innulWDT%Lzu9LjdYoI8p}A)f~4?SzFhDFOKz53YmYctAcJ#&3fScY<+F>%oPB zo1}0(pzjn5c!m?E@=-e6&lvcn1q!zV+$M0#6mB-Sso>Tq+(>Y5fLp6@ebDQYgr&Vg zVY|VveHA&nMBzfgZ3j0~;ljYp1UFjYBEf}$3sbmp=q7LK0W1QQBw!gc)6QQX^Z za67>zIoe(d+e=}4DQqu=O;gx3#cyZ|(S<_C=V1H#Siobp4E=IH5@u**PGxvj12B}` z!+=2njT_@(SisDK(FkYqgpR9-|J?1Y6I6}K-M?M;j=@-ro_CWSG4b8330s($UYg8u z+WtA6FgYD68q?rI*Je18d}*>9x+s2z3PSbv!8kcj8(szDyA_1mZgm*ycB@zbrCC9F zl%1@dorliSDL<&S9hgPOnxt<9B z+rT%07l6}&-vPw|$-vFPB;ZcqeqbW-TVRrPzZf`1aIP}$bp^Nqycm^U4HVmcwj5K+X+@ln_xfONv4I~?+>kS_y@^QHh1Cda)B z@Thqn;*5}pI}>LT;~}@P!ytBagbad)m3?uThe6Aj5(bfdZUy0fi{*{YbWirHE*G$_w=D<+gB zj4VXB&@QZ{i$Io&VgS7`w3#1iQ%TI|D;CyVS@2I{nyU(SE)KT@G*=VslW6AZf<>!p z31zNI7V}40+iPj+Inu1wqiC}hS#wYPq5L*J7kx+zE!6pvC)%xJ0F9@T8vb>Mg zArL_YO_>CB-SZNHLlMj@YnI6Ml~88xcjz@Gj+qDF1Yrweeink5nXS^#^EK4)i=svd>Es=0;gDUgB8yTEDPfz&q7dpXg3IGj1^bZ!TR7u z@x?-juQe%g#e%lSsO}z&Cu14Qf6}HBE1B5x?msG1Ti*TW??TZx?Uh9^;9Xf%O7vwF z4(^o2c10W}>n$x^#KA|h*1m{?t7A)rcT1~=x4FBT}0au{tL4apRar&1)C0LdpqG6vs)ER@iP5JVz2#3Cqz zFi8mdW0cDxK*O|O1NT=?IIt`de6HlQCnOyoVVa_HUQCbt(GQYV_s~cx68JLjw}hnG zZM24p1Y>$Rp^!Abj^+*$vw_GQ4uRJNG8PLAG>I!ZImd_+ZSti#l(*P6Ad*>lG#!!Yy^~;rRfFs&Hg7siP zsB44rrAs%!K>=w^!~mc7rKZ9$;hO9Zpo9R7@zEz(y?{;Ufy86vX38R%eW-<0SQNI( zB#Ho8ZL3VhDpOsm9X)s-{Y*nkrPy|9G=hO?|~A(S6pP^uaQc z0ADy>xGtrUSbkV{!cX{IbjKSbA_AZ^$ezcQ2HEqNzi^d#9t}WS?2(MN*zFM7;(huG z-=M-j4`&ol4wZQd+SG?*oN*oWSATd%CIV*zy8?Fzw~h$Bxq$@dkjf5U%5c?qLfgK+JrvM{>n}A~2PB@!PPK(H-FIN+#V0*gfx9mji zL}x7>P7pCivMEqZl|e)_EdXLN4)@0_9sW>wB{xA521#HpTxkjLSI)*Blb;B*N`hpL z2-5lIn2Ta;@32Wx^ ztRPH7@@s=-&@X$}6wA0LX1!U3%YvIW(vy{3UDf@d0Xrwt?|ZMZtY8#l+PI6*Bj*}pG_@^0 zL(zL@0ba5_-Y_mT_Dl|3a2;yEFcsdwp6lQsl;y9Q*J6^U*Yayv$25Oi2Nx{dJ$B=b zsw9~X>Kid;^64{m{o!jcObZMbcPVD{aVUzyCe zwoUHjii>OCSaGK&737~;Ke=C1EWqUb#*F=jdX%1hcK4c@qXvZrV`+S~t5@S@ZNo;- zT($oe*O$GB7tfYmw(R=rYL|E+5qf!ukL(5MBI~Z(N!BQ+n2pc2x{(1$$ zZNa`f2zXnd1i-mt;uj@~fH-4$5t$x`v>)Q*E~^yoJ8+TEYz^-_h#>af7+A!&aA>51 z7)n#0#oh<_2G5#uU?~nelc1!uSa%IpXOj%@%b>m7wv`cC68zF`&A0e{9)r47erqC^qvGkV->5`%4I#a6F3CeE3LIV`< zCy-1)#Cs)tY=OogYT+|zYJ7bRTw7cxMJ&(;{SL*KBL*}zIrwPtBEeG%c4KY^R`(a& zT5y<~!TESc!Qwxy#3-nwuOQgYV3RTSwG*SeVnUrO_$&;y-s)8jJe>s_jM3U1ZORCC z1K1Icm;$#qTx%x;7=ERt&Qy@`uMtg{5Ojy&8w@Sq+K)&>GuG`?rm$ZEicq>OK(RX6 zG@w}RtTzy|H7)C-iAnO;AZUagSRYN9axP-`gmo#FM@s;Tsp`UHyj5s2?uI~^jACr{ zJ>U@F7N9>+7=m|^&|R#SA{Iys#SSqg%_{b?J!NBpYMeMBcB@>^Enm{ zliDr$HIlC`>5LwUdPgnF*>f>7S2Cnu{dW1NRtV%@QyZU?qO~vM<5FCWugJlccH2^i zU`hL@yh^a6d!)M%LJYOD^Xn2!?oQ|G6ATL9j|&{Y)|)GI%`DPiQ4&}$J0E|F=<*!h3`N=&rk55-usLFm4VDphBo&Pp?24MG1Oq#7cE literal 0 HcmV?d00001 diff --git a/docs/source/_static/quickstart_example_fold.png b/docs/source/_static/quickstart_example_fold.png new file mode 100644 index 0000000000000000000000000000000000000000..12dbe2ab90ca8bd8f5ff8de1b4d2abbcc8cd73c9 GIT binary patch literal 18716 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

$cQ3{+v#p}I`9Q~3H&ZTNLdA@{b! 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 F{{>>P=Y;?O literal 0 HcmV?d00001 diff --git a/docs/source/_static/quickstart_example_fold_no_score.png b/docs/source/_static/quickstart_example_fold_no_score.png new file mode 100644 index 0000000000000000000000000000000000000000..ecef2caa03e2e8cdc8774d6df4dd307936b5dcf7 GIT binary patch literal 15408 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 literal 0 HcmV?d00001 diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..a80c1ef --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,322 @@ +.. Overview of all Prospr's functionality on a per module basis. + +API Reference +============= +The sections beneath contain all functions that can be used, ordered by module. +The modules that are part of the C++ core are indicated by their section title. +All functions have the same signature in the Python package and the C++ core. +Only the properties of the Protein class are called differently. All API +references are given in alphabetical order. + +Algorithms - core +----------------- +Prospr contains a couple of built-in search algorithms that will find the most +optimal conformation. These can all be imported directly from *prospr* without +specifying a submodule, e.g. + +.. code-block:: python + + from prospr import depth_first +.. + + | **depth_first**\ (*protein*) + | Finds the most optimal conformation using a depth-first algorithm. + | *Does not reset the Protein properties beforehand!* + | *Parameters:* + | * **protein** - *Protein*: the Protein object to fold. + | *Returns:* + | * **Protein** - the Protein object set at the found + conformation and with updated properties according to the + performedmoves. + + | **depth_first_bnb**\ (*protein*) + | Finds the most optimal conformation using a depth-first + branch-and-bound algorithm. + | *Does not reset the Protein properties beforehand!* + | *Parameters:* + | * **protein** - *Protein*: the Protein object to fold. + | *Returns:* + | * **Protein** - the Protein object set at the found + conformationand with updated properties according to the + performed moves. + +Datasets +-------- +Prospr provides many datasets. Each can be imported from the *prospr.datasets* +submodule, e.g. + +.. code-block:: python + + from prospr.datasets import load_vanEck250 +.. + + | **load_vanEck250**\ (*length=10*) + | Loads the vanEck250 dataset containing 250 proteins per length, with + lengths from 10 till 100. + | *Parameters:* + | * **length** - *int (optional)*: the length of the protein + sequences to load. + | *Returns:* + | * **DataFrame** - a Pandas DataFrame containing the protein + sequences. + + | **load_vanEck1000**\ (*length=10*) + | Loads the vanEck250 dataset containing 1000 proteins per length, with + lengths from 10 till 100. + | *Parameters:* + | * **length** - *int (optional)*: the length of the protein + sequences to load. + | *Returns:* + | * **DataFrame** - a Pandas DataFrame containing the protein + sequences. + +Helpers +------- +The helpers submodule contains functions used internally. These functions are +very specific for their internal use, but maybe of use to you as well. Each +can be imported from the *prospr.helpers* submodule, e.g. + +.. code-block:: python + + from prospr.helpers import get_ordered_positions +.. + + | **get_ordered_positions**\ (*protein*) + | Returns a Numpy ndarray with the positions of all placed amino acids + in order of placement. + | *Parameters:* + | * **protein** - *Protein*: the Protein object to fetch the + positions from. + | *Returns:* + | * **ndarray** - a Numpy ndarray with the positions and types + of all placed amino acids and in order of placement. + | E.g. `[[[0, 0], "H"], [[0, 1], "P"], [[[1, 1], "P"], + [[[1, 0], "H"]]` + + | **get_scoring_aminos**\ (*protein*) + | Returns a dictionary with the positions of all placed amino acids + from the given protein that may score points. + | *Parameters:* + | * **protein** - *Protein*: the Protein object to compute the + scoring amino acids from. + | *Returns:* + | * **dict** - a dictionary mapping the locations of all amino + acids that may score points to their previous move and next + move. + | E.g. `{[1, 0]: [-1, 2]}` + + | **get_scoring_pairs**\ (*protein*) + | Returns a Numpy ndarray with arrays containing tuples of the positions + of amino acid pairs from the given protein that score points. + | *Parameters:* + | * **protein** - *Protein*: the Protein object to compute the + scoring pairs from. + | *Returns:* + | * **ndarray** - a Numpy ndarray with arrays containing tuples + of the positions of amino acid pairs from the given protein + that score points. + | E.g. `[[(0, 0), (0, 1)], [(0, 0), (-1, 0)]]` + +Protein - core +-------------- +The Protein class is the cornerstone of Prospr. An instance tracks many +properties and has methods to alter the Protein's state. First, an overview +will be made of all the properties and how to reach them. Second, all the +non-property bounded methods will be given. The Protein class can be imported +directly from *prospr* without specifying a submodule, e.g. + +.. code-block:: python + + from prospr import Protein +.. + +Properties +~~~~~~~~~~ +When using the Python package, each property can be directly called as an +attribute. If the C++ core is used, the property can be accessed using a method. +Each property is described below with the Python and C++ syntax for accessing +them. + + | **changes** + | The number of amino acids placed so far. + + +-----------------+------------------+ + | **Python** | *.changes* | + +-----------------+------------------+ + | **C++** | *.get_changes()* | + +-----------------+------------------+ + | **Return type** | *int* | + +-----------------+------------------+ + + | **cur_len** + | The length of the current conformation. + + +-----------------+------------------+ + | **Python** | *.cur_len* | + +-----------------+------------------+ + | **C++** | *.get_cur_len()* | + +-----------------+------------------+ + | **Return type** | *int* | + +-----------------+------------------+ + + | **dim** + | The maximum dimension in which the Protein can fold. + + +-----------------+--------------+ + | **Python** | *.dim* | + +-----------------+--------------+ + | **C++** | *.get_dim()* | + +-----------------+--------------+ + | **Return type** | *int* | + +-----------------+--------------+ + + | **h_idxs** + | The indexes of the "H" amino acids in the sequence. + + +-----------------+-----------------+ + | **Python** | *.h_idxs* | + +-----------------+-----------------+ + | **C++** | *.get_h_idxs()* | + +-----------------+-----------------+ + | **Return type** | *List[int]* | + +-----------------+-----------------+ + + | **last_move** + | The last performed move. + + +-----------------+--------------------+ + | **Python** | *.last_move* | + +-----------------+--------------------+ + | **C++** | *.get_last_move()* | + +-----------------+--------------------+ + | **Return type** | *List[int]* | + +-----------------+--------------------+ + + | **last_pos** + | The position of the amimo acid at the end of the current conformation. + + +-----------------+-------------------+ + | **Python** | *.last_pos* | + +-----------------+-------------------+ + | **C++** | *.get_last_pos()* | + +-----------------+-------------------+ + | **Return type** | *List[int]* | + +-----------------+-------------------+ + + | **score** + | The score of the current conformation. + + +-----------------+----------------+ + | **Python** | *.score* | + +-----------------+----------------+ + | **C++** | *.get_score()* | + +-----------------+----------------+ + | **Return type** | *int* | + +-----------------+----------------+ + + | **sequence** + | The amino acid sequence of the Protein. + + +-----------------+-------------------+ + | **Python** | *.sequence* | + +-----------------+-------------------+ + | **C++** | *.get_sequence()* | + +-----------------+-------------------+ + | **Return type** | *str* | + +-----------------+-------------------+ + +Methods +~~~~~~~ +The Protein class knows many methods to interact with a protein. The Python +package and C++ core use the same signatures, so no distinction is made in the +references below. + + | **.get_amino**\ (*position*) + | Returns a list with the amino acid index and next move of the amino + acid placed at the given position. + | *Parameters:* + | * **position** - *List[int]*: position of the amino acid. + | *Returns:* + | * **List[int]** - a list with the amino acid's index and next + move. + | E.g. `[0, 1]` + + | **.hash_fold**\ () + | Returns a list of moves representing the current conformation. + | *Parameters:* + | * **None** + | *Returns:* + | * **List[int]** - a list of moves. + | E.g. `[1, 2, -1]` + + | **.is_hydro**\ (*index*) + | Returns if the amino acid at the given index is an H. + | *Parameters:* + | * **index** - *int*: index of the amino acid. + | *Returns:* + | * **bool** - A boolean indicating if the amino acid is an H. + + | **.is_valid**\ (*move*) + | Returns if the given move is a valid next move. + | *Parameters:* + | * **move** - *int*: possible next move to perform. + | *Returns:* + | * **bool** - A boolean indicating if the given move is valid. + + | **.place_amino**\ (*move, track=True*) + | Places the next amino acid in the given direction. + | *Parameters:* + | * **move** - *int*: direction to place the next amino acid. + | * **track** - *bool (optional)*: set to True if the move + should be tracked as a change. + | *Returns:* + | * **None** + + | **.remove_amino**\ () + | Removes the previously placed amino acid. + | *Parameters:* + | * **None** + | *Returns:* + | * **None** + + | **.reset**\ () + | Reset the whole Protein as if it was just created. + | *Parameters:* + | * **None** + | *Returns:* + | * **None** + + | **.reset_conformation**\ () + | Reset the placement of amino acids for the given Protein. Also sets + the *.score* property to 0. + | *Parameters:* + | * **None** + | *Returns:* + | * **None** + + | **.set_hash**\ (*fold_hash*) + | Set the conformation to the given sequence of moves. + | *Parameters:* + | * **fold_hash** - *List[int]*: a list of moves as provided by + **.hash_fold()**. + | *Returns:* + | * **None** + +Visualize +--------- +Functions from the visualize module of Prospr can be used to illustrate your +research. Each function can be imported from the *prospr.visualize* submodule, +e.g. + +.. code-block:: python + + from prospr.visualize import plot_protein +.. + + | **plot_protein**\ (*protein*) + | Plots the current set conformation of the given Protein object. + | *Parameters:* + | * **protein** - *Protein*: a Protein object to plot the + conformation of. + | *Returns:* + | * **None** diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..3a236f0 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,63 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = "prospr" +copyright = "2021, Okke van Eck" +author = "Okke van Eck" + +# The full version, including alpha/beta/rc tags +release = "0.2a3" + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ["sphinx.ext.autosectionlabel"] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "alabaster" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +html_theme_options = { + "logo": "prospr_logo.png", + "description": "Optimized Protein folding in Python and C++.", + "description_font_style": "italic", + "github_user": "OkkeVanEck", + "github_repo": "prospr", + "github_type": "star", +} diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..0041006 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,35 @@ +.. prospr documentation master file, created by + sphinx-quickstart on Fri Apr 30 14:15:36 2021. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Prospr: The Protein Structure Prediction Toolbox +================================================ +Release v\ |release| + +Welcome to Prospr's documentation! Prospr is a Python toolbox for protein +structure prediction, build on a C++ core. The Python package can be used when +quick development is of key, and when Prospr's datasets and visualization module +are of interest. The C++ core is available as a standalone for all +high-performance computing applications. Ideally, the C++ core is used for time +efficient data gathering, while the Python package is used for managing +experiments. However, the Python package wraps all the C++ core's functionality, +hence one can solely rely on using the Python package. + +See the :doc:`installation` and :doc:`quickstart` pages for an easy introduction +to the basics of Prospr. There is also the :doc:`api` where all +functionality of Prospr is explained in-depth per module. It is recommended to +first take a look at the :doc:`quickstart` before consulting the :doc:`api`. + +The source code of Prospr is publicly available on +`GitHub `_. All code is licenced under the +:ref:`LGPL V3 license`. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + installation + quickstart + api + license diff --git a/docs/source/installation.rst b/docs/source/installation.rst new file mode 100644 index 0000000..e4a9fcd --- /dev/null +++ b/docs/source/installation.rst @@ -0,0 +1,65 @@ +.. How to install Prospr. + +Installation +============ +One can choose to use the Python package, or only the C++ core. The C++ core is +handy for maximizing the execution speed of your experiments, while the Python +package may lower development time and offers more functionality. Installation +instructions are provided for both scenarios. + + +Python package +-------------- +Prospr offers support for Python 3.6 and newer. However, using the latest Python +version is always recommended. The instructions below assume that a new project +will be set up. + +Virtual environments +~~~~~~~~~~~~~~~~~~~~ +It is recommended to use a new virtual environment for each Python project. An +easy way to setup a new virtual environment is via the **venv** module that +comes with Python 3. After creation, one must activate the virtual environment +before installing any packages. Examples for Linux/MacOS and Windows are given +below. + +For Linux/MacOS: + +.. code-block:: text + + $ python3 -m venv venv + $ source venv/bin/activate + +For Windows: + +.. code-block:: text + + > py -3 -m venv venv + > venv/Scripts/activate + +Installing Prospr +~~~~~~~~~~~~~~~~~ +After activating the environment, use pip to install Prospr: + +.. code-block:: bash + + $ pip install prospr + +Congratulations! Prospr is now installed. Check out the :doc:`quickstart` +to see how to use the basics, or read the :doc:`api` for all functionality. + + +C++ core +-------- +Using the C++ core for your project is very easy. Follow the installation steps +below and include the header files you want to use in your code. + +Installing Prospr +~~~~~~~~~~~~~~~~~ +Using the C++ core is very easy. Download a *prospr_core* archive from the +`archives `_ folder +on GitHub, then drag the source files to your code directory. Add the files to +your Makefile in order to compile the Prospr files with your project. No +additional libraries need to be linked during compile time. + +Congratulations! Prospr is now installed. Check out the :doc:`quickstart` +to see how to use the basics, or read the :doc:`api` for all functionality. diff --git a/docs/source/license.rst b/docs/source/license.rst new file mode 100644 index 0000000..d302a96 --- /dev/null +++ b/docs/source/license.rst @@ -0,0 +1,6 @@ +.. Include of the License files provided within the repo. + +License +======= + +.. literalinclude:: ../../LICENSE diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst new file mode 100644 index 0000000..1dbf0db --- /dev/null +++ b/docs/source/quickstart.rst @@ -0,0 +1,348 @@ +.. Quickstart for using Prospr for the first time. + +Quickstart +========== +One can choose to use the Python package, or only the C++ core. The C++ core is +handy for maximizing the execution speed of your experiments, while the Python +package may lower development time and offers more functionality. + +Example usage is given using the Python package and only shows basic usage. +Please refer to the :doc:`api` to see the equivalent usage in C++ and all +functionality. + +Please take a look at the :doc:`installation` page first to see how Prospr can +be installed. + +Creating Proteins +----------------- +After installing Prospr, one can simply create a Protein object as +follows: + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPHPPH") + p_3d = Protein("HPPHPPH", dim=3) + p_4d = Protein("HPPHPPH", dim=4) + p_5d = Protein("HPPHPPH", dim=5) + ... + +Protein attributes +------------------ +A Protein object keeps track of multiple properties while it is being folded. +These properties can be checked as attributes of the Protein object. Below all +properties are listed, but please refer to the :doc:`api` to see what they +all keep track of exactly. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + + p_2d.sequence + >>> "HPPH" + + p_2d.h_idxs + >>> [0, 3] + + p_2d.cur_len + >>> 0 + + p_2d.dim + >>> 2 + + p_2d.last_move + >>> 0 + + p_2d.last_pos + >>> [0, 0] + + p_2d.score + >>> 0 + + p_2d.changes + >>> 0 + +Placing amino acids +------------------- +A Protein object is generated with the first amino acid fixed at the origin. +One can place the next amino acid via the *.place_amino(move)* function. +This function takes a move as an argument, which is a number representing the +axis to move over. As an example, 1 can be seen as the x-axis, 2 as the y-axis, +etc. Negative numbers represent movement in negative direction. + +.. code-block:: python + + ... + p_2d.place_amino(1) + p_2d.place_amino(2) + p_2d.place_amino(-1) + +Removing amino acids +-------------------- +Amino acids can be removed via the *.remove_amino()* function. + +.. code-block:: python + + ... + p_2d.remove_amino() # Leaving the previous moves [1, 2] + p_2d.remove_amino() # Leaving the previous move [1] + +Validating moves +---------------- +Before trying to place an amino acid, it it is recommended to check whether the +move is valid. This can be done via the *.is_valid(move)* function, which takes +the requested move as an argument. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.is_valid(1) + >>> True + + p_2d.place_amino(1) + p_2d.is_valid(-1) + >>> False + +Placement information +--------------------- +While writing algorithms, it might be necessary to check what amino acid is +placed at a specific spot, or where the previous and next ones are placed. This +can be checked via the *.get_amino(position)* function, which takes a list of +integers representing the requested position as an argument. It returns a list +containing the amino acids index, previous direction, and next direction. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.place_amino(1) + p_2d.place_amino(2) + p_2d.get_amino([1, 0]) + >>> [1, -1, 2] + +It might also occur that you want to check if an amino acid at a specific index +is hydrophilic. This can be checked via the *.is_hydro(index)* function, which +takes the index of the requested amino acid as an argument. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.is_hydro(0) + >>> True + + p_2d.is_hydro(1) + >>> False + +Checking stability +------------------ +The stability of a (partially) folded Protein is tracked in the *.score* +attribute. This attribute changes dynamically when placing and removing amino +acids. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.place_amino(1) + p_2d.place_amino(2) + p_2d.score + >>> 0 + + p_2d.place_amino(-1) + p_2d.score + >>> -1 + +|no_score| |with_score| + +.. |no_score| image:: _static/quickstart_example_fold_no_score.png + :width: 49% + +.. |with_score| image:: _static/quickstart_example_fold.png + :width: 49% + +Checking number of changes +-------------------------- +In order to compare the efficiency of algorithms, a Protein object also keeps +track of the number of moves performed thus far. This does not include the +removal of amino acids. The current number of performed moves is tracked in the +*.changes* attribute. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.place_amino(1) + p_2d.changes + >>> 1 + + p_2d.place_amino(2) + p_2d.remove_amino() + p_2d.place_amino(-2) + p_2d.place_amino(-1) + p_2d.changes + >>> 4 + +Hashing folds +------------- +The current fold of a Protein can be generated via the *.hash_fold()* function. +The function will return the sequence of moves for the current conformation. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.place_amino(1) + p_2d.hash_fold() + >>> [1] + + p_2d.place_amino(2) + p_2d.place_amino(-1) + p_2d.hash_fold() + >>> [1, 2, -1] + +Setting folds +------------- +At any time, a Protein's conformation can be set to a given set of moves. This +is done via the *.set_hash(fold_hash)* function, which takes a sequence of moves +as an argument, just like the ones generated by the *.hash_fold()* function. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.place_amino(2) + p_2d.place_amino(-1) + p_2d.hash_fold() + >>> [2, -1] + + p_2d.set_hash([1, 2, -1]) + p_2d.hash_fold() + >>> [1, 2, -1] + +Resetting Proteins +------------------ +Sometimes you might want to reset a Protein object. This can be because you want +to reuse the same Protein object, or because you want to clear the conformation. +Each of these scenarios has their own function. + +In order to reset the whole Protein object, use the *.reset()* function. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.place_amino(1) + p_2d.place_amino(2) + p_2d.place_amino(-1) + p_2d.changes + >>> 3 + + p_2d.hash_fold() + >>> [1, 2, -1] + + p_2d.reset() + p_2d.changes + >>> 0 + + p_2d.hash_fold() + >>> [] + +Use the *.reset_conformation()* function to only reset the placement of the +amino acids. This includes setting the *.score* to 0, as only the amino acid in +the origin remains in place. + +.. code-block:: python + + from prospr import Protein + + p_2d = Protein("HPPH") + p_2d.place_amino(1) + p_2d.place_amino(2) + p_2d.place_amino(-1) + p_2d.changes + >>> 3 + + p_2d.hash_fold() + >>> [1, 2, -1] + + p_2d.reset_conformation() + p_2d.changes + >>> 3 + + p_2d.hash_fold() + >>> [] + +Built-in algorithms +------------------- +Prospr offers some algorithms for finding the most optimal conformation of a +Protein. These are included in the C++ core, making them time efficient relative +to Python alternatives. The :doc:`api` contain a list of all available +built-in algorithms. They can all easily be used via a direct import, as is +shown below. + +.. code-block:: python + + from prospr import Protein, depth_first + + p_2d = Protein("HPPH") + p_2d = depth_first(p_2d) + p_2d.score + >>> 1 + + p_2d.hash_fold() + >> [1, 2, -1] + +Visualizing conformations +------------------------- +Visualizing conformations can be key to understanding how the optimal +conformation was found. It also helps illustrating your research. Prospr's +Python package has a built-in visualization module so you do not have to write +your own. Visualizing a conformation can easily be done via the *plot_protein()* +function from the *prospr.visualize* module. + +.. code-block:: python + + from prospr import Protein + from prospr.visualize import plot_protein + + p_2d = Protein("HPPH") + p_2d.place_amino(1) + p_2d.place_amino(2) + p_2d.place_amino(-1) + plot_protein(p_2d) + >>> + +.. image:: _static/quickstart_example_fold.png + :alt: Image of an example fold. + :align: center + :scale: 85 + +Using datasets +-------------- +Datasets are valuable for a fair comparison between algorithms. That is why +Prospr's Python package comes with a built-in collection of datasets. Loading a +dataset can easily be done via the available load functions in the +*prospr.datasets* module. Please refer to the :doc:`api` for all available +datasets. + +.. code-block:: python + + from prospr.datasets import load_vanEck250 + + length_10 = load_vanEck250() + length_15 = load_vanEck250(15) + length_20 = load_vanEck250(20) + ... diff --git a/prospr/core/core_module.cpp b/prospr/core/core_module.cpp index b3ac817..7f5213e 100644 --- a/prospr/core/core_module.cpp +++ b/prospr/core/core_module.cpp @@ -19,14 +19,14 @@ PYBIND11_MODULE(prospr_core, m) { py::class_(m, "Protein") .def(py::init(), "Protein constructor", py::arg("sequence"), py::arg("dim")=2) - .def_property_readonly("sequence", &Protein::get_sequence) - .def_property_readonly("h_idxs", &Protein::get_h_idxs) + .def_property_readonly("changes", &Protein::get_changes) .def_property_readonly("cur_len", &Protein::get_cur_len) .def_property_readonly("dim", &Protein::get_dim) + .def_property_readonly("h_idxs", &Protein::get_h_idxs) .def_property_readonly("last_move", &Protein::get_last_move) .def_property_readonly("last_pos", &Protein::get_last_pos) .def_property_readonly("score", &Protein::get_score) - .def_property_readonly("changes", &Protein::get_changes) + .def_property_readonly("sequence", &Protein::get_sequence) .def("get_amino", &Protein::get_amino, "Get amino index and next direction from amino at given position", diff --git a/prospr/core/src/protein.hpp b/prospr/core/src/protein.hpp index f82ccb1..cc01896 100644 --- a/prospr/core/src/protein.hpp +++ b/prospr/core/src/protein.hpp @@ -29,6 +29,7 @@ class Protein { void place_amino(int move, bool track=true); // TODO: Change function to use the last_move attribute. void remove_amino(int move); + // TODO: Make the change_score function private. void change_score(int move, int weight); std::vector hash_fold(); void set_hash(std::vector fold_hash, bool track=false); diff --git a/requirements.txt b/requirements.txt index 6750941..31f48bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,5 +7,6 @@ pytest==6.2.3 pytest-order==0.11.0 seaborn==0.10.1 setuptools>=49.2.0 +sphinx==3.5.4 twine>=3.2.0 wheel>=0.34.2 diff --git a/setup.py b/setup.py index 75f4e64..e1d68f4 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ from setuptools import setup from pybind11.setup_helpers import Pybind11Extension, build_ext -__version__ = "0.2a2" +__version__ = "0.2a3" # Define core module extension. ext_modules = [