pyCoReGraph 0.0.1a2__tar.gz → 0.0.1a4__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 (38) hide show
  1. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/PKG-INFO +1 -1
  2. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/pyproject.toml +1 -1
  3. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/__init__.py +2 -2
  4. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/analysis/bins.py +8 -3
  5. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/analysis/correlations.py +42 -7
  6. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/analysis/fdr.py +27 -6
  7. pycoregraph-0.0.1a4/src/coregraph/analysis/queries.py +206 -0
  8. pycoregraph-0.0.1a4/src/coregraph/analysis/reductions.py +113 -0
  9. pycoregraph-0.0.1a4/src/coregraph/graphics/animations.py +100 -0
  10. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/graphics/network.py +28 -25
  11. pycoregraph-0.0.1a4/src/coregraph/graphics/plots.py +140 -0
  12. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/models/coregraph.py +28 -11
  13. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/models/cors.py +0 -1
  14. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/models/graphics.py +0 -1
  15. pycoregraph-0.0.1a4/src/coregraph/models/stargraph.py +91 -0
  16. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/utils/formatting.py +3 -1
  17. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/utils/validation.py +17 -2
  18. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/pyCoReGraph.egg-info/PKG-INFO +1 -1
  19. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/pyCoReGraph.egg-info/SOURCES.txt +1 -1
  20. pycoregraph-0.0.1a2/src/coregraph/analysis/queries.py +0 -118
  21. pycoregraph-0.0.1a2/src/coregraph/analysis/subset.py +0 -64
  22. pycoregraph-0.0.1a2/src/coregraph/graphics/animations.py +0 -56
  23. pycoregraph-0.0.1a2/src/coregraph/graphics/plots.py +0 -85
  24. pycoregraph-0.0.1a2/src/coregraph/models/stargraph.py +0 -41
  25. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/LICENSE +0 -0
  26. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/README.md +0 -0
  27. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/setup.cfg +0 -0
  28. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/analysis/__init__.py +0 -0
  29. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/graphics/__init__.py +0 -0
  30. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/graphics/colors.py +0 -0
  31. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/models/__init__.py +0 -0
  32. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/utils/__init__.py +0 -0
  33. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/coregraph/utils/decorators.py +0 -0
  34. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/pyCoReGraph.egg-info/dependency_links.txt +0 -0
  35. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/pyCoReGraph.egg-info/requires.txt +0 -0
  36. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/src/pyCoReGraph.egg-info/top_level.txt +0 -0
  37. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/tests/test_coregraph.py +0 -0
  38. {pycoregraph-0.0.1a2 → pycoregraph-0.0.1a4}/tests/test_imports.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyCoReGraph
3
- Version: 0.0.1a2
3
+ Version: 0.0.1a4
4
4
  Summary: CoReGraph : Correlation-based dynamic gene Regulatory Graphs
5
5
  Author-email: Joseph Léger <josephleger@outlook.fr>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyCoReGraph"
7
- version = "0.0.1a2"
7
+ version = "0.0.1a4"
8
8
  description = "CoReGraph : Correlation-based dynamic gene Regulatory Graphs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,4 +1,4 @@
1
- __version__ = "0.0.1a2"
1
+ __version__ = "0.0.1a4"
2
2
 
3
3
  # Models
