risk-network 0.0.11__py3-none-any.whl → 0.0.12__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 (45) hide show
  1. risk/__init__.py +1 -1
  2. risk/annotation/__init__.py +10 -0
  3. risk/{annotations/annotations.py → annotation/annotation.py} +44 -44
  4. risk/{annotations → annotation}/io.py +93 -92
  5. risk/{annotations → annotation}/nltk_setup.py +6 -5
  6. risk/log/__init__.py +1 -1
  7. risk/log/parameters.py +26 -27
  8. risk/neighborhoods/__init__.py +0 -1
  9. risk/neighborhoods/api.py +38 -38
  10. risk/neighborhoods/community.py +33 -4
  11. risk/neighborhoods/domains.py +26 -28
  12. risk/neighborhoods/neighborhoods.py +8 -2
  13. risk/neighborhoods/stats/__init__.py +13 -0
  14. risk/neighborhoods/stats/permutation/__init__.py +6 -0
  15. risk/{stats → neighborhoods/stats}/permutation/permutation.py +24 -21
  16. risk/{stats → neighborhoods/stats}/permutation/test_functions.py +4 -4
  17. risk/{stats/stat_tests.py → neighborhoods/stats/tests.py} +62 -54
  18. risk/network/__init__.py +0 -2
  19. risk/network/graph/__init__.py +0 -2
  20. risk/network/graph/api.py +19 -19
  21. risk/network/graph/graph.py +73 -68
  22. risk/{stats/significance.py → network/graph/stats.py} +2 -2
  23. risk/network/graph/summary.py +12 -13
  24. risk/network/io.py +163 -20
  25. risk/network/plotter/__init__.py +0 -2
  26. risk/network/plotter/api.py +1 -1
  27. risk/network/plotter/canvas.py +36 -36
  28. risk/network/plotter/contour.py +14 -15
  29. risk/network/plotter/labels.py +303 -294
  30. risk/network/plotter/network.py +6 -6
  31. risk/network/plotter/plotter.py +8 -10
  32. risk/network/plotter/utils/colors.py +15 -8
  33. risk/network/plotter/utils/layout.py +3 -3
  34. risk/risk.py +6 -6
  35. risk_network-0.0.12.dist-info/METADATA +122 -0
  36. risk_network-0.0.12.dist-info/RECORD +40 -0
  37. {risk_network-0.0.11.dist-info → risk_network-0.0.12.dist-info}/WHEEL +1 -1
  38. risk/annotations/__init__.py +0 -7
  39. risk/network/geometry.py +0 -150
  40. risk/stats/__init__.py +0 -15
  41. risk/stats/permutation/__init__.py +0 -6
  42. risk_network-0.0.11.dist-info/METADATA +0 -798
  43. risk_network-0.0.11.dist-info/RECORD +0 -41
  44. {risk_network-0.0.11.dist-info → risk_network-0.0.12.dist-info/licenses}/LICENSE +0 -0
  45. {risk_network-0.0.11.dist-info → risk_network-0.0.12.dist-info}/top_level.txt +0 -0
@@ -94,10 +94,10 @@ class Network:
94
94
  # Draw the nodes of the graph
95
95
  nx.draw_networkx_nodes(
96
96
  self.graph.network,
97
- pos=node_coordinates,
97
+ pos=node_coordinates.tolist(),
98
98
  node_size=node_size,
99
99
  node_shape=node_shape,
100
- node_color=node_color_rgba,
100
+ node_color=node_color_rgba.tolist(),
101
101
  edgecolors=node_edgecolor_rgba,
102
102
  linewidths=node_edgewidth,
103
103
  ax=self.ax,
@@ -105,9 +105,9 @@ class Network:
105
105
  # Draw the edges of the graph
106
106
  nx.draw_networkx_edges(
107
107
  self.graph.network,
108
- pos=node_coordinates,
108
+ pos=node_coordinates.tolist(),
109
109
  width=edge_width,
110
- edge_color=edge_color_rgba,
110
+ edge_color=edge_color_rgba.tolist(),
111
111
  ax=self.ax,
112
112
  )
113
113
 
@@ -181,7 +181,7 @@ class Network:
181
181
  nodelist=node_ids,
182
182
  node_size=node_size,
183
183
  node_shape=node_shape,
184
- node_color=node_color_rgba,
184
+ node_color=node_color_rgba.tolist(),
185
185
  edgecolors=node_edgecolor_rgba,
186
186
  linewidths=node_edgewidth,
187
187
  ax=self.ax,
@@ -192,7 +192,7 @@ class Network:
192
192
  subgraph,
193
193
  pos=node_coordinates,
194
194
  width=edge_width,
195
- edge_color=edge_color_rgba,
195
+ edge_color=edge_color_rgba.tolist(),
196
196
  ax=self.ax,
197
197
  )
