trackplot 0.5.9__tar.gz → 0.6.0__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 (66) hide show
  1. {trackplot-0.5.9/trackplot.egg-info → trackplot-0.6.0}/PKG-INFO +1 -1
  2. {trackplot-0.5.9 → trackplot-0.6.0}/pyproject.toml +1 -1
  3. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/cli.py +3 -9
  4. trackplot-0.6.0/trackplot/plot/__init__.py +57 -0
  5. trackplot-0.6.0/trackplot/plot/coord.py +306 -0
  6. trackplot-0.6.0/trackplot/plot/core.py +1252 -0
  7. trackplot-0.6.0/trackplot/plot/info.py +163 -0
  8. trackplot-0.6.0/trackplot/plot/limits.py +193 -0
  9. trackplot-0.6.0/trackplot/plot/render.py +1263 -0
  10. trackplot-0.6.0/trackplot/plot/utils.py +129 -0
  11. trackplot-0.6.0/trackplot/plot_func.py +10 -0
  12. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/server.py +5 -1
  13. {trackplot-0.5.9 → trackplot-0.6.0/trackplot.egg-info}/PKG-INFO +1 -1
  14. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot.egg-info/SOURCES.txt +20 -2
  15. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot.egg-info/top_level.txt +1 -0
  16. trackplot-0.6.0/ui/assets/Home-B1EPE6Lq.js +1 -0
  17. trackplot-0.6.0/ui/assets/Home-DuHqFHEh.css +1 -0
  18. trackplot-0.6.0/ui/assets/Plot-CkylK0fA.css +1 -0
  19. trackplot-0.6.0/ui/assets/Plot-jZAsK7Tq.js +24 -0
  20. trackplot-0.6.0/ui/assets/_plugin-vue_export-helper-DLf8tVwz.css +1 -0
  21. trackplot-0.6.0/ui/assets/_plugin-vue_export-helper-IgiCOkTJ.js +1 -0
  22. trackplot-0.6.0/ui/assets/css-BDwM7dEv.css +1 -0
  23. trackplot-0.6.0/ui/assets/css-CKLNJEB6.js +4 -0
  24. trackplot-0.6.0/ui/assets/index-De-rfTdP.js +2 -0
  25. trackplot-0.6.0/ui/assets/index-Dlq_kUQH.css +1 -0
  26. trackplot-0.6.0/ui/index.html +16 -0
  27. trackplot-0.6.0/ui/vite.svg +1 -0
  28. trackplot-0.5.9/trackplot/plot.py +0 -1618
  29. trackplot-0.5.9/trackplot/plot_func.py +0 -1941
  30. {trackplot-0.5.9 → trackplot-0.6.0}/LICENSE +0 -0
  31. {trackplot-0.5.9 → trackplot-0.6.0}/README.md +0 -0
  32. {trackplot-0.5.9 → trackplot-0.6.0}/setup.cfg +0 -0
  33. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/__init__.py +0 -0
  34. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/anno/AxLabel.py +0 -0
  35. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/anno/__init__.py +0 -0
  36. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/anno/theme.py +0 -0
  37. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/CoordinateMap.py +0 -0
  38. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/GenomicLoci.py +0 -0
  39. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/Junction.py +0 -0
  40. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/Protein.py +0 -0
  41. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/ReadDepth.py +0 -0
  42. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/Readder.py +0 -0
  43. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/Stroke.py +0 -0
  44. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/Transcript.py +0 -0
  45. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/__init__.py +0 -0
  46. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/base/pyUniprot.py +0 -0
  47. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/conf/DomainSetting.py +0 -0
  48. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/conf/__init__.py +0 -0
  49. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/conf/config.py +0 -0
  50. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/conf/drawing.py +0 -0
  51. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/conf/ui.py +0 -0
  52. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/ATAC.py +0 -0
  53. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/Annotation.py +0 -0
  54. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/Bam.py +0 -0
  55. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/BedGraph.py +0 -0
  56. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/Bigwig.py +0 -0
  57. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/Depth.py +0 -0
  58. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/Fasta.py +0 -0
  59. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/File.py +0 -0
  60. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/HiCMatrixTrack.py +0 -0
  61. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/Junction.py +0 -0
  62. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/Motif.py +0 -0
  63. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/ReadSegments.py +0 -0
  64. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot/file/__init__.py +0 -0
  65. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot.egg-info/dependency_links.txt +0 -0
  66. {trackplot-0.5.9 → trackplot-0.6.0}/trackplot.egg-info/requires.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trackplot
