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
tests/test_edgelist.py
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import pandas as pd
|
4
|
+
from napistu.ingestion import cpr_edgelist
|
5
|
+
|
6
|
+
|
7
|
+
def test_edgelist_remove_reciprocal_reactions():
|
8
|
+
edgelist = pd.DataFrame({"from": ["A", "B", "C", "D"], "to": ["B", "A", "D", "C"]})
|
9
|
+
|
10
|
+
nondegenerate_edgelist = cpr_edgelist.remove_reciprocal_interactions(edgelist)
|
11
|
+
|
12
|
+
assert nondegenerate_edgelist.shape == (2, 2)
|
13
|
+
|
14
|
+
|
15
|
+
################################################
|
16
|
+
# __main__
|
17
|
+
################################################
|
18
|
+
|
19
|
+
if __name__ == "__main__":
|
20
|
+
test_edgelist_remove_reciprocal_reactions()
|
tests/test_gcs.py
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
import pytest
|
5
|
+
import shutil
|
6
|
+
|
7
|
+
from napistu.gcs.downloads import load_public_cpr_asset
|
8
|
+
|
9
|
+
@pytest.mark.skip_on_windows
|
10
|
+
def test_download_and_load_gcs_asset():
|
11
|
+
|
12
|
+
local_path = load_public_cpr_asset(
|
13
|
+
asset="test_pathway", subasset="sbml_dfs", data_dir="/tmp"
|
14
|
+
)
|
15
|
+
|
16
|
+
assert local_path == "/tmp/test_pathway/sbml_dfs.pkl"
|
17
|
+
|
18
|
+
# clean-up
|
19
|
+
clean_up_dir = "/tmp/test_pathway"
|
20
|
+
shutil.rmtree(clean_up_dir)
|
21
|
+
|
22
|
+
if os.path.exists(clean_up_dir):
|
23
|
+
raise Exception(f"Failed to clean up {clean_up_dir}")
|
@@ -0,0 +1,151 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
import pandas as pd
|
7
|
+
from napistu import identifiers
|
8
|
+
|
9
|
+
# logger = logging.getLogger()
|
10
|
+
# logger.setLevel("DEBUG")
|
11
|
+
|
12
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
13
|
+
identifier_examples = pd.read_csv(
|
14
|
+
os.path.join(test_path, "test_data", "identifier_examples.tsv"),
|
15
|
+
sep="\t",
|
16
|
+
header=0,
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
def test_identifiers():
|
21
|
+
assert (
|
22
|
+
identifiers.Identifiers(
|
23
|
+
[{"ontology": "KEGG", "identifier": "C00031", "bqb": "BQB_IS"}]
|
24
|
+
).ids[0]["ontology"]
|
25
|
+
== "KEGG"
|
26
|
+
)
|
27
|
+
|
28
|
+
example_identifiers = identifiers.Identifiers(
|
29
|
+
[
|
30
|
+
{"ontology": "SGD", "identifier": "S000004535", "bqb": "BQB_IS"},
|
31
|
+
{"ontology": "foo", "identifier": "bar", "bqb": "BQB_IS"},
|
32
|
+
]
|
33
|
+
)
|
34
|
+
|
35
|
+
assert type(example_identifiers) is identifiers.Identifiers
|
36
|
+
|
37
|
+
assert example_identifiers.filter("SGD") is True
|
38
|
+
assert example_identifiers.filter("baz") is False
|
39
|
+
assert example_identifiers.filter("SGD", summarize=False) == [True, False]
|
40
|
+
assert example_identifiers.filter(["SGD", "foo"], summarize=False) == [True, True]
|
41
|
+
assert example_identifiers.filter(["foo", "SGD"], summarize=False) == [True, True]
|
42
|
+
assert example_identifiers.filter(["baz", "bar"], summarize=False) == [False, False]
|
43
|
+
|
44
|
+
assert example_identifiers.hoist("SGD") == "S000004535"
|
45
|
+
assert example_identifiers.hoist("baz") is None
|
46
|
+
|
47
|
+
|
48
|
+
def test_identifiers_from_urls():
|
49
|
+
for i in range(0, identifier_examples.shape[0]):
|
50
|
+
# print(identifier_examples["url"][i])
|
51
|
+
testIdentifiers = identifiers.Identifiers(
|
52
|
+
[
|
53
|
+
identifiers.format_uri(
|
54
|
+
identifier_examples["url"][i], biological_qualifier_type="BQB_IS"
|
55
|
+
)
|
56
|
+
]
|
57
|
+
)
|
58
|
+
|
59
|
+
# print(f"ontology = {testIdentifiers.ids[0]['ontology']}; identifier = {testIdentifiers.ids[0]['identifier']}")
|
60
|
+
assert (
|
61
|
+
testIdentifiers.ids[0]["ontology"] == identifier_examples["ontology"][i]
|
62
|
+
), f"ontology {testIdentifiers.ids[0]['ontology']} does not equal {identifier_examples['ontology'][i]}"
|
63
|
+
|
64
|
+
assert (
|
65
|
+
testIdentifiers.ids[0]["identifier"] == identifier_examples["identifier"][i]
|
66
|
+
), f"identifier {testIdentifiers.ids[0]['identifier']} does not equal {identifier_examples['identifier'][i]}"
|
67
|
+
|
68
|
+
|
69
|
+
def test_url_from_identifiers():
|
70
|
+
for row in identifier_examples.iterrows():
|
71
|
+
# some urls (e.g., chebi) will be converted to a canonical url (e.g., chebi) since multiple URIs exist
|
72
|
+
|
73
|
+
if row[1]["canonical_url"] is not np.nan:
|
74
|
+
expected_url_out = row[1]["canonical_url"]
|
75
|
+
else:
|
76
|
+
expected_url_out = row[1]["url"]
|
77
|
+
|
78
|
+
url_out = identifiers.create_uri_url(
|
79
|
+
ontology=row[1]["ontology"], identifier=row[1]["identifier"]
|
80
|
+
)
|
81
|
+
|
82
|
+
# print(f"expected: {expected_url_out}; observed: {url_out}")
|
83
|
+
assert url_out == expected_url_out
|
84
|
+
|
85
|
+
# test non-strict treatment
|
86
|
+
|
87
|
+
assert (
|
88
|
+
identifiers.create_uri_url(ontology="chebi", identifier="abc", strict=False)
|
89
|
+
is None
|
90
|
+
)
|
91
|
+
|
92
|
+
|
93
|
+
def test_parsing_ensembl_ids():
|
94
|
+
ensembl_examples = {
|
95
|
+
# human foxp2
|
96
|
+
"ENSG00000128573": ("ENSG00000128573", "ensembl_gene", "Homo sapiens"),
|
97
|
+
"ENST00000441290": ("ENST00000441290", "ensembl_transcript", "Homo sapiens"),
|
98
|
+
"ENSP00000265436": ("ENSP00000265436", "ensembl_protein", "Homo sapiens"),
|
99
|
+
# mouse leptin
|
100
|
+
"ENSMUSG00000059201": ("ENSMUSG00000059201", "ensembl_gene", "Mus musculus"),
|
101
|
+
"ENSMUST00000069789": (
|
102
|
+
"ENSMUST00000069789",
|
103
|
+
"ensembl_transcript",
|
104
|
+
"Mus musculus",
|
105
|
+
),
|
106
|
+
# substrings are okay
|
107
|
+
"gene=ENSMUSG00000017146": (
|
108
|
+
"ENSMUSG00000017146",
|
109
|
+
"ensembl_gene",
|
110
|
+
"Mus musculus",
|
111
|
+
),
|
112
|
+
}
|
113
|
+
|
114
|
+
for k, v in ensembl_examples.items():
|
115
|
+
assert identifiers.parse_ensembl_id(k) == v
|
116
|
+
|
117
|
+
|
118
|
+
def test_reciprocal_ensembl_dicts():
|
119
|
+
assert len(identifiers.ENSEMBL_SPECIES_TO_CODE) == len(
|
120
|
+
identifiers.ENSEMBL_SPECIES_FROM_CODE
|
121
|
+
)
|
122
|
+
for k in identifiers.ENSEMBL_SPECIES_TO_CODE.keys():
|
123
|
+
assert (
|
124
|
+
identifiers.ENSEMBL_SPECIES_FROM_CODE[
|
125
|
+
identifiers.ENSEMBL_SPECIES_TO_CODE[k]
|
126
|
+
]
|
127
|
+
== k
|
128
|
+
)
|
129
|
+
|
130
|
+
assert len(identifiers.ENSEMBL_MOLECULE_TYPES_TO_ONTOLOGY) == len(
|
131
|
+
identifiers.ENSEMBL_MOLECULE_TYPES_FROM_ONTOLOGY
|
132
|
+
)
|
133
|
+
for k in identifiers.ENSEMBL_MOLECULE_TYPES_TO_ONTOLOGY.keys():
|
134
|
+
assert (
|
135
|
+
identifiers.ENSEMBL_MOLECULE_TYPES_FROM_ONTOLOGY[
|
136
|
+
identifiers.ENSEMBL_MOLECULE_TYPES_TO_ONTOLOGY[k]
|
137
|
+
]
|
138
|
+
== k
|
139
|
+
)
|
140
|
+
|
141
|
+
|
142
|
+
################################################
|
143
|
+
# __main__
|
144
|
+
################################################
|
145
|
+
|
146
|
+
if __name__ == "__main__":
|
147
|
+
test_identifiers()
|
148
|
+
test_identifiers_from_urls()
|
149
|
+
test_url_from_identifiers()
|
150
|
+
test_parsing_ensembl_ids()
|
151
|
+
test_reciprocal_ensembl_dicts()
|
tests/test_igraph.py
ADDED
@@ -0,0 +1,353 @@
|
|
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.constants import DEFAULT_WT_TRANS
|
8
|
+
from napistu.constants import MINI_SBO_FROM_NAME
|
9
|
+
from napistu.ingestion import sbml
|
10
|
+
from napistu.network import neighborhoods
|
11
|
+
from napistu.network import net_create
|
12
|
+
from napistu.network import net_utils
|
13
|
+
from napistu.network import paths
|
14
|
+
|
15
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
16
|
+
test_data = os.path.join(test_path, "test_data")
|
17
|
+
|
18
|
+
sbml_path = os.path.join(test_data, "R-HSA-1237044.sbml")
|
19
|
+
sbml_model = sbml.SBML(sbml_path).model
|
20
|
+
sbml_dfs = sbml_dfs_core.SBML_dfs(sbml_model)
|
21
|
+
|
22
|
+
# create a dict containing reaction species for a few example reactions
|
23
|
+
reaction_species_examples_dict = dict()
|
24
|
+
|
25
|
+
# stub with a random reaction
|
26
|
+
r_id = sbml_dfs.reactions.index[0]
|
27
|
+
|
28
|
+
reaction_species_examples_dict["valid_interactor"] = pd.DataFrame(
|
29
|
+
{
|
30
|
+
"r_id": [r_id, r_id],
|
31
|
+
"sbo_term": [
|
32
|
+
MINI_SBO_FROM_NAME["interactor"],
|
33
|
+
MINI_SBO_FROM_NAME["interactor"],
|
34
|
+
],
|
35
|
+
"sc_id": ["sc1", "sc2"],
|
36
|
+
"stoichiometry": [0, 0],
|
37
|
+
}
|
38
|
+
).set_index(["r_id", "sbo_term"])
|
39
|
+
|
40
|
+
reaction_species_examples_dict["invalid_interactor"] = pd.DataFrame(
|
41
|
+
{
|
42
|
+
"r_id": [r_id, r_id],
|
43
|
+
"sbo_term": [
|
44
|
+
MINI_SBO_FROM_NAME["interactor"],
|
45
|
+
MINI_SBO_FROM_NAME["product"],
|
46
|
+
],
|
47
|
+
"sc_id": ["sc1", "sc2"],
|
48
|
+
"stoichiometry": [0, 0],
|
49
|
+
}
|
50
|
+
).set_index(["r_id", "sbo_term"])
|
51
|
+
|
52
|
+
|
53
|
+
# simple reaction with just substrates and products
|
54
|
+
reaction_species_examples_dict["sub_and_prod"] = pd.DataFrame(
|
55
|
+
{
|
56
|
+
"r_id": [r_id, r_id],
|
57
|
+
"sbo_term": [MINI_SBO_FROM_NAME["reactant"], MINI_SBO_FROM_NAME["product"]],
|
58
|
+
"sc_id": ["sub", "prod"],
|
59
|
+
"stoichiometry": [-1, 1],
|
60
|
+
}
|
61
|
+
).set_index(["r_id", "sbo_term"])
|
62
|
+
|
63
|
+
reaction_species_examples_dict["stimulator"] = pd.DataFrame(
|
64
|
+
{
|
65
|
+
"r_id": [r_id, r_id, r_id],
|
66
|
+
"sbo_term": [
|
67
|
+
MINI_SBO_FROM_NAME["reactant"],
|
68
|
+
MINI_SBO_FROM_NAME["product"],
|
69
|
+
MINI_SBO_FROM_NAME["stimulator"],
|
70
|
+
],
|
71
|
+
"sc_id": ["sub", "prod", "stim"],
|
72
|
+
"stoichiometry": [-1, 1, 0],
|
73
|
+
}
|
74
|
+
).set_index(["r_id", "sbo_term"])
|
75
|
+
|
76
|
+
reaction_species_examples_dict["all_entities"] = pd.DataFrame(
|
77
|
+
{
|
78
|
+
"r_id": [r_id, r_id, r_id, r_id],
|
79
|
+
"sbo_term": [
|
80
|
+
MINI_SBO_FROM_NAME["reactant"],
|
81
|
+
MINI_SBO_FROM_NAME["product"],
|
82
|
+
MINI_SBO_FROM_NAME["stimulator"],
|
83
|
+
MINI_SBO_FROM_NAME["catalyst"],
|
84
|
+
],
|
85
|
+
"sc_id": ["sub", "prod", "stim", "cat"],
|
86
|
+
"stoichiometry": [-1, 1, 0, 0],
|
87
|
+
}
|
88
|
+
).set_index(["r_id", "sbo_term"])
|
89
|
+
|
90
|
+
reaction_species_examples_dict["no_substrate"] = pd.DataFrame(
|
91
|
+
{
|
92
|
+
"r_id": [r_id, r_id, r_id, r_id, r_id],
|
93
|
+
"sbo_term": [
|
94
|
+
MINI_SBO_FROM_NAME["product"],
|
95
|
+
MINI_SBO_FROM_NAME["stimulator"],
|
96
|
+
MINI_SBO_FROM_NAME["stimulator"],
|
97
|
+
MINI_SBO_FROM_NAME["inhibitor"],
|
98
|
+
MINI_SBO_FROM_NAME["catalyst"],
|
99
|
+
],
|
100
|
+
"sc_id": ["prod", "stim1", "stim2", "inh", "cat"],
|
101
|
+
"stoichiometry": [1, 0, 0, 0, 0],
|
102
|
+
}
|
103
|
+
).set_index(["r_id", "sbo_term"])
|
104
|
+
|
105
|
+
|
106
|
+
def test_create_cpr_graph():
|
107
|
+
_ = net_create.create_cpr_graph(sbml_dfs, graph_type="bipartite")
|
108
|
+
_ = net_create.create_cpr_graph(sbml_dfs, graph_type="regulatory")
|
109
|
+
_ = net_create.create_cpr_graph(sbml_dfs, graph_type="surrogate")
|
110
|
+
|
111
|
+
|
112
|
+
def test_igraph_construction():
|
113
|
+
_ = net_create.process_cpr_graph(sbml_dfs)
|
114
|
+
|
115
|
+
|
116
|
+
def test_igraph_loading():
|
117
|
+
# test read/write of an igraph network
|
118
|
+
directeds = [True, False]
|
119
|
+
graph_types = ["bipartite", "regulatory"]
|
120
|
+
|
121
|
+
net_utils.export_networks(
|
122
|
+
sbml_dfs,
|
123
|
+
model_prefix="tmp",
|
124
|
+
outdir="/tmp",
|
125
|
+
directeds=directeds,
|
126
|
+
graph_types=graph_types,
|
127
|
+
)
|
128
|
+
|
129
|
+
for graph_type in graph_types:
|
130
|
+
for directed in directeds:
|
131
|
+
import_pkl_path = net_utils._create_network_save_string(
|
132
|
+
model_prefix="tmp",
|
133
|
+
outdir="/tmp",
|
134
|
+
directed=directed,
|
135
|
+
graph_type=graph_type,
|
136
|
+
)
|
137
|
+
network_graph = net_utils.read_network_pkl(
|
138
|
+
model_prefix="tmp",
|
139
|
+
network_dir="/tmp",
|
140
|
+
directed=directed,
|
141
|
+
graph_type=graph_type,
|
142
|
+
)
|
143
|
+
|
144
|
+
assert network_graph.is_directed() == directed
|
145
|
+
# cleanup
|
146
|
+
os.unlink(import_pkl_path)
|
147
|
+
|
148
|
+
|
149
|
+
def test_shortest_paths():
|
150
|
+
species = sbml_dfs.species
|
151
|
+
source_species = species[species["s_name"] == "NADH"]
|
152
|
+
dest_species = species[species["s_name"] == "NAD+"]
|
153
|
+
target_species_paths = net_utils.compartmentalize_species_pairs(
|
154
|
+
sbml_dfs, source_species.index.tolist(), dest_species.index.tolist()
|
155
|
+
)
|
156
|
+
|
157
|
+
# directed graph
|
158
|
+
cpr_graph = net_create.process_cpr_graph(
|
159
|
+
sbml_dfs, directed=True, weighting_strategy="topology"
|
160
|
+
)
|
161
|
+
(
|
162
|
+
all_shortest_reaction_paths_df,
|
163
|
+
all_shortest_reaction_path_edges_df,
|
164
|
+
edge_sources,
|
165
|
+
paths_graph,
|
166
|
+
) = paths.find_all_shortest_reaction_paths(
|
167
|
+
cpr_graph, sbml_dfs, target_species_paths, weight_var="weights"
|
168
|
+
)
|
169
|
+
|
170
|
+
# undirected graph
|
171
|
+
cpr_graph = net_create.process_cpr_graph(
|
172
|
+
sbml_dfs, directed=False, weighting_strategy="topology"
|
173
|
+
)
|
174
|
+
(
|
175
|
+
all_shortest_reaction_paths_df,
|
176
|
+
all_shortest_reaction_path_edges_df,
|
177
|
+
edge_sources,
|
178
|
+
paths_graph,
|
179
|
+
) = paths.find_all_shortest_reaction_paths(
|
180
|
+
cpr_graph, sbml_dfs, target_species_paths, weight_var="weights"
|
181
|
+
)
|
182
|
+
|
183
|
+
assert all_shortest_reaction_paths_df.shape[0] == 3
|
184
|
+
|
185
|
+
|
186
|
+
def test_neighborhood():
|
187
|
+
species = sbml_dfs.species
|
188
|
+
source_species = species[species["s_name"] == "NADH"].index.tolist()
|
189
|
+
|
190
|
+
query_sc_species = net_utils.compartmentalize_species(sbml_dfs, source_species)
|
191
|
+
compartmentalized_species = query_sc_species["sc_id"].tolist()
|
192
|
+
|
193
|
+
cpr_graph = net_create.process_cpr_graph(
|
194
|
+
sbml_dfs, directed=True, weighting_strategy="topology"
|
195
|
+
)
|
196
|
+
|
197
|
+
neighborhood = neighborhoods.find_neighborhoods(
|
198
|
+
sbml_dfs,
|
199
|
+
cpr_graph,
|
200
|
+
compartmentalized_species=compartmentalized_species,
|
201
|
+
order=3,
|
202
|
+
)
|
203
|
+
|
204
|
+
assert neighborhood["species_73473"]["vertices"].shape[0] == 6
|
205
|
+
|
206
|
+
|
207
|
+
def test_format_interactors():
|
208
|
+
# interactions are formatted
|
209
|
+
|
210
|
+
graph_hierarchy_df = net_create._create_graph_hierarchy_df("regulatory")
|
211
|
+
|
212
|
+
assert (
|
213
|
+
net_create._format_tiered_reaction_species(
|
214
|
+
r_id,
|
215
|
+
reaction_species_examples_dict["valid_interactor"],
|
216
|
+
sbml_dfs,
|
217
|
+
graph_hierarchy_df,
|
218
|
+
).shape[0]
|
219
|
+
== 1
|
220
|
+
)
|
221
|
+
|
222
|
+
print("Re-enable test once Issue #102 is solved")
|
223
|
+
|
224
|
+
# catch error from invalid interactor specification
|
225
|
+
# with pytest.raises(ValueError) as excinfo:
|
226
|
+
# net_create._format_tiered_reaction_species(
|
227
|
+
# r_id, reaction_species_examples_dict["invalid_interactor"], sbml_dfs
|
228
|
+
# )
|
229
|
+
# assert str(excinfo.value).startswith("Invalid combinations of SBO_terms")
|
230
|
+
|
231
|
+
# simple reaction with just substrates and products
|
232
|
+
assert (
|
233
|
+
net_create._format_tiered_reaction_species(
|
234
|
+
r_id,
|
235
|
+
reaction_species_examples_dict["sub_and_prod"],
|
236
|
+
sbml_dfs,
|
237
|
+
graph_hierarchy_df,
|
238
|
+
).shape[0]
|
239
|
+
== 2
|
240
|
+
)
|
241
|
+
|
242
|
+
# add a stimulator (activator)
|
243
|
+
rxn_edges = net_create._format_tiered_reaction_species(
|
244
|
+
r_id, reaction_species_examples_dict["stimulator"], sbml_dfs, graph_hierarchy_df
|
245
|
+
)
|
246
|
+
|
247
|
+
assert rxn_edges.shape[0] == 3
|
248
|
+
assert rxn_edges.iloc[0][["from", "to"]].tolist() == ["stim", "sub"]
|
249
|
+
|
250
|
+
# add catalyst + stimulator
|
251
|
+
rxn_edges = net_create._format_tiered_reaction_species(
|
252
|
+
r_id,
|
253
|
+
reaction_species_examples_dict["all_entities"],
|
254
|
+
sbml_dfs,
|
255
|
+
graph_hierarchy_df,
|
256
|
+
)
|
257
|
+
|
258
|
+
assert rxn_edges.shape[0] == 4
|
259
|
+
assert rxn_edges.iloc[0][["from", "to"]].tolist() == ["stim", "cat"]
|
260
|
+
assert rxn_edges.iloc[1][["from", "to"]].tolist() == ["cat", "sub"]
|
261
|
+
|
262
|
+
# no substrate
|
263
|
+
rxn_edges = net_create._format_tiered_reaction_species(
|
264
|
+
r_id,
|
265
|
+
reaction_species_examples_dict["no_substrate"],
|
266
|
+
sbml_dfs,
|
267
|
+
graph_hierarchy_df,
|
268
|
+
)
|
269
|
+
|
270
|
+
assert rxn_edges.shape[0] == 5
|
271
|
+
# stimulator -> reactant
|
272
|
+
assert rxn_edges.iloc[0][["from", "to"]].tolist() == ["stim1", "cat"]
|
273
|
+
assert rxn_edges.iloc[1][["from", "to"]].tolist() == ["stim2", "cat"]
|
274
|
+
assert rxn_edges.iloc[2][["from", "to"]].tolist() == ["inh", "cat"]
|
275
|
+
|
276
|
+
# use the surrogate model tiered layout also
|
277
|
+
|
278
|
+
graph_hierarchy_df = net_create._create_graph_hierarchy_df("surrogate")
|
279
|
+
|
280
|
+
rxn_edges = net_create._format_tiered_reaction_species(
|
281
|
+
r_id,
|
282
|
+
reaction_species_examples_dict["all_entities"],
|
283
|
+
sbml_dfs,
|
284
|
+
graph_hierarchy_df,
|
285
|
+
)
|
286
|
+
|
287
|
+
assert rxn_edges.shape[0] == 4
|
288
|
+
assert rxn_edges.iloc[0][["from", "to"]].tolist() == ["stim", "sub"]
|
289
|
+
assert rxn_edges.iloc[1][["from", "to"]].tolist() == ["sub", "cat"]
|
290
|
+
|
291
|
+
|
292
|
+
def test_reverse_network_edges():
|
293
|
+
graph_hierarchy_df = net_create._create_graph_hierarchy_df("regulatory")
|
294
|
+
|
295
|
+
rxn_edges = net_create._format_tiered_reaction_species(
|
296
|
+
r_id,
|
297
|
+
reaction_species_examples_dict["all_entities"],
|
298
|
+
sbml_dfs,
|
299
|
+
graph_hierarchy_df,
|
300
|
+
)
|
301
|
+
augmented_network_edges = rxn_edges.assign(r_isreversible=True)
|
302
|
+
augmented_network_edges["sc_parents"] = range(0, augmented_network_edges.shape[0])
|
303
|
+
augmented_network_edges["sc_children"] = range(
|
304
|
+
augmented_network_edges.shape[0], 0, -1
|
305
|
+
)
|
306
|
+
|
307
|
+
assert net_create._reverse_network_edges(augmented_network_edges).shape[0] == 2
|
308
|
+
|
309
|
+
|
310
|
+
def test_net_polarity():
|
311
|
+
polarity_series = pd.Series(
|
312
|
+
["ambiguous", "ambiguous"], index=[0, 1], name="link_polarity"
|
313
|
+
)
|
314
|
+
assert all(
|
315
|
+
[x == "ambiguous" for x in paths._calculate_net_polarity(polarity_series)]
|
316
|
+
)
|
317
|
+
|
318
|
+
polarity_series = pd.Series(
|
319
|
+
["activation", "inhibition", "inhibition", "ambiguous"],
|
320
|
+
index=range(0, 4),
|
321
|
+
name="link_polarity",
|
322
|
+
)
|
323
|
+
assert paths._calculate_net_polarity(polarity_series) == [
|
324
|
+
"activation",
|
325
|
+
"inhibition",
|
326
|
+
"activation",
|
327
|
+
"ambiguous activation",
|
328
|
+
]
|
329
|
+
assert paths._terminal_net_polarity(polarity_series) == "ambiguous activation"
|
330
|
+
|
331
|
+
|
332
|
+
def test_entity_validation():
|
333
|
+
entity_attrs = {"table": "reactions", "variable": "foo"}
|
334
|
+
|
335
|
+
assert net_create._EntityAttrValidator(**entity_attrs).model_dump() == {
|
336
|
+
**entity_attrs,
|
337
|
+
**{"trans": DEFAULT_WT_TRANS},
|
338
|
+
}
|
339
|
+
|
340
|
+
|
341
|
+
################################################
|
342
|
+
# __main__
|
343
|
+
################################################
|
344
|
+
|
345
|
+
if __name__ == "__main__":
|
346
|
+
test_create_cpr_graph()
|
347
|
+
test_igraph_loading()
|
348
|
+
test_igraph_construction()
|
349
|
+
test_shortest_paths()
|
350
|
+
test_neighborhood()
|
351
|
+
test_format_interactors()
|
352
|
+
test_reverse_network_edges()
|
353
|
+
test_entity_validation()
|
tests/test_indices.py
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
|
5
|
+
import pandas as pd
|
6
|
+
import pytest
|
7
|
+
from napistu import indices
|
8
|
+
|
9
|
+
test_path = os.path.abspath(os.path.join(__file__, os.pardir))
|
10
|
+
test_data = os.path.join(test_path, "test_data")
|
11
|
+
|
12
|
+
|
13
|
+
def test_pwindex_from_file():
|
14
|
+
pw_index_path = os.path.join(test_data, "pw_index.tsv")
|
15
|
+
pw_index = indices.PWIndex(pw_index_path)
|
16
|
+
|
17
|
+
assert pw_index.index.shape == (5, 6)
|
18
|
+
|
19
|
+
|
20
|
+
def test_pwindex_from_df():
|
21
|
+
stub_pw_df = pd.DataFrame(
|
22
|
+
{
|
23
|
+
"file": "DNE",
|
24
|
+
"source": "The farm",
|
25
|
+
"species": "Gallus gallus",
|
26
|
+
"pathway_id": "chickens",
|
27
|
+
"name": "Chickens",
|
28
|
+
"date": "2020-01-01",
|
29
|
+
},
|
30
|
+
index=[0],
|
31
|
+
)
|
32
|
+
|
33
|
+
assert indices.PWIndex(pw_index=stub_pw_df, validate_paths=False).index.equals(
|
34
|
+
stub_pw_df
|
35
|
+
)
|
36
|
+
|
37
|
+
with pytest.raises(FileNotFoundError) as _:
|
38
|
+
indices.PWIndex(pw_index=stub_pw_df, pw_index_base_path="missing_directory")
|
39
|
+
|
40
|
+
with pytest.raises(FileNotFoundError) as _:
|
41
|
+
indices.PWIndex(pw_index=stub_pw_df, pw_index_base_path=test_data)
|
42
|
+
|
43
|
+
|
44
|
+
@pytest.fixture
|
45
|
+
def pw_testindex():
|
46
|
+
pw_index = indices.PWIndex(os.path.join(test_data, "pw_index.tsv"))
|
47
|
+
return pw_index
|
48
|
+
|
49
|
+
|
50
|
+
def test_index(pw_testindex):
|
51
|
+
pw_index = pw_testindex
|
52
|
+
full_index_shape = (5, 6)
|
53
|
+
assert pw_index.index.shape == full_index_shape
|
54
|
+
|
55
|
+
ref_index = pw_index.index.copy()
|
56
|
+
pw_index.filter(sources="Reactome")
|
57
|
+
assert pw_index.index.shape == full_index_shape
|
58
|
+
|
59
|
+
pw_index.filter(species="Homo sapiens")
|
60
|
+
assert pw_index.index.shape == full_index_shape
|
61
|
+
|
62
|
+
pw_index.filter(sources=("Reactome",))
|
63
|
+
assert pw_index.index.shape == full_index_shape
|
64
|
+
|
65
|
+
pw_index.filter(species=("Homo sapiens",))
|
66
|
+
assert pw_index.index.shape == full_index_shape
|
67
|
+
|
68
|
+
pw_index.filter(sources="NotValid")
|
69
|
+
assert pw_index.index.shape == (0, full_index_shape[1])
|
70
|
+
pw_index.index = ref_index.copy()
|
71
|
+
|
72
|
+
pw_index.filter(species="NotValid")
|
73
|
+
assert pw_index.index.shape == (0, full_index_shape[1])
|
74
|
+
pw_index.index = ref_index.copy()
|
75
|
+
|
76
|
+
pw_index.search("erythrocytes")
|
77
|
+
assert pw_index.index.shape == (2, 6)
|
78
|
+
pw_index.index = ref_index.copy()
|
79
|
+
|
80
|
+
pw_index.search("erythrocytes|HYDROCARBON")
|
81
|
+
assert pw_index.index.shape == (3, 6)
|
82
|
+
|
83
|
+
|
84
|
+
def test_missing_file(pw_testindex):
|
85
|
+
pw_index = pw_testindex
|
86
|
+
pw_index.index.loc[0, "file"] = "not_existing.sbml"
|
87
|
+
with pytest.raises(FileNotFoundError) as _:
|
88
|
+
pw_index._check_files()
|