pylocuszoom 0.2.0__py3-none-any.whl → 0.5.0__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.
- pylocuszoom/__init__.py +52 -1
- pylocuszoom/backends/base.py +47 -0
- pylocuszoom/backends/bokeh_backend.py +323 -61
- pylocuszoom/backends/matplotlib_backend.py +133 -7
- pylocuszoom/backends/plotly_backend.py +423 -33
- pylocuszoom/colors.py +3 -1
- pylocuszoom/finemapping.py +0 -1
- pylocuszoom/gene_track.py +232 -23
- pylocuszoom/loaders.py +862 -0
- pylocuszoom/plotter.py +354 -245
- pylocuszoom/py.typed +0 -0
- pylocuszoom/recombination.py +4 -4
- pylocuszoom/schemas.py +395 -0
- {pylocuszoom-0.2.0.dist-info → pylocuszoom-0.5.0.dist-info}/METADATA +125 -31
- pylocuszoom-0.5.0.dist-info/RECORD +24 -0
- pylocuszoom-0.2.0.dist-info/RECORD +0 -21
- {pylocuszoom-0.2.0.dist-info → pylocuszoom-0.5.0.dist-info}/WHEEL +0 -0
- {pylocuszoom-0.2.0.dist-info → pylocuszoom-0.5.0.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -9,7 +9,7 @@ import matplotlib.pyplot as plt
|
|
|
9
9
|
import pandas as pd
|
|
10
10
|
from matplotlib.axes import Axes
|
|
11
11
|
from matplotlib.figure import Figure
|
|
12
|
-
from matplotlib.patches import Rectangle
|
|
12
|
+
from matplotlib.patches import Polygon, Rectangle
|
|
13
13
|
from matplotlib.ticker import FuncFormatter, MaxNLocator
|
|
14
14
|
|
|
15
15
|
|
|
@@ -55,13 +55,8 @@ class MatplotlibBackend:
|
|
|
55
55
|
figsize=figsize,
|
|
56
56
|
height_ratios=height_ratios,
|
|
57
57
|
sharex=sharex,
|
|
58
|
-
gridspec_kw={"hspace": 0},
|
|
59
58
|
)
|
|
60
59
|
|
|
61
|
-
# Ensure axes is always a list
|
|
62
|
-
if n_panels == 1:
|
|
63
|
-
axes = [axes]
|
|
64
|
-
|
|
65
60
|
return fig, list(axes)
|
|
66
61
|
|
|
67
62
|
def scatter(
|
|
@@ -139,11 +134,17 @@ class MatplotlibBackend:
|
|
|
139
134
|
color: str = "grey",
|
|
140
135
|
linestyle: str = "--",
|
|
141
136
|
linewidth: float = 1.0,
|
|
137
|
+
alpha: float = 1.0,
|
|
142
138
|
zorder: int = 1,
|
|
143
139
|
) -> Any:
|
|
144
140
|
"""Add a horizontal line across the axes."""
|
|
145
141
|
return ax.axhline(
|
|
146
|
-
y=y,
|
|
142
|
+
y=y,
|
|
143
|
+
color=color,
|
|
144
|
+
linestyle=linestyle,
|
|
145
|
+
linewidth=linewidth,
|
|
146
|
+
alpha=alpha,
|
|
147
|
+
zorder=zorder,
|
|
147
148
|
)
|
|
148
149
|
|
|
149
150
|
def add_text(
|
|
@@ -187,6 +188,27 @@ class MatplotlibBackend:
|
|
|
187
188
|
ax.add_patch(rect)
|
|
188
189
|
return rect
|
|
189
190
|
|
|
191
|
+
def add_polygon(
|
|
192
|
+
self,
|
|
193
|
+
ax: Axes,
|
|
194
|
+
points: List[List[float]],
|
|
195
|
+
facecolor: str = "blue",
|
|
196
|
+
edgecolor: str = "black",
|
|
197
|
+
linewidth: float = 0.5,
|
|
198
|
+
zorder: int = 2,
|
|
199
|
+
) -> Any:
|
|
200
|
+
"""Add a polygon patch to axes."""
|
|
201
|
+
polygon = Polygon(
|
|
202
|
+
points,
|
|
203
|
+
closed=True,
|
|
204
|
+
facecolor=facecolor,
|
|
205
|
+
edgecolor=edgecolor,
|
|
206
|
+
linewidth=linewidth,
|
|
207
|
+
zorder=zorder,
|
|
208
|
+
)
|
|
209
|
+
ax.add_patch(polygon)
|
|
210
|
+
return polygon
|
|
211
|
+
|
|
190
212
|
def set_xlim(self, ax: Axes, left: float, right: float) -> None:
|
|
191
213
|
"""Set x-axis limits."""
|
|
192
214
|
ax.set_xlim(left, right)
|
|
@@ -268,6 +290,110 @@ class MatplotlibBackend:
|
|
|
268
290
|
"""Close the figure and free resources."""
|
|
269
291
|
plt.close(fig)
|
|
270
292
|
|
|
293
|
+
def add_eqtl_legend(
|
|
294
|
+
self,
|
|
295
|
+
ax: Axes,
|
|
296
|
+
eqtl_positive_bins: List[Tuple[float, float, str, str]],
|
|
297
|
+
eqtl_negative_bins: List[Tuple[float, float, str, str]],
|
|
298
|
+
) -> None:
|
|
299
|
+
"""Add eQTL effect size legend using matplotlib Line2D markers."""
|
|
300
|
+
from matplotlib.lines import Line2D
|
|
301
|
+
|
|
302
|
+
legend_elements = []
|
|
303
|
+
|
|
304
|
+
# Positive effects (upward triangles)
|
|
305
|
+
for _, _, label, color in eqtl_positive_bins:
|
|
306
|
+
legend_elements.append(
|
|
307
|
+
Line2D(
|
|
308
|
+
[0],
|
|
309
|
+
[0],
|
|
310
|
+
marker="^",
|
|
311
|
+
color="w",
|
|
312
|
+
markerfacecolor=color,
|
|
313
|
+
markeredgecolor="black",
|
|
314
|
+
markersize=7,
|
|
315
|
+
label=label,
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
# Negative effects (downward triangles)
|
|
320
|
+
for _, _, label, color in eqtl_negative_bins:
|
|
321
|
+
legend_elements.append(
|
|
322
|
+
Line2D(
|
|
323
|
+
[0],
|
|
324
|
+
[0],
|
|
325
|
+
marker="v",
|
|
326
|
+
color="w",
|
|
327
|
+
markerfacecolor=color,
|
|
328
|
+
markeredgecolor="black",
|
|
329
|
+
markersize=7,
|
|
330
|
+
label=label,
|
|
331
|
+
)
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
ax.legend(
|
|
335
|
+
handles=legend_elements,
|
|
336
|
+
loc="upper right",
|
|
337
|
+
fontsize=8,
|
|
338
|
+
frameon=True,
|
|
339
|
+
framealpha=0.9,
|
|
340
|
+
title="eQTL effect",
|
|
341
|
+
title_fontsize=9,
|
|
342
|
+
handlelength=1.2,
|
|
343
|
+
handleheight=1.0,
|
|
344
|
+
labelspacing=0.3,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
def add_finemapping_legend(
|
|
348
|
+
self,
|
|
349
|
+
ax: Axes,
|
|
350
|
+
credible_sets: List[int],
|
|
351
|
+
get_color_func: Any,
|
|
352
|
+
) -> None:
|
|
353
|
+
"""Add fine-mapping credible set legend using matplotlib Line2D markers."""
|
|
354
|
+
from matplotlib.lines import Line2D
|
|
355
|
+
|
|
356
|
+
if not credible_sets:
|
|
357
|
+
return
|
|
358
|
+
|
|
359
|
+
legend_elements = []
|
|
360
|
+
for cs_id in credible_sets:
|
|
361
|
+
color = get_color_func(cs_id)
|
|
362
|
+
legend_elements.append(
|
|
363
|
+
Line2D(
|
|
364
|
+
[0],
|
|
365
|
+
[0],
|
|
366
|
+
marker="o",
|
|
367
|
+
color="w",
|
|
368
|
+
markerfacecolor=color,
|
|
369
|
+
markeredgecolor="black",
|
|
370
|
+
markersize=7,
|
|
371
|
+
label=f"CS{cs_id}",
|
|
372
|
+
)
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
ax.legend(
|
|
376
|
+
handles=legend_elements,
|
|
377
|
+
loc="upper right",
|
|
378
|
+
fontsize=8,
|
|
379
|
+
frameon=True,
|
|
380
|
+
framealpha=0.9,
|
|
381
|
+
title="Credible sets",
|
|
382
|
+
title_fontsize=9,
|
|
383
|
+
handlelength=1.2,
|
|
384
|
+
handleheight=1.0,
|
|
385
|
+
labelspacing=0.3,
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
def add_simple_legend(
|
|
389
|
+
self,
|
|
390
|
+
ax: Axes,
|
|
391
|
+
label: str,
|
|
392
|
+
loc: str = "upper right",
|
|
393
|
+
) -> None:
|
|
394
|
+
"""Add simple legend for labeled scatter data."""
|
|
395
|
+
ax.legend(loc=loc, fontsize=9)
|
|
396
|
+
|
|
271
397
|
def finalize_layout(
|
|
272
398
|
self,
|
|
273
399
|
fig: Figure,
|