-
Notifications
You must be signed in to change notification settings - Fork 90
/
MultilinePlottableMixin.py
153 lines (128 loc) · 5.17 KB
/
MultilinePlottableMixin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
import numpy
class MultilinePlottableMixin:
def plot_on_multiple_lines(
self,
n_lines=None,
nucl_per_line=None,
plot_sequence=False,
figure_width="auto",
**plot_params
):
"""Plot the features on different lines (one Matplotlib ax per line).
Parameters
----------
n_lines
Number of lines on which the record will be plotted. A number of
nucleotides per line can be provided instead (see below).
nucl_per_line
Number of nucleotides to be represented on every line (determines
the number of lines ``n_lines``).
plot_sequence
Whether to plot the nucleotide sequence on each line.
figure_width
Width of the figure in inches. Leave to auto for a width of either 10
(if not sequence is plotted) or 0.15*nucl_per_line inches
(if a sequence is plotted).
**plot_params
Parameters from ``graphic_record.plot()`` to be used in the plotting
of the individual lines. This includes ``draw_line``, ``with_ruler``,
``annotate_inline``, ``plot_sequence``,
``evelate_outline_annotations``, ``strand_in_label_pixel_threshold``.
Returns
-------
figure, axes
The matplotlib figure and axes generated.
"""
if n_lines is None:
n_lines = int(numpy.ceil(self.sequence_length / nucl_per_line))
else:
nucl_per_line = self.sequence_length // n_lines + 1
if figure_width == "auto":
if plot_sequence:
figure_width = 0.15 * nucl_per_line
else:
figure_width = 10
figures_heights = []
def plot_line(line_index, ax=None):
first, last = self.first_index, self.last_index
line_start = first + line_index * nucl_per_line
line_virtual_end = first + (line_index + 1) * nucl_per_line
line_end = min(last, line_virtual_end)
line_record = self.crop((line_start, line_end))
line_ax, _ = line_record.plot(
figure_width=figure_width,
x_lim=(line_start, line_virtual_end),
ax=ax,
plot_sequence=plot_sequence,
**plot_params
)
return line_ax
for line_index in range(n_lines):
line_ax = plot_line(line_index)
figures_heights.append(line_ax.figure.get_figheight())
plt.close(line_ax.figure)
fig, axes = plt.subplots(
n_lines,
1,
gridspec_kw={"height_ratios": figures_heights},
figsize=(figure_width, 0.9 * sum(figures_heights)),
)
if n_lines == 1:
axes = [axes]
for line_index, ax in enumerate(axes):
plot_line(line_index, ax=ax)
fig.tight_layout()
return fig, axes
def plot_on_multiple_pages(
self,
pdf_target,
n_lines=None,
nucl_per_line=None,
lines_per_page=5,
figure_width="auto",
**plot_params
):
"""Plot the features on different lines on different pages of a PDF.
This function returns None
Parameters
----------
pdf_target
Either a path to a PDF, or a file(-like) handle.
n_lines
Number of lines on which the record will be plotted. A number of
nucleotides per line can be provided instead (see below).
nucl_per_line
Number of nucleotides to be represented on every line (determines
the number of lines ``n_lines``).
lines_per_page
Number of lines on each page.
plot_sequence
Whether to plot the nucleotide sequence on each line.
figure_width
Width of the figure in inches. Leave to auto for a width of either 10
(if not sequence is plotted) or 0.15*nucl_per_line inches
(if a sequence is plotted).
**plot_params
Parameters from ``graphic_record.plot()`` to be used in the plotting
of the individual lines. This includes ``draw_line``, ``with_ruler``,
``annotate_inline``, ``plot_sequence``,
``evelate_outline_annotations``, ``strand_in_label_pixel_threshold``.
"""
nucl_per_page = nucl_per_line * lines_per_page
number_of_pages = int(numpy.ceil(self.sequence_length / nucl_per_page))
with PdfPages(pdf_target) as pdf:
for page_index in range(number_of_pages):
first, last = self.first_index, self.last_index
page_start = first + page_index * nucl_per_page
page_end = first + (page_index + 1) * nucl_per_page
page_end = min(last, page_end)
page_record = self.crop((page_start, page_end))
fig, axes = page_record.plot_on_multiple_lines(
nucl_per_line=nucl_per_line,
figure_width=figure_width,
**plot_params
)
pdf.savefig(fig)
plt.close(fig)