3
- Version: 0.5.9
3
+ Version: 0.6.0
4
4
  Summary: The trackplot is a tool for visualizing various next-generation sequencing (NGS) data, including DNA-seq, RNA-seq, single-cell RNA-seq and full-length sequencing datasets. https://sashimi.readthedocs.io/
5
5
  Author-email: ygidtu <ygidtu@gmail.com>
6
6
  License-Expression: BSD-3-Clause
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "trackplot"
3
- version = "0.5.9"
3
+ version = "0.6.0"
4
4
  description = "The trackplot is a tool for visualizing various next-generation sequencing (NGS) data, including DNA-seq, RNA-seq, single-cell RNA-seq and full-length sequencing datasets. https://sashimi.readthedocs.io/"
5
5
  authors = [
6
6
  { name = "ygidtu", email = "ygidtu@gmail.com" }
@@ -16,17 +16,11 @@ from click_option_group import optgroup
16
16
  from loguru import logger
17
17
 
18
18
  from trackplot.base.GenomicLoci import GenomicLoci
19
- from trackplot.conf.config import (
20
- CLUSTERING_METHOD,
21
- COLORMAP,
22
- COLORS,
23
- DISTANCE_METRIC,
24
- IMAGE_TYPE,
25
- NORMALIZATION,
26
- )
19
+ from trackplot.conf.config import (CLUSTERING_METHOD, COLORMAP, COLORS,
20
+ DISTANCE_METRIC, IMAGE_TYPE, NORMALIZATION)
27
21
  from trackplot.plot import Plot, __version__
28
22
  from trackplot.plot_func import load_barcodes
29
- from trackplot.server import __PLOT__, run
23
+ from trackplot.server import __PLOT__
30
24
 
31
25
 
32
26
  def decode_region(region: str):
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ """
4
+ trackplot.plot — plot orchestration and rendering package.
5
+
6
+ Re-exports all public symbols for backward compatibility.
7
+ Use ``from trackplot.plot.core import Plot`` or ``from trackplot.plot.render import plot_density`` for direct access.
8
+ """
9
+
10
+ from trackplot.plot.coord import (init_graph_coords, set_focus,
11
+ set_indicator_lines, set_x_ticks,
12
+ set_y_ticks)
13
+ from trackplot.plot.core import (Plot, __author__, __email__, __version__,
14
+ add_object_error)
15
+ from trackplot.plot.info import PlotInfo
16
+ from trackplot.plot.limits import precompute_y_limits
17
+ from trackplot.plot.render import (plot_annotation, plot_density, plot_heatmap,
18
+ plot_hic, plot_igv_like, plot_line,
19
+ plot_links, plot_motif, plot_site_plot,
20
+ plot_stroke)
21
+ from trackplot.plot.utils import (__merge_exons__, cubic_bezier,
22
+ get_limited_index, load_barcodes,
23
+ make_text_elements)
24
+
25
+ __all__ = [
26
+ "Plot",
27
+ "PlotInfo",
28
+ "add_object_error",
29
+ "__version__",
30
+ "__author__",
31
+ "__email__",
32
+ # utils
33
+ "load_barcodes",
34
+ "get_limited_index",
35
+ "cubic_bezier",
36
+ "__merge_exons__",
37
+ "make_text_elements",
38
+ # coord
39
+ "init_graph_coords",
40
+ "set_x_ticks",
41
+ "set_y_ticks",
42
+ "set_focus",
43
+ "set_indicator_lines",
44
+ # limits
45
+ "precompute_y_limits",
46
+ # render
47
+ "plot_stroke",
48
+ "plot_annotation",
49
+ "plot_density",
50
+ "plot_site_plot",
51
+ "plot_heatmap",
52
+ "plot_hic",
53
+ "plot_line",
54
+ "plot_igv_like",
55
+ "plot_links",
56
+ "plot_motif",
57
+ ]
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ """
4
+ Coordinate system transformation, axis helpers, and overlay drawing.
5
+
6
+ Dependencies: GenomicLoci, Theme, utils
7
+ """
8
+
9
+ import itertools
10
+ import math
11
+ from typing import Dict, List, Optional, Union
12
+
13
+ import numpy as np
14
+ from loguru import logger
15
+ from matplotlib import pylab
16
+
17
+ from trackplot.anno.theme import Theme
18
+ from trackplot.base.GenomicLoci import GenomicLoci
19
+ from trackplot.plot.utils import __merge_exons__
20
+
21
+ # ============================================================================
22
+ # Coordinate system
23
+ # ============================================================================
24
+
25
+
26
+ def init_graph_coords(
27
+ region: GenomicLoci,
28
+ exons: Optional[List[List[int]]] = None,
29
+ exon_scale=1,
30
+ intron_scale=0.5,
31
+ ) -> np.ndarray:
32
+ """
33
+ init the default
34
+ :param region: the plot region
35
+ :param exons: list of start and end sites of exons [[start, end], [start, end]]
36
+ :param exon_scale: the scale of exon, default set to 1
37
+ :param intron_scale: the scale of intron, default set to 0.5 -> the intron showed in final will be half size of real
38
+ """
39
+ graph_coords = np.zeros(len(region), dtype=int)
40
+
41
+ if exons:
42
+ if intron_scale <= 1:
43
+ for i in range(0, exons[0][0] - region.start):
44
+ graph_coords[i] = (i - 0) * intron_scale
45
+ exons = __merge_exons__(exons)
46
+ for i in range(0, len(exons)):
47
+ exon = exons[i]
48
+ if i > 0:
49
+ intron = [exons[i - 1][1], exons[i][0]]
50
+ for j in range(intron[0], intron[1]):
51
+ if j >= region.start:
52
+ graph_coords[j - region.start] = (
53
+ graph_coords[intron[0] - region.start - 1]
54
+ + (j - intron[0] + 1) * intron_scale
55
+ )
56
+ for j in range(exon[0], exon[1] + 1):
57
+ if j >= region.start:
58
+ graph_coords[j - region.start] = (
59
+ graph_coords[exon[0] - region.start - 1]
60
+ + (j - exon[0] + 1) * exon_scale
61
+ )
62
+ intron = [exons[-1][-1], region.end]
63
+ for i in range(intron[0], intron[1]):
64
+ if i >= region.start:
65
+ graph_coords[i - region.start] = (
66
+ graph_coords[intron[0] - region.start - 1]
67
+ + (i - intron[0] + 1) * intron_scale
68
+ )
69
+ else:
70
+ exons = __merge_exons__(exons)
71
+ while exons[0][1] < region.start:
72
+ exons = exons[1:]
73
+ while exons[-1][0] > region.end:
74
+ exons = exons[:-1]
75
+ exons[0][0] = max(exons[0][0], region.start)
76
+ exons[-1][1] = min(exons[-1][1], region.end)
77
+
78
+ for i, e in enumerate(exons):
79
+ exons[i][0] -= region.start
80
+ exons[i][1] -= region.start
81
+
82
+ steps = [float(exon_scale)] * len(region)
83
+ if exons[0][0] > 0:
84
+ step = intron_scale / exons[0][0]
85
+ for i in range(exons[0][0]):
86
+ steps[i] = step
87
+ for e in range(1, len(exons)):
88
+ interval = exons[e][0] - exons[e - 1][1] - 2
89
+ step = intron_scale / interval
90
+ for i in range(exons[e - 1][1], exons[e][0]):
91
+ steps[i] = step
92
+
93
+ if last_interval := len(region) - exons[-1][1] - 1:
94
+ step = intron_scale / last_interval
95
+ for i in range(exons[1][1] + 1, len(region)):
96
+ steps[i] = step
97
+ graph_coords = list(map(int, itertools.accumulate(steps)))
98
+ else:
99
+ for i, j in enumerate(range(region.start, region.end + 1)):
100
+ graph_coords[j - region.start] = i
101
+
102
+ if graph_coords[-1] == 0:
103
+ current_max = max(np.where(graph_coords == np.max(graph_coords))[-1])
104
+ for i in np.where(graph_coords == 0)[0]:
105
+ if i > current_max:
106
+ graph_coords[i] = max(graph_coords) + 1
107
+ return graph_coords
108
+
109
+
110
+ # ============================================================================
111
+ # Axis helpers
112
+ # ============================================================================
113
+
114
+
115
+ def set_x_ticks(
116
+ ax,
117
+ region: GenomicLoci,
118
+ graph_coords: Optional[Union[Dict, np.ndarray]] = None,
119
+ sequence: Optional[Dict[int, str]] = None,
120
+ log_trans: Optional[str] = None,
121
+ nx_ticks: int = 4,
122
+ font_size: int = 6,
123
+ **kwargs,
124
+ ):
125
+ Theme.set_theme(ax, "blank")
126
+ if graph_coords is None:
127
+ graph_coords = init_graph_coords(region)
128
+
129
+ x_label = str(region)
130
+
131
+ if log_trans:
132
+ if log_trans in ["2", "10"]:
133
+ log_trans = f"log{log_trans}"
134
+ x_label = f"{x_label}, y axis is {log_trans} transformed"
135
+
136
+ ax.hlines(y=0, xmin=0, xmax=max(graph_coords), color="black", lw=1)
137
+ ax.text(
138
+ x=graph_coords[len(graph_coords) // 2],
139
+ y=-2.8,
140
+ s=x_label,
141
+ fontsize=font_size,
142
+ ha="center",
143
+ va="top",
144
+ )
145
+
146
+ bk = 1
147
+ if not sequence and nx_ticks > 1:
148
+ bk = max(graph_coords) // (nx_ticks - 1)
149
+
150
+ reverse_graph_coords = {}
151
+ for i in range(1, len(graph_coords)):
152
+ for x, y in zip(
153
+ range(graph_coords[i - 1], graph_coords[i]),
154
+ np.linspace(i - 1, i, num=graph_coords[i] - graph_coords[i - 1]),
155
+ ):
156
+ reverse_graph_coords[x] = int(y)
157
+
158
+ for i in range(graph_coords[0]):
159
+ reverse_graph_coords[i] = graph_coords[0]
160
+
161
+ line_space = {}
162
+ for i in range(nx_ticks - 1):
163
+ i = bk * i
164
+ line_space[i] = reverse_graph_coords[i] + region.start
165
+ line_space[max(graph_coords)] = region.end
166
+
167
+ if sequence:
168
+ for i, seq in sequence.items():
169
+ relative_i = graph_coords[i - region.start]
170
+ if relative_i in line_space.keys():
171
+ temp_txs = "{}\\n{}".format(sequence.get(i, ""), line_space[relative_i])
172
+ else:
173
+ temp_txs = "\\n{}".format(sequence.get(i, ""))
174
+ line_space[relative_i] = temp_txs
175
+
176
+ for x, s in line_space.items():
177
+ ax.vlines(x=x, ymin=-0.5, ymax=0, color="black", lw=1)
178
+ ax.text(x=x, y=-1, s=s, fontsize=font_size, ha="center", va="top")
179
+
180
+ ax.set_ylim(-3.5, 1)
181
+ ax.set_xlim(min(graph_coords), max(graph_coords))
182
+
183
+
184
+ def set_y_ticks(
185
+ ax,
186
+ label: str,
187
+ graph_coords: Union[Dict, np.array],
188
+ max_used_y_val: Union[int, float],
189
+ min_used_y_val: Optional[Union[int, float]] = None,
190
+ distance_between_label_axis: float = 0,
191
+ n_y_ticks: int = 4,
192
+ theme: str = "ticks",
193
+ font_size: int = 5,
194
+ show_y_label: bool = True,
195
+ set_label_only: bool = False,
196
+ **kwargs,
197
+ ):
198
+ """
199
+ The y ticks are formatted here
200
+ @2019.03.31 add little check here to make sure the y-axis shows the real value
201
+ """
202
+ Theme.set_theme(ax, theme)
203
+ ax.set_xlim(min(graph_coords), max(graph_coords))
204
+ if min_used_y_val is None:
205
+ min_used_y_val, _ = ax.get_ylim()
206
+
207
+ curr_y_tick_labels = []
208
+ if not set_label_only:
209
+ max_ = max_used_y_val
210
+ plus = 0.2
211
+ while max_ > 10:
212
+ max_ /= 10
213
+ plus /= 10
214
+
215
+ plus = (max_used_y_val - min_used_y_val) * plus
216
+ ax.set_ylim(min_used_y_val - plus, plus + max_used_y_val)
217
+ ax.spines["left"].set_bounds(min_used_y_val, max_used_y_val)
218
+
219
+ assign_ticks_y = [
220
+ int(x / (abs(min_used_y_val) + max_used_y_val) * n_y_ticks)
221
+ for x in [abs(min_used_y_val), abs(max_used_y_val)]
222
+ ]
223
+ universal_y_ticks = pylab.linspace(min_used_y_val, 0, assign_ticks_y[0] + 1)
224
+ for i in pylab.linspace(0, max_used_y_val, assign_ticks_y[1] + 1):
225
+ universal_y_ticks = np.append(universal_y_ticks, i)
226
+
227
+ universal_y_ticks = np.unique(np.append(universal_y_ticks, 0))
228
+ universal_y_ticks = sorted(universal_y_ticks)
229
+
230
+ for lab in universal_y_ticks:
231
+ curr_y_tick_labels.append(f"{int(lab)}")
232
+
233
+ ax.set_yticks(universal_y_ticks)
234
+ ax.set_yticklabels(curr_y_tick_labels, fontsize=font_size)
235
+ ax.yaxis.set_ticks_position("left")
236
+
237
+ if show_y_label:
238
+
239
+ def __dynamic_distance__(
240
+ distance_between_label_axis: float, label: str, scale: int = 100
241
+ ) -> float:
242
+ if distance_between_label_axis != 0:
243
+ return -distance_between_label_axis
244
+ return max(0.01, math.ceil(len(label) / 10) * 10 / scale) * -1
245
+
246
+ curr_y_tick_labels = sorted(
247
+ curr_y_tick_labels, key=lambda x: len(x), reverse=True
248
+ )
249
+ ax.text(
250
+ x=__dynamic_distance__(
251
+ distance_between_label_axis,
252
+ curr_y_tick_labels[0] if curr_y_tick_labels else "",
253
+ )
254
+ * max(graph_coords),
255
+ y=(max_used_y_val + min_used_y_val) / 2,
256
+ s=label,
257
+ fontsize=font_size,
258
+ ha="right",
259
+ )
260
+
261
+ if max_used_y_val is not None and min_used_y_val is not None:
262
+ ax.set_ylim(ymin=min_used_y_val, ymax=max_used_y_val)
263
+
264
+
265
+ # ============================================================================
266
+ # Overlays
267
+ # ============================================================================
268
+
269
+
270
+ def set_focus(ax, graph_coords: Union[Dict, np.array], focus: Dict[int, int]):
271
+ for left, right in focus.items():
272
+ try:
273
+ left, right = graph_coords[left], graph_coords[right]
274
+ fill_x = [left, right, right, left]
275
+ y1, y2 = ax.get_ylim()
276
+ fill_y = [y1, y1, y2, y2]
277
+ ax.fill(fill_x, fill_y, alpha=0.1, color="grey")
278
+ except IndexError as err:
279
+ logger.debug("focus region is out of bound: " + str(err))
280
+
281
+
282
+ def set_indicator_lines(
283
+ ax,
284
+ graph_coords: Union[Dict, np.array],
285
+ sites: Dict[int, str],
286
+ min_y_used: Union[int, float] = 0,
287
+ max_y_used: Union[int, float] = None,
288
+ ):
289
+ if sites is None:
290
+ return
291
+
292
+ if not max_y_used:
293
+ min_y_used, max_y_used = ax.get_ylim()
294
+
295
+ for site, color in sites.items():
296
+ try:
297
+ ax.vlines(
298
+ x=graph_coords[site],
299
+ ymin=min_y_used,
300
+ ymax=max_y_used,
301
+ color=color,
302
+ linestyles="dashed",
303
+ lw=0.5,
304
+ )
305
+ except IndexError as err:
306
+ logger.debug("Indicator line is out of bound: " + str(err))