napistu 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- napistu/__init__.py +12 -0
- napistu/__main__.py +867 -0
- napistu/consensus.py +1557 -0
- napistu/constants.py +500 -0
- napistu/gcs/__init__.py +10 -0
- napistu/gcs/constants.py +69 -0
- napistu/gcs/downloads.py +180 -0
- napistu/identifiers.py +805 -0
- napistu/indices.py +227 -0
- napistu/ingestion/__init__.py +10 -0
- napistu/ingestion/bigg.py +146 -0
- napistu/ingestion/constants.py +296 -0
- napistu/ingestion/cpr_edgelist.py +106 -0
- napistu/ingestion/identifiers_etl.py +148 -0
- napistu/ingestion/obo.py +268 -0
- napistu/ingestion/psi_mi.py +276 -0
- napistu/ingestion/reactome.py +218 -0
- napistu/ingestion/sbml.py +621 -0
- napistu/ingestion/string.py +356 -0
- napistu/ingestion/trrust.py +285 -0
- napistu/ingestion/yeast.py +147 -0
- napistu/mechanism_matching.py +597 -0
- napistu/modify/__init__.py +10 -0
- napistu/modify/constants.py +86 -0
- napistu/modify/curation.py +628 -0
- napistu/modify/gaps.py +635 -0
- napistu/modify/pathwayannot.py +1381 -0
- napistu/modify/uncompartmentalize.py +264 -0
- napistu/network/__init__.py +10 -0
- napistu/network/constants.py +117 -0
- napistu/network/neighborhoods.py +1594 -0
- napistu/network/net_create.py +1647 -0
- napistu/network/net_utils.py +652 -0
- napistu/network/paths.py +500 -0
- napistu/network/precompute.py +221 -0
- napistu/rpy2/__init__.py +127 -0
- napistu/rpy2/callr.py +168 -0
- napistu/rpy2/constants.py +101 -0
- napistu/rpy2/netcontextr.py +464 -0
- napistu/rpy2/rids.py +697 -0
- napistu/sbml_dfs_core.py +2216 -0
- napistu/sbml_dfs_utils.py +304 -0
- napistu/source.py +394 -0
- napistu/utils.py +943 -0
- napistu-0.1.0.dist-info/METADATA +56 -0
- napistu-0.1.0.dist-info/RECORD +77 -0
- napistu-0.1.0.dist-info/WHEEL +5 -0
- napistu-0.1.0.dist-info/entry_points.txt +2 -0
- napistu-0.1.0.dist-info/licenses/LICENSE +21 -0
- napistu-0.1.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/conftest.py +83 -0
- tests/test_consensus.py +255 -0
- tests/test_constants.py +20 -0
- tests/test_curation.py +134 -0
- tests/test_data/__init__.py +0 -0
- tests/test_edgelist.py +20 -0
- tests/test_gcs.py +23 -0
- tests/test_identifiers.py +151 -0
- tests/test_igraph.py +353 -0
- tests/test_indices.py +88 -0
- tests/test_mechanism_matching.py +126 -0
- tests/test_net_utils.py +66 -0
- tests/test_netcontextr.py +105 -0
- tests/test_obo.py +34 -0
- tests/test_pathwayannot.py +95 -0
- tests/test_precomputed_distances.py +222 -0
- tests/test_rpy2.py +61 -0
- tests/test_sbml.py +46 -0
- tests/test_sbml_dfs_create.py +307 -0
- tests/test_sbml_dfs_utils.py +22 -0
- tests/test_sbo.py +11 -0
- tests/test_set_coverage.py +50 -0
- tests/test_source.py +67 -0
- tests/test_uncompartmentalize.py +40 -0
- tests/test_utils.py +487 -0
- tests/utils.py +30 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: napistu
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: Connecting high-dimensional data to curated pathways
|
5
|
+
Home-page: https://github.com/napistu/napistu-py
|
6
|
+
Author: Sean Hackett
|
7
|
+
Author-email: seanmchackett@gmail.com
|
8
|
+
Project-URL: Bug Tracker, https://github.com/napistu/napistu-py/issues
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
13
|
+
Requires-Python: >=3.11
|
14
|
+
Description-Content-Type: text/markdown
|
15
|
+
License-File: LICENSE
|
16
|
+
Requires-Dist: Jinja2
|
17
|
+
Requires-Dist: PyYAML==6.*
|
18
|
+
Requires-Dist: click==8.*
|
19
|
+
Requires-Dist: click-logging
|
20
|
+
Requires-Dist: fs==2.4.*
|
21
|
+
Requires-Dist: fs-gcsfs==1.5.*
|
22
|
+
Requires-Dist: igraph
|
23
|
+
Requires-Dist: matplotlib==3.*
|
24
|
+
Requires-Dist: numpy==1.26.*
|
25
|
+
Requires-Dist: pandas==1.5.*
|
26
|
+
Requires-Dist: pydantic==2.*
|
27
|
+
Requires-Dist: python-libsbml
|
28
|
+
Requires-Dist: requests>=2
|
29
|
+
Requires-Dist: scipy==1.14.*
|
30
|
+
Requires-Dist: tqdm
|
31
|
+
Requires-Dist: zeep==3.*
|
32
|
+
Provides-Extra: dev
|
33
|
+
Requires-Dist: black==25.*; extra == "dev"
|
34
|
+
Requires-Dist: ipykernel; extra == "dev"
|
35
|
+
Requires-Dist: pre-commit==3.3.*; extra == "dev"
|
36
|
+
Requires-Dist: pytest==7.*; extra == "dev"
|
37
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
38
|
+
Requires-Dist: ruff; extra == "dev"
|
39
|
+
Requires-Dist: testcontainers; extra == "dev"
|
40
|
+
Provides-Extra: rpy2
|
41
|
+
Requires-Dist: pyarrow==18.0.0; extra == "rpy2"
|
42
|
+
Requires-Dist: rpy2==3.5.*; extra == "rpy2"
|
43
|
+
Requires-Dist: rpy2-arrow==0.1.1; extra == "rpy2"
|
44
|
+
Dynamic: license-file
|
45
|
+
|
46
|
+
# Napistu Python Library
|
47
|
+
|
48
|
+
This Python package hosts the majority of the algorithmic code for the [Napistu project](https://github.com/napistu/napistu).
|
49
|
+
|
50
|
+
## Setup
|
51
|
+
|
52
|
+
Currently the only way to use this repository is to clone the repo and perform a local install. e.g., from this directory:
|
53
|
+
|
54
|
+
```bash
|
55
|
+
pip install .
|
56
|
+
```
|
@@ -0,0 +1,77 @@
|
|
1
|
+
napistu/__init__.py,sha256=rz6NdV9Fm6a6bBR17VQPHeJQD4DUZWC7zR9a7nNMOhw,269
|
2
|
+
napistu/__main__.py,sha256=i1OyReHD58GjyGYShXmMuBfA0VoGBF9dirg2nA4JCa8,28334
|
3
|
+
napistu/consensus.py,sha256=p8GjWFzq1cvBB-H-LVSatWL_9fxbdYq2wsF4-JZnc_M,54641
|
4
|
+
napistu/constants.py,sha256=hQ1OLH07xFTxMukJLCptzqqHk22vgrByej8lvMb2qbc,14702
|
5
|
+
napistu/identifiers.py,sha256=wque0qsMZK2AMsAhkF1ERSMrEF7h6b5SMp3iqVu8e1o,28796
|
6
|
+
napistu/indices.py,sha256=UeJjjsYs0sGvZIKz1y4ZQ6aUkABn-6TCUDZ2VCVT9JI,7534
|
7
|
+
napistu/mechanism_matching.py,sha256=CPhtM6GERmGlBK8zH1cEvSpsasa0mG7ojLKDOze3dyE,21704
|
8
|
+
napistu/sbml_dfs_core.py,sha256=iSng-3cpJVpVMb340YGM6s0pFBTA9SyYCdYvHdZRSMA,79387
|
9
|
+
napistu/sbml_dfs_utils.py,sha256=j6Bu3acqOFSEbyVzASXhlnV8hQvi4k-vdMYzVMPzz5A,10318
|
10
|
+
napistu/source.py,sha256=oBgw2OZLVBETQG8Mwoc5ZUe-6cg_Yt6Mxsto3fCdw1k,13386
|
11
|
+
napistu/utils.py,sha256=G4IfG_WBSxkn5RBdPPn9sAkzrz2BdKgXlFFmMsB9wsA,28038
|
12
|
+
napistu/gcs/__init__.py,sha256=1kqmRHlEyI7VpILzurZb1URwC_UIc1PTMEBHQnjXW6s,246
|
13
|
+
napistu/gcs/constants.py,sha256=rc-oQBh6pdu7cjqTCerHG_fDub-FQcEjzWh2ic715cs,2844
|
14
|
+
napistu/gcs/downloads.py,sha256=EiOxLW1MMexdPTSiakWknTB-BGY1y__s2n1z9Sd8VYM,5033
|
15
|
+
napistu/ingestion/__init__.py,sha256=1kqmRHlEyI7VpILzurZb1URwC_UIc1PTMEBHQnjXW6s,246
|
16
|
+
napistu/ingestion/bigg.py,sha256=XPJZv64mrIMCuKe1mjQfS5QPR9tmengGvndSjc3QFLA,5559
|
17
|
+
napistu/ingestion/constants.py,sha256=TYATiVNrLyuQ1AvLVt35F1xQ8pQ3U19o_N6ZSkdW3PA,9941
|
18
|
+
napistu/ingestion/cpr_edgelist.py,sha256=eVT9M7gmdBuGHcAYlvkD_zzvTtyzXufKWjwDiT8OxF4,3572
|
19
|
+
napistu/ingestion/identifiers_etl.py,sha256=6ppDUA6lEZurdmVbiFLOUzphYbr-hndMhtqsQnq_yAc,5009
|
20
|
+
napistu/ingestion/obo.py,sha256=pszLLfImZxDYjL3WQUCow2hQFURROGHqIq3qbgVtzAM,8836
|
21
|
+
napistu/ingestion/psi_mi.py,sha256=Icj73EK75ytFPBw-TH2B6yW1ZWAmckmn5mtPl9pIxuA,9389
|
22
|
+
napistu/ingestion/reactome.py,sha256=-Q3GsAsfVkTD7cDD1fLEEnWQbI6vs7nxsdYInk7ZvVE,7907
|
23
|
+
napistu/ingestion/sbml.py,sha256=gK6_jHgo6oaiG16WlrbBSvxq_0VzFR4a5fG9IQrp5bU,24153
|
24
|
+
napistu/ingestion/string.py,sha256=tsaHrjppgFbl9NnRcB2DytpoontqrpfQL65zD9HPgEM,11668
|
25
|
+
napistu/ingestion/trrust.py,sha256=ccjZc_eF3PdxxurnukiEo_e0-aKc_3z22NYbaJBtHdY,9774
|
26
|
+
napistu/ingestion/yeast.py,sha256=bwFBNxRq-dLDaddgBL1hpfZj0eQ56nBXyR_9n0NZT9Y,5233
|
27
|
+
napistu/modify/__init__.py,sha256=1kqmRHlEyI7VpILzurZb1URwC_UIc1PTMEBHQnjXW6s,246
|
28
|
+
napistu/modify/constants.py,sha256=KHigix_8A8kCLWYVGR9_6_n34UNDcq2guDLC1KLeNZ4,2648
|
29
|
+
napistu/modify/curation.py,sha256=UNeAfJ26XDFvSwkPL8WHCAP0FQYiVUrSvJn3UIt5jy8,21607
|
30
|
+
napistu/modify/gaps.py,sha256=XqwfvzgJywA7ws5hzDlj22xs5tRGc4xOdbQ2v51UJqc,23983
|
31
|
+
napistu/modify/pathwayannot.py,sha256=onbQy9YNYPbeOih8fSxymxUQJc1jXjRIQOABv3xkvng,47183
|
32
|
+
napistu/modify/uncompartmentalize.py,sha256=U5X4Q7Z-YIkC8_711x3sU21vTVdv9rKfauwz4JNzl6c,9690
|
33
|
+
napistu/network/__init__.py,sha256=1kqmRHlEyI7VpILzurZb1URwC_UIc1PTMEBHQnjXW6s,246
|
34
|
+
napistu/network/constants.py,sha256=jz8vRjgns74piUcvmoIP_f-8s9w15SxWAEw2lf6XmDY,3661
|
35
|
+
napistu/network/neighborhoods.py,sha256=TopPpcUD09bAfJuT_L4dkHwJhV1VJJlzXpyzldYi85A,55512
|
36
|
+
napistu/network/net_create.py,sha256=9Rb5I6uLlL50SNADucsT_90F9k7rzmp2EQfEgNlr37E,60343
|
37
|
+
napistu/network/net_utils.py,sha256=cMWLOHlz4XvPA8PlPiSFYNDjAEv4t1qlZxwabBaZrK8,21188
|
38
|
+
napistu/network/paths.py,sha256=a2J3JWIdMufdNs8Amh6I7s3TOVD2EzLV9khqbWHvGlA,16652
|
39
|
+
napistu/network/precompute.py,sha256=83Vr2pxCmEtJJmE_Lq1BI-pEmESDNG0N7vByXjBf_oQ,7517
|
40
|
+
napistu/rpy2/__init__.py,sha256=B9tZHiEp6bvysjqvBRQ1aGY493Ks9kouwb0pW7KsKqA,4100
|
41
|
+
napistu/rpy2/callr.py,sha256=76ICWj7Jso-qrYLNfiV-DgPyrMTdRXz_EhyGOD9CbFM,4301
|
42
|
+
napistu/rpy2/constants.py,sha256=JpJqsxImZis8fFFfePXYdbkhUZhXDZoHSHVf92w1h8U,2619
|
43
|
+
napistu/rpy2/netcontextr.py,sha256=gkpBgrASNeH_8IjFyY-Tj-S87HjNOkGdfMta0WRdEnU,16278
|
44
|
+
napistu/rpy2/rids.py,sha256=sGMTRuOQRDpHBHZwfTS7uKUW9TBI_yMpht6SFhup8vw,23937
|
45
|
+
napistu-0.1.0.dist-info/licenses/LICENSE,sha256=kW8wVT__JWoHjl2BbbJDAZInWa9AxzJeR_uv6-i5x1g,1063
|
46
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
|
+
tests/conftest.py,sha256=uDuqgZKR37csoUI4t4U-pzEoANMFAIyTA4k8XLRu_Bw,2572
|
48
|
+
tests/test_consensus.py,sha256=u_5Hyocz2peNbJMd5ydgoAwQ4il0lFm-PrzrckTCitI,9403
|
49
|
+
tests/test_constants.py,sha256=gJLDv7QMeeBiiupyMazj6mumk20KWvGMgm2myHMKKfc,531
|
50
|
+
tests/test_curation.py,sha256=-Q2J0D7qs9PGjHZX-rM4NxRLLdwxoapytSo_98q9ItY,3864
|
51
|
+
tests/test_edgelist.py,sha256=bdEtQJdd4MeQsNtng9afHYNVDsEy0U07sfVwguAdIBM,560
|
52
|
+
tests/test_gcs.py,sha256=sq-zIDfmLIpZ5oFKCmyuaw9tfSzAY5hSnpuN-xqiqpk,561
|
53
|
+
tests/test_identifiers.py,sha256=RyuPAMhYI8cDOl2r62idweLxgy7rAs9omeZQ62h56kY,5019
|
54
|
+
tests/test_igraph.py,sha256=HoYeFAAFXWtxdonnUTpV59-jCLicNa0_utPaaGKXMAw,10926
|
55
|
+
tests/test_indices.py,sha256=-TrKfX4qXsofg_TPQEhHaQc_CuQMEd4_0maJgGCgSfE,2468
|
56
|
+
tests/test_mechanism_matching.py,sha256=gD_n2saM7yYa56QU0RMAYMKMAk7oF8ESbM7GHbI6bFY,4156
|
57
|
+
tests/test_net_utils.py,sha256=4HqfFF6yycAz7oQYRz6MefzQVQ_ZjWpeUEA4lUDOMJc,1614
|
58
|
+
tests/test_netcontextr.py,sha256=PKH0D-8EL0HNrCMtF-fAaYv5Lao4mwVPDZLQ5LHJXqc,3399
|
59
|
+
tests/test_obo.py,sha256=47qNCElPzu2nA36Oq83Dqp1RGhITqztjl7UyZ5cMsj4,959
|
60
|
+
tests/test_pathwayannot.py,sha256=bceosccNy9tgxQei_7j7ATBSSvBSxOngJvK-mAzR_K0,3312
|
61
|
+
tests/test_precomputed_distances.py,sha256=ht7lVz0wGOOQl9UTI1o9ftm0Dk7q8E40UV2jxVmE-Tg,7203
|
62
|
+
tests/test_rpy2.py,sha256=beihvGlWsQA9U7V3tfqBIOUL-S8m8Nj84Bg2Wt2sNH8,1491
|
63
|
+
tests/test_sbml.py,sha256=w_VU06psAP0Ku3B0flbP4hKhBfx2ZWV3oOdUgWzrMP4,1276
|
64
|
+
tests/test_sbml_dfs_create.py,sha256=w29mUcnC6g9Yqp8Q3b-oRQc5GiDvzjS5_GOE_LjwGZo,9982
|
65
|
+
tests/test_sbml_dfs_utils.py,sha256=onFWdhrTix30XR1-CMrMXld37BYxEGi6TZrweugLDzI,505
|
66
|
+
tests/test_sbo.py,sha256=x_PENFaXYsrZIzOZu9cj_Wrej7i7SNGxgBYYvcigLs0,308
|
67
|
+
tests/test_set_coverage.py,sha256=gM6Zl3MhVRHUi0_z0ISqpeXckWT8XdpXb58ipCoWyHU,1606
|
68
|
+
tests/test_source.py,sha256=hT0IlpexR5zP0OhWl5BBaho9d1aCYQlFZLwRIRRnw_Y,1969
|
69
|
+
tests/test_uncompartmentalize.py,sha256=nAk5kfAVLU9a2VWe2x2HYVcKqj-EnwmwddERIPRax8c,1289
|
70
|
+
tests/test_utils.py,sha256=knOWMN9xgaNLDj_4T_ZI3f22p1ZqovRLVDBFaMhOnFs,14845
|
71
|
+
tests/utils.py,sha256=SoWQ_5roJteFGcMaOeEiQ5ucwq3Z2Fa3AAs9iXHTsJY,749
|
72
|
+
tests/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
73
|
+
napistu-0.1.0.dist-info/METADATA,sha256=bFJYn_d8Q0WfF5fpnE5tRZAqU3jNHuxXV0xyI-bt0yk,1830
|
74
|
+
napistu-0.1.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
75
|
+
napistu-0.1.0.dist-info/entry_points.txt,sha256=_QnaPOvJNA3IltxmZgWIiBoen-L1bPYX18YQfC7oJgQ,41
|
76
|
+
napistu-0.1.0.dist-info/top_level.txt,sha256=Gpvk0a_PjrtqhYcQ9IDr3zR5LqpZ-uIHidQMIpjlvhY,14
|
77
|
+
napistu-0.1.0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Calico
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
tests/__init__.py
ADDED
File without changes
|
tests/conftest.py
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
|
6
|
+
from napistu import consensus
|
7
|
+
from napistu import indices
|
8
|
+
from napistu import sbml_dfs_core
|
9
|
+
from napistu.ingestion import sbml
|
10
|
+
from pytest import fixture
|
11
|
+
from pytest import skip
|
12
|
+
|
13
|
+
|
14
|
+
@fixture
|
15
|
+
def sbml_path():
|
16
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
17
|
+
sbml_path = os.path.join(test_path, "test_data", "R-HSA-1237044.sbml")
|
18
|
+
|
19
|
+
if not os.path.isfile(sbml_path):
|
20
|
+
raise ValueError(f"{sbml_path} not found")
|
21
|
+
return sbml_path
|
22
|
+
|
23
|
+
|
24
|
+
@fixture
|
25
|
+
def sbml_model(sbml_path):
|
26
|
+
sbml_model = sbml.SBML(sbml_path)
|
27
|
+
return sbml_model
|
28
|
+
|
29
|
+
|
30
|
+
@fixture
|
31
|
+
def sbml_dfs(sbml_model):
|
32
|
+
sbml_dfs = sbml_dfs_core.SBML_dfs(sbml_model)
|
33
|
+
return sbml_dfs
|
34
|
+
|
35
|
+
|
36
|
+
@fixture
|
37
|
+
def sbml_dfs_metabolism():
|
38
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
39
|
+
test_data = os.path.join(test_path, "test_data")
|
40
|
+
|
41
|
+
pw_index = indices.PWIndex(os.path.join(test_data, "pw_index_metabolism.tsv"))
|
42
|
+
sbml_dfs_dict = consensus.construct_sbml_dfs_dict(pw_index)
|
43
|
+
sbml_dfs = consensus.construct_consensus_model(sbml_dfs_dict, pw_index)
|
44
|
+
|
45
|
+
return sbml_dfs
|
46
|
+
|
47
|
+
|
48
|
+
@fixture
|
49
|
+
def sbml_dfs_glucose_metabolism():
|
50
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
51
|
+
test_data = os.path.join(test_path, "test_data")
|
52
|
+
sbml_path = os.path.join(test_data, "reactome_glucose_metabolism.sbml")
|
53
|
+
|
54
|
+
sbml_model = sbml.SBML(sbml_path).model
|
55
|
+
sbml_dfs = sbml_dfs_core.SBML_dfs(sbml_model)
|
56
|
+
|
57
|
+
return sbml_dfs
|
58
|
+
|
59
|
+
|
60
|
+
# Define custom markers for platforms
|
61
|
+
def pytest_configure(config):
|
62
|
+
config.addinivalue_line("markers", "skip_on_windows: mark test to skip on Windows")
|
63
|
+
config.addinivalue_line("markers", "skip_on_macos: mark test to skip on macOS")
|
64
|
+
config.addinivalue_line("markers", "unix_only: mark test to run only on Unix/Linux systems")
|
65
|
+
|
66
|
+
# Define platform conditions
|
67
|
+
is_windows = sys.platform == "win32"
|
68
|
+
is_macos = sys.platform == "darwin"
|
69
|
+
is_unix = not (is_windows or is_macos)
|
70
|
+
|
71
|
+
# Apply skipping based on platform
|
72
|
+
def pytest_runtest_setup(item):
|
73
|
+
# Skip tests marked to be skipped on Windows
|
74
|
+
if is_windows and any(mark.name == "skip_on_windows" for mark in item.iter_markers()):
|
75
|
+
skip("Test skipped on Windows")
|
76
|
+
|
77
|
+
# Skip tests marked to be skipped on macOS
|
78
|
+
if is_macos and any(mark.name == "skip_on_macos" for mark in item.iter_markers()):
|
79
|
+
skip("Test skipped on macOS")
|
80
|
+
|
81
|
+
# Skip tests that should run only on Unix
|
82
|
+
if not is_unix and any(mark.name == "unix_only" for mark in item.iter_markers()):
|
83
|
+
skip("Test runs only on Unix systems")
|
tests/test_consensus.py
ADDED
@@ -0,0 +1,255 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
|
5
|
+
import pandas as pd
|
6
|
+
import pytest
|
7
|
+
from napistu import consensus
|
8
|
+
from napistu import indices
|
9
|
+
from napistu import source
|
10
|
+
from napistu.ingestion import sbml
|
11
|
+
from napistu.modify import pathwayannot
|
12
|
+
|
13
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
14
|
+
test_data = os.path.join(test_path, "test_data")
|
15
|
+
|
16
|
+
|
17
|
+
def test_reduce_to_consensus_ids():
|
18
|
+
sbml_path = os.path.join(test_data, "R-HSA-1237044.sbml")
|
19
|
+
|
20
|
+
# test aggregating by IDs, by moving from compartmentalized_species -> species
|
21
|
+
|
22
|
+
sbml_model = sbml.SBML(sbml_path).model
|
23
|
+
comp_species_df = sbml.setup_cspecies(sbml_model)
|
24
|
+
comp_species_df.index.names = ["s_id"]
|
25
|
+
consensus_species, species_lookup = consensus.reduce_to_consensus_ids(
|
26
|
+
comp_species_df, {"pk": "s_id", "id": "s_Identifiers"}
|
27
|
+
)
|
28
|
+
|
29
|
+
assert isinstance(consensus_species, pd.DataFrame)
|
30
|
+
assert consensus_species.shape == (18, 4)
|
31
|
+
assert isinstance(species_lookup, pd.Series)
|
32
|
+
assert species_lookup.size == 23
|
33
|
+
|
34
|
+
|
35
|
+
def test_consensus():
|
36
|
+
pw_index = indices.PWIndex(os.path.join(test_data, "pw_index.tsv"))
|
37
|
+
sbml_dfs_dict = consensus.construct_sbml_dfs_dict(pw_index)
|
38
|
+
|
39
|
+
consensus_model = consensus.construct_consensus_model(sbml_dfs_dict, pw_index)
|
40
|
+
assert consensus_model.species.shape == (38, 3)
|
41
|
+
assert consensus_model.reactions.shape == (30, 4)
|
42
|
+
assert consensus_model.reaction_species.shape == (137, 4)
|
43
|
+
|
44
|
+
consensus_model = pathwayannot.drop_cofactors(consensus_model)
|
45
|
+
assert consensus_model.species.shape == (38, 3)
|
46
|
+
assert consensus_model.reaction_species.shape == (52, 4)
|
47
|
+
# update reaction_species.shape after more cofactors identified
|
48
|
+
|
49
|
+
consensus_model.validate()
|
50
|
+
|
51
|
+
|
52
|
+
def test_source_tracking():
|
53
|
+
# create input data
|
54
|
+
table_schema = {"source": "source_var", "pk": "primary_key"}
|
55
|
+
|
56
|
+
# define existing sources and the new_id entity they belong to
|
57
|
+
# here, we are assuming that each model has a blank source object
|
58
|
+
# as if it came from a non-consensus model
|
59
|
+
agg_tbl = pd.DataFrame(
|
60
|
+
{
|
61
|
+
"new_id": [0, 0, 1, 1],
|
62
|
+
}
|
63
|
+
)
|
64
|
+
agg_tbl[table_schema["source"]] = source.Source(init=True)
|
65
|
+
|
66
|
+
# define new_ids and the models they came from
|
67
|
+
# these models will be matched to the pw_index to flush out metadata
|
68
|
+
lookup_table = pd.DataFrame(
|
69
|
+
{
|
70
|
+
"new_id": [0, 0, 1, 1],
|
71
|
+
"model": ["R-HSA-1237044", "R-HSA-425381", "R-HSA-1237044", "R-HSA-425381"],
|
72
|
+
}
|
73
|
+
)
|
74
|
+
|
75
|
+
# use an existing pw_index since pw_index currently checks for the existence of the source file
|
76
|
+
pw_index = indices.PWIndex(os.path.join(test_data, "pw_index.tsv"))
|
77
|
+
|
78
|
+
# test create source table
|
79
|
+
source_table = source.create_source_table(lookup_table, table_schema, pw_index)
|
80
|
+
assert source_table["source_var"][0].source.shape == (2, 8)
|
81
|
+
|
82
|
+
# test create_consensus_sources
|
83
|
+
consensus_sources = consensus.create_consensus_sources(
|
84
|
+
agg_tbl, lookup_table, table_schema, pw_index
|
85
|
+
)
|
86
|
+
assert consensus_sources[0].source.shape == (2, 8)
|
87
|
+
|
88
|
+
# lets add a model which does not have a reference in the pw_index
|
89
|
+
invalid_lookup_table = pd.DataFrame(
|
90
|
+
{
|
91
|
+
"new_id": [0, 0, 1, 1],
|
92
|
+
"model": ["R-HSA-1237044", "R-HSA-425381", "R-HSA-1237044", "typo"],
|
93
|
+
}
|
94
|
+
)
|
95
|
+
|
96
|
+
# expect a ValueError when the model is not found
|
97
|
+
with pytest.raises(ValueError) as _:
|
98
|
+
source.create_source_table(invalid_lookup_table, table_schema, pw_index)
|
99
|
+
|
100
|
+
# now we will aggregate the consensus model above with a new single model (which has some
|
101
|
+
# overlapping entries with the consensusd (id 1) and some new ids (id 2)
|
102
|
+
|
103
|
+
agg_tbl2 = pd.DataFrame(
|
104
|
+
{
|
105
|
+
"new_id": [0, 1, 1, 2],
|
106
|
+
}
|
107
|
+
)
|
108
|
+
|
109
|
+
agg_tbl2[table_schema["source"]] = consensus_sources.tolist() + [
|
110
|
+
source.Source(init=True) for i in range(0, 2)
|
111
|
+
]
|
112
|
+
|
113
|
+
lookup_table2 = pd.DataFrame(
|
114
|
+
{
|
115
|
+
"new_id": [0, 1, 1, 2],
|
116
|
+
# the model for the first two entries should really correspond to the "consensus"
|
117
|
+
# but since this is not a file I will stub with one of the pw_index entries
|
118
|
+
"model": [
|
119
|
+
"R-HSA-1247673",
|
120
|
+
"R-HSA-1247673",
|
121
|
+
"R-HSA-1475029",
|
122
|
+
"R-HSA-1475029",
|
123
|
+
],
|
124
|
+
}
|
125
|
+
)
|
126
|
+
|
127
|
+
source_table = source.create_source_table(lookup_table2, table_schema, pw_index)
|
128
|
+
assert source_table.shape == (3, 1)
|
129
|
+
assert [
|
130
|
+
source_table["source_var"][i].source.shape
|
131
|
+
for i in range(0, source_table.shape[0])
|
132
|
+
] == [(1, 8), (2, 8), (1, 8)]
|
133
|
+
|
134
|
+
consensus_sources = consensus.create_consensus_sources(
|
135
|
+
agg_tbl2, lookup_table2, table_schema, pw_index
|
136
|
+
)
|
137
|
+
assert [
|
138
|
+
consensus_sources[i].source.shape for i in range(0, consensus_sources.shape[0])
|
139
|
+
] == [(3, 8), (4, 8), (1, 8)]
|
140
|
+
|
141
|
+
|
142
|
+
def test_passing_entity_data():
|
143
|
+
pw_index = indices.PWIndex(os.path.join(test_data, "pw_index.tsv"))
|
144
|
+
sbml_dfs_dict = consensus.construct_sbml_dfs_dict(pw_index)
|
145
|
+
|
146
|
+
for model in list(sbml_dfs_dict.keys())[0:3]:
|
147
|
+
sbml_dfs_dict[model].add_species_data(
|
148
|
+
"my_species_data",
|
149
|
+
sbml_dfs_dict[model]
|
150
|
+
.species.iloc[0:5]
|
151
|
+
.assign(my_species_data_var="testing")["my_species_data_var"]
|
152
|
+
.to_frame(),
|
153
|
+
)
|
154
|
+
sbml_dfs_dict[model].add_reactions_data(
|
155
|
+
"my_reactions_data",
|
156
|
+
sbml_dfs_dict[model]
|
157
|
+
.reactions.iloc[0:5]
|
158
|
+
.assign(my_reactions_data_var1="testing")
|
159
|
+
.assign(my_reactions_data_var2="testing2")[
|
160
|
+
["my_reactions_data_var1", "my_reactions_data_var2"]
|
161
|
+
],
|
162
|
+
)
|
163
|
+
|
164
|
+
# create a consensus with perfect merges of overlapping id-table-variable values
|
165
|
+
# i.e., when combined all merged entries have the same attributes
|
166
|
+
consensus_model = consensus.construct_consensus_model(sbml_dfs_dict, pw_index)
|
167
|
+
|
168
|
+
assert len(consensus_model.species_data) == 1
|
169
|
+
assert consensus_model.species_data["my_species_data"].shape == (10, 1)
|
170
|
+
assert len(consensus_model.reactions_data) == 1
|
171
|
+
assert consensus_model.reactions_data["my_reactions_data"].shape == (14, 2)
|
172
|
+
|
173
|
+
# add different tables from different models
|
174
|
+
for model in list(sbml_dfs_dict.keys())[3:5]:
|
175
|
+
sbml_dfs_dict[model].add_species_data(
|
176
|
+
"my_other_species_data",
|
177
|
+
sbml_dfs_dict[model]
|
178
|
+
.species.iloc[0:5]
|
179
|
+
.assign(my_species_data="testing")["my_species_data"]
|
180
|
+
.to_frame(),
|
181
|
+
)
|
182
|
+
|
183
|
+
consensus_model = consensus.construct_consensus_model(sbml_dfs_dict, pw_index)
|
184
|
+
assert len(consensus_model.species_data) == 2
|
185
|
+
|
186
|
+
# create a case where reactions will be merged and the same reaction
|
187
|
+
# in different models has a different value for its reactions_data
|
188
|
+
minimal_pw_index = pw_index
|
189
|
+
minimal_pw_index.index = minimal_pw_index.index.iloc[0:2]
|
190
|
+
minimal_pw_index.index["file"].loc[1] = minimal_pw_index.index["file"][0]
|
191
|
+
|
192
|
+
duplicated_sbml_dfs_dict = consensus.construct_sbml_dfs_dict(minimal_pw_index)
|
193
|
+
# explicitely define the order we'll loop through models so that
|
194
|
+
# the position of a model can be used to set mismatching attributes
|
195
|
+
# for otherwise identical models
|
196
|
+
model_order = list(duplicated_sbml_dfs_dict.keys())
|
197
|
+
|
198
|
+
for model in duplicated_sbml_dfs_dict.keys():
|
199
|
+
model_index = model_order.index(model)
|
200
|
+
|
201
|
+
duplicated_sbml_dfs_dict[model].add_reactions_data(
|
202
|
+
"my_mismatched_data",
|
203
|
+
duplicated_sbml_dfs_dict[model]
|
204
|
+
.reactions.iloc[0:5]
|
205
|
+
.assign(my_reactions_data_var1=model)["my_reactions_data_var1"]
|
206
|
+
.to_frame()
|
207
|
+
.assign(numeric_var=[x + model_index for x in range(0, 5)])
|
208
|
+
.assign(bool_var=[x + model_index % 2 == 0 for x in range(0, 5)]),
|
209
|
+
)
|
210
|
+
|
211
|
+
# assign reversibility is True for one model to
|
212
|
+
# confirm that reversibility trumps irreversible
|
213
|
+
# when merging reactions with identical stoichiometry but
|
214
|
+
# different reversibility attributes
|
215
|
+
|
216
|
+
duplicated_sbml_dfs_dict["R-HSA-1237044"].reactions = duplicated_sbml_dfs_dict[
|
217
|
+
"R-HSA-1237044"
|
218
|
+
].reactions.assign(r_isreversible=True)
|
219
|
+
|
220
|
+
consensus_model = consensus.construct_consensus_model(
|
221
|
+
duplicated_sbml_dfs_dict, pw_index
|
222
|
+
)
|
223
|
+
assert consensus_model.reactions_data["my_mismatched_data"].shape == (5, 3)
|
224
|
+
assert consensus_model.reactions["r_isreversible"].eq(True).all()
|
225
|
+
|
226
|
+
|
227
|
+
def test_consensus_ontology_check():
|
228
|
+
pw_index = indices.PWIndex(os.path.join(test_data, "pw_index.tsv"))
|
229
|
+
|
230
|
+
test_sbml_dfs_dict = consensus.construct_sbml_dfs_dict(pw_index)
|
231
|
+
test_consensus_model = consensus.construct_consensus_model(
|
232
|
+
test_sbml_dfs_dict, pw_index
|
233
|
+
)
|
234
|
+
|
235
|
+
pre_shared_onto_sp_list, pre_onto_df = consensus.pre_consensus_ontology_check(
|
236
|
+
test_sbml_dfs_dict, "species"
|
237
|
+
)
|
238
|
+
assert set(pre_shared_onto_sp_list) == {"chebi", "reactome", "uniprot"}
|
239
|
+
|
240
|
+
post_shared_onto_sp_set = consensus.post_consensus_species_ontology_check(
|
241
|
+
test_consensus_model
|
242
|
+
)
|
243
|
+
assert post_shared_onto_sp_set == {"chebi", "reactome", "uniprot"}
|
244
|
+
|
245
|
+
|
246
|
+
################################################
|
247
|
+
# __main__
|
248
|
+
################################################
|
249
|
+
|
250
|
+
if __name__ == "__main__":
|
251
|
+
test_reduce_to_consensus_ids()
|
252
|
+
test_consensus()
|
253
|
+
test_source_tracking()
|
254
|
+
test_passing_entity_data()
|
255
|
+
test_consensus_ontology_check()
|
tests/test_constants.py
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from napistu import constants
|
4
|
+
|
5
|
+
|
6
|
+
def test_sbo_constants():
|
7
|
+
# all SBO terms in "MINI_SBO" set have a role
|
8
|
+
assert set(constants.SBO_NAME_TO_ROLE.keys()) == set(
|
9
|
+
constants.MINI_SBO_FROM_NAME.keys()
|
10
|
+
)
|
11
|
+
# all roles are valid
|
12
|
+
assert [x in constants.VALID_SBO_ROLES for x in constants.SBO_NAME_TO_ROLE.values()]
|
13
|
+
|
14
|
+
|
15
|
+
################################################
|
16
|
+
# __main__
|
17
|
+
################################################
|
18
|
+
|
19
|
+
if __name__ == "__main__":
|
20
|
+
test_sbo_constants()
|
tests/test_curation.py
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
|
5
|
+
import pandas as pd
|
6
|
+
from napistu import sbml_dfs_core
|
7
|
+
from napistu.ingestion import sbml
|
8
|
+
from napistu.modify import curation
|
9
|
+
|
10
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
11
|
+
sbml_path = os.path.join(test_path, "test_data", "R-HSA-1237044.sbml")
|
12
|
+
|
13
|
+
if not os.path.isfile(sbml_path):
|
14
|
+
raise ValueError(f"{sbml_path} not found")
|
15
|
+
|
16
|
+
# setup mock curations
|
17
|
+
curation_dict = dict()
|
18
|
+
curation_dict["species"] = pd.DataFrame(
|
19
|
+
[
|
20
|
+
{
|
21
|
+
"species": "hello",
|
22
|
+
"uri": "http://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:35828",
|
23
|
+
"curator": "Sean",
|
24
|
+
},
|
25
|
+
{"species": "good day", "uri": None, "curator": "Sean"},
|
26
|
+
]
|
27
|
+
)
|
28
|
+
|
29
|
+
curation_dict["compartmentalized_species"] = pd.DataFrame(
|
30
|
+
[
|
31
|
+
{
|
32
|
+
"compartmentalized_species": "hello [cytosol]",
|
33
|
+
"s_name": "hello",
|
34
|
+
"c_name": "cytosol",
|
35
|
+
"curator": "Sean",
|
36
|
+
}
|
37
|
+
]
|
38
|
+
)
|
39
|
+
|
40
|
+
curation_dict["reactions"] = pd.DataFrame(
|
41
|
+
[
|
42
|
+
{
|
43
|
+
"reactions": "there",
|
44
|
+
"stoichiometry": "hello [cytosol] -> CO2 [cytosol]",
|
45
|
+
"uri": None,
|
46
|
+
"evidence": "how is",
|
47
|
+
"curator": "Sean",
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"reactions": "where",
|
51
|
+
"stoichiometry": "CO2 [cytosol] -> hello [cytosol]",
|
52
|
+
"uri": None,
|
53
|
+
"evidence": "your family",
|
54
|
+
"curator": "Sean",
|
55
|
+
},
|
56
|
+
]
|
57
|
+
)
|
58
|
+
|
59
|
+
curation_dict["reaction_species"] = pd.DataFrame(
|
60
|
+
[
|
61
|
+
{
|
62
|
+
"reaction_species": "NADH [cytosol]",
|
63
|
+
"r_name": "CYB5Rs reduce MetHb to HbA",
|
64
|
+
"stoichiometry": 0,
|
65
|
+
"sbo_term_name": "stimulator",
|
66
|
+
"evidence": "weeeee",
|
67
|
+
"curator": "Sean",
|
68
|
+
}
|
69
|
+
]
|
70
|
+
)
|
71
|
+
|
72
|
+
curation_dict["remove"] = pd.DataFrame(
|
73
|
+
[
|
74
|
+
{"remove": "reaction_1237042", "table": "reactions", "variable": "r_id"},
|
75
|
+
{
|
76
|
+
"remove": "CYB5Rs reduce MetHb to HbA",
|
77
|
+
"table": "reactions",
|
78
|
+
"variable": "r_name",
|
79
|
+
},
|
80
|
+
{"remove": "CO2", "table": "species", "variable": "s_name"},
|
81
|
+
]
|
82
|
+
)
|
83
|
+
|
84
|
+
|
85
|
+
def test_remove_entities():
|
86
|
+
sbml_model = sbml.SBML(sbml_path)
|
87
|
+
sbml_dfs = sbml_dfs_core.SBML_dfs(sbml_model)
|
88
|
+
sbml_dfs.validate()
|
89
|
+
|
90
|
+
invalid_entities_dict = curation._find_invalid_entities(
|
91
|
+
sbml_dfs, curation_dict["remove"]
|
92
|
+
)
|
93
|
+
invalid_pks = set(invalid_entities_dict.keys())
|
94
|
+
|
95
|
+
assert invalid_pks == {"sc_id", "rsc_id", "r_id", "s_id"}
|
96
|
+
|
97
|
+
n_species = sbml_dfs.species.shape[0]
|
98
|
+
n_reactions = sbml_dfs.reactions.shape[0]
|
99
|
+
n_compartmentalized_species = sbml_dfs.compartmentalized_species.shape[0]
|
100
|
+
n_reaction_species = sbml_dfs.reaction_species.shape[0]
|
101
|
+
# should be untouched
|
102
|
+
n_compartments = sbml_dfs.compartments.shape[0]
|
103
|
+
|
104
|
+
sbml_dfs = curation._remove_entities(sbml_dfs, invalid_entities_dict)
|
105
|
+
|
106
|
+
assert n_species - sbml_dfs.species.shape[0] == 1
|
107
|
+
assert n_reactions - sbml_dfs.reactions.shape[0] == 2
|
108
|
+
assert (
|
109
|
+
n_compartmentalized_species - sbml_dfs.compartmentalized_species.shape[0] == 2
|
110
|
+
)
|
111
|
+
assert n_reaction_species - sbml_dfs.reaction_species.shape[0] == 14
|
112
|
+
assert n_compartments - sbml_dfs.compartments.shape[0] == 0
|
113
|
+
|
114
|
+
|
115
|
+
def test_add_entities():
|
116
|
+
sbml_model = sbml.SBML(sbml_path)
|
117
|
+
sbml_dfs = sbml_dfs_core.SBML_dfs(sbml_model)
|
118
|
+
sbml_dfs.validate()
|
119
|
+
|
120
|
+
new_entities = curation.format_curations(curation_dict, sbml_dfs)
|
121
|
+
|
122
|
+
assert new_entities["species"].shape == (2, 3)
|
123
|
+
assert new_entities["reactions"].shape == (2, 4)
|
124
|
+
assert new_entities["compartmentalized_species"].shape == (1, 4)
|
125
|
+
assert new_entities["reaction_species"].shape == (5, 4)
|
126
|
+
|
127
|
+
|
128
|
+
################################################
|
129
|
+
# __main__
|
130
|
+
################################################
|
131
|
+
|
132
|
+
if __name__ == "__main__":
|
133
|
+
test_remove_entities()
|
134
|
+
test_add_entities()
|
File without changes
|