198
198
 
@@ -29,7 +29,7 @@ class Plotter(Canvas, Network, Contour, Labels):
29
29
  def __init__(
30
30
  self,
31
31
  graph: Graph,
32
- figsize: Tuple = (10, 10),
32
+ figsize: Union[List, Tuple, np.ndarray] = (10, 10),
33
33
  background_color: Union[str, List, Tuple, np.ndarray] = "white",
34
34
  background_alpha: Union[float, None] = 1.0,
35
35
  pad: float = 0.3,
@@ -38,7 +38,7 @@ class Plotter(Canvas, Network, Contour, Labels):
38
38
 
39
39
  Args:
40
40
  graph (Graph): The network data and attributes to be visualized.
41
- figsize (Tuple, optional): Size of the figure in inches (width, height). Defaults to (10, 10).
41
+ figsize (List, Tuple, np.ndarray, optional): Size of the figure in inches (width, height). Defaults to (10, 10).
42
42
  background_color (str, List, Tuple, np.ndarray, optional): Background color of the plot. Defaults to "white".
43
43
  background_alpha (float, None, optional): Transparency level of the background color. If provided, it overrides
44
44
  any existing alpha values found in background_color. Defaults to 1.0.
@@ -58,7 +58,7 @@ class Plotter(Canvas, Network, Contour, Labels):
58
58
  def _initialize_plot(
59
59
  self,
60
60
  graph: Graph,
61
- figsize: Tuple,
61
+ figsize: Union[List, Tuple, np.ndarray],
62
62
  background_color: Union[str, List, Tuple, np.ndarray],
63
63
  background_alpha: Union[float, None],
64
64
  pad: float,
@@ -67,7 +67,7 @@ class Plotter(Canvas, Network, Contour, Labels):
67
67
 
68
68
  Args:
69
69
  graph (Graph): The network data and attributes to be visualized.
70
- figsize (Tuple): Size of the figure in inches (width, height).
70
+ figsize (List, Tuple, np.ndarray, optional): Size of the figure in inches (width, height). Defaults to (10, 10).
71
71
  background_color (str, List, Tuple, or np.ndarray): Background color of the plot. Can be a single color or an array of colors.
72
72
  background_alpha (float, None, optional): Transparency level of the background color. If provided, it overrides any existing
73
73
  alpha values found in `background_color`.
@@ -93,8 +93,8 @@ class Plotter(Canvas, Network, Contour, Labels):
93
93
  fig, ax = plt.subplots(figsize=figsize)
94
94
  fig.tight_layout() # Adjust subplot parameters to give specified padding
95
95
  # Set axis limits based on the calculated bounding box and radius
96
- ax.set_xlim([center[0] - radius - pad, center[0] + radius + pad])
97
- ax.set_ylim([center[1] - radius - pad, center[1] + radius + pad])
96
+ ax.set_xlim((float(center[0] - radius - pad), float(center[0] + radius + pad)))
97
+ ax.set_ylim((float(center[1] - radius - pad), float(center[1] + radius + pad)))
98
98
  ax.set_aspect("equal") # Ensure the aspect ratio is equal
99
99
 
100
100
  # Set the background color of the plot
@@ -114,8 +114,7 @@ class Plotter(Canvas, Network, Contour, Labels):
114
114
 
115
115
  return ax
116
116
 
117
- @staticmethod
118
- def savefig(*args, pad_inches: float = 0.5, dpi: int = 100, **kwargs) -> None:
117
+ def savefig(self, *args, pad_inches: float = 0.5, dpi: int = 100, **kwargs) -> None:
119
118
  """Save the current plot to a file with additional export options.
120
119
 
121
120
  Args:
@@ -132,8 +131,7 @@ class Plotter(Canvas, Network, Contour, Labels):
132
131
  # Call plt.savefig with combined arguments
133
132
  plt.savefig(*args, **kwargs)
134
133
 
135
- @staticmethod
136
- def show(*args, **kwargs) -> None:
134
+ def show(self, *args, **kwargs) -> None:
137
135
  """Display the current plot.
138
136
 
139
137
  Args:
@@ -23,8 +23,8 @@ def get_annotated_domain_colors(
23
23
  scale_factor: float = 1.0,
24
24
  ids_to_colors: Union[Dict[int, Any], None] = None,
25
25
  random_seed: int = 888,
26
- ) -> np.ndarray:
27
- """Get colors for the domains based on node annotations, or use a specified color.
26
+ ) -> List[Tuple]:
27
+ """Get colors for the domains based on node annotation, or use a specified color.
28
28
 
29
29
  Args:
30
30
  graph (Graph): The network data and attributes to be visualized.
@@ -41,7 +41,7 @@ def get_annotated_domain_colors(
41
41
  random_seed (int, optional): Seed for random number generation to ensure reproducibility. Defaults to 888.
42
42
 
43
43
  Returns:
44
- np.ndarray: Array of RGBA colors for each domain.
44
+ List[Tuple]: List of RGBA colors for each domain, based on significance or the specified color.
45
45
  """
46
46
  # Generate domain colors based on the significance data
47
47
  node_colors = get_domain_colors(
@@ -61,10 +61,12 @@ def get_annotated_domain_colors(
61
61
  if len(node_ids) > 1:
62
62
  # For multi-node domains, choose the brightest color based on RGB sum
63
63
  domain_colors = np.array([node_colors[node] for node in node_ids])
64
- color = domain_colors[np.argmax(domain_colors[:, :3].sum(axis=1))] # Sum the RGB values
64
+ color = tuple(
65
+ domain_colors[np.argmax(domain_colors[:, :3].sum(axis=1))]
66
+ ) # Sum the RGB values
65
67
  else:
66
68
  # Single-node domains default to white (RGBA)
67
- color = np.array([1.0, 1.0, 1.0, 1.0])
69
+ color = tuple([1.0, 1.0, 1.0, 1.0])
68
70
 
69
71
  annotated_colors.append(color)
70
72
 
@@ -202,7 +204,7 @@ def _get_composite_node_colors(
202
204
  significances = node_info["significances"] # List of significance values
203
205
  # Filter domains and significances to keep only those with corresponding colors in domain_ids_to_colors
204
206
  filtered_domains_significances = [
205
- (domain_id, significance)
207
+ (domain_id, float(significance))
206
208
  for domain_id, significance in zip(domains, significances)
207
209
  if domain_id in domain_ids_to_colors
208
210
  ]
@@ -216,7 +218,9 @@ def _get_composite_node_colors(
216
218
  colors = [domain_ids_to_colors[domain_id] for domain_id in filtered_domains]
217
219
  # Blend the colors using the given gamma (default is 2.2 if None)
218
220
  gamma = blend_gamma if blend_gamma is not None else 2.2
219
- composite_color = _blend_colors_perceptually(colors, filtered_significances, gamma)
221
+ composite_color = _blend_colors_perceptually(
222
+ colors, list(filtered_significances), gamma
223
+ )
220
224
  # Assign the composite color to the node
221
225
  composite_colors[node] = composite_color
222
226
 
@@ -246,7 +250,7 @@ def _get_colors(
246
250
  if color:
247
251
  # If a single color is specified, apply it to all domains
248
252
  rgba = to_rgba(color, num_repeats=num_domains)
249
- return rgba
253
+ return list(rgba)
250
254
 
251
255
  # Load colormap and generate a large, maximally separated set of colors
252
256
  colormap = matplotlib.colormaps.get_cmap(cmap)
@@ -356,6 +360,9 @@ def to_rgba(
356
360
 
357
361
  Returns:
358
362
  np.ndarray: Array of RGBA colors repeated `num_repeats` times, if applicable.
363
+
364
+ Raises:
365
+ ValueError: If the provided color format is invalid or cannot be converted to RGBA.
359
366
  """
360
367
 
361
368
  def convert_to_rgba(c: Union[str, List, Tuple, np.ndarray]) -> np.ndarray:
@@ -11,7 +11,7 @@ import numpy as np
11
11
 
12
12
  def calculate_bounding_box(
13
13
  node_coordinates: np.ndarray, radius_margin: float = 1.05
14
- ) -> Tuple[np.ndarray, float]:
14
+ ) -> Tuple[Tuple, float]:
15
15
  """Calculate the bounding box of the network based on node coordinates.
16
16
 
17
17
  Args:
@@ -19,13 +19,13 @@ def calculate_bounding_box(
19
19
  radius_margin (float, optional): Margin factor to apply to the bounding box radius. Defaults to 1.05.
20
20
 
21
21
  Returns:
22
- tuple: Center of the bounding box and the radius (adjusted by the radius margin).
22
+ Tuple[Tuple, float]: Center (x, y) and radius of the bounding box.
23
23
  """
24
24
  # Find minimum and maximum x, y coordinates
25
25
  x_min, y_min = np.min(node_coordinates, axis=0)
26
26
  x_max, y_max = np.max(node_coordinates, axis=0)
27
27
  # Calculate the center of the bounding box
28
- center = np.array([(x_min + x_max) / 2, (y_min + y_max) / 2])
28
+ center = ((x_min + x_max) / 2, (y_min + y_max) / 2)
29
29
  # Calculate the radius of the bounding box, adjusted by the margin
30
30
  radius = max(x_max - x_min, y_max - y_min) / 2 * radius_margin
31
31
  return center, radius
risk/risk.py CHANGED
@@ -3,15 +3,15 @@ risk/risk
3
3
  ~~~~~~~~~
4
4
  """
5
5
 
6
- from risk.annotations import AnnotationsIO
6
+ from risk.annotation.io import AnnotationIO
7
7
  from risk.log import params, set_global_verbosity
8
- from risk.neighborhoods import NeighborhoodsAPI
9
- from risk.network import NetworkIO
10
- from risk.network.graph import GraphAPI
11
- from risk.network.plotter import PlotterAPI
8
+ from risk.neighborhoods.api import NeighborhoodsAPI
9
+ from risk.network.graph.api import GraphAPI
10
+ from risk.network.io import NetworkIO
11
+ from risk.network.plotter.api import PlotterAPI
12
12
 
13
13
 
14
- class RISK(NetworkIO, AnnotationsIO, NeighborhoodsAPI, GraphAPI, PlotterAPI):
14
+ class RISK(NetworkIO, AnnotationIO, NeighborhoodsAPI, GraphAPI, PlotterAPI):
15
15
  """RISK: A class for network analysis and visualization.
16
16
 
17
17
  The RISK class integrates functionalities for loading networks, processing annotations,
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.4
2
+ Name: risk-network
3
+ Version: 0.0.12
4
+ Summary: A Python package for biological network analysis
5
+ Author-email: Ira Horecka <ira89@icloud.com>
6
+ License: GPL-3.0-or-later
7
+ Project-URL: Homepage, https://github.com/riskportal/network
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
15
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
16
+ Classifier: Topic :: Scientific/Engineering :: Visualization
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: Development Status :: 4 - Beta
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: ipywidgets
23
+ Requires-Dist: leidenalg
24
+ Requires-Dist: markov_clustering
25
+ Requires-Dist: matplotlib
26
+ Requires-Dist: networkx
27
+ Requires-Dist: nltk
28
+ Requires-Dist: numpy
29
+ Requires-Dist: openpyxl
30
+ Requires-Dist: pandas
31
+ Requires-Dist: python-igraph
32
+ Requires-Dist: python-louvain
33
+ Requires-Dist: scikit-learn
34
+ Requires-Dist: scipy
35
+ Requires-Dist: statsmodels
36
+ Requires-Dist: threadpoolctl
37
+ Requires-Dist: tqdm
38
+ Dynamic: license-file
39
+
40
+ # RISK Network
41
+
42
+ <p align="center">
43
+ <img src="https://i.imgur.com/8TleEJs.png" width="50%" />
44
+ </p>
45
+
46
+ <br>
47
+
48
+ ![Python](https://img.shields.io/badge/python-3.8%2B-yellow)
49
+ [![pypiv](https://img.shields.io/pypi/v/risk-network.svg)](https://pypi.python.org/pypi/risk-network)
50
+ ![License](https://img.shields.io/badge/license-GPLv3-purple)
51
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.xxxxxxx.svg)](https://doi.org/10.5281/zenodo.xxxxxxx)
52
+ ![Downloads](https://img.shields.io/pypi/dm/risk-network)
53
+ ![Tests](https://github.com/riskportal/network/actions/workflows/ci.yml/badge.svg)
54
+
55
+ **RISK** (Regional Inference of Significant Kinships) is a next-generation tool for biological network annotation and visualization. RISK integrates community detection-based clustering, rigorous statistical enrichment analysis, and a modular framework to uncover biologically meaningful relationships and generate high-resolution visualizations. RISK supports diverse data formats and is optimized for large-scale network analysis, making it a valuable resource for researchers in systems biology and beyond.
56
+
57
+ ## Documentation and Tutorial
58
+
59
+ Full documentation is available at:
60
+
61
+ - **Docs:** [https://riskportal.github.io/network-tutorial](https://riskportal.github.io/network-tutorial)
62
+ - **Tutorial Jupyter Notebook Repository:** [https://github.com/riskportal/network-tutorial](https://github.com/riskportal/network-tutorial)
63
+
64
+ ## Installation
65
+
66
+ RISK is compatible with Python 3.8 or later and runs on all major operating systems. To install the latest version of RISK, run:
67
+
68
+ ```bash
69
+ pip install risk-network --upgrade
70
+ ```
71
+
72
+ ## Features
73
+
74
+ - **Comprehensive Network Analysis**: Analyze biological networks (e.g., protein–protein interaction and genetic interaction networks) as well as non-biological networks.
75
+ - **Advanced Clustering Algorithms**: Supports Louvain, Leiden, Markov Clustering, Greedy Modularity, Label Propagation, Spinglass, and Walktrap for identifying structured network regions.
76
+ - **Flexible Visualization**: Produce customizable, high-resolution network visualizations with kernel density estimate overlays, adjustable node and edge attributes, and export options in SVG, PNG, and PDF formats.
77
+ - **Efficient Data Handling**: Supports multiple input/output formats, including JSON, CSV, TSV, Excel, Cytoscape, and GPickle.
78
+ - **Statistical Analysis**: Assess functional enrichment using hypergeometric, permutation (network-aware), binomial, chi-squared, Poisson, and z-score tests, ensuring statistical adaptability across datasets.
79
+ - **Cross-Domain Applicability**: Suitable for network analysis across biological and non-biological domains, including social and communication networks.
80
+
81
+ ## Example Usage
82
+
83
+ We applied RISK to a *Saccharomyces cerevisiae* protein–protein interaction network from Michaelis et al. (2023), filtering for proteins with six or more interactions to emphasize core functional relationships. RISK identified compact, statistically enriched clusters corresponding to biological processes such as ribosomal assembly and mitochondrial organization.
84
+
85
+ [![Figure 1](https://i.imgur.com/lJHJrJr.jpeg)](https://i.imgur.com/lJHJrJr.jpeg)
86
+
87
+ This figure highlights RISK’s capability to detect both established and novel functional modules within the yeast interactome.
88
+
89
+ ## Citation
90
+
91
+ If you use RISK in your research, please cite:
92
+
93
+ **Horecka et al.**, "RISK: a next-generation tool for biological network annotation and visualization", **Bioinformatics**, 2025. DOI: [10.1234/zenodo.xxxxxxx](https://doi.org/10.1234/zenodo.xxxxxxx)
94
+
95
+ ## Software Architecture and Implementation
96
+
97
+ RISK features a streamlined, modular architecture designed to meet diverse research needs. RISK’s modular design enables users to run individual components—such as clustering, statistical testing, or visualization—independently or in combination, depending on the analysis workflow. It includes dedicated modules for:
98
+
99
+ - **Data I/O**: Supports JSON, CSV, TSV, Excel, Cytoscape, and GPickle formats.
100
+ - **Clustering**: Supports multiple clustering methods, including Louvain, Leiden, Markov Clustering, Greedy Modularity, Label Propagation, Spinglass, and Walktrap. Provides flexible distance metrics tailored to network structure.
101
+ - **Statistical Analysis**: Provides a suite of tests for overrepresentation analysis of annotations.
102
+ - **Visualization**: Offers customizable, high-resolution output in multiple formats, including SVG, PNG, and PDF.
103
+ - **Configuration Management**: Centralized parameters in risk.params ensure reproducibility and easy tuning for large-scale analyses.
104
+
105
+ ## Performance and Efficiency
106
+
107
+ Benchmarking results demonstrate that RISK efficiently scales to networks exceeding hundreds of thousands of edges, maintaining low execution times and optimal memory usage across statistical tests.
108
+
109
+ ## Contributing
110
+
111
+ We welcome contributions from the community:
112
+
113
+ - [Issues Tracker](https://github.com/riskportal/network/issues)
114
+ - [Source Code](https://github.com/riskportal/network/tree/main/risk)
115
+
116
+ ## Support
117
+
118
+ If you encounter issues or have suggestions for new features, please use the [Issues Tracker](https://github.com/riskportal/network/issues) on GitHub.
119
+
120
+ ## License
121
+
122
+ RISK is open source under the [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html).
@@ -0,0 +1,40 @@
1
+ risk/__init__.py,sha256=-5Lvlnij5rJO1Sh2goXIrvMz_vJ6BhKt65-zF7EbeQU,120
2
+ risk/risk.py,sha256=Wjuxob5bI70Tpz9t71i05g94AQ3qXEMjfEcm5IV9HSY,1118
3
+ risk/annotation/__init__.py,sha256=1EbGo41ClQb5ESTtitjOhrZhaLzzwr5aT-RYDX8w-h4,185
4
+ risk/annotation/annotation.py,sha256=OE859FpVnp69hDi1cN_CQqeiG0SrJ2ZCuIdQKzY-gt0,14675
5
+ risk/annotation/io.py,sha256=iffCXePQuMluytYQDg5tbu34g9ZsCUq1H4j-z-W25lE,10695
6
+ risk/annotation/nltk_setup.py,sha256=14B6L56_dwIgAOC9Rl4dNd4-b-aEngUCoJP9L9kEilU,3572
7
+ risk/log/__init__.py,sha256=en-hKzuFtQWos4oZd8PxJ9u9Pe5bdihiqH9-qk_5ppw,217
8
+ risk/log/console.py,sha256=PgjyEvyhYLUSHXPUKEqOmxsDsfrjPICIgqo_cAHq0N8,4575
9
+ risk/log/parameters.py,sha256=FnP-kdg0Kip0SyxFEn7su7BG51FbMtTfm3Rk96cnCoc,5801
10
+ risk/neighborhoods/__init__.py,sha256=CNS0VNbh_IdxldXjDkPqeTrxgY4hqi_Tc_MTADW_tzQ,182
11
+ risk/neighborhoods/api.py,sha256=TXbjbHfQDi2eZeD9086BBsUjhDiJq2BNEYALiGs_rPc,23299
12
+ risk/neighborhoods/community.py,sha256=0YdTh6wgMLiGMdtlaD7Vu_uxOVoZ9vDBjxbkglkrTV8,17808
13
+ risk/neighborhoods/domains.py,sha256=9cWcGYGALcYruvAjWKztnEZlnYyT6DSoAPP6VsgA2wQ,14601
14
+ risk/neighborhoods/neighborhoods.py,sha256=ykJu2d0Z6gRCOAMyBtpWpxXQ2Dei4nOv7w3XN0LpiX8,21672
15
+ risk/neighborhoods/stats/__init__.py,sha256=1evLEAa7trCWj2DapCV4vW_f0zsyKHqTsn4--E_fDPg,306
16
+ risk/neighborhoods/stats/tests.py,sha256=Z14H8G2qHzM5AOhKqp4YfCOL_wp3QwzUzfeGQJOqTTU,12060
17
+ risk/neighborhoods/stats/permutation/__init__.py,sha256=V-uLSoi4SIPKjSRl7rhcDR4HJ4tquAn3QxNTXH9KzK8,169
18
+ risk/neighborhoods/stats/permutation/permutation.py,sha256=k9-Yw-1wWBqeD9cGcTh_d2ypqN-HzoJrcCEAR5-BK0o,10673
19
+ risk/neighborhoods/stats/permutation/test_functions.py,sha256=Wuop4WDY3foGeKp-hMGc2Gdqf85s-x9BDXGB8ifp0oE,3147
20
+ risk/network/__init__.py,sha256=C9GisdyJM7fizwUIipy1vC4lbry9ceqLn1iBcW0-mZg,34
21
+ risk/network/io.py,sha256=1JViOU1YY0DgRP-dK-n-Tkj2ZrpVJJm4vq-5mzvK7kM,27856
22
+ risk/network/graph/__init__.py,sha256=iG6IlE8xtAyF6_NuCBUpsJrjrjd1vsXO1Ajsr0K8EA0,46
23
+ risk/network/graph/api.py,sha256=gXheVl1xw7vFDHOOQdRxCFwVy4ajEJ1dk4GQxm13sCI,8528
24
+ risk/network/graph/graph.py,sha256=jPNJea9JiLKedGFvSKmZ5Kf2R9go0HJkZ4wYNJwZRJI,12410
25
+ risk/network/graph/stats.py,sha256=xITodchaF8Pgngynil_GM9IeMBtxuraPX-Gjp6WBEMY,7338
26
+ risk/network/graph/summary.py,sha256=UZvZk5w2BZ5zs8IDfr-YYYBr2eM1wmXh0FKp_p9UdB4,10260
27
+ risk/network/plotter/__init__.py,sha256=9kdeONe8NaJvJ5FO7eOdZiobqL4CeR7q2MghG4z6Kt8,50
28
+ risk/network/plotter/api.py,sha256=GFP0n_0-tSdCZQd6cuaH3w55953sXCR02nwyJhAEqK4,1789
29
+ risk/network/plotter/canvas.py,sha256=i8i-ARLCNsHkAW3W_E63PpbEjmQLJplpqK6mSivgz4k,13610
30
+ risk/network/plotter/contour.py,sha256=TJA4C9G07iFBBSuSCYGZJ6NZfXGWH8zVw0LC2eqU3JA,15540
31
+ risk/network/plotter/labels.py,sha256=89Ege5NkfFMZJXw_mF-rhtIPa4-S8UKtYSkj8ty_VeQ,46805
32
+ risk/network/plotter/network.py,sha256=c9rPQ5mjil0sxVQnprRaKMAUqT6PZmKiATWz0m-TvQU,14185
33
+ risk/network/plotter/plotter.py,sha256=WZcOrBW3vBQ_aLwv8c8pXJO8ZlyswHHHfEsiLxzEYaI,6121
34
+ risk/network/plotter/utils/colors.py,sha256=xZt4877ORTQqySiMh-tUGe0sXvhLbXO04iGNeBDkbbw,19144
35
+ risk/network/plotter/utils/layout.py,sha256=Lty16T-Q-oWwo9fXqm-nnS_dMS3BMhuFt4SFqxFC3Ng,3610
36
+ risk_network-0.0.12.dist-info/licenses/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
37
+ risk_network-0.0.12.dist-info/METADATA,sha256=pbVTDf2xW6i7C9XYpJgk7YituPyoC5KDjMcvyb3J3bs,6665
38
+ risk_network-0.0.12.dist-info/WHEEL,sha256=ooBFpIzZCPdw3uqIQsOo4qqbA4ZRPxHnOH7peeONza0,91
39
+ risk_network-0.0.12.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
40
+ risk_network-0.0.12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (80.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,7 +0,0 @@
1
- """
2
- risk/annotations
3
- ~~~~~~~~~~~~~~~~
4
- """
5
-
6
- from risk.annotations.annotations import define_top_annotations, get_weighted_description
7
- from risk.annotations.io import AnnotationsIO
risk/network/geometry.py DELETED
@@ -1,150 +0,0 @@
1
- """
2
- risk/network/geometry
3
- ~~~~~~~~~~~~~~~~~~~~~
4
- """
5
-
6
- import networkx as nx
7
- import numpy as np
8
-
9
-
10
- def assign_edge_lengths(
11
- G: nx.Graph,
12
- compute_sphere: bool = True,
13
- surface_depth: float = 0.0,
14
- ) -> nx.Graph:
15
- """Assign edge lengths in the graph, optionally mapping nodes to a sphere.
16
-
17
- Args:
18
- G (nx.Graph): The input graph.
19
- compute_sphere (bool): Whether to map nodes to a sphere. Defaults to True.
20
- surface_depth (float): The surface depth for mapping to a sphere. Defaults to 0.0.
21
-
22
- Returns:
23
- nx.Graph: The graph with applied edge lengths.
24
- """
25
-
26
- def compute_distance_vectorized(coords, is_sphere):
27
- """Compute distances between pairs of coordinates."""
28
- u_coords, v_coords = coords[:, 0, :], coords[:, 1, :]
29
- if is_sphere:
30
- u_coords /= np.linalg.norm(u_coords, axis=1, keepdims=True)
31
- v_coords /= np.linalg.norm(v_coords, axis=1, keepdims=True)
32
- dot_products = np.einsum("ij,ij->i", u_coords, v_coords)
33
- return np.arccos(np.clip(dot_products, -1.0, 1.0))
34
- return np.linalg.norm(u_coords - v_coords, axis=1)
35
-
36
- # Normalize graph coordinates
37
- _normalize_graph_coordinates(G)
38
-
39
- # Map nodes to sphere and adjust depth if required
40
- if compute_sphere:
41
- _map_to_sphere(G)
42
- G_depth = _create_depth(G, surface_depth=surface_depth)
43
- else:
44
- G_depth = G
45
-
46
- # Precompute edge coordinate arrays and compute distances in bulk
47
- edge_data = np.array(
48
- [
49
- [
50
- np.array(
51
- [G_depth.nodes[u]["x"], G_depth.nodes[u]["y"], G_depth.nodes[u].get("z", 0)]
52
- ),
53
- np.array(
54
- [G_depth.nodes[v]["x"], G_depth.nodes[v]["y"], G_depth.nodes[v].get("z", 0)]
55
- ),
56
- ]
57
- for u, v in G_depth.edges
58
- ]
59
- )
60
- # Compute distances
61
- distances = compute_distance_vectorized(edge_data, compute_sphere)
62
- # Assign distances back to the graph
63
- for (u, v), distance in zip(G_depth.edges, distances):
64
- G.edges[u, v]["length"] = distance
65
-
66
- return G
67
-
68
-
69
- def _map_to_sphere(G: nx.Graph) -> None:
70
- """Map the x and y coordinates of graph nodes onto a 3D sphere.
71
-
72
- Args:
73
- G (nx.Graph): The input graph with nodes having 'x' and 'y' coordinates.
74
- """
75
- # Extract x, y coordinates as a NumPy array
76
- nodes = list(G.nodes)
77
- xy_coords = np.array([[G.nodes[node]["x"], G.nodes[node]["y"]] for node in nodes])
78
- # Normalize coordinates between [0, 1]
79
- min_vals = xy_coords.min(axis=0)
80
- max_vals = xy_coords.max(axis=0)
81
- normalized_xy = (xy_coords - min_vals) / (max_vals - min_vals)
82
- # Convert normalized coordinates to spherical coordinates
83
- theta = normalized_xy[:, 0] * np.pi * 2
84
- phi = normalized_xy[:, 1] * np.pi
85
- # Compute 3D Cartesian coordinates
86
- x = np.sin(phi) * np.cos(theta)
87
- y = np.sin(phi) * np.sin(theta)
88
- z = np.cos(phi)
89
- # Assign coordinates back to graph nodes in bulk
90
- xyz_coords = {node: {"x": x[i], "y": y[i], "z": z[i]} for i, node in enumerate(nodes)}
91
- nx.set_node_attributes(G, xyz_coords)
92
-
93
-
94
- def _normalize_graph_coordinates(G: nx.Graph) -> None:
95
- """Normalize the x and y coordinates of the nodes in the graph to the [0, 1] range.
96
-
97
- Args:
98
- G (nx.Graph): The input graph with nodes having 'x' and 'y' coordinates.
99
- """
100
- # Extract x, y coordinates from the graph nodes
101
- xy_coords = np.array([[G.nodes[node]["x"], G.nodes[node]["y"]] for node in G.nodes()])
102
- # Calculate min and max values for x and y
103
- min_vals = np.min(xy_coords, axis=0)
104
- max_vals = np.max(xy_coords, axis=0)
105
- # Normalize the coordinates to [0, 1]
106
- normalized_xy = (xy_coords - min_vals) / (max_vals - min_vals)
107
- # Update the node coordinates with the normalized values
108
- for i, node in enumerate(G.nodes()):
109
- G.nodes[node]["x"], G.nodes[node]["y"] = normalized_xy[i]
110
-
111
-
112
- def _create_depth(G: nx.Graph, surface_depth: float = 0.0) -> nx.Graph:
113
- """Adjust the 'z' attribute of each node based on the subcluster strengths and normalized surface depth.
114
-
115
- Args:
116
- G (nx.Graph): The input graph.
117
- surface_depth (float): The maximum surface depth to apply for the strongest subcluster.
118
-
119
- Returns:
120
- nx.Graph: The graph with adjusted 'z' attribute for each node.
121
- """
122
- if surface_depth >= 1.0:
123
- surface_depth -= 1e-6 # Cap the surface depth to prevent a value of 1.0
124
-
125
- # Compute subclusters as connected components
126
- connected_components = list(nx.connected_components(G))
127
- subcluster_strengths = {}
128
- max_strength = 0
129
- # Precompute strengths and track the maximum strength
130
- for component in connected_components:
131
- size = len(component)
132
- max_strength = max(max_strength, size)
133
- for node in component:
134
- subcluster_strengths[node] = size
135
-
136
- # Avoid repeated lookups and computations by pre-fetching node data
137
- nodes = list(G.nodes(data=True))
138
- node_updates = {}
139
- for node, attrs in nodes:
140
- strength = subcluster_strengths[node]
141
- normalized_surface_depth = (strength / max_strength) * surface_depth
142
- x, y, z = attrs["x"], attrs["y"], attrs["z"]
143
- norm = np.sqrt(x**2 + y**2 + z**2)
144
- adjusted_z = z - (z / norm) * normalized_surface_depth
145
- node_updates[node] = {"z": adjusted_z}
146
-
147
- # Batch update node attributes
148
- nx.set_node_attributes(G, node_updates)
149
-
150
- return G
risk/stats/__init__.py DELETED
@@ -1,15 +0,0 @@
1
- """
2
- risk/stats
3
- ~~~~~~~~~~
4
- """
5
-
6
- from risk.stats.permutation import compute_permutation_test
7
- from risk.stats.stat_tests import (
8
- compute_binom_test,
9
- compute_chi2_test,
10
- compute_hypergeom_test,
11
- compute_poisson_test,
12
- compute_zscore_test,
13
- )
14
-
15
- from risk.stats.significance import calculate_significance_matrices
@@ -1,6 +0,0 @@
1
- """
2
- risk/stats/permutation
3
- ~~~~~~~~~~~~~~~~~~~~~~
4
- """
5
-
6
- from risk.stats.permutation.permutation import compute_permutation_test