|
1 | | -import matplotlib.pyplot as plt |
2 | 1 | import numpy as np |
3 | | -import seaborn as sns |
4 | | -from ripser import ripser |
5 | 2 | from scipy.signal import find_peaks |
6 | 3 | from scipy.stats import gaussian_kde |
7 | 4 |
|
@@ -65,6 +62,10 @@ def get_kde_density(expression_array, return_xgrid=False, plot=False): |
65 | 62 | x_grid = np.concatenate([[min_val - step], x_grid]) |
66 | 63 |
|
67 | 64 | if plot: |
| 65 | + # only needed when debugging locally, so don't import at module level |
| 66 | + import matplotlib.pyplot as plt |
| 67 | + import seaborn as sns |
| 68 | + |
68 | 69 | fig, ax = plt.subplots() |
69 | 70 | sns.scatterplot(x=x_grid, y=density, ax=ax) |
70 | 71 | ax.set_title("KDE Density Estimation") |
@@ -98,40 +99,3 @@ def call_peaks(density): |
98 | 99 | num_peaks = len(peaks) |
99 | 100 |
|
100 | 101 | return num_peaks |
101 | | - |
102 | | - |
103 | | -def persistent_peak_count(ys, persistence_cutoff=0.08): |
104 | | - """ |
105 | | - Counts robust peaks in a 1D dataset using persistent homology. |
106 | | -
|
107 | | - Args: |
108 | | - ys (np.ndarray): KDE of a marker expression (1D array) |
109 | | - persistence_cutoff (float): a threshold that decides which peaks are “significant enough” to count. |
110 | | - A large persistence peak survives over many levels of smoothing (i.e. a strong, real peak). |
111 | | - A small persistence peak quickly merges into a neighbor — likely noise. |
112 | | - 0.01: very low threshold counts even weak bumps as peaks |
113 | | - 0.05: moderate (default) counts clearly separated peaks |
114 | | - 0.1–0.2: high threshold counts only strong, dominant peaks |
115 | | - Default to 0.08 to biased towards strong peaks but not overly. |
116 | | -
|
117 | | - Returns: |
118 | | - int: number of significant peaks |
119 | | - """ |
120 | | - |
121 | | - y = np.asarray(ys) |
122 | | - if y.size == 0: |
123 | | - return 0 |
124 | | - |
125 | | - # Shift if max is at the first bin |
126 | | - if y.size > 1 and np.argmax(y) == 0: |
127 | | - y = np.concatenate([[0.0], y[:-1]]) |
128 | | - |
129 | | - # Invert to turn peaks into "holes" for 0D persistence |
130 | | - Y = -ys.reshape(-1, 1) |
131 | | - diagram = ripser(Y, maxdim=0)["dgms"][0] |
132 | | - persistence = diagram[:, 1] - diagram[:, 0] |
133 | | - |
134 | | - # Define significance threshold relative to data range |
135 | | - threshold = persistence_cutoff * np.ptp(ys) |
136 | | - n_peaks = np.sum(persistence > threshold) |
137 | | - return n_peaks |
0 commit comments