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.
Files changed (77) hide show
  1. napistu/__init__.py +12 -0
  2. napistu/__main__.py +867 -0
  3. napistu/consensus.py +1557 -0
  4. napistu/constants.py +500 -0
  5. napistu/gcs/__init__.py +10 -0
  6. napistu/gcs/constants.py +69 -0
  7. napistu/gcs/downloads.py +180 -0
  8. napistu/identifiers.py +805 -0
  9. napistu/indices.py +227 -0
  10. napistu/ingestion/__init__.py +10 -0
  11. napistu/ingestion/bigg.py +146 -0
  12. napistu/ingestion/constants.py +296 -0
  13. napistu/ingestion/cpr_edgelist.py +106 -0
  14. napistu/ingestion/identifiers_etl.py +148 -0
  15. napistu/ingestion/obo.py +268 -0
  16. napistu/ingestion/psi_mi.py +276 -0
  17. napistu/ingestion/reactome.py +218 -0
  18. napistu/ingestion/sbml.py +621 -0
  19. napistu/ingestion/string.py +356 -0
  20. napistu/ingestion/trrust.py +285 -0
  21. napistu/ingestion/yeast.py +147 -0
  22. napistu/mechanism_matching.py +597 -0
  23. napistu/modify/__init__.py +10 -0
  24. napistu/modify/constants.py +86 -0
  25. napistu/modify/curation.py +628 -0
  26. napistu/modify/gaps.py +635 -0
  27. napistu/modify/pathwayannot.py +1381 -0
  28. napistu/modify/uncompartmentalize.py +264 -0
  29. napistu/network/__init__.py +10 -0
  30. napistu/network/constants.py +117 -0
  31. napistu/network/neighborhoods.py +1594 -0
  32. napistu/network/net_create.py +1647 -0
  33. napistu/network/net_utils.py +652 -0
  34. napistu/network/paths.py +500 -0
  35. napistu/network/precompute.py +221 -0
  36. napistu/rpy2/__init__.py +127 -0
  37. napistu/rpy2/callr.py +168 -0
  38. napistu/rpy2/constants.py +101 -0
  39. napistu/rpy2/netcontextr.py +464 -0
  40. napistu/rpy2/rids.py +697 -0
  41. napistu/sbml_dfs_core.py +2216 -0
  42. napistu/sbml_dfs_utils.py +304 -0
  43. napistu/source.py +394 -0
  44. napistu/utils.py +943 -0
  45. napistu-0.1.0.dist-info/METADATA +56 -0
  46. napistu-0.1.0.dist-info/RECORD +77 -0
  47. napistu-0.1.0.dist-info/WHEEL +5 -0
  48. napistu-0.1.0.dist-info/entry_points.txt +2 -0
  49. napistu-0.1.0.dist-info/licenses/LICENSE +21 -0
  50. napistu-0.1.0.dist-info/top_level.txt +2 -0
  51. tests/__init__.py +0 -0
  52. tests/conftest.py +83 -0
  53. tests/test_consensus.py +255 -0
  54. tests/test_constants.py +20 -0
  55. tests/test_curation.py +134 -0
  56. tests/test_data/__init__.py +0 -0
  57. tests/test_edgelist.py +20 -0
  58. tests/test_gcs.py +23 -0
  59. tests/test_identifiers.py +151 -0
  60. tests/test_igraph.py +353 -0
  61. tests/test_indices.py +88 -0
  62. tests/test_mechanism_matching.py +126 -0
  63. tests/test_net_utils.py +66 -0
  64. tests/test_netcontextr.py +105 -0
  65. tests/test_obo.py +34 -0
  66. tests/test_pathwayannot.py +95 -0
  67. tests/test_precomputed_distances.py +222 -0
  68. tests/test_rpy2.py +61 -0
  69. tests/test_sbml.py +46 -0
  70. tests/test_sbml_dfs_create.py +307 -0
  71. tests/test_sbml_dfs_utils.py +22 -0
  72. tests/test_sbo.py +11 -0
  73. tests/test_set_coverage.py +50 -0
  74. tests/test_source.py +67 -0
  75. tests/test_uncompartmentalize.py +40 -0
  76. tests/test_utils.py +487 -0
  77. 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()