trackplot 0.5.2__tar.gz → 0.5.3__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.
- {trackplot-0.5.2 → trackplot-0.5.3}/PKG-INFO +1 -1
- {trackplot-0.5.2 → trackplot-0.5.3}/pyproject.toml +1 -1
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/Junction.py +13 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/Annotation.py +23 -7
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/Bam.py +22 -4
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/ReadSegments.py +3 -1
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/plot.py +2 -2
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/plot_func.py +124 -63
- trackplot-0.5.3/ui/assets/Home-7GzAh8lS.js +1 -0
- trackplot-0.5.3/ui/assets/Home-CDW3Zwoa.js +1 -0
- trackplot-0.5.3/ui/assets/Home-zRV7yePL.css +1 -0
- trackplot-0.5.3/ui/assets/Plot-BrjU8Kwg.js +17 -0
- trackplot-0.5.3/ui/assets/Plot-COvGnprQ.css +1 -0
- trackplot-0.5.3/ui/assets/Plot-Cyj_LlDt.js +17 -0
- trackplot-0.5.3/ui/assets/Plot-DpL7z7tp.css +1 -0
- trackplot-0.5.3/ui/assets/el-divider-BVZhQIwQ.js +1 -0
- trackplot-0.5.3/ui/assets/el-divider-Brt4-Qvr.js +1 -0
- trackplot-0.5.3/ui/assets/el-divider-Cwxg0Ado.css +1 -0
- trackplot-0.5.3/ui/assets/el-divider-i9JMIXVR.css +1 -0
- trackplot-0.5.3/ui/assets/index-4hxJ_zbq.js +26 -0
- trackplot-0.5.3/ui/assets/index-CWfdj0DH.js +26 -0
- trackplot-0.5.3/ui/assets/index-O8P0XkxB.css +1 -0
- trackplot-0.5.3/ui/assets/index-ns9n7-F7.css +1 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/index.html +2 -2
- {trackplot-0.5.2 → trackplot-0.5.3}/LICENSE +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/README.md +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/__init__.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/anno/AxLabel.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/anno/__init__.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/anno/theme.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/CoordinateMap.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/GenomicLoci.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/Protein.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/ReadDepth.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/Readder.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/Stroke.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/Transcript.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/__init__.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/base/pyUniprot.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/cli.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/conf/DomainSetting.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/conf/__init__.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/conf/config.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/conf/drawing.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/conf/ui.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/ATAC.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/BedGraph.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/Bigwig.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/Depth.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/Fasta.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/File.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/HiCMatrixTrack.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/Junction.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/Motif.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/file/__init__.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/plot_tests.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/trackplot/server.py +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Home-DOO13BH7.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Home-QmeAKOl4.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Home-RdVPWns6.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Home-jSR0MsHI.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Plot-BmqHZ4QE.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Plot-Bvyo6ju9.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Plot-CTM-EDrj.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Plot-DiuFnwNK.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Plot-hvkDteAn.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/Plot-rbQz1TOM.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/el-divider-BHm65SRq.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/el-divider-BuEUMHwE.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/el-divider-SYT5K-ds.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/el-divider-VYjL3C7L.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/el-divider-eEJXnQD5.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/el-divider-u9f0bZWY.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/index-CETGMNio.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/index-Cexhr_fn.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/index-CrzyEb9s.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/index-D_Cw0sbX.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/index-Dd6Bavnk.js +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/assets/index-Sq2gI4sE.css +0 -0
- {trackplot-0.5.2 → trackplot-0.5.3}/ui/vite.svg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: trackplot
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
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
|
License: BSD-3
|
|
6
6
|
Author: ygidtu
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "trackplot"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.3"
|
|
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 = ["ygidtu <ygidtu@gmail.com>"]
|
|
6
6
|
license = "BSD-3"
|
|
@@ -134,6 +134,19 @@ class Junction(object):
|
|
|
134
134
|
|
|
135
135
|
return self.start > other.end
|
|
136
136
|
|
|
137
|
+
def str(self, with_strand: bool = True) -> str:
|
|
138
|
+
u"""convert junctions to string, with or without strand
|
|
139
|
+
|
|
140
|
+
Keyword arguments:
|
|
141
|
+
:param with_strand: as name says
|
|
142
|
+
Return: chr:strat-end:strand or chr:start-end
|
|
143
|
+
"""
|
|
144
|
+
if with_strand:
|
|
145
|
+
return str(self)
|
|
146
|
+
return f"{self.chromosome}:{self.start}-{self.end}"
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
137
150
|
|
|
138
151
|
if __name__ == '__main__':
|
|
139
152
|
pass
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
# -*- coding:utf-8 -*-
|
|
3
3
|
u"""
|
|
4
4
|
Created by ygidtu@gmail.com at 2020.05.07
|
|
5
|
-
|
|
6
5
|
This scripts contains the class handle the reference file
|
|
6
|
+
|
|
7
|
+
Modified by AD 2025/01/12 to include only specified transcripts, otherwise their exon coordinates still occupy the alignments.
|
|
8
|
+
|
|
7
9
|
"""
|
|
8
10
|
import glob
|
|
9
11
|
import gzip
|
|
@@ -349,16 +351,15 @@ class Annotation(File):
|
|
|
349
351
|
|
|
350
352
|
return output_gtf
|
|
351
353
|
|
|
352
|
-
def __load_gtf__(self):
|
|
353
|
-
|
|
354
|
+
def __load_gtf__(self, transcripts_to_show: list[str]|None = None):
|
|
354
355
|
u"""
|
|
355
356
|
Load transcripts inside of region from gtf file
|
|
356
357
|
:param region: target region
|
|
357
358
|
:return: list of Transcript
|
|
358
|
-
"""
|
|
359
|
+
"""
|
|
360
|
+
# AD - passing transcripts_to_show
|
|
359
361
|
transcripts = {}
|
|
360
362
|
exons = {}
|
|
361
|
-
|
|
362
363
|
for rec in Reader.read_gtf(self.path, self.region):
|
|
363
364
|
start = max(rec.start, self.region.start)
|
|
364
365
|
end = min(rec.end, self.region.end)
|
|
@@ -369,6 +370,13 @@ class Annotation(File):
|
|
|
369
370
|
break
|
|
370
371
|
|
|
371
372
|
if re.search(r"(rna|transcript|cds)", rec.feature, re.I):
|
|
373
|
+
|
|
374
|
+
if transcripts_to_show:
|
|
375
|
+
_name = rec.transcript_name if "transcript_name" in rec.attributes else rec.transcript_id
|
|
376
|
+
if _name not in transcripts_to_show:
|
|
377
|
+
logger.info(f"Skipping transcript {_name}")
|
|
378
|
+
continue
|
|
379
|
+
|
|
372
380
|
if rec.transcript_id not in transcripts.keys():
|
|
373
381
|
transcripts[rec.transcript_id] = Transcript(
|
|
374
382
|
chromosome=rec.contig,
|
|
@@ -380,7 +388,8 @@ class Annotation(File):
|
|
|
380
388
|
gene=rec.gene_name if "gene_name" in rec.attributes else "",
|
|
381
389
|
transcript=rec.transcript_name if "transcript_name" in rec.attributes else "",
|
|
382
390
|
exons=[]
|
|
383
|
-
|
|
391
|
+
)
|
|
392
|
+
|
|
384
393
|
elif re.search(r"(exon)", rec.feature, re.I):
|
|
385
394
|
if rec.transcript_id not in exons.keys():
|
|
386
395
|
exons[rec.transcript_id] = []
|
|
@@ -581,9 +590,16 @@ class Annotation(File):
|
|
|
581
590
|
assert isinstance(region, GenomicLoci), "region should be a GenomicLoci object"
|
|
582
591
|
if transcripts is None:
|
|
583
592
|
transcripts = []
|
|
593
|
+
elif isinstance(transcripts, str):
|
|
594
|
+
# AD when no transcripts are specified, transcripts is an empty string, not None
|
|
595
|
+
if transcripts == "":
|
|
596
|
+
transcripts = []
|
|
597
|
+
else:
|
|
598
|
+
transcripts = transcripts.split(",")
|
|
584
599
|
self.region = region
|
|
600
|
+
# AD - pass specified transcripts early
|
|
585
601
|
if self.category == "gtf":
|
|
586
|
-
self.__load_gtf__()
|
|
602
|
+
self.__load_gtf__(transcripts)
|
|
587
603
|
if self.add_local_domain:
|
|
588
604
|
self.__load_local_domain__(region)
|
|
589
605
|
|
|
@@ -20,7 +20,7 @@ from trackplot.base.Junction import Junction
|
|
|
20
20
|
from trackplot.base.ReadDepth import ReadDepth
|
|
21
21
|
from trackplot.base.Readder import Reader
|
|
22
22
|
from trackplot.conf.config import NORMALIZATION
|
|
23
|
-
from trackplot.file.File import SingleCell
|
|
23
|
+
from trackplot.file.File import SingleCell
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class Bam(SingleCell):
|
|
@@ -275,14 +275,32 @@ class Bam(SingleCell):
|
|
|
275
275
|
site_minus[start - region.start] += 1
|
|
276
276
|
|
|
277
277
|
for k, v in spanned_junctions.items():
|
|
278
|
-
|
|
278
|
+
kept = v >= threshold
|
|
279
|
+
|
|
280
|
+
# if the number of junctiosn is lower than threshold, then skip
|
|
281
|
+
if not kept:
|
|
279
282
|
continue
|
|
280
|
-
|
|
281
|
-
if
|
|
283
|
+
|
|
284
|
+
# if included_junctions is provided, then skip all junctions by default
|
|
285
|
+
if included_junctions:
|
|
286
|
+
kept = False
|
|
287
|
+
|
|
288
|
+
# check whether junctions should be kept
|
|
289
|
+
if k.str(with_strand = True) in included_junctions:
|
|
290
|
+
logger.debug(f"{str(k)} is included")
|
|
291
|
+
kept = True
|
|
292
|
+
elif k.str(with_strand = False) in included_junctions:
|
|
293
|
+
logger.debug(f"{str(k)} is included, but strand is ignored")
|
|
294
|
+
kept = True
|
|
295
|
+
|
|
296
|
+
if not kept:
|
|
297
|
+
logger.debug(f"{str(k)} is not included")
|
|
298
|
+
else:
|
|
282
299
|
if k.strand == "+":
|
|
283
300
|
spanned_junctions_plus[k] = 1 + spanned_junctions_plus.get(k, v)
|
|
284
301
|
elif k.strand == "-":
|
|
285
302
|
spanned_junctions_minus[k] = -1 + spanned_junctions_minus.get(k, v)
|
|
303
|
+
|
|
286
304
|
except IOError as err:
|
|
287
305
|
logger.error('There is no .bam file at {0}'.format(self.path))
|
|
288
306
|
logger.error(err)
|
|
@@ -382,7 +382,9 @@ class ReadSegment(File):
|
|
|
382
382
|
current_ignore_num = min(
|
|
383
383
|
[self.deletion_ignore, read.query_alignment_length * self.del_ratio_ignore])
|
|
384
384
|
else:
|
|
385
|
-
current_ignore_num = np.
|
|
385
|
+
current_ignore_num = np.inf
|
|
386
|
+
# AD - AttributeError: `np.Inf` was removed in the NumPy 2.0 release. Use `np.inf` instead.
|
|
387
|
+
|
|
386
388
|
|
|
387
389
|
exon_bound = []
|
|
388
390
|
intron_bound = []
|
|
@@ -30,7 +30,7 @@ logging.getLogger('matplotlib.font_manager').setLevel(logging.ERROR)
|
|
|
30
30
|
faulthandler.enable()
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
__version__ = "0.5.
|
|
33
|
+
__version__ = "0.5.3"
|
|
34
34
|
__author__ = "ygidtu & Ran Zhou"
|
|
35
35
|
__email__ = "ygidtu@gmail.com"
|
|
36
36
|
|
|
@@ -1437,7 +1437,7 @@ class Plot(object):
|
|
|
1437
1437
|
|
|
1438
1438
|
if output:
|
|
1439
1439
|
logger.info(f"saving fig into {output}")
|
|
1440
|
-
fig.savefig(output, transparent=
|
|
1440
|
+
fig.savefig(output, transparent=False, bbox_inches='tight') # AD
|
|
1441
1441
|
elif return_image:
|
|
1442
1442
|
output = io.BytesIO()
|
|
1443
1443
|
if return_image == "png":
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
# -*- coding:utf-8 -*-
|
|
3
3
|
u"""
|
|
4
4
|
This script contains the functions to draw different images
|
|
5
|
+
Modified by AD 2025/01/13
|
|
5
6
|
"""
|
|
6
|
-
import
|
|
7
|
+
import itertools # AD - for cumulative sum of graph_coords
|
|
8
|
+
#import gzip
|
|
7
9
|
import math
|
|
8
10
|
from copy import deepcopy
|
|
9
|
-
from decimal import Decimal
|
|
11
|
+
#from decimal import Decimal
|
|
10
12
|
from typing import Dict, List, Optional, Union, Tuple, Set
|
|
11
13
|
|
|
12
14
|
import matplotlib as mpl
|
|
@@ -25,6 +27,7 @@ from matplotlib.textpath import TextPath
|
|
|
25
27
|
from matplotlib.transforms import Affine2D
|
|
26
28
|
from scipy.cluster.hierarchy import dendrogram, linkage
|
|
27
29
|
from scipy.stats import gaussian_kde, zscore
|
|
30
|
+
from scipy.stats import beta # AD
|
|
28
31
|
|
|
29
32
|
from trackplot.anno.theme import Theme
|
|
30
33
|
from trackplot.base.GenomicLoci import GenomicLoci
|
|
@@ -100,7 +103,6 @@ def cubic_bezier(pts, t):
|
|
|
100
103
|
p3 = np.array(p3)
|
|
101
104
|
return p0 * (1 - t) ** 3 + 3 * t * p1 * (1 - t) ** 2 + 3 * t ** 2 * (1 - t) * p2 + t ** 3 * p3
|
|
102
105
|
|
|
103
|
-
|
|
104
106
|
def __merge_exons__(exons: List[List[int]]):
|
|
105
107
|
u"""
|
|
106
108
|
merge the overlap exons into one
|
|
@@ -124,7 +126,7 @@ def __merge_exons__(exons: List[List[int]]):
|
|
|
124
126
|
|
|
125
127
|
|
|
126
128
|
def init_graph_coords(region: GenomicLoci, exons: Optional[List[List[int]]] = None, exon_scale=1,
|
|
127
|
-
intron_scale
|
|
129
|
+
intron_scale=0.5) -> np.array:
|
|
128
130
|
u"""
|
|
129
131
|
init the default
|
|
130
132
|
:param region: the plot region
|
|
@@ -135,33 +137,62 @@ def init_graph_coords(region: GenomicLoci, exons: Optional[List[List[int]]] = No
|
|
|
135
137
|
graph_coords = np.zeros(len(region), dtype=int)
|
|
136
138
|
|
|
137
139
|
if exons:
|
|
138
|
-
# if
|
|
139
|
-
|
|
140
|
-
graph_coords
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
140
|
+
# AD - if user specifies an intron scale in line with Trackplot, addition is transparent
|
|
141
|
+
if intron_scale <= 1:
|
|
142
|
+
# if there have exons, init graph_coords by exon and intron scales
|
|
143
|
+
for i in range(0, exons[0][0] - region.start):
|
|
144
|
+
graph_coords[i] = (i - 0) * intron_scale
|
|
145
|
+
exons = __merge_exons__(exons)
|
|
146
|
+
for i in range(0, len(exons)):
|
|
147
|
+
exon = exons[i]
|
|
148
|
+
if i > 0:
|
|
149
|
+
intron = [exons[i - 1][1], exons[i][0]]
|
|
150
|
+
|
|
151
|
+
for j in range(intron[0], intron[1]):
|
|
152
|
+
if j >= region.start:
|
|
153
|
+
graph_coords[j - region.start] = graph_coords[intron[0] - region.start - 1] + (
|
|
154
|
+
j - intron[0] + 1) * intron_scale
|
|
155
|
+
for j in range(exon[0], exon[1] + 1):
|
|
150
156
|
if j >= region.start:
|
|
151
|
-
graph_coords[j - region.start] = graph_coords[
|
|
152
|
-
j -
|
|
153
|
-
|
|
154
|
-
for
|
|
155
|
-
if
|
|
156
|
-
graph_coords[
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
157
|
+
graph_coords[j - region.start] = graph_coords[exon[0] - region.start - 1] + (
|
|
158
|
+
j - exon[0] + 1) * exon_scale
|
|
159
|
+
intron = [exons[-1][-1], region.end]
|
|
160
|
+
for i in range(intron[0], intron[1]):
|
|
161
|
+
if i >= region.start:
|
|
162
|
+
graph_coords[i - region.start] = graph_coords[intron[0] - region.start - 1] + (
|
|
163
|
+
i - intron[0] + 1) * intron_scale
|
|
164
|
+
else:
|
|
165
|
+
exons = __merge_exons__(exons)
|
|
166
|
+
while exons[0][1] < region.start:
|
|
167
|
+
exons = exons[1:]
|
|
168
|
+
while exons[-1][0] > region.end:
|
|
169
|
+
exons = exons[:-1]
|
|
170
|
+
exons[0][0] = max(exons[0][0], region.start)
|
|
171
|
+
exons[-1][1] = min(exons[-1][1], region.end)
|
|
172
|
+
last_interval = region.end - exons[-1][1]
|
|
173
|
+
for i, e in enumerate(exons):
|
|
174
|
+
exons[i][0] -= region.start
|
|
175
|
+
exons[i][1] -= region.start
|
|
176
|
+
|
|
177
|
+
steps = [float(exon_scale)] * len(region)
|
|
178
|
+
if exons[0][0] > 0:
|
|
179
|
+
step = intron_scale / exons[0][0]
|
|
180
|
+
for i in range(exons[0][0]):
|
|
181
|
+
steps[i] = step
|
|
182
|
+
for e in range(1, len(exons)):
|
|
183
|
+
interval = exons[e][0] - exons[e-1][1] - 2
|
|
184
|
+
step = intron_scale / interval
|
|
185
|
+
for i in range(exons[e-1][1], exons[e][0]):
|
|
186
|
+
steps[i] = step
|
|
187
|
+
interval = exons[e][0] - exons[e-1][1] - 2
|
|
188
|
+
if last_interval := len(region) - exons[-1][1] - 1:
|
|
189
|
+
step = intron_scale / last_interval
|
|
190
|
+
for i in range(exons[1][1] +1, len(region)):
|
|
191
|
+
steps[i] = step
|
|
192
|
+
graph_coords = list(map(int, itertools.accumulate(steps)))
|
|
193
|
+
#increments match exactly with original code
|
|
194
|
+
#for i, e in enumerate(graph_objects):
|
|
195
|
+
# print(f"{i}\t{e}")
|
|
165
196
|
else:
|
|
166
197
|
# if there is not any exons, just init graph_coords by region
|
|
167
198
|
for i, j in enumerate(range(region.start, region.end + 1)):
|
|
@@ -175,7 +206,6 @@ def init_graph_coords(region: GenomicLoci, exons: Optional[List[List[int]]] = No
|
|
|
175
206
|
graph_coords[i] = max(graph_coords) + 1
|
|
176
207
|
return graph_coords
|
|
177
208
|
|
|
178
|
-
|
|
179
209
|
def set_x_ticks(
|
|
180
210
|
ax: mpl.axes.Axes,
|
|
181
211
|
region: GenomicLoci,
|
|
@@ -284,6 +314,8 @@ def set_y_ticks(
|
|
|
284
314
|
universal_y_ticks = sorted(universal_y_ticks)
|
|
285
315
|
|
|
286
316
|
for lab in universal_y_ticks:
|
|
317
|
+
curr_y_tick_labels.append(f"{int(lab)}")
|
|
318
|
+
"""
|
|
287
319
|
if y_axis_skip_zero and lab == 0:
|
|
288
320
|
# Exclude label for 0
|
|
289
321
|
curr_y_tick_labels.append("")
|
|
@@ -291,6 +323,7 @@ def set_y_ticks(
|
|
|
291
323
|
curr_y_tick_labels.append(f"{Decimal(lab):.2E}")
|
|
292
324
|
else:
|
|
293
325
|
curr_y_tick_labels.append(f"{lab:.1f}" if lab % 1 != 0 else f"{int(lab)}")
|
|
326
|
+
"""
|
|
294
327
|
u"""
|
|
295
328
|
@2019.01.04
|
|
296
329
|
If there is no bam file, draw a blank y-axis
|
|
@@ -306,6 +339,7 @@ def set_y_ticks(
|
|
|
306
339
|
"""
|
|
307
340
|
|
|
308
341
|
if show_y_label:
|
|
342
|
+
|
|
309
343
|
def __dynamic_distance__(distance_between_label_axis: float, label: str, scale: int = 100) -> float:
|
|
310
344
|
if distance_between_label_axis != 0:
|
|
311
345
|
return -distance_between_label_axis
|
|
@@ -314,9 +348,7 @@ def set_y_ticks(
|
|
|
314
348
|
|
|
315
349
|
curr_y_tick_labels = sorted(curr_y_tick_labels, key=lambda x: len(x), reverse=True)
|
|
316
350
|
ax.text(
|
|
317
|
-
x=__dynamic_distance__(
|
|
318
|
-
distance_between_label_axis, curr_y_tick_labels[0] if curr_y_tick_labels else ""
|
|
319
|
-
) * max(graph_coords),
|
|
351
|
+
x=__dynamic_distance__(distance_between_label_axis, curr_y_tick_labels[0] if curr_y_tick_labels else "") * max(graph_coords),
|
|
320
352
|
y=(max_used_y_val + min_used_y_val) / 2,
|
|
321
353
|
s=label, fontsize=font_size, ha="right"
|
|
322
354
|
)
|
|
@@ -629,7 +661,7 @@ def plot_density(
|
|
|
629
661
|
color="blue",
|
|
630
662
|
font_size: int = 8,
|
|
631
663
|
show_junction_number: bool = True,
|
|
632
|
-
junction_number_font_size: int =
|
|
664
|
+
junction_number_font_size: int = 12,
|
|
633
665
|
n_y_ticks: int = 4,
|
|
634
666
|
distance_between_label_axis: float = .1,
|
|
635
667
|
show_y_label: bool = True,
|
|
@@ -664,6 +696,8 @@ def plot_density(
|
|
|
664
696
|
:param kwargs:
|
|
665
697
|
:return:
|
|
666
698
|
"""
|
|
699
|
+
# max_used_y_val is None
|
|
700
|
+
# distance_between_label_axis: 0
|
|
667
701
|
if obj:
|
|
668
702
|
assert obj.region is not None, "please load data first"
|
|
669
703
|
region = obj.region
|
|
@@ -684,7 +718,17 @@ def plot_density(
|
|
|
684
718
|
except AttributeError:
|
|
685
719
|
# depth do not have junctions
|
|
686
720
|
jxns = {}
|
|
721
|
+
|
|
722
|
+
# AD - convert junction counts to log scale early if requested
|
|
723
|
+
if obj.log_trans and obj.log_trans.isdigit() and int(obj.log_trans) > 0: # in ["2", "10"]:
|
|
724
|
+
|
|
725
|
+
y_label += f" (log{obj.log_trans})"
|
|
726
|
+
denominator = np.log(int(obj.log_trans))
|
|
727
|
+
for k, v in jxns.items():
|
|
728
|
+
jxns[k] = np.log1p(v) / denominator
|
|
687
729
|
|
|
730
|
+
min_used_y_val = 0 # AD
|
|
731
|
+
fixed_min_used_y = True # AD
|
|
688
732
|
fixed_max_used_y, fixed_min_used_y = max_used_y_val is not None, min_used_y_val is not None
|
|
689
733
|
if max_used_y_val is None:
|
|
690
734
|
if isinstance(data, dict):
|
|
@@ -720,7 +764,6 @@ def plot_density(
|
|
|
720
764
|
if data.strand_aware:
|
|
721
765
|
max_used_y_val = max(abs(min_used_y_val), max_used_y_val)
|
|
722
766
|
min_used_y_val = -max(abs(min_used_y_val), max_used_y_val) if data.minus is not None else 0
|
|
723
|
-
|
|
724
767
|
if jxns:
|
|
725
768
|
# sort the junctions by intron length for better plotting look
|
|
726
769
|
jxns_sorted_list = sorted(jxns.keys(), key=lambda x: (x.end - x.start, x.start, x.end), reverse=True)
|
|
@@ -732,10 +775,11 @@ def plot_density(
|
|
|
732
775
|
min_junction_count = min(jxns.values())
|
|
733
776
|
junction_count_gap = max_junction_count - min_junction_count
|
|
734
777
|
|
|
735
|
-
recorded_pts = set()
|
|
778
|
+
#recorded_pts = set()
|
|
736
779
|
jxn_numbers = []
|
|
780
|
+
|
|
737
781
|
for jxn_idx, jxn in enumerate(jxns_sorted_list):
|
|
738
|
-
logger.
|
|
782
|
+
#logger.info(f"junctions of {y_label}: {jxn} - {round(jxns[jxn], 2)}")
|
|
739
783
|
leftss, rightss = jxn.start, jxn.end
|
|
740
784
|
|
|
741
785
|
# junction must at least have one anchor located in plotted region
|
|
@@ -748,20 +792,26 @@ def plot_density(
|
|
|
748
792
|
# the junction out of boundaries, set the boundaries as coordinate
|
|
749
793
|
ss1_idx, ss1_modified = get_limited_index(leftss - region.start, len(graph_coords))
|
|
750
794
|
ss2_idx, ss2_modified = get_limited_index(rightss - region.start, len(graph_coords))
|
|
795
|
+
#logger.info(f"{y_label} ss1_idx {ss1_idx} ss1_modified {ss1_modified} ss2_idx {ss2_idx} ss2_modified {ss2_modified}")
|
|
751
796
|
u"""
|
|
752
797
|
@2019.01.14
|
|
753
798
|
add two new variables to make it clear which one is index, which one is genomic site
|
|
754
799
|
"""
|
|
755
800
|
ss1, ss2 = graph_coords[ss1_idx], graph_coords[ss2_idx]
|
|
756
|
-
|
|
801
|
+
# AD = keep junction arcs on top
|
|
802
|
+
#min_used_y_val = 1
|
|
803
|
+
jxn_on_top = True
|
|
804
|
+
min_used_y_val = 0
|
|
757
805
|
# draw junction on bottom
|
|
806
|
+
"""
|
|
758
807
|
if kwargs.get("density_by_strand"):
|
|
759
808
|
jxn_on_top = jxn.strand == "+"
|
|
760
809
|
else:
|
|
761
810
|
jxn_on_top = jxn_idx % 2 == 0
|
|
811
|
+
#jxn_on_top = True # AD - keep all junctions on same strand
|
|
762
812
|
if abs(min_used_y_val) < max_used_y_val:
|
|
763
813
|
min_used_y_val = -max_used_y_val
|
|
764
|
-
|
|
814
|
+
"""
|
|
765
815
|
if fill_step == "post":
|
|
766
816
|
ss1_idx = max(0, ss1_idx - 1)
|
|
767
817
|
elif fill_step == "pre":
|
|
@@ -785,46 +835,57 @@ def plot_density(
|
|
|
785
835
|
-right_dens - current_height,
|
|
786
836
|
-right_dens if not ss2_modified else -right_dens - current_height
|
|
787
837
|
]
|
|
788
|
-
|
|
838
|
+
"""
|
|
789
839
|
if sum(pts) > 0:
|
|
790
840
|
pts_ = "_".join([str(x) for x in pts])
|
|
791
841
|
while pts_ in recorded_pts:
|
|
792
842
|
pts[1], pts[2] = pts[1] * 1.1, pts[2] * 1.1
|
|
793
843
|
pts_ = "_".join([str(x) for x in pts])
|
|
794
844
|
recorded_pts.add(pts_)
|
|
795
|
-
|
|
845
|
+
"""
|
|
796
846
|
"""
|
|
797
847
|
@2018.12.26
|
|
798
848
|
scale the junctions line width
|
|
799
849
|
"""
|
|
800
850
|
if junction_count_gap > 0:
|
|
801
|
-
line_width = (jxns[jxn] - min_junction_count) / junction_count_gap
|
|
851
|
+
#line_width = (jxns[jxn] - min_junction_count) / junction_count_gap
|
|
852
|
+
line_width = .5 + 1.5 * (jxns[jxn] - min_junction_count) / junction_count_gap
|
|
802
853
|
else:
|
|
803
854
|
line_width = 0
|
|
855
|
+
#line_width = max(.5,np.log())
|
|
856
|
+
#pts = [(ss1, pts[0]), (ss1, pts[1]), (ss2, pts[2]), (ss2, pts[3])]
|
|
857
|
+
|
|
804
858
|
|
|
805
|
-
|
|
859
|
+
temp = np.linspace(0, 1.0, 100)
|
|
860
|
+
bdist = beta.pdf(temp, 3, 3) # or 2, 2
|
|
861
|
+
bdist /= np.max(bdist) # max = 1
|
|
862
|
+
bdist *= jxns[jxn]
|
|
863
|
+
pts_x = np.linspace(ss1, ss2, 100)
|
|
864
|
+
|
|
865
|
+
#pts = [(ss1, 0), (ss1+5, jxns[jxn]), (ss2-5, jxns[jxn]), (ss2, 0)]
|
|
866
|
+
path = Path(np.array([pts_x, bdist]).T)
|
|
867
|
+
patch = PathPatch(path, facecolor='none', edgecolor="#BA55D3", linewidth=line_width)
|
|
868
|
+
ax.add_patch(patch)
|
|
869
|
+
"""
|
|
870
|
+
# pts = [(ss1, 0), (midpt-5, jxns[jxn]), (midpt+5, jxns[jxn]), (ss2, 0)]
|
|
806
871
|
ax.add_patch(PathPatch(Path(pts, [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4]),
|
|
807
|
-
ec=
|
|
808
|
-
|
|
872
|
+
ec="#BA55D3", lw=line_width, fc='none'))
|
|
873
|
+
#ec=color, lw=line_width + 0.2, fc='none'))
|
|
874
|
+
"""
|
|
809
875
|
if show_junction_number:
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
'{0}'.format(round(jxns[jxn], 2)),
|
|
815
|
-
fontsize=junction_number_font_size,
|
|
816
|
-
ha='center', va='center',
|
|
817
|
-
backgroundcolor='w'
|
|
818
|
-
)
|
|
819
|
-
|
|
876
|
+
t = ax.text( (ss1+ss2)/2, jxns[jxn] * 1.1,
|
|
877
|
+
'{0}'.format(round(jxns[jxn], 2)),
|
|
878
|
+
fontsize=junction_number_font_size, ha='center', va='center')
|
|
879
|
+
#, backgroundcolor='w' ) AD - white here overrides transparency below
|
|
820
880
|
# @2018.12.19 transparent background
|
|
821
881
|
t.set_bbox(dict(alpha=0))
|
|
822
882
|
jxn_numbers.append(t)
|
|
823
883
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
884
|
+
# AD - this adds a dot next to the counts
|
|
885
|
+
#try:
|
|
886
|
+
# adjust_text(jxn_numbers, force_text=(0.2, 0.2), arrowprops=dict(arrowstyle="-", color='black', lw=1))
|
|
887
|
+
#except IndexError as err:
|
|
888
|
+
# logger.debug(err)
|
|
828
889
|
|
|
829
890
|
if obj and obj.title:
|
|
830
891
|
ax.text(max(graph_coords) - len(obj.title), max_used_y_val, obj.title, color=color, fontsize=font_size)
|
|
@@ -849,13 +910,13 @@ def plot_density(
|
|
|
849
910
|
set_y_ticks(
|
|
850
911
|
ax, label=y_label, theme=theme,
|
|
851
912
|
graph_coords=graph_coords,
|
|
852
|
-
max_used_y_val=max_used_y_val * 1.1, # keep a buffer at top and bottom of junctions
|
|
853
|
-
min_used_y_val=min_used_y_val * 1.1,
|
|
913
|
+
max_used_y_val=max_used_y_val, # * 1.1, # keep a buffer at top and bottom of junctions
|
|
914
|
+
min_used_y_val=min_used_y_val, # * 1.1, # AD
|
|
854
915
|
n_y_ticks=n_y_ticks,
|
|
855
916
|
distance_between_label_axis=distance_between_label_axis,
|
|
856
917
|
font_size=font_size,
|
|
857
918
|
show_y_label=show_y_label,
|
|
858
|
-
y_axis_skip_zero=False if not isinstance(data, dict) and data.strand_aware else True
|
|
919
|
+
y_axis_skip_zero=False #if not isinstance(data, dict) and data.strand_aware else True
|
|
859
920
|
)
|
|
860
921
|
|
|
861
922
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as _,o as m,c as u,a as c,t as f,b as e,w as t,E as g,e as n,u as i,f as h,_ as y}from"./index-CWfdj0DH.js";import{E as k,a as w,b as E,m as v,v as b}from"./el-divider-BVZhQIwQ.js";const x={name:"Home",data(){return{msg:"Welcome to trackplot App",example:"https://trackplot.readthedocs.io/en/latest/imgs/diagram.png"}}},C=_({...x,setup(B){return(r,a)=>{const s=k,l=w,o=h,p=g,d=E;return m(),u("div",null,[c("h1",null,f(r.msg),1),e(s),e(p,null,{default:t(()=>[e(o,{span:12,offset:3},{default:t(()=>[e(l,{type:"primary",href:"/#/plot"},{default:t(()=>a[0]||(a[0]=[n("Create your own plot")])),_:1})]),_:1}),e(o,{span:6},{default:t(()=>[e(l,{type:"primary",href:"https://github.com/ygidtu/trackplot/issues",icon:i(v)},{default:t(()=>a[1]||(a[1]=[n("Report bug at Github")])),_:1},8,["icon"]),e(s,{direction:"vertical"}),e(l,{type:"primary",icon:i(b),href:"https://trackplot.readthedocs.io/en/latest/web/"},{default:t(()=>a[2]||(a[2]=[n("Read the tutorial")])),_:1},8,["icon"])]),_:1}),e(o,{span:6})]),_:1}),e(s),e(p,null,{default:t(()=>[e(o,{span:20,offset:2},{default:t(()=>[e(d,{src:r.example,width:"100%"},null,8,["src"])]),_:1})]),_:1})])}}}),V=y(C,[["__scopeId","data-v-3d7de397"]]);export{V as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as _,c as m,a as u,b as e,t as c,w as t,E as f,o as g,e as h,f as n,u as i,_ as y}from"./index-4hxJ_zbq.js";import{E as k,a as w,m as E,v,b}from"./el-divider-Brt4-Qvr.js";const x={name:"Home",data(){return{msg:"Welcome to trackplot App",example:"https://trackplot.readthedocs.io/en/latest/imgs/diagram.png"}}},C=_({...x,setup(B){return(r,a)=>{const s=k,l=w,o=h,p=f,d=b;return g(),m("div",null,[u("h1",null,c(r.msg),1),e(s),e(p,null,{default:t(()=>[e(o,{span:12,offset:3},{default:t(()=>[e(l,{type:"primary",href:"/#/plot"},{default:t(()=>a[0]||(a[0]=[n("Create your own plot")])),_:1})]),_:1}),e(o,{span:6},{default:t(()=>[e(l,{type:"primary",href:"https://github.com/ygidtu/trackplot/issues",icon:i(E)},{default:t(()=>a[1]||(a[1]=[n("Report bug at Github")])),_:1},8,["icon"]),e(s,{direction:"vertical"}),e(l,{type:"primary",icon:i(v),href:"https://trackplot.readthedocs.io/en/latest/web/"},{default:t(()=>a[2]||(a[2]=[n("Read the tutorial")])),_:1},8,["icon"])]),_:1}),e(o,{span:6})]),_:1}),e(s),e(p,null,{default:t(()=>[e(o,{span:20,offset:2},{default:t(()=>[e(d,{src:r.example,width:"100%"},null,8,["src"])]),_:1})]),_:1})])}}}),V=y(C,[["__scopeId","data-v-3d7de397"]]);export{V as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
h3[data-v-3d7de397]{margin:40px 0 0}ul[data-v-3d7de397]{list-style-type:none;padding:0}li[data-v-3d7de397]{display:inline-block;margin:0 10px}a[data-v-3d7de397]{color:#42b983}
|