napistu 0.2.5.dev7__py3-none-any.whl → 0.3.1__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 (107) hide show
  1. napistu/__main__.py +126 -96
  2. napistu/constants.py +35 -41
  3. napistu/context/__init__.py +10 -0
  4. napistu/context/discretize.py +462 -0
  5. napistu/context/filtering.py +387 -0
  6. napistu/gcs/__init__.py +1 -1
  7. napistu/identifiers.py +74 -15
  8. napistu/indices.py +68 -0
  9. napistu/ingestion/__init__.py +1 -1
  10. napistu/ingestion/bigg.py +47 -62
  11. napistu/ingestion/constants.py +18 -133
  12. napistu/ingestion/gtex.py +113 -0
  13. napistu/ingestion/hpa.py +147 -0
  14. napistu/ingestion/sbml.py +0 -97
  15. napistu/ingestion/string.py +2 -2
  16. napistu/matching/__init__.py +10 -0
  17. napistu/matching/constants.py +18 -0
  18. napistu/matching/interactions.py +518 -0
  19. napistu/matching/mount.py +529 -0
  20. napistu/matching/species.py +510 -0
  21. napistu/mcp/__init__.py +7 -4
  22. napistu/mcp/__main__.py +128 -72
  23. napistu/mcp/client.py +16 -25
  24. napistu/mcp/codebase.py +201 -145
  25. napistu/mcp/component_base.py +170 -0
  26. napistu/mcp/config.py +223 -0
  27. napistu/mcp/constants.py +45 -2
  28. napistu/mcp/documentation.py +253 -136
  29. napistu/mcp/documentation_utils.py +13 -48
  30. napistu/mcp/execution.py +372 -305
  31. napistu/mcp/health.py +47 -65
  32. napistu/mcp/profiles.py +10 -6
  33. napistu/mcp/server.py +161 -80
  34. napistu/mcp/tutorials.py +139 -87
  35. napistu/modify/__init__.py +1 -1
  36. napistu/modify/gaps.py +1 -1
  37. napistu/network/__init__.py +1 -1
  38. napistu/network/constants.py +101 -34
  39. napistu/network/data_handling.py +388 -0
  40. napistu/network/ig_utils.py +351 -0
  41. napistu/network/napistu_graph_core.py +354 -0
  42. napistu/network/neighborhoods.py +40 -40
  43. napistu/network/net_create.py +373 -309
  44. napistu/network/net_propagation.py +47 -19
  45. napistu/network/{net_utils.py → ng_utils.py} +124 -272
  46. napistu/network/paths.py +67 -51
  47. napistu/network/precompute.py +11 -11
  48. napistu/ontologies/__init__.py +10 -0
  49. napistu/ontologies/constants.py +129 -0
  50. napistu/ontologies/dogma.py +243 -0
  51. napistu/ontologies/genodexito.py +649 -0
  52. napistu/ontologies/mygene.py +369 -0
  53. napistu/ontologies/renaming.py +198 -0
  54. napistu/rpy2/__init__.py +229 -86
  55. napistu/rpy2/callr.py +47 -77
  56. napistu/rpy2/constants.py +24 -23
  57. napistu/rpy2/rids.py +61 -648
  58. napistu/sbml_dfs_core.py +587 -222
  59. napistu/scverse/__init__.py +15 -0
  60. napistu/scverse/constants.py +28 -0
  61. napistu/scverse/loading.py +727 -0
  62. napistu/utils.py +118 -10
  63. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dist-info}/METADATA +8 -3
  64. napistu-0.3.1.dist-info/RECORD +133 -0
  65. tests/conftest.py +22 -0
  66. tests/test_context_discretize.py +56 -0
  67. tests/test_context_filtering.py +267 -0
  68. tests/test_identifiers.py +100 -0
  69. tests/test_indices.py +65 -0
  70. tests/{test_edgelist.py → test_ingestion_napistu_edgelist.py} +2 -2
  71. tests/test_matching_interactions.py +108 -0
  72. tests/test_matching_mount.py +305 -0
  73. tests/test_matching_species.py +394 -0
  74. tests/test_mcp_config.py +193 -0
  75. tests/test_mcp_documentation_utils.py +12 -3
  76. tests/test_mcp_server.py +156 -19
  77. tests/test_network_data_handling.py +397 -0
  78. tests/test_network_ig_utils.py +23 -0
  79. tests/test_network_neighborhoods.py +19 -0
  80. tests/test_network_net_create.py +459 -0
  81. tests/test_network_ng_utils.py +30 -0
  82. tests/test_network_paths.py +56 -0
  83. tests/{test_precomputed_distances.py → test_network_precompute.py} +8 -6
  84. tests/test_ontologies_genodexito.py +58 -0
  85. tests/test_ontologies_mygene.py +39 -0
  86. tests/test_ontologies_renaming.py +110 -0
  87. tests/test_rpy2_callr.py +79 -0
  88. tests/test_rpy2_init.py +151 -0
  89. tests/test_sbml.py +0 -31
  90. tests/test_sbml_dfs_core.py +134 -10
  91. tests/test_scverse_loading.py +778 -0
  92. tests/test_set_coverage.py +2 -2
  93. tests/test_utils.py +121 -1
  94. napistu/mechanism_matching.py +0 -1353
  95. napistu/rpy2/netcontextr.py +0 -467
  96. napistu-0.2.5.dev7.dist-info/RECORD +0 -98
  97. tests/test_igraph.py +0 -367
  98. tests/test_mechanism_matching.py +0 -784
  99. tests/test_net_utils.py +0 -149
  100. tests/test_netcontextr.py +0 -105
  101. tests/test_rpy2.py +0 -61
  102. /napistu/ingestion/{cpr_edgelist.py → napistu_edgelist.py} +0 -0
  103. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dist-info}/WHEEL +0 -0
  104. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dist-info}/entry_points.txt +0 -0
  105. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dist-info}/licenses/LICENSE +0 -0
  106. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dist-info}/top_level.txt +0 -0
  107. /tests/{test_obo.py → test_ingestion_obo.py} +0 -0
