risk-network 0.0.5b6__tar.gz → 0.0.6b1__tar.gz

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 (37) hide show
  1. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/PKG-INFO +3 -4
  2. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/README.md +2 -3
  3. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/__init__.py +1 -1
  4. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/annotations/io.py +15 -3
  5. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/neighborhoods/community.py +7 -3
  6. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/neighborhoods/neighborhoods.py +2 -2
  7. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/network/io.py +30 -10
  8. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/network/plot.py +343 -163
  9. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/risk.py +6 -18
  10. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk_network.egg-info/PKG-INFO +3 -4
  11. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/LICENSE +0 -0
  12. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/MANIFEST.in +0 -0
  13. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/pyproject.toml +0 -0
  14. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/annotations/__init__.py +0 -0
  15. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/annotations/annotations.py +0 -0
  16. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/constants.py +0 -0
  17. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/log/__init__.py +0 -0
  18. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/log/console.py +0 -0
  19. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/log/params.py +0 -0
  20. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/neighborhoods/__init__.py +0 -0
  21. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/neighborhoods/domains.py +0 -0
  22. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/network/__init__.py +0 -0
  23. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/network/geometry.py +0 -0
  24. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/network/graph.py +0 -0
  25. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/stats/__init__.py +0 -0
  26. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/stats/fisher_exact.py +0 -0
  27. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/stats/hypergeom.py +0 -0
  28. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/stats/permutation/__init__.py +0 -0
  29. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/stats/permutation/permutation.py +0 -0
  30. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/stats/permutation/test_functions.py +0 -0
  31. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk/stats/stats.py +0 -0
  32. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk_network.egg-info/SOURCES.txt +0 -0
  33. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk_network.egg-info/dependency_links.txt +0 -0
  34. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk_network.egg-info/requires.txt +0 -0
  35. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/risk_network.egg-info/top_level.txt +0 -0
  36. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/setup.cfg +0 -0
  37. {risk_network-0.0.5b6 → risk_network-0.0.6b1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: risk-network
3
- Version: 0.0.5b6
3
+ Version: 0.0.6b1
4
4
  Summary: A Python package for biological network analysis
5
5
  Author: Ira Horecka
6
6
  Author-email: Ira Horecka <ira89@icloud.com>
@@ -710,8 +710,7 @@ Requires-Dist: threadpoolctl
710
710
  Requires-Dist: tqdm
711
711
 
712
712
  <p align="center">
713
- <img src="./docs/github/risk-logo-dark.png#gh-dark-mode-only" width="400" />
714
- <img src="./docs/github/risk-logo-light.png#gh-light-mode-only" width="400" />
713
+ <img src="https://i.imgur.com/Fo9EmnK.png" width="400" />
715
714
  </p>
716
715
 
717
716
  <p align="center">
@@ -736,7 +735,7 @@ RISK is a software tool for visualizing spatial relationships in networks. It ai
736
735
 
737
736
  *Saccharomyces cerevisiae* proteins oriented by physical interactions discovered through affinity enrichment and mass spectrometry (Michaelis et al., 2023).
738
737
 
739
- ![PPI Network Demo](./docs/github/network.png)
738
+ ![PPI Network Demo](https://i.imgur.com/NnyK6nO.png)
740
739
 
741
740
  ## Installation
742
741
 
@@ -1,6 +1,5 @@
1
1
  <p align="center">
2
- <img src="./docs/github/risk-logo-dark.png#gh-dark-mode-only" width="400" />
3
- <img src="./docs/github/risk-logo-light.png#gh-light-mode-only" width="400" />
2
+ <img src="https://i.imgur.com/Fo9EmnK.png" width="400" />
4
3
  </p>
5
4
 
6
5
  <p align="center">
@@ -25,7 +24,7 @@ RISK is a software tool for visualizing spatial relationships in networks. It ai
25
24
 
26
25
  *Saccharomyces cerevisiae* proteins oriented by physical interactions discovered through affinity enrichment and mass spectrometry (Michaelis et al., 2023).
27
26
 
28
- ![PPI Network Demo](./docs/github/network.png)
27
+ ![PPI Network Demo](https://i.imgur.com/NnyK6nO.png)
29
28
 
30
29
  ## Installation
31
30
 
@@ -7,4 +7,4 @@ RISK: RISK Infers Spatial Kinships
7
7
 
8
8
  from risk.risk import RISK
9
9
 
10
- __version__ = "0.0.5-beta.6"
10
+ __version__ = "0.0.6-beta.1"
@@ -36,13 +36,15 @@ class AnnotationsIO:
36
36
  dict: A dictionary containing ordered nodes, ordered annotations, and the annotations matrix.
37
37
  """
38
38
  filetype = "JSON"
39
+ # Log the loading of the JSON file
39
40
  params.log_annotations(filepath=filepath, filetype=filetype)
40
41
  _log_loading(filetype, filepath=filepath)
42
+
41
43
  # Open and read the JSON file
42
44
  with open(filepath, "r") as file:
43
45
  annotations_input = json.load(file)
44
46
 
45
- # Process the JSON data and return it in the context of the network
47
+ # Load the annotations into the provided network
46
48
  return load_annotations(network, annotations_input)
47
49
 
48
50
  def load_excel_annotation(
@@ -69,14 +71,18 @@ class AnnotationsIO:
69
71
  linked to the provided network.
70
72
  """
71
73
  filetype = "Excel"
74
+ # Log the loading of the Excel file
72
75
  params.log_annotations(filepath=filepath, filetype=filetype)
73
76
  _log_loading(filetype, filepath=filepath)
77
+
74
78
  # Load the specified sheet from the Excel file
75
79
  df = pd.read_excel(filepath, sheet_name=sheet_name)
76
80
  # Split the nodes column by the specified nodes_delimiter
77
81
  df[nodes_colname] = df[nodes_colname].apply(lambda x: x.split(nodes_delimiter))
78
82
  # Convert the DataFrame to a dictionary pairing labels with their corresponding nodes
79
83
  label_node_dict = df.set_index(label_colname)[nodes_colname].to_dict()
84
+
85
+ # Load the annotations into the provided network
80
86
  return load_annotations(network, label_node_dict)
81
87
 
82
88
  def load_csv_annotation(
@@ -101,13 +107,16 @@ class AnnotationsIO:
101
107
  linked to the provided network.
102
108
  """
103
109
  filetype = "CSV"
110
+ # Log the loading of the CSV file
104
111
  params.log_annotations(filepath=filepath, filetype=filetype)
105
112
  _log_loading(filetype, filepath=filepath)
113
+
106
114
  # Load the CSV file into a dictionary
107
115
  annotations_input = _load_matrix_file(
108
116
  filepath, label_colname, nodes_colname, delimiter=",", nodes_delimiter=nodes_delimiter
109
117
  )
110
- # Process and return the annotations in the context of the network
118
+
119
+ # Load the annotations into the provided network
111
120
  return load_annotations(network, annotations_input)
112
121
 
113
122
  def load_tsv_annotation(
@@ -132,13 +141,16 @@ class AnnotationsIO:
132
141
  linked to the provided network.
133
142
  """
134
143
  filetype = "TSV"
144
+ # Log the loading of the TSV file
135
145
  params.log_annotations(filepath=filepath, filetype=filetype)
136
146
  _log_loading(filetype, filepath=filepath)
147
+
137
148
  # Load the TSV file into a dictionary
138
149
  annotations_input = _load_matrix_file(
139
150
  filepath, label_colname, nodes_colname, delimiter="\t", nodes_delimiter=nodes_delimiter
140
151
  )
141
- # Process and return the annotations in the context of the network
152
+
153
+ # Load the annotations into the provided network
142
154
  return load_annotations(network, annotations_input)
143
155
 
144
156
 
@@ -25,10 +25,14 @@ def calculate_dijkstra_neighborhoods(network: nx.Graph) -> np.ndarray:
25
25
 
26
26
  # Populate the neighborhoods matrix based on Dijkstra's distances
27
27
  for source, targets in all_dijkstra_paths.items():
28
+ max_length = max(targets.values()) if targets else 1 # Handle cases with no targets
28
29
  for target, length in targets.items():
29
- neighborhoods[source, target] = (
30
- 1 if np.isnan(length) or length == 0 else np.sqrt(1 / length)
31
- )
30
+ if np.isnan(length):
31
+ neighborhoods[source, target] = max_length # Use max distance for NaN
32
+ elif length == 0:
33
+ neighborhoods[source, target] = 1 # Assign 1 for zero-length paths (self-loops)
34
+ else:
35
+ neighborhoods[source, target] = 1 / length # Inverse of the distance
32
36
 
33
37
  return neighborhoods
34
38
 
@@ -4,7 +4,7 @@ risk/neighborhoods/neighborhoods
4
4
  """
5
5
 
6
6
  import warnings
7
- from typing import Any, Dict, Tuple
7
+ from typing import Any, Dict, List, Tuple
8
8
 
9
9
  import networkx as nx
10
10
  import numpy as np
@@ -305,7 +305,7 @@ def _get_node_position(network: nx.Graph, node: Any) -> np.ndarray:
305
305
  )
306
306
 
307
307
 
308
- def _calculate_threshold(average_distances: list, distance_threshold: float) -> float:
308
+ def _calculate_threshold(average_distances: List, distance_threshold: float) -> float:
309
309
  """Calculate the distance threshold based on the given average distances and a percentile threshold.
310
310
 
311
311
  Args:
@@ -48,6 +48,7 @@ class NetworkIO:
48
48
  self.min_edges_per_node = min_edges_per_node
49
49
  self.include_edge_weight = include_edge_weight
50
50
  self.weight_label = weight_label
51
+ # Log the initialization of the NetworkIO class
51
52
  params.log_network(
52
53
  compute_sphere=compute_sphere,
53
54
  surface_depth=surface_depth,
@@ -98,11 +99,14 @@ class NetworkIO:
98
99
  nx.Graph: Loaded and processed network.
99
100
  """
100
101
  filetype = "GPickle"
102
+ # Log the loading of the GPickle file
101
103
  params.log_network(filetype=filetype, filepath=filepath)
102
104
  self._log_loading(filetype, filepath=filepath)
105
+
103
106
  with open(filepath, "rb") as f:
104
107
  G = pickle.load(f)
105
108
 
109
+ # Initialize the graph
106
110
  return self._initialize_graph(G)
107
111
 
108
112
  @classmethod
@@ -147,8 +151,11 @@ class NetworkIO:
147
151
  nx.Graph: Processed network.
148
152
  """
149
153
  filetype = "NetworkX"
154
+ # Log the loading of the NetworkX graph
150
155
  params.log_network(filetype=filetype)
151
156
  self._log_loading(filetype)
157
+
158
+ # Initialize the graph
152
159
  return self._initialize_graph(network)
153
160
 
154
161
  @classmethod
@@ -213,8 +220,10 @@ class NetworkIO:
213
220
  nx.Graph: Loaded and processed network.
214
221
  """
215
222
  filetype = "Cytoscape"
223
+ # Log the loading of the Cytoscape file
216
224
  params.log_network(filetype=filetype, filepath=str(filepath))
217
225
  self._log_loading(filetype, filepath=filepath)
226
+
218
227
  cys_files = []
219
228
  tmp_dir = ".tmp_cytoscape"
220
229
  # Try / finally to remove unzipped files
@@ -295,6 +304,7 @@ class NetworkIO:
295
304
  node
296
305
  ] # Assuming you have a dict `node_y_positions` for y coordinates
297
306
 
307
+ # Initialize the graph
298
308
  return self._initialize_graph(G)
299
309
 
300
310
  finally:
@@ -354,6 +364,7 @@ class NetworkIO:
354
364
  NetworkX graph: Loaded and processed network.
355
365
  """
356
366
  filetype = "Cytoscape JSON"
367
+ # Log the loading of the Cytoscape JSON file
357
368
  params.log_network(filetype=filetype, filepath=str(filepath))
358
369
  self._log_loading(filetype, filepath=filepath)
359
370
 
@@ -418,29 +429,37 @@ class NetworkIO:
418
429
  return G
419
430
 
420
431
  def _remove_invalid_graph_properties(self, G: nx.Graph) -> None:
421
- """Remove invalid properties from the graph.
432
+ """Remove invalid properties from the graph, including self-loops, nodes with fewer edges than
433
+ the threshold, and isolated nodes.
422
434
 
423
435
  Args:
424
436
  G (nx.Graph): A NetworkX graph object.
425
437
  """
426
- # First, Remove self-loop edges to ensure correct edge count
438
+ # Count number of nodes and edges before cleaning
439
+ num_initial_nodes = G.number_of_nodes()
440
+ num_initial_edges = G.number_of_edges()
441
+ # Remove self-loops to ensure correct edge count
427
442
  G.remove_edges_from(list(nx.selfloop_edges(G)))
428
- # Then, iteratively remove nodes with fewer edges than the specified threshold
443
+ # Iteratively remove nodes with fewer edges than the threshold
429
444
  while True:
430
- nodes_to_remove = [
431
- node for node in G.nodes() if G.degree(node) < self.min_edges_per_node
432
- ]
445
+ nodes_to_remove = [node for node in G.nodes if G.degree(node) < self.min_edges_per_node]
433
446
  if not nodes_to_remove:
434
- break # Exit loop if no more nodes to remove
435
-
436
- # Remove the nodes and their associated edges
447
+ break # Exit loop if no more nodes need removal
437
448
  G.remove_nodes_from(nodes_to_remove)
438
449
 
439
- # Optionally: Remove any isolated nodes if needed
450
+ # Remove isolated nodes
440
451
  isolated_nodes = list(nx.isolates(G))
441
452
  if isolated_nodes:
442
453
  G.remove_nodes_from(isolated_nodes)
443
454
 
455
+ # Log the number of nodes and edges before and after cleaning
456
+ num_final_nodes = G.number_of_nodes()
457
+ num_final_edges = G.number_of_edges()
458
+ print(f"Initial node count: {num_initial_nodes}")
459
+ print(f"Final node count: {num_final_nodes}")
460
+ print(f"Initial edge count: {num_initial_edges}")
461
+ print(f"Final edge count: {num_final_edges}")
462
+
444
463
  def _assign_edge_weights(self, G: nx.Graph) -> None:
445
464
  """Assign weights to the edges in the graph.
446
465
 
@@ -502,6 +521,7 @@ class NetworkIO:
502
521
  print(f"Edge weight: {'Included' if self.include_edge_weight else 'Excluded'}")
503
522
  if self.include_edge_weight:
504
523
  print(f"Weight label: {self.weight_label}")
524
+ print(f"Minimum edges per node: {self.min_edges_per_node}")
505
525
  print(f"Projection: {'Sphere' if self.compute_sphere else 'Plane'}")
506
526
  if self.compute_sphere:
507
527
  print(f"Surface depth: {self.surface_depth}")