Skip to content

Commit 3c84789

Browse files
authored
Merge pull request #72 from moshi4/develop
Bump to v1.6.0
2 parents bf74abb + 02cbebd commit 3c84789

File tree

12 files changed

+118
-39
lines changed

12 files changed

+118
-39
lines changed

docs/plot_tips.ipynb

+19-4
Large diffs are not rendered by default.

pyproject.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pyCirclize"
3-
version = "1.5.0"
3+
version = "1.6.0"
44
description = "Circular visualization in Python"
55
authors = ["moshi4"]
66
license = "MIT"
@@ -19,7 +19,6 @@ classifiers = [
1919
"Topic :: Scientific/Engineering :: Bio-Informatics",
2020
"Framework :: Matplotlib",
2121
]
22-
include = ["tests"]
2322

2423
[tool.pytest.ini_options]
2524
minversion = "6.0"

src/pycirclize/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from pycirclize.circos import Circos
22

3-
__version__ = "1.5.0"
3+
__version__ = "1.6.0"
44

55
__all__ = [
66
"Circos",

src/pycirclize/circos.py

+34-11
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@
3838
class Circos:
3939
"""Circos Visualization Class"""
4040

41+
# By default, after saving a figure using the `savefig()` method, figure object is
42+
# automatically deleted to avoid memory leaks (no display on jupyter notebook)
43+
# If you want to display the figure on jupyter notebook using `savefig()` method,
44+
# set clear_savefig=False.
45+
clear_savefig: bool = True
46+
4147
def __init__(
4248
self,
4349
sectors: Mapping[str, int | float | tuple[float, float]],
@@ -522,8 +528,10 @@ def initialize_from_tree(
522528
523529
Returns
524530
-------
525-
circos, tv : tuple[Circos, TreeViz]
526-
Circos & TreeViz instances initialized from tree
531+
circos : Circos
532+
Circos instance
533+
tv : TreeViz
534+
TreeViz instance
527535
"""
528536
# Initialize circos sector with tree size
529537
tree = TreeViz.load_tree(tree_data, format=format)
@@ -946,7 +954,9 @@ def colorbar(
946954
vmax: float = 1,
947955
cmap: str | Colormap = "bwr",
948956
orientation: str = "vertical",
957+
label: str | None = None,
949958
colorbar_kws: dict[str, Any] | None = None,
959+
label_kws: dict[str, Any] | None = None,
950960
tick_kws: dict[str, Any] | None = None,
951961
) -> None:
952962
"""Plot colorbar
@@ -964,27 +974,35 @@ def colorbar(
964974
<https://matplotlib.org/stable/tutorials/colors/colormaps.html>
965975
orientation : str, optional
966976
Colorbar orientation (`vertical`|`horizontal`)
977+
label : str | None, optional
978+
Colorbar label. If None, no label shown.
967979
colorbar_kws : dict[str, Any] | None, optional
968-
Colorbar properties (e.g. `dict(label="name", format="%.1f", ...)`)
980+
Colorbar properties (e.g. `dict(format="%.1f", ...)`)
969981
<https://matplotlib.org/stable/api/colorbar_api.html>
982+
label_kws : dict[str, Any] | None, optional
983+
Text properties (e.g. `dict(size=15, color="red", ...)`)
984+
<https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.text.html>
970985
tick_kws : dict[str, Any] | None, optional
971986
Axes.tick_params properties (e.g. `dict(labelsize=12, colors="red", ...)`)
972987
<https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.tick_params.html>
973988
"""
974989
colorbar_kws = {} if colorbar_kws is None else deepcopy(colorbar_kws)
990+
label_kws = {} if label_kws is None else deepcopy(label_kws)
975991
tick_kws = {} if tick_kws is None else deepcopy(tick_kws)
976992

977993
def plot_colorbar(ax: PolarAxes) -> None:
978994
axin: Axes = ax.inset_axes(bounds)
979995
norm = Normalize(vmin=vmin, vmax=vmax)
980-
Colorbar(
996+
cb = Colorbar(
981997
axin,
982998
cmap=cmap, # type: ignore
983999
norm=norm,
9841000
orientation=orientation, # type: ignore
9851001
**colorbar_kws,
9861002
)
9871003
axin.tick_params(**tick_kws)
1004+
if label:
1005+
cb.set_label(label, **label_kws)
9881006

9891007
self._plot_funcs.append(plot_colorbar)
9901008

@@ -1055,9 +1073,6 @@ def savefig(
10551073
) -> None:
10561074
"""Save figure to file
10571075
1058-
`circos.savefig("result.png")` is alias for
1059-
`circos.plotfig().savefig("result.png")`
1060-
10611076
Parameters
10621077
----------
10631078
savefile : str | Path
@@ -1068,6 +1083,11 @@ def savefig(
10681083
Figure size
10691084
pad_inches : float, optional
10701085
Padding inches
1086+
1087+
Warnings
1088+
--------
1089+
To plot a figure that settings a user-defined legend, subtracks, or annotations,
1090+
call `fig.savefig()` instead of `gv.savefig()`.
10711091
"""
10721092
fig = self.plotfig(dpi=dpi, figsize=figsize)
10731093
fig.savefig(
@@ -1077,8 +1097,9 @@ def savefig(
10771097
bbox_inches="tight",
10781098
)
10791099
# Clear & close figure to suppress memory leak
1080-
fig.clear()
1081-
plt.close(fig)
1100+
if self.clear_savefig:
1101+
fig.clear()
1102+
plt.close(fig)
10821103

10831104
############################################################
10841105
# Private Method
@@ -1136,8 +1157,10 @@ def _initialize_figure(
11361157
11371158
Returns
11381159
-------
1139-
fig, ax : tuple[Figure, PolarAxes]
1140-
Figure, PolarAxes
1160+
fig : Figure
1161+
Figure
1162+
ax : PolarAxes
1163+
PolarAxes
11411164
"""
11421165
fig = plt.figure(figsize=figsize, dpi=dpi, tight_layout=True)
11431166
ax = fig.add_subplot(projection="polar")

src/pycirclize/parser/genbank.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,10 @@ def calc_gc_skew(
148148
149149
Returns
150150
-------
151-
gc_skew_result_tuple : tuple[NDArray[np.int64], NDArray[np.float64]]
152-
Position list & GC skew list
151+
pos_list : NDArray[np.int64]
152+
Position list
153+
gc_skew_list : NDArray[np.float64]
154+
GC skew list
153155
"""
154156
pos_list, gc_skew_list = [], []
155157
seq = self.genome_seq if seq is None else seq
@@ -200,8 +202,10 @@ def calc_gc_content(
200202
201203
Returns
202204
-------
203-
gc_content_result_tuple : tuple[NDArray[np.int64], NDArray[np.float64]]
204-
Position list & GC content list
205+
pos_list : NDArray[np.int64]
206+
Position list
207+
gc_content_list : NDArray[np.float64]
208+
GC content list
205209
"""
206210
pos_list, gc_content_list = [], []
207211
seq = self.genome_seq if seq is None else seq

src/pycirclize/parser/gff.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,12 @@ def _parse_gff(
271271
272272
Returns
273273
-------
274-
gff_records, start, end : tuple[list[GffRecord], int, int]
275-
GFF record list, start, end
274+
gff_records : list[GffRecord]
275+
GFF record list
276+
start : int
277+
Start position of target_seqid record
278+
end : int
279+
End position of target_seqid record
276280
"""
277281
gff_file = Path(gff_file)
278282
if gff_file.suffix == ".gz":
@@ -308,8 +312,12 @@ def _parse_gff_textio(
308312
309313
Returns
310314
-------
311-
gff_records, start, end : tuple[list[GffRecord], int, int]
312-
GFF record list, start, end
315+
gff_records : list[GffRecord]
316+
GFF record list
317+
start : int
318+
Start position of target_seqid record
319+
end : int
320+
End position of target_seqid record
313321
"""
314322
# Parse GFF lines
315323
gff_all_lines = handle.read().splitlines()

src/pycirclize/parser/matrix.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -202,16 +202,19 @@ def to_links(
202202
) -> list[tuple[tuple[str, float, float], tuple[str, float, float]]]:
203203
"""Convert matrix to links data for `circos.link()` method
204204
205-
>>> # Example usage
205+
Returns
206+
-------
207+
link_target1 : tuple[str, float, float]
208+
name1, start1, end1
209+
link_target2 : tuple[str, float, float]
210+
name2, start2, end2
211+
212+
Examples
213+
--------
206214
>>> matrix = Matrix(matrix_file)
207215
>>> circos = Circos(matrix.to_sectors())
208216
>>> for link in matrix.to_links():
209217
>>> circos.link(*link)
210-
211-
Returns
212-
-------
213-
links : list[tuple[tuple[str, float, float], tuple[str, float, float]]]
214-
List of link `((name1, start1, end1), (name2, end2, start2))`
215218
"""
216219
return self._links
217220

src/pycirclize/track.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1318,8 +1318,10 @@ def _to_arc_radr(
13181318
13191319
Returns
13201320
-------
1321-
arc_rad, arc_r : tuple[list[float], list[float]]
1322-
Arc radian list, Ard radius list
1321+
arc_rad : list[float]
1322+
Arc radian list
1323+
arc_r : list[float]
1324+
Arc radius list
13231325
"""
13241326
all_arc_rad, all_arc_r = [], []
13251327
for i in range(len(rad) - 1):

src/pycirclize/tree.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,10 @@ def _set_uniq_innode_name(self, tree: Tree) -> tuple[Tree, list[str]]:
442442
443443
Returns
444444
-------
445-
tree, uniq_node_names: tuple[Tree, list[str]]
446-
Unique node name set tree object & set unique node names
445+
tree : Tree
446+
Tree (set unique node names)
447+
uniq_node_names : list[str]
448+
Unique node names
447449
"""
448450
tree = deepcopy(tree)
449451
uniq_innode_names: list[str] = []

src/pycirclize/utils/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
load_example_tree_file,
77
load_prokaryote_example_file,
88
)
9-
from pycirclize.utils.helper import ColorCycler, calc_group_spaces
9+
from pycirclize.utils.helper import ColorCycler, calc_group_spaces, is_pseudo_feature
1010

1111
__all__ = [
1212
"plot",
@@ -17,4 +17,5 @@
1717
"load_example_tree_file",
1818
"ColorCycler",
1919
"calc_group_spaces",
20+
"is_pseudo_feature",
2021
]

src/pycirclize/utils/dataset.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,12 @@ def load_eukaryote_example_dataset(
9696
9797
Returns
9898
-------
99-
chr_bed_file, cytoband_file, chr_links : tuple[Path, Path, list[ChrLink]]
100-
BED file, Cytoband file, Chromosome links
99+
chr_bed_file : Path
100+
BED file
101+
cytoband_file : Path
102+
Cytoband file
103+
chr_links : list[ChrLink]
104+
Chromosome links
101105
"""
102106
# Check specified name dataset exists or not
103107
if name not in config.EUKARYOTE_DATASET:

src/pycirclize/utils/helper.py

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import matplotlib as mpl
44
import numpy as np
5+
from Bio.SeqFeature import SeqFeature
56
from matplotlib.colors import Colormap, to_hex
67

78

@@ -129,3 +130,20 @@ def calc_group_spaces(
129130
return spaces
130131
else:
131132
return spaces[:-1]
133+
134+
135+
def is_pseudo_feature(feature: SeqFeature) -> bool:
136+
"""Check target feature is pseudo or not from qualifiers tag
137+
138+
Parameters
139+
----------
140+
feature : SeqFeature
141+
Target feature
142+
143+
Returns
144+
-------
145+
check_result : bool
146+
pseudo check result
147+
"""
148+
quals = feature.qualifiers
149+
return True if "pseudo" in quals or "pseudogene" in quals else False

0 commit comments

Comments
 (0)