napistu/utils.py CHANGED
@@ -12,17 +12,19 @@ import urllib.request as request
12
12
  import zipfile
13
13
  from contextlib import closing
14
14
  from itertools import starmap
15
+ from textwrap import fill
15
16
  from typing import Any
16
17
  from typing import Union
17
18
  from typing import Optional
18
19
  from typing import List
19
20
  from urllib.parse import urlparse
21
+ import requests
22
+ from requests.adapters import HTTPAdapter
23
+ from requests.adapters import Retry
20
24
 
21
25
  import igraph as ig
26
+ import numpy as np
22
27
  import pandas as pd
23
- import requests
24
- from napistu.constants import FILE_EXT_GZ
25
- from napistu.constants import FILE_EXT_ZIP
26
28
  from fs import open_fs
27
29
  from fs.copy import copy_dir
28
30
  from fs.copy import copy_file
@@ -32,8 +34,9 @@ from fs.errors import ResourceNotFound
32
34
  from fs.tarfs import TarFS
33
35
  from fs.tempfs import TempFS
34
36
  from fs.zipfs import ZipFS
35
- from requests.adapters import HTTPAdapter
36
- from requests.adapters import Retry
37
+
38
+ from napistu.constants import FILE_EXT_GZ
39
+ from napistu.constants import FILE_EXT_ZIP
37
40
 
38
41
  logger = logging.getLogger(__name__)
39
42
 
@@ -261,22 +264,42 @@ def write_file_contents_to_path(path: str, contents) -> None:
261
264
 
262
265
 
263
266
  def download_wget(
264
- url: str, path, target_filename: str = None, verify: bool = True
267
+ url: str,
268
+ path,
269
+ target_filename: str = None,
270
+ verify: bool = True,
271
+ timeout: int = 30,
272
+ max_retries: int = 3,
265
273
  ) -> None:
266
- """Downloades file / archive with wget
274
+ """Downloads file / archive with wget
267
275
 
268
276
  Args:
269
277
  url (str): url
270
278
  path (FilePath | WriteBuffer): file path or buffer
271
279
  target_filename (str): specific file to extract from ZIP if URL is a ZIP file
272
280
  verify (bool): verify argument to pass to requests.get
281
+ timeout (int): timeout in seconds for the request
282
+ max_retries (int): number of times to retry the download if it fails
273
283
 
274
284
  Returns:
275
285
  None