4
4
  from coregraph.models import (
@@ -32,7 +32,7 @@ from coregraph.graphics.network import (
32
32
  animate_network,
33
33
  )
34
34
 
35
- from coregraph.analysis.subset import (
35
+ from coregraph.analysis.reductions import (
36
36
  starry,
37
37
  subset_coregraph,
38
38
  )
@@ -3,9 +3,14 @@
3
3
  import numpy as np
4
4
 
5
5
 
6
- def _calculate_bins(data, pseudotime, n_bins):
7
- '''Discretize pseudotime expression in bins'''
8
-
6
+ def _calculate_bins(
7
+ data,
8
+ pseudotime,
9
+ n_bins
10
+ ):
11
+ '''
12
+ Discretize pseudotime expression in bins.
13
+ '''
9
14
  bin_range = (pseudotime.max() - pseudotime.min())/n_bins
10
15
  bin_seq = pseudotime.min() + np.arange(1,n_bins)*bin_range
11
16
  bins = (np.digitize(pseudotime, bin_seq)*bin_range)+(bin_range/2)
@@ -3,8 +3,24 @@
3
3
  import numpy as np
4
4
 
5
5
 
6
- def _calculate_all_cors(data, window, i, tensor, reflag, MAC, LAG_id, LAG, LAG_means, dim3_start, step=1, num_format=np.array([1,15]), dtype=np.float64):
7
- '''Calculate all lagged correlations for a unique given reference i'''
6
+ def _calculate_all_cors(
7
+ data,
8
+ window,
9
+ i,
10
+ tensor,
11
+ reflag,
12
+ MAC,
13
+ LAG_id,
14
+ LAG,
15
+ LAG_means,
16
+ dim3_start,
17
+ step = 1,
18
+ num_format = np.array([1,15]),
19
+ dtype = np.float64
20
+ ):
21
+ '''
22
+ Calculate all lagged correlations for a unique given reference i.
23
+ '''
8
24
  dim3 = dim3_start
9
25
  n_genes, n_cells = data.shape
10
26
 
@@ -43,8 +59,17 @@ def _calculate_all_cors(data, window, i, tensor, reflag, MAC, LAG_id, LAG, LAG_m
43
59
 
44
60
  return dim3, MAC, LAG_id, LAG, LAG_means
45
61
 
46
- def _calculate_LEAP_cors(data, window, i=0, step=1, num_format=np.array([1,15]), dtype=np.float64):
47
- '''Calculate all lagged correlations for a unique given reference i using LEAP traditional algorithm'''
62
+ def _calculate_LEAP_cors(
63
+ data,
64
+ window,
65
+ i = 0,
66
+ step = 1,
67
+ num_format = np.array([1,15]),
68
+ dtype = np.float64
69
+ ):
70
+ '''
71
+ Calculate all lagged correlations for a unique given reference i using LEAP traditional algorithm.
72
+ '''
48
73
  n_genes, n_cells = data.shape
49
74
  MAC = np.zeros((n_genes, n_genes))
50
75
  LAG = np.zeros((n_genes, n_genes))
@@ -76,9 +101,19 @@ def _calculate_LEAP_cors(data, window, i=0, step=1, num_format=np.array([1,15]),
76
101
  return MAC, LAG
77
102
 
78
103
 
79
- def _calculate_star_cors(data, target_row, MAC, window, i, step=1, num_format=np.array([1,15]), dtype=np.float64):
80
- '''Calculate all lagged correlations for a unique given reference i using a single reference row against all rows.'''
81
-
104
+ def _calculate_star_cors(
105
+ data,
106
+ target_row,
107
+ MAC,
108
+ window,
109
+ i,
110
+ step = 1,
111
+ num_format = np.array([1,15]),
112
+ dtype = np.float64
113
+ ):
114
+ '''
115
+ Calculate all lagged correlations for a unique given reference i using a single reference row against all rows.
116
+ '''
82
117
  n_genes, n_cells = data.shape
83
118
 
84
119
  # Take reference row only
@@ -5,9 +5,19 @@ import numpy as np
5
5
  from coregraph.analysis.correlations import (_calculate_LEAP_cors, _calculate_star_cors)
6
6
 
7
7
 
8
- def _calculate_FDR(data, MAC, window, n_perms = 100, FDR_cutoffs = 101, step=1, num_format=np.array([1,15]), dtype=np.float64):
9
- '''Calculate False Discovery Rate by permutations'''
10
-
8
+ def _calculate_FDR(
9
+ data,
10
+ MAC,
11
+ window,
12
+ n_perms = 100,
13
+ FDR_cutoffs = 101,
14
+ step = 1,
15
+ num_format = np.array([1,15]),
16
+ dtype = np.float64
17
+ ):
18
+ '''
19
+ Calculate False Discovery Rate by permutations.
20
+ '''
11
21
  MAC_true = np.absolute(MAC.copy())
12
22
  samp_size = np.minimum(100, data.shape[0])
13
23
  MACs_perm = np.zeros((n_perms, samp_size, samp_size))
@@ -51,9 +61,20 @@ def _calculate_FDR(data, MAC, window, n_perms = 100, FDR_cutoffs = 101, step=1,
51
61
 
52
62
  return results[::-1]
53
63
 
54
- def _calculate_star_FDR(data, target_row, MAC, window, n_perms = 100, FDR_cutoffs = 101, step=1, num_format=np.array([1,15]), dtype=np.float64):
55
- '''Calculate False Discovery Rate by permutations for a single reference row against all rows.'''
56
-
64
+ def _calculate_star_FDR(
65
+ data,
66
+ target_row,
67
+ MAC,
68
+ window,
69
+ n_perms = 100,
70
+ FDR_cutoffs = 101,
71
+ step = 1,
72
+ num_format = np.array([1,15]),
73
+ dtype = np.float64
74
+ ):
75
+ '''
76
+ Calculate False Discovery Rate by permutations for a single reference row against all rows.
77
+ '''
57
78
  MAC_true = np.absolute(MAC.copy())
58
79
  samp_size = np.minimum(100, data.shape[0])
59
80
  MACs_perm = np.zeros((n_perms, samp_size))
@@ -0,0 +1,206 @@
1
+ ## QUERIES ##
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+
8
+ from coregraph.utils.decorators import (requires_cors, requires_FDR)
9
+
10
+
11
+ @requires_cors
12
+ def get_correlation(
13
+ C: CoReGraph,
14
+ regulator: str,
15
+ target: str,
16
+ ref_lag: tuple[int, int]
17
+ ) -> float :
18
+ '''
19
+ Get correlation value between two genes at a specific (reference, lag) window pair.
20
+
21
+ Parameters
22
+ ----------
23
+ C : CoReGraph
24
+ CoReGraph object with calculated correlations
25
+ regulator : str
26
+ Gene to consider as regulator for the relationship
27
+ target : str
28
+ Gene to consider as regulated for the relationship
29
+ ref_lag : tuple[int, int]
30
+ Tuple containing reference and lagged window for regulator and target genes respectively
31
+ '''
32
+ ref, lag = ref_lag
33
+
34
+ if (ref % C.cors.step != 0) or (lag % C.cors.step != 0):
35
+ raise ValueError(f"ref_lag must be multiples of step={C.cors.step}")
36
+
37
+ reg_idx = C.gene_to_idx[regulator]
38
+ tar_idx = C.gene_to_idx[target]
39
+
40
+ if ref <= lag:
41
+ tensor_i = reg_idx
42
+ tensor_j = tar_idx
43
+ search_ref = ref
44
+ search_lag = lag
45
+ else:
46
+ tensor_i = tar_idx
47
+ tensor_j = reg_idx
48
+ search_ref = lag
49
+ search_lag = ref
50
+
51
+ dim3 = np.argwhere((C.cors.reflag[:, 0] == search_ref) & (C.cors.reflag[:, 1] == search_lag))[0][0]
52
+
53
+ value = (C.cors.tensor[tensor_i, tensor_j, dim3] / C.cors.num_format[0])
54
+
55
+ return float(value)
56
+
57
+
58
+ @requires_cors
59
+ def get_all_correlations(
60
+ C: CoReGraph,
61
+ regulator: str,
62
+ target: str,
63
+ ref: int
64
+ ) -> np.ndarray :
65
+ '''
66
+ Get all lagged correlations between two genes for a fixed reference window.
67
+
68
+ Parameters
69
+ ----------
70
+ C : CoReGraph
71
+ CoReGraph object with calculated correlations
72
+ regulator : str
73
+ Gene to consider as regulator for the relationship
74
+ target : str
75
+ Gene to consider as regulated for the relationship
76
+ ref : int
77
+ Reference window to consider
78
+ '''
79
+ if (ref % C.cors.step != 0) :
80
+ raise ValueError(f"ref must be a multiple of step={C.cors.step}")
81
+
82
+ correlations = np.empty(C.cors.n_steps, dtype=C.cors.dtype)
83
+
84
+ for i in range(C.cors.n_steps):
85
+ lag = i * C.cors.step
86
+ correlations[i] = get_correlation(C,regulator,target,(ref, lag))
87
+
88
+ return correlations
89
+
90
+
91
+ @requires_cors
92
+ def get_mac(
93
+ C: CoReGraph,
94
+ regulator: str,
95
+ target: str
96
+ ) -> dict :
97
+ '''
98
+ Get maximal absolute correlation (MAC) and corresponding reference/lag pair for two genes.
99
+
100
+ Parameters
101
+ ----------
102
+ C : CoReGraph
103
+ CoReGraph object with calculated correlations
104
+ regulator : str
105
+ Gene to consider as regulator for the relationship
106
+ target : str
107
+ Gene to consider as regulated for the relationship
108
+ '''
109
+ reg_idx = C.gene_to_idx[regulator]
110
+ tar_idx = C.gene_to_idx[target]
111
+
112
+ return {
113
+ "ref": int(C.cors.LAG_id[0, reg_idx, tar_idx]),
114
+ "lag": int(C.cors.LAG_id[1, reg_idx, tar_idx]),
115
+ "cor": float(C.cors.MAC[reg_idx, tar_idx] / C.cors.num_format[0])
116
+ }
117
+
118
+
119
+ @requires_cors
120
+ def get_mac_results(C: CoReGraph) -> tuple[pd.DataFrame, pd.DataFrame] :
121
+ '''
122
+ Get MAC and LAG matrices.
123
+
124
+ Parameters
125
+ ----------
126
+ C : CoReGraph
127
+ CoReGraph object with calculated correlations
128
+ '''
129
+ mac_df = pd.DataFrame(C.cors.MAC / C.cors.num_format[0], index=C.gene_id, columns=C.gene_id)
130
+ lag_df = pd.DataFrame(C.cors.LAG, index=C.gene_id, columns=C.gene_id)
131
+
132
+ return mac_df, lag_df
133
+
134
+
135
+ @requires_cors
136
+ @requires_FDR
137
+ def get_regulated_genes(
138
+ C: CoReGraph,
139
+ regulator: str,
140
+ cor_threshold: float = 0.0
141
+ ) -> pd.DataFrame :
142
+ '''
143
+ Get genes regulated by a regulator gene.
144
+
145
+ Parameters
146
+ ----------
147
+ C : CoReGraph
148
+ CoReGraph object with calculated correlations and FDR
149
+ regulator : str
150
+ Gene to consider as regulator for the relationship
151
+ cor_threshold : float
152
+ Correlation threshold required for genes to be considered as targets
153
+ '''
154
+ reg_idx = C.gene_to_idx[regulator]
155
+
156
+ values = (C.cors.MAC[reg_idx, :] / C.cors.num_format[0])
157
+
158
+ df = pd.DataFrame({
159
+ "gene": C.gene_id,
160
+ "correlation": values,
161
+ "lag": C.cors.LAG[reg_idx, :]
162
+ })
163
+
164
+ df = df[np.abs(df["correlation"]) > cor_threshold]
165
+
166
+ df = df.sort_values(by="correlation", key=np.abs, ascending=False)
167
+
168
+ return df.set_index("gene")
169
+
170
+
171
+ @requires_cors
172
+ @requires_FDR
173
+ def get_regulator_genes(
174
+ C: CoReGraph,
175
+ target: str,
176
+ cor_threshold: float = 0.0
177
+ ) -> pd.DataFrame :
178
+ '''
179
+ Get genes regulating a target gene.
180
+
181
+ Parameters
182
+ ----------
183
+ C : CoReGraph
184
+ CoReGraph object with calculated correlations and FDR
185
+ target : str
186
+ Gene to consider as target for the relationship
187
+ cor_threshold : float
188
+ Correlation threshold required for genes to be considered as regulators
189
+ '''
190
+ tar_idx = C.gene_to_idx[target]
191
+
192
+ values = (C.cors.MAC[:, tar_idx] / C.cors.num_format[0])
193
+
194
+ df = pd.DataFrame({
195
+ "gene": C.gene_id,
196
+ "correlation": values,
197
+ "lag": C.cors.LAG[:, tar_idx]
198
+ })
199
+
200
+ df = df[np.abs(df["correlation"]) > cor_threshold]
201
+
202
+ df = df.sort_values(by="correlation", key=np.abs, ascending=False)
203
+
204
+ return df.set_index("gene")
205
+
206
+
@@ -0,0 +1,113 @@
1
+ ## REDUCTIONS ##
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+
6
+ from tqdm import tqdm
7
+
8
+ from coregraph.models.coregraph import CoReGraph
9
+ from coregraph.models.stargraph import StarGraph
10
+
11
+ from coregraph.analysis.correlations import _calculate_star_cors
12
+ from coregraph.analysis.fdr import _calculate_star_FDR
13
+ from coregraph.utils.validation import _solve_step
14
+
15
+
16
+ def starry(
17
+ C : CoReGraph,
18
+ central_gene : str,
19
+ window: int | None = None,
20
+ FDR_thr : float = 0.05,
21
+ n_perms : int = 100,
22
+ FDR_cutoffs : int = 501,
23
+ step: int | None = None,
24
+ n_steps: int | None = None,
25
+ verbose : bool = False
26
+ ) -> StarGraph :
27
+ '''
28
+ Estimate starry gene regulatory network centered on a given gene
29
+
30
+ Parameters
31
+ ----------
32
+ C : CoReGraph
33
+ CoReGraph object to turn into a stargraph object
34
+ central_gene : str
35
+ Central gene of the newly created stargraph
36
+ window : int | None
37
+ Number of cells in the window for applying lags (default : n_cells*2/3)
38
+ FDR_thr : float
39
+ Maximal FDR for genes to be selected as in relationship with the central gene
40
+ n_perms : int
41
+ Number of repetition of matrix permutation to establish FDR
42
+ FDR_cutoffs : int
43
+ Number of levels between 0 and 1 calculated to determine the FDR
44
+ step : int | None
45
+ Step to apply while shifting window
46
+ n_steps : int | None
47
+ Total number of steps to consider while shifting window
48
+ verbose : bool
49
+ Wether show progression bar (slightly slow down the process)
50
+ '''
51
+ if window is None:
52
+ window = round(C.n_cells*(2/3))
53
+
54
+ n_genes, n_cells = C.data.shape
55
+ target_row = C.gene_id.index(central_gene)
56
+ step, n_steps = _solve_step(step, n_steps, window, n_cells)
57
+
58
+ ## Calculate MAC ##
59
+ MAC = np.zeros((n_genes), dtype=np.float64)
60
+
61
+ np.seterr(divide='ignore', invalid='ignore')
62
+ iterator = tqdm(range(0, n_cells-window+1, step), desc="Calculating Correlations", disable=not verbose)
63
+ for i in iterator:
64
+ MAC = _calculate_star_cors(C.data, target_row, MAC, window, i, step)
65
+
66
+ ## Calculate FDR ##
67
+ FDR = _calculate_star_FDR(C.data, target_row, MAC, window, n_perms, FDR_cutoffs, step)
68
+ FDR = pd.DataFrame(FDR)
69
+ FDR.columns = ["cors", "MACs_observed", "MACs_ave_perm", "FDR"]
70
+ FDR[["MACs_observed"]] = FDR[["MACs_observed"]].astype(int)
71
+
72
+ cor_thr = min(FDR['cors'][FDR['FDR'] < FDR_thr])
73
+ MAC = pd.DataFrame(MAC, index=C.gene_id, columns=['MAC'])
74
+ MAC = MAC.sort_values(by='MAC', key=abs, ascending=False)
75
+
76
+ ## Create a new object and fill in it ##
77
+ star = StarGraph()
78
+ star.central_gene = central_gene
79
+ star.window = window
80
+ star.step = step
81
+ star.n_steps = n_steps
82
+ star.MAC = MAC
83
+ star.FDR = FDR
84
+ star.set_FDR_threshold(FDR_thr)
85
+
86
+ return star
87
+
88
+
89
+ def subset_coregraph(
90
+ C: CoReGraph,
91
+ gene_list : list[str],
92
+ ) -> CoReGraph :
93
+ '''
94
+ Reduct a CoReGraph object based on a gene list.
95
+
96
+ Parameters
97
+ ----------
98
+ C : CoReGraph
99
+ CoReGraph object to turn into a stargraph object
100
+ gene_list : str
101
+ List of genes to keep in subsetted object
102
+ '''
103
+ id_dict = {}
104
+ for i, b in enumerate(C.gene_id):
105
+ id_dict[b] = i
106
+
107
+ shared_id = [id_dict[g] for g in gene_list]
108
+ shared_id.sort()
109
+ subdata = C.data[shared_id,:]
110
+ subid = [C.gene_id[g] for g in shared_id]
111
+
112
+ subobject = CoReGraph(subdata, C.pseudotime, subid, C.cell_id)
113
+ return subobject
@@ -0,0 +1,100 @@
1
+ ## ANIMATIONS ##
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+ import matplotlib.patches as patches
8
+
9
+ from matplotlib.animation import FuncAnimation
10
+
11
+ from coregraph.graphics.colors import ColorBlind
12
+ from coregraph.analysis.queries import (get_all_correlations)
13
+ from coregraph.utils.decorators import (requires_cors, requires_bins)
14
+
15
+
16
+ @requires_bins
17
+ @requires_cors
18
+ def animate_correlations(
19
+ C: CoReGraph,
20
+ regulator: str,
21
+ target: str,
22
+ ref: int,
23
+ scaled: bool = False,
24
+ decimals: int = 15,
25
+ color: tuple = (ColorBlind[0], ColorBlind[3]),
26
+ linewidth: float = 1 ,
27
+ figsize: tuple = (8,4)
28
+ ):
29
+ '''
30
+ Animate lagged correlations.
31
+
32
+ Parameters
33
+ ----------
34
+ C : CoReGraph
35
+ CoReGraph object with calculated correlations
36
+ regulator : str
37
+ Gene to consider as regulator for the relationship
38
+ target : str
39
+ Gene to consider as regulated for the relationship
40
+ ref : int
41
+ Reference window to consider
42
+ scaled : bool
43
+ Whether displayed expressions has to be scaled from 0 to 1
44
+ decimals : int
45
+ Number of decimals to display for correlation values
46
+ color : tuple
47
+ Colors for each considered gene
48
+ linewidth : float
49
+ Width of expression curves
50
+ figsize : tuple
51
+ Figure width and height
52
+ '''
53
+ if C.graphics.n_bins is None:
54
+ raise ValueError("Bins have not been calculated.")
55
+
56
+ values = (C.graphics.scaled if scaled else C.graphics.mean)
57
+ reg_idx = C.gene_to_idx[regulator]
58
+ tar_idx = C.gene_to_idx[target]
59
+ y_max = np.max([values[reg_idx, :], values[tar_idx, :]]) * 1.1
60
+ all_cors = get_all_correlations(C, regulator, target, ref)
61
+ all_cors_norm = (all_cors / np.max(np.abs(all_cors)))
62
+
63
+ vmin = min(all_cors_norm)
64
+ vmax = max(all_cors_norm)
65
+
66
+ fig, ax = plt.subplots(1, 2, figsize=figsize, width_ratios=[25, 1],)
67
+ x = np.unique(C.graphics.bin_id)
68
+
69
+ # Regulator and target lines
70
+ ax[0].plot(x, values[reg_idx, :], color=color[0], linewidth=linewidth)
71
+ ax[0].plot(x, values[tar_idx, :], color=color[1], linewidth=linewidth)
72
+ ax[1].set(xlim=[0,1], ylim=[-1 if vmin <= 0 else 0, 1 if vmax >= 0 else 0])
73
+ ax[1].yaxis.tick_right()
74
+ ax[1].set_xticks([])
75
+ #ax[1].axis('off')
76
+
77
+ fixed_rect = ax[0].add_patch(patches.Rectangle((ref, 0), C.cors.window, y_max, facecolor=color[0], alpha=0.1,))
78
+ moving_rect = ax[0].add_patch(patches.Rectangle((0, 0), C.cors.window, y_max, facecolor=color[1], alpha=0.1,))
79
+ moving_bar = ax[1].add_patch(patches.Rectangle((0, 0), 0, 0, facecolor=(1,1,1), edgecolor = None, fill=True, alpha=1))
80
+
81
+ def update(frame):
82
+ lag = frame * C.cors.step
83
+ moving_rect.set_x(lag)
84
+ moving_bar.set_bounds(0, 0, 1, all_cors_norm[frame])
85
+ if all_cors_norm[frame] >= 0:
86
+ moving_bar.set(facecolor=(1,(1-all_cors_norm[frame])/2,(1-all_cors_norm[frame])/2))
87
+ else:
88
+ moving_bar.set(facecolor=((1+all_cors_norm[frame])/2,(1+all_cors_norm[frame])/2,1))
89
+
90
+ cor = all_cors[frame]
91
+ ax[0].set_title(f"lag = {lag}\ncor = {np.round(cor, decimals)}")
92
+ ax[1].set_title(f"{np.absolute(round(all_cors_norm[frame]*100,1))}% of MAC\n ")
93
+
94
+ return (moving_rect, moving_bar)
95
+
96
+ ani = FuncAnimation(fig, update, frames=C.cors.n_steps, blit=True)
97
+ #HTML(ani.to_jshtml())
98
+ return ani
99
+
100
+
@@ -14,7 +14,11 @@ from coregraph.analysis.queries import (get_all_correlations, get_mac)
14
14
  from coregraph.utils.decorators import (requires_cors, requires_FDR)
15
15
 
16
16
 
17
- def _build_correlation_tensor(C, genes, correlation_threshold):
17
+ def _build_correlation_tensor(
18
+ C,
19
+ genes,
20
+ correlation_threshold
21
+ ):
18
22
  '''
19
23
  Build tensor (n_genes, n_genes, n_steps) containing all dynamic correlations.
20
24
  '''
@@ -48,7 +52,11 @@ def _build_adjacency_tensor(cor_tensor):
48
52
  return filtered
49
53
 
50
54
 
51
- def _compute_node_sizes(C, genes, node_ratio=1):
55
+ def _compute_node_sizes(
56
+ C,
57
+ genes,
58
+ node_ratio = 1
59
+ ):
52
60
  '''
53
61
  Compute node size evolution through time.
54
62
  '''
@@ -116,15 +124,15 @@ def _draw_network_frame(ax, G, pos, genes, adjacency_matrix, node_sizes, cmap, n
116
124
  def animate_network(
117
125
  C: CoReGraph,
118
126
  genes: list[str],
119
- fdr_threshold: float=0.01,
127
+ fdr_threshold: float = 0.01,
120
128
  correlation_threshold: float | None = None,
121
- edge_ratio: float=1,
122
- node_ratio: float=1,
123
- min_target_margin: float=15,
124
- min_source_margin: float=15,
125
- font_size: int=8,
126
- figsize: tuple=(6, 6)
127
- ):
129
+ edge_ratio: float = 1,
130
+ node_ratio: float = 1,
131
+ min_target_margin: float = 15,
132
+ min_source_margin: float = 15,
133
+ font_size: int = 8,
134
+ figsize: tuple = (6, 6)
135
+ ):
128
136
  '''
129
137
  Animate dynamic gene regulatory network.
130
138
 
@@ -132,25 +140,25 @@ def animate_network(
132
140
  ----------
133
141
  C : CoreGraph
134
142
  CoreGraph object.
135
-
136
143
  genes : list[str]
137
144
  Genes to include in network.
138
-
139
145
  fdr_threshold : float
140
146
  FDR threshold used to infer minimum correlation threshold.
141
-
142
147
  correlation_threshold : float | None
143
148
  Correlation threshold.
144
-
145
149
  edge_ratio : float
146
150
  Edge width scaling factor.
147
-
148
151
  node_ratio : float
149
152
  Node size scaling factor.
150
-
153
+ min_target_margin : float
154
+ The minimum margin (gap) at the end of the edge at the target.
155
+ min_source_margin : float
156
+ The minimum margin (gap) at the beginning of the edge at the source.
157
+ font_size : int
158
+ Text size
151
159
  figsize : tuple
152
160
  Figure size.
153
- '''
161
+ '''
154
162
  # Validate threshold
155
163
  if correlation_threshold is None:
156
164
  correlation_threshold = np.min(C.cors.FDR.loc[C.cors.FDR["FDR"] < fdr_threshold, "cors"])
@@ -167,13 +175,9 @@ def animate_network(
167
175
  # Figure
168
176
  fig, ax = plt.subplots(figsize=figsize)
169
177
  cmap = cm.bwr
170
- vmin = cor_tensor.min()
171
- vmax = cor_tensor.max()
172
-
173
- if vmin == vmax:
174
- vmax += 1e-10
175
-
176
- norm = mcolors.TwoSlopeNorm(vmin=vmin, vcenter=0.0, vmax=vmax)
178
+ vmax = np.max(np.abs(cor_tensor))
179
+
180
+ norm = mcolors.TwoSlopeNorm(vmin=-vmax, vcenter=0, vmax=vmax)
177
181
 
178
182
  # Edge normalization
179
183
  if C.cors.dtype == np.int64:
@@ -181,7 +185,6 @@ def animate_network(
181
185
  else:
182
186
  edge_ratio *= 10
183
187
 
184
-
185
188
  # Update function
186
189
  def update(frame):
187
190
  adjacency_matrix = cor_tensor[:, :, frame]