276
286
  """
277
- r = requests.get(url, allow_redirects=True, verify=verify)
278
- # throw an exception if one was generated
279
- r.raise_for_status()
287
+ session = requests.Session()
288
+ retry_strategy = Retry(
289
+ total=max_retries,
290
+ backoff_factor=1,
291
+ status_forcelist=[429, 500, 502, 503, 504],
292
+ )
293
+ adapter = HTTPAdapter(max_retries=retry_strategy)
294
+ session.mount("http://", adapter)
295
+ session.mount("https://", adapter)
296
+
297
+ try:
298
+ r = session.get(url, allow_redirects=True, verify=verify, timeout=timeout)
299
+ r.raise_for_status()
300
+ except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
301
+ logger.error(f"Failed to download {url} after {max_retries} retries: {str(e)}")
302
+ raise
280
303
 
281
304
  # check if the content is a ZIP file
282
305
  if (
@@ -787,6 +810,52 @@ def drop_extra_cols(
787
810
  return df_out.loc[:, ordered_cols]
788
811
 
789
812
 
813
+ def _merge_and_log_overwrites(
814
+ left_df: pd.DataFrame, right_df: pd.DataFrame, merge_context: str, **merge_kwargs
815
+ ) -> pd.DataFrame:
816
+ """
817
+ Merge two DataFrames and log any column overwrites.
818
+
819
+ Parameters
820
+ ----------
821
+ left_df : pd.DataFrame
822
+ Left DataFrame for merge
823
+ right_df : pd.DataFrame
824
+ Right DataFrame for merge
825
+ merge_context : str
826
+ Description of the merge operation for logging
827
+ **merge_kwargs : dict
828
+ Additional keyword arguments passed to pd.merge
829
+
830
+ Returns
831
+ -------
832
+ pd.DataFrame
833
+ Merged DataFrame with overwritten columns removed
834
+ """
835
+ # Track original columns
836
+ original_cols = left_df.columns.tolist()
837
+
838
+ # Ensure we're using the correct suffixes
839
+ merge_kwargs["suffixes"] = ("_old", "")
840
+
841
+ # Perform merge
842
+ merged_df = pd.merge(left_df, right_df, **merge_kwargs)
843
+
844
+ # Check for and log any overwritten columns
845
+ new_cols = merged_df.columns.tolist()
846
+ overwritten_cols = [col for col in original_cols if col + "_old" in new_cols]
847
+ if overwritten_cols:
848
+ logger.warning(
849
+ f"The following columns were overwritten during {merge_context} merge and their original values "
850
+ f"have been suffixed with '_old': {', '.join(overwritten_cols)}"
851
+ )
852
+ # Drop the old columns
853
+ cols_to_drop = [col + "_old" for col in overwritten_cols]
854
+ merged_df = merged_df.drop(columns=cols_to_drop)
855
+
856
+ return merged_df
857
+
858
+
790
859
  def format_identifiers_as_edgelist(
791
860
  df: pd.DataFrame, defining_vars: list[str]
792
861
  ) -> pd.DataFrame:
@@ -841,6 +910,20 @@ def format_identifiers_as_edgelist(
841
910
  return df
842
911
 
843
912
 
913
+ def matrix_to_edgelist(matrix, row_labels=None, col_labels=None):
914
+ rows, cols = np.where(~np.isnan(matrix))
915
+
916
+ edgelist = pd.DataFrame(
917
+ {
918
+ "row": rows if row_labels is None else [row_labels[i] for i in rows],
919
+ "column": cols if col_labels is None else [col_labels[i] for i in cols],
920
+ "value": matrix[rows, cols],
921
+ }
922
+ )
923
+
924
+ return edgelist
925
+
926
+
844
927
  def find_weakly_connected_subgraphs(edgelist: pd.DataFrame) -> pd.DataFrame:
845
928
  """Find all cliques of loosly connected components."""
846
929
 
@@ -983,6 +1066,31 @@ def click_str_to_list(string: str) -> list[str]:
983
1066
  )
984
1067
 
985
1068
 
1069
+ def safe_fill(x: str, fill_width: int = 15) -> str:
1070
+ """
1071
+ Safely wrap a string to a specified width.
1072
+
1073
+ Parameters
1074
+ ----------
1075
+ x : str
1076
+ The string to wrap.
1077
+ fill_width : int, optional
1078
+ The width to wrap the string to. Default is 15.
1079
+
1080
+ Returns
1081
+ -------
1082
+ str
1083
+ The wrapped string.
1084
+ """
1085
+
1086
+ # TODO - move to non-network utils
1087
+
1088
+ if x == "":
1089
+ return ""
1090
+ else:
1091
+ return fill(x, fill_width)
1092
+
1093
+
986
1094
  def _add_nameness_score_wrapper(df, name_var, table_schema):
987
1095
  """Call _add_nameness_score with default value."""
988
1096
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: napistu
3
- Version: 0.2.5.dev7
3
+ Version: 0.3.1
4
4
  Summary: Connecting high-dimensional data to curated pathways
5
5
  Home-page: https://github.com/napistu/napistu-py
6
6
  Author: Sean Hackett
@@ -23,6 +23,7 @@ Requires-Dist: fs<3.0.0,>=2.4.0
23
23
  Requires-Dist: fs-gcsfs<2.0.0,>=1.5.0
24
24
  Requires-Dist: igraph
25
25
  Requires-Dist: matplotlib<4.0.0,>=3.5.0
26
+ Requires-Dist: mygene<4.0.0,>=3.0.0
26
27
  Requires-Dist: numpy<3.0.0,>=1.24.0
27
28
  Requires-Dist: pandas<3.0.0,>=1.5.0
28
29
  Requires-Dist: pydantic<3.0.0,>=2.0.0
@@ -32,6 +33,7 @@ Requires-Dist: scipy<2.0.0,>=1.10.0
32
33
  Requires-Dist: tqdm
33
34
  Requires-Dist: zeep<4.0.0,>=3.0.0
34
35
  Provides-Extra: dev
36
+ Requires-Dist: napistu[mcp,scverse]; extra == "dev"
35
37
  Requires-Dist: black>=24.0.0; extra == "dev"
36
38
  Requires-Dist: ipykernel; extra == "dev"
37
39
  Requires-Dist: pre-commit<4.0.0,>=3.0.0; extra == "dev"
@@ -52,6 +54,9 @@ Provides-Extra: rpy2
52
54
  Requires-Dist: pyarrow<19.0.0,>=15.0.0; extra == "rpy2"
53
55
  Requires-Dist: rpy2<4.0.0,>=3.5.0; extra == "rpy2"
54
56
  Requires-Dist: rpy2-arrow<1.0.0,>=0.1.0; extra == "rpy2"
57
+ Provides-Extra: scverse
58
+ Requires-Dist: anndata; extra == "scverse"
59
+ Requires-Dist: mudata; extra == "scverse"
55
60
  Dynamic: license-file
56
61
 
57
62
  # Napistu Python Library
@@ -75,8 +80,8 @@ pip install .
75
80
  ```
76
81
 
77
82
  ## Documentation
78
- 📘 **Full Documentation**: [https://napistu.readthedocs.io](https://napistu.readthedocs.io)
79
- ** Wiki **: [napistu/wiki](https://github.com/napistu/napistu/wiki)
83
+ - 📘 **Library Documentation**: [napistu.readthedocs.io](https://napistu.readthedocs.io)
84
+ - 🚸 **Project Documentation**: [napistu/wiki](https://github.com/napistu/napistu/wiki)
80
85
 
81
86
  ### Quick Links
82
87
  - [Installation Guide](https://napistu.readthedocs.io/en/latest/installation.html)
@@ -0,0 +1,133 @@
1
+ napistu/__init__.py,sha256=HEXcB6w8PCTD-tm4rq7AoFi7ufZNDuoG3EoM0kz9aPY,269
2
+ napistu/__main__.py,sha256=1O_ZyCqNeHcyuL4rbbz6R7_jnPOAamKtTNXZ68gSA7U,28624
3
+ napistu/consensus.py,sha256=UbKKSLP1O46e3Rk8d_aqNlhRHeR3sZRztAgIm7-XK6Y,69960
4
+ napistu/constants.py,sha256=Wb1eir8DKSAjukNPknNkKTS4kQSqZjTcTjFaOYNyrC8,15317
5
+ napistu/identifiers.py,sha256=wsVriQdvPllA5uvh5CiREklA2tYW2MIB14dV7CPaMVU,34003
6
+ napistu/indices.py,sha256=E_djN1XWc6l1lrFw_QnQXfZTKYTaUv8-jFPP7cHkY5A,9780
7
+ napistu/sbml_dfs_core.py,sha256=5t2TYQeuvZeBqR3_eX0oEfAVHyaWSYMLkEO7zmSpo4Y,91779
8
+ napistu/sbml_dfs_utils.py,sha256=LJo6WWTrmnE58ZLDuibeeHk88uCdfunWdja7XxdZpps,11525
9
+ napistu/source.py,sha256=9uUJrkY4jHaKlzz5nNcQQ8wUAep2pfqhlHxHw1hmEkI,13648
10
+ napistu/utils.py,sha256=TcholWrFbRSu_sn9ODMA8y2YyAhekEKZjwf4S0WQNzI,33241
11
+ napistu/context/__init__.py,sha256=LQBEqipcHKK0E5UlDEg1ct-ymCs93IlUrUaH8BCevf0,242
12
+ napistu/context/discretize.py,sha256=Qq7zg46F_I-PvQIT2_pEDQV7YEtUQCxKoRvT5Gu9QsE,15052
13
+ napistu/context/filtering.py,sha256=oH1uNsf-_qSWRFtoxR8gDvCfZOzO3Ps40YO0qGAGXXs,13660
14
+ napistu/gcs/__init__.py,sha256=dFXAhIqlTLJMwowS4BUDT08-Vy3Q0u1L0CMCErSZT1Y,239
15
+ napistu/gcs/constants.py,sha256=g6PaU99GY5XvaRHx4BGmWHUpcJ36-Zh_GzeNVOeHviM,2856
16
+ napistu/gcs/downloads.py,sha256=SvGv9WYr_Vt3guzyz1QiAuBndeKPTBtWSFLj1-QbLf4,6348
17
+ napistu/gcs/utils.py,sha256=eLSsvewWJdCguyj2k0ozUGP5BTemaE1PZg41Z3aY5kM,571
18
+ napistu/ingestion/__init__.py,sha256=dFXAhIqlTLJMwowS4BUDT08-Vy3Q0u1L0CMCErSZT1Y,239
19
+ napistu/ingestion/bigg.py,sha256=q0HeVSO6pFftbrxxVfFGUtMvCoak9Wi9ngMggRfjFjo,4364
20
+ napistu/ingestion/constants.py,sha256=JmIefW8qektzpJr5t0GBtcAq-4bVLougTrOAegm5bl8,5410
21
+ napistu/ingestion/gtex.py,sha256=X0hSC1yrpf4xSJWFhpeNcnHwJzKDII2MvjfUqYA0JN8,3720
22
+ napistu/ingestion/hpa.py,sha256=R27ExrryKQ4Crxv9ATXmBJCa-yd01TMOrDjkeBhIQac,5054
23
+ napistu/ingestion/identifiers_etl.py,sha256=6ppDUA6lEZurdmVbiFLOUzphYbr-hndMhtqsQnq_yAc,5009
24
+ napistu/ingestion/napistu_edgelist.py,sha256=eVT9M7gmdBuGHcAYlvkD_zzvTtyzXufKWjwDiT8OxF4,3572
25
+ napistu/ingestion/obo.py,sha256=AQkIPWbjA464Lma0tx91JucWkIwLjC7Jgv5VHGRTDkE,9601
26
+ napistu/ingestion/psi_mi.py,sha256=5eJjm7XWogL9oTyGqR52kntHClLwLsTePKqCvUGyi-w,10111
27
+ napistu/ingestion/reactome.py,sha256=Hn9X-vDp4o_HK-OtaQvel3vJeZ8_TC1-4N2rruK9Oks,7099
28
+ napistu/ingestion/sbml.py,sha256=muLTo-LTeL9lvvdEOjnSg82PQM2jpRExkK0UyF1qea8,20262
29
+ napistu/ingestion/string.py,sha256=8igOC3j8cPdG_pMl14Z2OZsbvHUldPTJOJOUD7IJ-Mc,11676
30
+ napistu/ingestion/trrust.py,sha256=ccjZc_eF3PdxxurnukiEo_e0-aKc_3z22NYbaJBtHdY,9774
31
+ napistu/ingestion/yeast.py,sha256=bwFBNxRq-dLDaddgBL1hpfZj0eQ56nBXyR_9n0NZT9Y,5233
32
+ napistu/matching/__init__.py,sha256=dFXAhIqlTLJMwowS4BUDT08-Vy3Q0u1L0CMCErSZT1Y,239
33
+ napistu/matching/constants.py,sha256=j4XSOE9Bpma9F6apVJ1LijKOUPgRk8Geo_u_rvNtpSU,610
34
+ napistu/matching/interactions.py,sha256=5GQCOFVvPPS7tCJodcSy51Fzh4c-biaP1dbbhgc8VLs,18818
35
+ napistu/matching/mount.py,sha256=8JEtiDIy7qdjWyDAs0vuVwEQkpwRf5ah4xMLZ4jKHag,19428
36
+ napistu/matching/species.py,sha256=5-hmH8_UrvDmGfeJ1283trkCtPOC3BEmtYPcMHuZyNY,18893
37
+ napistu/mcp/__init__.py,sha256=EmtcdtYyfhXdxxPB5cY_pshXnFv6XZ5CtRU0JMHn3aQ,2074
38
+ napistu/mcp/__main__.py,sha256=o9C4J3YHkfh_pQi-K9OC5bwFmsNWHuK2l8GL7M90uFc,8057
39
+ napistu/mcp/client.py,sha256=Zyy7unFFq9XPBDrr2Hl7dMVDTGoZbtj_YFuUH18QScs,6350
40
+ napistu/mcp/codebase.py,sha256=q3L76xzpIalcw1ZBy2Zt59G22rX1knila__QdQMh-OA,7950
41
+ napistu/mcp/codebase_utils.py,sha256=r1nbDmGzq-NaH9cT11jC53mEjszQpwQ0uZUJkMHvgVs,10567
42
+ napistu/mcp/component_base.py,sha256=nTa8RMW2rRBpFXfhUSHMgaA0sUS2Vy-ERZe__OB-R6Y,4461
43
+ napistu/mcp/config.py,sha256=2CMUlcYhS0TMziAHFfmwQXpR1jx1qxSnZoP7UcNKYBk,7149
44
+ napistu/mcp/constants.py,sha256=XlU5P9uY3LfRPjpSbe9xU35LkcBShP-oRNk_iQ2CqQk,3945
45
+ napistu/mcp/documentation.py,sha256=BduopA2YiJQ43Gz_EtK3JGAE2HvFhuknj_pB1KaLBnQ,10738
46
+ napistu/mcp/documentation_utils.py,sha256=dxzyu2pNxqlvCWJ2Au87_Q1BlmKrVnOo3qyTctoSogc,5873
47
+ napistu/mcp/execution.py,sha256=ATwMNhrZTZHQCvWPAwmC95B-Yj9QjMyVR_1kqop5dak,16049
48
+ napistu/mcp/health.py,sha256=dtXhdR5j0SQ-Vqk6rxDcW8KpxhNe-r3AqZbrjaJ8FUg,7248
49
+ napistu/mcp/profiles.py,sha256=W_877wmTD_-rIeDBF_0-OCUWnzCOsHt4wKxorJptLtQ,2126
50
+ napistu/mcp/server.py,sha256=svSx9DPckvqjDSv2-7OJ4IKKQPI10644toZ24a72sZw,8281
51
+ napistu/mcp/tutorials.py,sha256=-HNC6xdwLXt4gNZOqK-Yb5XndK6ZuFXNSzh1FN0XQ3g,5297
52
+ napistu/mcp/tutorials_utils.py,sha256=6_s6FP2i8Na6VaKVzLDnSnA5JQVgyd3ZHEIz8HSHtzU,6599
53
+ napistu/mcp/utils.py,sha256=WB4c6s8aPZLgi_Wvhhq0DE8Cnz2QGff0V8hrF1feVRg,1296
54
+ napistu/modify/__init__.py,sha256=dFXAhIqlTLJMwowS4BUDT08-Vy3Q0u1L0CMCErSZT1Y,239
55
+ napistu/modify/constants.py,sha256=H6K6twzPlxt0yp6QLAxIx0Tp8YzYhtKKXPdmXi5V_QQ,3689
56
+ napistu/modify/curation.py,sha256=sQeSO53ZLdn14ww2GSKkoP0vJnDpAoSWb-YDjUf5hDQ,21743
57
+ napistu/modify/gaps.py,sha256=nhoo30iQai16NzYYfHQ4PE42psWp5hA20Oq7yae1pzw,26743
58
+ napistu/modify/pathwayannot.py,sha256=xuBSMDFWbg_d6-Gzv0Td3Q5nnFTa-Qzic48g1b1AZtQ,48081
59
+ napistu/modify/uncompartmentalize.py,sha256=U5X4Q7Z-YIkC8_711x3sU21vTVdv9rKfauwz4JNzl6c,9690
60
+ napistu/network/__init__.py,sha256=dFXAhIqlTLJMwowS4BUDT08-Vy3Q0u1L0CMCErSZT1Y,239
61
+ napistu/network/constants.py,sha256=fC1njZDu6in1JiaZ1-T1_fhmmkcc2HKSUUomDVyQ7Dw,5789
62
+ napistu/network/data_handling.py,sha256=mxplWwyXNrjZRN-jjWWUI9IZOqX69k8qSMDIrL9h0Og,14736
63
+ napistu/network/ig_utils.py,sha256=87vFuyLksYhfGoKBvjYeQt1yM_lg83m-14OaGbW64Wg,10478
64
+ napistu/network/napistu_graph_core.py,sha256=2NbjiLcDcFWFyX1MuN17pobPDgoQFtcYWOwuPSFTT4g,10429
65
+ napistu/network/neighborhoods.py,sha256=Q9HWUvf_J4a_4RQDKd7ywEy4cp3Wq2OPOfVsotDbEe0,56098
66
+ napistu/network/net_create.py,sha256=2N5ocGmibdBxIUVtv3H36iFWwkbys9ECCERFRlByhLc,69407
67
+ napistu/network/net_propagation.py,sha256=89ZR4p2mGpkCCIemofZ53XbUjQsuNABxIc6UmF8A5n8,4935
68
+ napistu/network/ng_utils.py,sha256=ijWDa5MTuULJpdV6dcVFGmLmtB_xy87jaUG7F5nvC_k,15240
69
+ napistu/network/paths.py,sha256=S4ZaV0yVmI-o8sXfom5eXA3yy2IEbleYUyXEvnmVw98,17468
70
+ napistu/network/precompute.py,sha256=aEynTDdKK_WJbEqBd6Q8iihXzuk3rheurkPcnh9bYqQ,7651
71
+ napistu/ontologies/__init__.py,sha256=dFXAhIqlTLJMwowS4BUDT08-Vy3Q0u1L0CMCErSZT1Y,239
72
+ napistu/ontologies/constants.py,sha256=GyOFvezSxDK1VigATcruTKtNhjcYaid1ggulEf_HEtQ,4345
73
+ napistu/ontologies/dogma.py,sha256=jGZS-J3d29AoUOow-HVjfVZQJ87lnqO5L1aozieN1ec,8825
74
+ napistu/ontologies/genodexito.py,sha256=5_gtdVtKHp5z-jtPXkHlZRiTsuHdZeA3TVI9u4SXqrQ,24725
75
+ napistu/ontologies/mygene.py,sha256=RMFQTWsLkeYxmsOPxxmeIya2phdcUMcF5V2abaS8MVg,11109
76
+ napistu/ontologies/renaming.py,sha256=bL15T0CswjM81NFVIVp-3CEsa1kxIIk2xJ2kE5eTeeg,6817
77
+ napistu/rpy2/__init__.py,sha256=8WzSK_tmdcbyMUtb17OmqdQqbisqIBl8OQrDsaFDeX4,8356
78
+ napistu/rpy2/callr.py,sha256=yFCGobZTVgH1vJc5h0njAflvFr6zmCWIP-uuLWnZL-g,3701
79
+ napistu/rpy2/constants.py,sha256=3thZa4UUfpDpXaUzGcqfDEyEIQaf4a_C01-O2pciZ7c,2760
80
+ napistu/rpy2/rids.py,sha256=AfXLTfTdonfspgAHYO0Ph7jSUWv8YuyT8x3fyLfAqc8,3413
81
+ napistu/scverse/__init__.py,sha256=Lgxr3iMQAkTzXE9BNz93CndNP5djzerLvmHM-D0PU3I,357
82
+ napistu/scverse/constants.py,sha256=0iAkhyJUIeFGHdLLU3fCaEU1O3Oix4qAsxr3CxGTjVs,653
83
+ napistu/scverse/loading.py,sha256=jqiE71XB-wdV50GyZrauFNY0Lai4bX9Fm2Gv80VR8t8,27016
84
+ napistu-0.3.1.dist-info/licenses/LICENSE,sha256=kW8wVT__JWoHjl2BbbJDAZInWa9AxzJeR_uv6-i5x1g,1063
85
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
+ tests/conftest.py,sha256=XVkd0tQywhnf2cgab7fIjBo3NlaTVX3cO8HaRS2jIwM,3190
87
+ tests/test_consensus.py,sha256=3dJvvPsPG7bHbw_FY4Pm647N_Gt_Ud9157OKYfPCUd4,9502
88
+ tests/test_constants.py,sha256=gJLDv7QMeeBiiupyMazj6mumk20KWvGMgm2myHMKKfc,531
89
+ tests/test_context_discretize.py,sha256=5Mr9WqwHGYMO37M1TnMmSfC64UZ73mnoCiEM2IQHVDY,1667
90
+ tests/test_context_filtering.py,sha256=0CWbmxKxerraJJgUqXiYHSYCfmRyOFvFRMG1u6mLbwI,9483
91
+ tests/test_curation.py,sha256=-Q2J0D7qs9PGjHZX-rM4NxRLLdwxoapytSo_98q9ItY,3864
92
+ tests/test_gaps.py,sha256=mGGeyx1vUnmEOF__bsqfCYq9Y8a1P-9mefqna4Qgc_k,4062
93
+ tests/test_gcs.py,sha256=p_uQWuY2TcGj3zV3qFC-GXBqj4St8YENR_XRpQ6UH5g,570
94
+ tests/test_identifiers.py,sha256=9QlGCG27zposzEvazEuZqoMausNMLLuUwfA3FuYU1mc,8345
95
+ tests/test_indices.py,sha256=e_8GSNzIT4JHGmelX9PseJzFXTxo-TQAus3r21AUt7I,4547
96
+ tests/test_ingestion_napistu_edgelist.py,sha256=xH82MZfRK_VD9Rv5z49CveX0KFbQoRsNGwTpePKK7RY,568
97
+ tests/test_ingestion_obo.py,sha256=47qNCElPzu2nA36Oq83Dqp1RGhITqztjl7UyZ5cMsj4,959
98
+ tests/test_matching_interactions.py,sha256=OVyc6iLdlkBJeNyTSH1n66PLfSTI7DRJao8Gu2Q2cv4,3558
99
+ tests/test_matching_mount.py,sha256=txFd3Au2DldA505i_4QCmiaQuHfwJt-idx6DNDu3MmQ,11123
100
+ tests/test_matching_species.py,sha256=OuUWp0-X3WYXkc-g51XyOqhp4MgO8cJvUSqt8ZvqRaU,14729
101
+ tests/test_mcp_config.py,sha256=GTu9vywqAHTYkolywdYS_BEIW3gBzs4A4qcneMSPpRk,7007
102
+ tests/test_mcp_documentation_utils.py,sha256=OW0N2N_2IOktbYTcCWhhWz4bANi8IB60l1q3DJi8Ra4,810
103
+ tests/test_mcp_server.py,sha256=bP3PWVQsEfX6-lAgXKP32njdg__o65n2WuLvkxTTHkQ,11215
104
+ tests/test_net_propagation.py,sha256=9pKkUdduWejH4iKNCJXKFzAkdNpCfrMbiUWySgI_LH4,3244
105
+ tests/test_network_data_handling.py,sha256=oBSZuB3IRG9bwmD6n8FY-UZLe2UqGzXpNSxVtkHRSvE,12605
106
+ tests/test_network_ig_utils.py,sha256=uojDLtL7oT9S9NJrXL8kBEHHFq5DB1GnJQT0v-gHEBE,632
107
+ tests/test_network_neighborhoods.py,sha256=8BV17m5X1OUd5FwasTTYUOkNYUHDPUkxOKH_VZCsyBE,631
108
+ tests/test_network_net_create.py,sha256=VNFZTwQawAZQPDnVk_qFevgZErx5KyQZ24bMoZF4T4w,16462
109
+ tests/test_network_ng_utils.py,sha256=CwDw4MKTPhVZXz2HA2XU2QjjBv8CXc1_yQ0drvkBkFw,724
110
+ tests/test_network_paths.py,sha256=TWZnxY5bF3m6gahcxcYJGrBIawh2-_vUcec1LyPmXV8,1686
111
+ tests/test_network_precompute.py,sha256=iyqvxdlt_LQdAoFr8x-NZUbq5VH4Xo64fTg3gyXiWEg,7245
112
+ tests/test_ontologies_genodexito.py,sha256=hBlunyEPiKskqagjWKW5Z6DJwKvpueYHJLwbfyeeAdo,2256
113
+ tests/test_ontologies_mygene.py,sha256=BuBLm8VatzpK39-Ew_fFTK9ueLE4eqmKIDS5UKE59n8,1541
114
+ tests/test_ontologies_renaming.py,sha256=k7bQzP24zG7W3fpULwk1me2sOWEWlxylr4Mhx1_gJJY,3740
115
+ tests/test_pathwayannot.py,sha256=bceosccNy9tgxQei_7j7ATBSSvBSxOngJvK-mAzR_K0,3312
116
+ tests/test_rpy2_callr.py,sha256=UVzXMvYN3wcc-ikDIjH2sA4BqkbwiNbMm561BcbnbD4,2936
117
+ tests/test_rpy2_init.py,sha256=APrNt9GEQV9va3vU5k250TxFplAoWFc-FJRFhM2GcDk,5927
118
+ tests/test_sbml.py,sha256=-Lxr_Iu7zl15c98NLG-ty9d1V9lLYHsieKbU_s96F6s,471
119
+ tests/test_sbml_dfs_core.py,sha256=z2dYl5-3ZvIsEeK_sHxm8VtWSdL81Eljz_9aeedlM6U,16806
120
+ tests/test_sbml_dfs_utils.py,sha256=onFWdhrTix30XR1-CMrMXld37BYxEGi6TZrweugLDzI,505
121
+ tests/test_sbo.py,sha256=x_PENFaXYsrZIzOZu9cj_Wrej7i7SNGxgBYYvcigLs0,308
122
+ tests/test_scverse_loading.py,sha256=bnU1lQSYYWhOAs0IIBoi4ZohqPokDQJ0n_rtkAfEyMU,29948
123
+ tests/test_set_coverage.py,sha256=J-6m6LuOjcQa9pxRuWglSfJk4Ltm7kt_eOrn_Q-7P6Q,1604
124
+ tests/test_source.py,sha256=hT0IlpexR5zP0OhWl5BBaho9d1aCYQlFZLwRIRRnw_Y,1969
125
+ tests/test_uncompartmentalize.py,sha256=nAk5kfAVLU9a2VWe2x2HYVcKqj-EnwmwddERIPRax8c,1289
126
+ tests/test_utils.py,sha256=JRJFmjDNZpjG59a-73JkTyGqa_a7Z8d0fE2cZt0CRII,22580
127
+ tests/utils.py,sha256=SoWQ_5roJteFGcMaOeEiQ5ucwq3Z2Fa3AAs9iXHTsJY,749
128
+ tests/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
129
+ napistu-0.3.1.dist-info/METADATA,sha256=Dy28usEPYFT-rbmyJSn2lvcNhc7tU2kcCZsj8oTlRWQ,3413
130
+ napistu-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
131
+ napistu-0.3.1.dist-info/entry_points.txt,sha256=_QnaPOvJNA3IltxmZgWIiBoen-L1bPYX18YQfC7oJgQ,41
132
+ napistu-0.3.1.dist-info/top_level.txt,sha256=Gpvk0a_PjrtqhYcQ9IDr3zR5LqpZ-uIHidQMIpjlvhY,14
133
+ napistu-0.3.1.dist-info/RECORD,,
tests/conftest.py CHANGED
@@ -3,10 +3,12 @@ from __future__ import annotations
3
3
  import os
4
4
  import sys
5
5
 
6
+
6
7
  from napistu import consensus
7
8
  from napistu import indices
8
9
  from napistu import sbml_dfs_core
9
10
  from napistu.ingestion import sbml
11
+ from napistu.network import net_create
10
12
  from pytest import fixture
11
13
  from pytest import skip
12
14
 
@@ -57,6 +59,26 @@ def sbml_dfs_glucose_metabolism():
57
59
  return sbml_dfs
58
60
 
59
61
 
62
+ @fixture
63
+ def napistu_graph(sbml_dfs):
64
+ """
65
+ Pytest fixture to create a NapistuGraph from sbml_dfs with directed=True and topology weighting.
66
+ """
67
+ return net_create.process_napistu_graph(
68
+ sbml_dfs, directed=True, weighting_strategy="topology"
69
+ )
70
+
71
+
72
+ @fixture
73
+ def napistu_graph_undirected(sbml_dfs):
74
+ """
75
+ Pytest fixture to create a NapistuGraph from sbml_dfs with directed=False and topology weighting.
76
+ """
77
+ return net_create.process_napistu_graph(
78
+ sbml_dfs, directed=False, weighting_strategy="topology"
79
+ )
80
+
81
+
60
82
  # Define custom markers for platforms
61
83
  def pytest_configure(config):
62
84
  config.addinivalue_line("markers", "skip_on_windows: mark test to skip on Windows")
@@ -0,0 +1,56 @@
1
+ import numpy as np
2
+
3
+ from napistu.context import discretize
4
+
5
+
6
+ def test_peak_selector():
7
+
8
+ # Test Case 0: No peaks (flat/monotonic)
9
+ x0 = np.linspace(-5, 5, 100)
10
+ y0 = np.exp(-x0) # Monotonic decreasing
11
+ peaks0 = discretize.PeakSelector().find_peaks(y0, x0)
12
+
13
+ assert peaks0.major == -5
14
+ assert peaks0.minor is None
15
+ assert peaks0.other is None
16
+
17
+ # Test Case 2: Single peak (Gaussian)
18
+ x1 = np.linspace(-5, 5, 100)
19
+ y1 = np.exp(-0.5 * x1**2) # Single Gaussian peak
20
+ peaks1 = discretize.PeakSelector().find_peaks(y1, x1)
21
+
22
+ assert abs(peaks1.major - -0.05) < 0.01
23
+ assert peaks1.minor is None
24
+ assert peaks1.other is None
25
+
26
+ # Test Case 3: Two peaks (bimodal)
27
+ x2 = np.linspace(-5, 5, 100)
28
+ y2 = 0.6 * np.exp(-0.5 * (x2 + 1.5) ** 2) + 0.4 * np.exp(-0.5 * (x2 - 1.5) ** 2)
29
+ peaks2 = discretize.PeakSelector().find_peaks(y2, x2)
30
+
31
+ assert abs(peaks2.major - 1.46) < 0.01
32
+ assert abs(peaks2.minor - -1.46) < 0.01
33
+ assert peaks2.other is None
34
+
35
+ # Test Case 4: Three peaks (trimodal)
36
+ x3 = np.linspace(-8, 8, 100)
37
+ y3 = (
38
+ 0.4 * np.exp(-0.5 * (x3 + 4) ** 2)
39
+ + 0.5 * np.exp(-0.5 * x3**2)
40
+ + 0.3 * np.exp(-0.5 * (x3 - 4) ** 2)
41
+ )
42
+ peaks3 = discretize.PeakSelector().find_peaks(y3, x3)
43
+
44
+ assert abs(peaks3.major - 3.95) < 0.01
45
+ assert abs(peaks3.minor - -0.08) < 0.01
46
+ assert abs(peaks3.other[0] - -3.95) < 0.01
47
+
48
+
49
+ def test_zfpkm():
50
+
51
+ fpkm_df = discretize.generate_simple_test_data()
52
+ zfpkm_df = discretize.zfpkm(fpkm_df)
53
+
54
+ assert zfpkm_df.shape == fpkm_df.shape
55
+ assert zfpkm_df.index.equals(fpkm_df.index)
56
+ assert zfpkm_df.columns.equals(fpkm_df.columns)