geneview 0.3.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.
- geneview/.DS_Store +0 -0
- geneview/__init__.py +16 -0
- geneview/_fastqplot.py +97 -0
- geneview/_manhattan.py +406 -0
- geneview/_qq.py +368 -0
- geneview/algorithm/__init__.py +1 -0
- geneview/algorithm/_cluster.py +146 -0
- geneview/baseplot/__init__.py +1 -0
- geneview/baseplot/_distribution.py +63 -0
- geneview/baseplot/_forest.py +0 -0
- geneview/baseplot/_sns_axisgrid.py +939 -0
- geneview/baseplot/_sns_distribution.py +707 -0
- geneview/baseplot/_sns_linearmodel.py +212 -0
- geneview/baseplot/_venn.py +584 -0
- geneview/baseplot/_venn_old.py +422 -0
- geneview/cli/__init__.py +12 -0
- geneview/cli/admixture.py +153 -0
- geneview/cli/main.py +89 -0
- geneview/cli/manhattan.py +199 -0
- geneview/cli/qq.py +132 -0
- geneview/cli/utils.py +122 -0
- geneview/cli/venn.py +155 -0
- geneview/conftest.py +216 -0
- geneview/ext/__init__.py +3 -0
- geneview/ext/fractal.py +87 -0
- geneview/ext/husl.py +312 -0
- geneview/ext/miscplot.py +46 -0
- geneview/ext/six.py +632 -0
- geneview/genome_tracks/__init__.py +5 -0
- geneview/genometracks/__init__.py +5 -0
- geneview/gwas/__init__.py +2 -0
- geneview/gwas/_locuszoom.py +1 -0
- geneview/gwas/_manhattan.py +413 -0
- geneview/gwas/_qq.py +365 -0
- geneview/io/__init__.py +2 -0
- geneview/io/_backport.py +399 -0
- geneview/io/_bam.py +258 -0
- geneview/io/_fastq.py +134 -0
- geneview/io/_io_util.py +207 -0
- geneview/karyotype/__init__.py +1 -0
- geneview/karyotype/_karyotype.py +109 -0
- geneview/palette/__init__.py +9 -0
- geneview/palette/_circos.py +235 -0
- geneview/palette/_crayons.py +121 -0
- geneview/palette/_palettes.py +12 -0
- geneview/palette/_rcmod.py +507 -0
- geneview/palette/_xkcd_rgb.py +950 -0
- geneview/popgen/__init__.py +0 -0
- geneview/popgen/_admixture.py +0 -0
- geneview/popgene/__init__.py +1 -0
- geneview/popgene/_admixture.py +363 -0
- geneview/popgene/_ldblock.py +0 -0
- geneview/tests/__init__.py +0 -0
- geneview/tests/test_admixture.py +156 -0
- geneview/tests/test_algorithms.py +115 -0
- geneview/tests/test_cli.py +699 -0
- geneview/tests/test_decorators.py +84 -0
- geneview/tests/test_karyotype.py +154 -0
- geneview/tests/test_manhattan.py +283 -0
- geneview/tests/test_misc.py +57 -0
- geneview/tests/test_palettes.py +101 -0
- geneview/tests/test_qq.py +205 -0
- geneview/tests/test_venn.py +260 -0
- geneview/utils/__init__.py +19 -0
- geneview/utils/_adjust_text.py +758 -0
- geneview/utils/_dataset.py +87 -0
- geneview/utils/_decorators.py +59 -0
- geneview/utils/_misc.py +42 -0
- geneview/utils/_palette.py +81 -0
- geneview/utils/_plott.py +27 -0
- geneview-0.3.0.dist-info/METADATA +412 -0
- geneview-0.3.0.dist-info/RECORD +76 -0
- geneview-0.3.0.dist-info/WHEEL +5 -0
- geneview-0.3.0.dist-info/entry_points.txt +2 -0
- geneview-0.3.0.dist-info/licenses/LICENSE +675 -0
- geneview-0.3.0.dist-info/top_level.txt +1 -0
geneview/.DS_Store
ADDED
|
Binary file
|
geneview/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
__version__ = "0.3.0"
|
|
2
|
+
|
|
3
|
+
import matplotlib
|
|
4
|
+
|
|
5
|
+
from .palette import *
|
|
6
|
+
from .utils import load_dataset, get_dataset_names
|
|
7
|
+
from .karyotype import karyoplot
|
|
8
|
+
from .baseplot import venn, generate_petal_labels
|
|
9
|
+
from .gwas import manhattanplot, qqplot, qqnorm
|
|
10
|
+
from .popgene import admixtureplot
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
matplotlib.rcParams['ps.fonttype'] = 42
|
|
14
|
+
matplotlib.rcParams['pdf.fonttype'] = 42
|
|
15
|
+
matplotlib.rcParams['font.sans-serif'] = ["Arial","Lucida Sans","DejaVu Sans","Lucida Grande","Verdana"]
|
|
16
|
+
matplotlib.rcParams['font.family'] = 'sans-serif'
|
geneview/_fastqplot.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Functions for visulization fastq data
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import print_function, division
|
|
5
|
+
import numpy as np
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
|
|
8
|
+
from .utils import get_color_cycle
|
|
9
|
+
from .io import Fastq, FastqReader
|
|
10
|
+
|
|
11
|
+
def fqqualplot(fqdata, phred=64, ax=None, title=None,
|
|
12
|
+
xlabel=None, ylabel=None, **kwargs):
|
|
13
|
+
"""
|
|
14
|
+
Plotting fastq data quality distribution.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
fqdata : Array like. A list of Fastq type data, array or Series
|
|
19
|
+
The input fastq data for plot.
|
|
20
|
+
|
|
21
|
+
phred : int, or 64, optional
|
|
22
|
+
The phred value to convert the base quality from ASCII to int
|
|
23
|
+
For Illumina fastq: 64(default)
|
|
24
|
+
For Sanger data: 33
|
|
25
|
+
|
|
26
|
+
ax : matplotlib axis, optional
|
|
27
|
+
Axes to plot on, otherwise use current axis.
|
|
28
|
+
|
|
29
|
+
title : string, or None, optional
|
|
30
|
+
If not None, set title on the plot
|
|
31
|
+
|
|
32
|
+
xlabel, ylabel : string,or None, optional
|
|
33
|
+
Set the x/y axis label of the current axis.
|
|
34
|
+
|
|
35
|
+
kwargs : key, values pairings, or None, optional
|
|
36
|
+
Other keyword arguments are passed to boxplot in
|
|
37
|
+
maplotlib.axis.Axes.boxplot.
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
ax : matplotlib Axes
|
|
43
|
+
Axes object with the plot
|
|
44
|
+
|
|
45
|
+
Examples
|
|
46
|
+
--------
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
if ax is None:
|
|
50
|
+
ax = plt.gca()
|
|
51
|
+
|
|
52
|
+
if len(fqdata) == 0:
|
|
53
|
+
return ax
|
|
54
|
+
|
|
55
|
+
if 'showfliers' not in kwargs:
|
|
56
|
+
kwargs.setdefault("showfliers", False)
|
|
57
|
+
|
|
58
|
+
data = []
|
|
59
|
+
for r in fqdata:
|
|
60
|
+
# Convert base quality from ASCII to be integer
|
|
61
|
+
data.append([ord(b) - phred for b in r.qual])
|
|
62
|
+
data = np.array(data)
|
|
63
|
+
|
|
64
|
+
ax.boxplot(data, **kwargs)
|
|
65
|
+
|
|
66
|
+
# Set xtick
|
|
67
|
+
xticks = [i for i in range(0, len(data[0])+1, 10)]
|
|
68
|
+
ax.set_xticks(xticks)
|
|
69
|
+
ax.set_xticklabels(xticks)
|
|
70
|
+
|
|
71
|
+
ax.set_ylim(ymax=data.max()+1)
|
|
72
|
+
if title:
|
|
73
|
+
ax.set_title(title)
|
|
74
|
+
if xlabel:
|
|
75
|
+
ax.set_xlabel(xlabel)
|
|
76
|
+
if ylabel:
|
|
77
|
+
ax.set_ylabel(ylabel)
|
|
78
|
+
|
|
79
|
+
return ax
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def fastqreport(fqfile, fqfilelist=None):
|
|
83
|
+
"""
|
|
84
|
+
Create a report for fastq data by input one fastq file or
|
|
85
|
+
a fq file list.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
|
|
93
|
+
Examples
|
|
94
|
+
--------
|
|
95
|
+
|
|
96
|
+
"""
|
|
97
|
+
pass
|
geneview/_manhattan.py
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
"""Plotting functions for manhattan plot.
|
|
2
|
+
|
|
3
|
+
Copyright (c) Shujia Huang
|
|
4
|
+
Date: 2021-02-21
|
|
5
|
+
|
|
6
|
+
This model is based on brentp's script on github:
|
|
7
|
+
https://github.com/brentp/bio-playground/blob/master/plots/manhattan-plot.py
|
|
8
|
+
|
|
9
|
+
Thanks for Brentp's contributions
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
from itertools import cycle
|
|
13
|
+
from pandas import DataFrame
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
from matplotlib.pyplot import subplots
|
|
17
|
+
from .utils import adjust_text
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# learn something from "https://github.com/reneshbedre/bioinfokit/blob/38fb4966827337f00421119a69259b92bb67a7d0/bioinfokit/visuz.py"
|
|
21
|
+
def manhattanplot(data, chrom="#CHROM", pos="POS", pv="P", snp="ID", logp=True, ax=None,
|
|
22
|
+
marker=".", color="#3B5488,#53BBD5", alpha=0.8,
|
|
23
|
+
title=None, xlabel="Chromosome", ylabel=r"$-log_{10}{(P)}$",
|
|
24
|
+
xtick_label_set=None, CHR=None, xticklabel_kws=None,
|
|
25
|
+
suggestiveline=1e-5, genomewideline=5e-8, sign_line_cols="#D62728,#2CA02C", hline_kws=None,
|
|
26
|
+
sign_marker_p=None, sign_marker_color="r",
|
|
27
|
+
is_annotate_topsnp=False, text_kws=None, ld_block_size=50000, **kwargs):
|
|
28
|
+
"""Creates a manhattan plot from PLINK assoc output (or any data frame with chromosome, position, and p-value).
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
data : DataFrame.
|
|
33
|
+
A DataFrame with columns "#CHROM," "POS," "P," and optionally, "SNP."
|
|
34
|
+
|
|
35
|
+
chrom : string, default is "#CHROM", optional
|
|
36
|
+
A string denoting the column name for chromosome. Defaults to be PLINK2.x's "#CHROM".
|
|
37
|
+
Said column must be a character.
|
|
38
|
+
|
|
39
|
+
pos : string, default is "POS", optional.
|
|
40
|
+
A string denoting the column name for chromosomal position. Default to PLINK2.x's "POS".
|
|
41
|
+
Said column must be numeric.
|
|
42
|
+
|
|
43
|
+
pv : string, default is "P", optional.
|
|
44
|
+
A string denoting the column name for chromosomal p-value. Default to PLINK2.x's "P".
|
|
45
|
+
Said column must be float type.
|
|
46
|
+
|
|
47
|
+
snp : string, default is "ID", optional.
|
|
48
|
+
A string denoting the column name for the SNP name (rs number) or the column which you want to
|
|
49
|
+
represent the variants. Default to PLINK2.x's "P". Said column should be a character.
|
|
50
|
+
|
|
51
|
+
logp : bool, optional
|
|
52
|
+
If TRUE, the -log10 of the p-value is plotted. It isn't very useful
|
|
53
|
+
to plot raw p-values, but plotting the raw value could be useful for
|
|
54
|
+
other genome-wide plots, for example, peak heights, bayes factors, test
|
|
55
|
+
statistics, other "scores," etc. default: True
|
|
56
|
+
|
|
57
|
+
ax : matplotlib axis, optional
|
|
58
|
+
Axis to plot on, otherwise uses current axis.
|
|
59
|
+
|
|
60
|
+
marker : matplotlib markers for scatter plot, default is "o", optional
|
|
61
|
+
|
|
62
|
+
color : matplotlib color, optional, defauft: "#3B5488,#53BBD5"
|
|
63
|
+
Color used for the plot elements. Could hex-code or rgb,
|
|
64
|
+
e.g: '#3B5488,#53BBD5' or 'rb'
|
|
65
|
+
|
|
66
|
+
alpha : float scalar, default is 0.8, optional
|
|
67
|
+
The alpha blending value, between 0(transparent) and 1(opaque)
|
|
68
|
+
|
|
69
|
+
title : string, or None, optional
|
|
70
|
+
Set the title of the current plot.
|
|
71
|
+
|
|
72
|
+
xlabel: string, optional
|
|
73
|
+
Set the x axis label of the current axis.
|
|
74
|
+
|
|
75
|
+
ylabel: string, optional
|
|
76
|
+
Set the y axis label of the current axis.
|
|
77
|
+
|
|
78
|
+
xtick_label_set : a set. optional
|
|
79
|
+
Set the current x axis ticks of the current axis.
|
|
80
|
+
|
|
81
|
+
CHR : string, or None, optional
|
|
82
|
+
Select a specific chromosome to plot. And the x-axis will be the
|
|
83
|
+
position of this chromosome instead of the chromosome id.
|
|
84
|
+
|
|
85
|
+
CAUTION: this parameter could not be used with ``xtick_label_set``
|
|
86
|
+
together.
|
|
87
|
+
|
|
88
|
+
xticklabel_kws : key, value pairings, or None, optional
|
|
89
|
+
Other keyword arguments are passed to set xtick labels in
|
|
90
|
+
maplotlib.axis.Axes.set_xticklabels.
|
|
91
|
+
|
|
92
|
+
suggestiveline : float or None, default is 1e-5, optional
|
|
93
|
+
Where to draw a suggestive ax.axhline. Set None to be disable.
|
|
94
|
+
|
|
95
|
+
genomewideline : float or None, default is 5e-8
|
|
96
|
+
Where to draw a genome-wide significant ax.axhline. Set None to be disable.
|
|
97
|
+
|
|
98
|
+
sign_line_cols : matplotlib color, default: "#D62728,#2CA02C", optional.
|
|
99
|
+
Color used for ``suggestiveline`` and ``genomewideline``.
|
|
100
|
+
Could be hex-code or rgb, e.g: "#D62728,#2CA02C" or 'rb'
|
|
101
|
+
|
|
102
|
+
hline_kws : key, value pairings, or None, optional
|
|
103
|
+
keyword arguments for plotting ax.axhline(``suggestiveline`` and ``genomewideline``)
|
|
104
|
+
except the "color" key-pair.
|
|
105
|
+
|
|
106
|
+
sign_marker_p : float or None, default None, optional.
|
|
107
|
+
A P-value threshold (suggestive to be 1e-6) for marking the significant SNP sites.
|
|
108
|
+
|
|
109
|
+
sign_marker_color : matplotlib color, default: "r", optional.
|
|
110
|
+
Define a color code for significant SNP sites.
|
|
111
|
+
|
|
112
|
+
is_annotate_topsnp : boolean, default is False, optional.
|
|
113
|
+
Annotate the top SNP or not for the significant locus.
|
|
114
|
+
|
|
115
|
+
text_kws: key, value pairings, or None, optional
|
|
116
|
+
keyword arguments for plotting plt.annotate in`` matplotlib.axes.Axes.text(x, y, s, fontdict=None, **kwargs)``
|
|
117
|
+
|
|
118
|
+
ld_block_size : integer, default is 50000, optional
|
|
119
|
+
Set the size of LD block which for finding top SNP. And the top SNP's annotation represent the block.
|
|
120
|
+
|
|
121
|
+
kwargs : key, value pairings, optional
|
|
122
|
+
Other keyword arguments are passed to ``plt.scatter()`` or
|
|
123
|
+
``plt.vlines()`` (in matplotlib.pyplot) depending on whether
|
|
124
|
+
a scatter or line plot is being drawn.
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
Returns
|
|
128
|
+
-------
|
|
129
|
+
ax : matplotlib Axes
|
|
130
|
+
Axes object with the manhattanplot.
|
|
131
|
+
|
|
132
|
+
Notes
|
|
133
|
+
-----
|
|
134
|
+
1. This plot function is not just suit for GWAS manhattan plot,
|
|
135
|
+
it could also be used for any input data which have [chromo-
|
|
136
|
+
some, position and p-value] dataframe.
|
|
137
|
+
|
|
138
|
+
2. The right and top spines of the plot have been set to be
|
|
139
|
+
invisible by hand.
|
|
140
|
+
|
|
141
|
+
Examples
|
|
142
|
+
--------
|
|
143
|
+
|
|
144
|
+
Plot a basic manhattan plot from PLINK2.x association output and reture the figure:
|
|
145
|
+
|
|
146
|
+
.. plot::
|
|
147
|
+
:context: close-figs
|
|
148
|
+
|
|
149
|
+
>>> import pandas as pd
|
|
150
|
+
>>> from geneview import manhattanplot
|
|
151
|
+
>>> from geneview.utils import load_dataset
|
|
152
|
+
>>> df = load_dataset("gwas")
|
|
153
|
+
>>> ax = manhattanplot(data=df)
|
|
154
|
+
|
|
155
|
+
Plot a basic manhattan plot with horizontal xtick labels:
|
|
156
|
+
|
|
157
|
+
.. plot::
|
|
158
|
+
:context: close-figs
|
|
159
|
+
|
|
160
|
+
>>> xtick = set(['chr' + i for i in list(map(str, range(1, 10))) + ['11', '13', '15', '18', '21', 'X']])
|
|
161
|
+
>>> manhattanplot(data=df, xlabel="Chromosome", ylabel=r"$-log_{10}{(P)}$",
|
|
162
|
+
... xtick_label_set=xtick)
|
|
163
|
+
|
|
164
|
+
Add a horizontal at y position=3 line with linestyle="--" and lingwidth=1.3
|
|
165
|
+
across the axis:
|
|
166
|
+
|
|
167
|
+
.. plot::
|
|
168
|
+
:context: close-figs
|
|
169
|
+
|
|
170
|
+
>>> manhattanplot(data=df,
|
|
171
|
+
... hline_kws={"linestyle": "--", "lw": 1.3},
|
|
172
|
+
... xlabel="Chromosome",
|
|
173
|
+
... ylabel=r"$-log_{10}{(P)}$",
|
|
174
|
+
... xtick_label_set = xtick)
|
|
175
|
+
|
|
176
|
+
Rotate the x-axis ticklabel by setting ``xticklabel_kws``:
|
|
177
|
+
|
|
178
|
+
.. plot::
|
|
179
|
+
:context: close-figs
|
|
180
|
+
|
|
181
|
+
>>> manhattanplot(data=df,
|
|
182
|
+
... hline_kws={"linestyle": "--", "lw": 1.3},
|
|
183
|
+
... xlabel="Chromosome",
|
|
184
|
+
... ylabel=r"$-log_{10}{(P)}$",
|
|
185
|
+
... xticklabel_kws={"rotation": "vertical"})
|
|
186
|
+
|
|
187
|
+
Plot a better one with genome-wide significant mark and annotate the Top SNP and save
|
|
188
|
+
the figure to "output_manhattan_plot.png":
|
|
189
|
+
|
|
190
|
+
.. plot::
|
|
191
|
+
:context: close-figs
|
|
192
|
+
|
|
193
|
+
>>> fig, ax = plt.subplots(figsize=(12, 4), facecolor="w", edgecolor="k") # define a plot
|
|
194
|
+
>>> manhattanplot(data=df,
|
|
195
|
+
... marker=".",
|
|
196
|
+
... sign_marker_p=1e-6, # Genome wide significant p-value
|
|
197
|
+
... sign_marker_color="r",
|
|
198
|
+
... snp="ID",
|
|
199
|
+
... title="Test",
|
|
200
|
+
... xtick_label_set=xtick,
|
|
201
|
+
... xlabel="Chromosome",
|
|
202
|
+
... ylabel=r"$-log_{10}{(P)}$",
|
|
203
|
+
... sign_line_cols=["#D62728", "#2CA02C"],
|
|
204
|
+
... hline_kws={"linestyle": "--", "lw": 1.3},
|
|
205
|
+
... is_annotate_topsnp=True,
|
|
206
|
+
... ld_block_size=50000, # 50000 bp
|
|
207
|
+
... annotext_kws={"fontsize": 12, # The fontsize of annotate text
|
|
208
|
+
... "arrowprops": dict(arrowstyle="-", color="k", alpha=0.6)},
|
|
209
|
+
... ax=ax)
|
|
210
|
+
"""
|
|
211
|
+
if not isinstance(data, DataFrame):
|
|
212
|
+
raise ValueError("[ERROR] Input data must be a pandas.DataFrame.")
|
|
213
|
+
if chrom not in data:
|
|
214
|
+
raise ValueError("[ERROR] Column \"%s\" not found!" % chrom)
|
|
215
|
+
if pos not in data:
|
|
216
|
+
raise ValueError("[ERROR] Column \"%s\" not found!" % pos)
|
|
217
|
+
if pv not in data:
|
|
218
|
+
raise ValueError("[ERROR] Column \"%s\" not found!" % pv)
|
|
219
|
+
if is_annotate_topsnp and (snp not in data):
|
|
220
|
+
raise ValueError("[ERROR] You're trying to annotate a set of SNPs but "
|
|
221
|
+
"NO SNP \"%s\" column found!" % snp)
|
|
222
|
+
if CHR is not None and xtick_label_set is not None:
|
|
223
|
+
raise ValueError("[ERROR] ``CHR`` and ``xtick_label_set`` can't be set simultaneously.")
|
|
224
|
+
|
|
225
|
+
data[[chrom]] = data[[chrom]].astype(str) # make sure all the chromosome id are character.
|
|
226
|
+
|
|
227
|
+
# Draw the plot and return the Axes
|
|
228
|
+
if ax is None:
|
|
229
|
+
# ax = plt.gca()
|
|
230
|
+
_, ax = subplots(figsize=(9, 3), facecolor="w", edgecolor="k") # default
|
|
231
|
+
|
|
232
|
+
if xticklabel_kws is None:
|
|
233
|
+
xticklabel_kws = {}
|
|
234
|
+
if hline_kws is None:
|
|
235
|
+
hline_kws = {}
|
|
236
|
+
if text_kws is None:
|
|
237
|
+
text_kws = {}
|
|
238
|
+
|
|
239
|
+
if "," in color:
|
|
240
|
+
color = color.split(",")
|
|
241
|
+
colors = cycle(color)
|
|
242
|
+
|
|
243
|
+
last_xpos = 0
|
|
244
|
+
xs_by_id = [] # use for collecting chromosome's position on x-axis
|
|
245
|
+
x, y, c = [], [], []
|
|
246
|
+
sign_snp_sites = []
|
|
247
|
+
for seqid, group_data in data.groupby(by=chrom, sort=False): # keep the raw order of chromosome
|
|
248
|
+
|
|
249
|
+
if (CHR is not None) and (seqid != CHR):
|
|
250
|
+
continue
|
|
251
|
+
|
|
252
|
+
color = next(colors)
|
|
253
|
+
for i, (site, p_value) in enumerate(zip(group_data[pos], group_data[pv])):
|
|
254
|
+
y_value = -np.log10(p_value) if logp else p_value
|
|
255
|
+
|
|
256
|
+
x.append(last_xpos + site)
|
|
257
|
+
y.append(y_value)
|
|
258
|
+
|
|
259
|
+
c.append(sign_marker_color if ((sign_marker_p is not None) and (p_value <= sign_marker_p)) else color)
|
|
260
|
+
if (sign_marker_p is not None) and (p_value <= sign_marker_p):
|
|
261
|
+
snp_id = group_data[snp].iloc[i]
|
|
262
|
+
sign_snp_sites.append([last_xpos + site, y_value, snp_id]) # x_pos, y_value, text
|
|
263
|
+
|
|
264
|
+
# ``xs_by_id`` is for setting up positions and ticks. Ticks should
|
|
265
|
+
# be placed in the middle of a chromosome. The a new pos column is
|
|
266
|
+
# added that keeps a running sum of the positions of each successive
|
|
267
|
+
# chromsome.
|
|
268
|
+
xs_by_id.append([seqid, last_xpos + (group_data[pos].iloc[0] + group_data[pos].iloc[-1]) / 2])
|
|
269
|
+
last_xpos = x[-1] # keep track so that chromosome will not overlap in the plot.
|
|
270
|
+
|
|
271
|
+
if not x:
|
|
272
|
+
raise ValueError("zero-size array to reduction operation minimum which has no "
|
|
273
|
+
"identity. This could be caused by zero-size array of ``x`` "
|
|
274
|
+
"in the ``manhattanplot(...)`` function.")
|
|
275
|
+
|
|
276
|
+
if "marker" not in kwargs:
|
|
277
|
+
kwargs["marker"] = marker
|
|
278
|
+
|
|
279
|
+
# plot the main manhattan dot plot
|
|
280
|
+
ax.scatter(x, y, c=c, alpha=alpha, edgecolors="none", **kwargs)
|
|
281
|
+
|
|
282
|
+
if is_annotate_topsnp is not None:
|
|
283
|
+
index = _find_SNPs_which_overlap_sign_neighbour_region(
|
|
284
|
+
sign_snp_neighbour_region=_sign_snp_regions(sign_snp_sites, ld_block_size),
|
|
285
|
+
x=x)
|
|
286
|
+
|
|
287
|
+
# reset color for all SNPs which nearby the top SNPs.
|
|
288
|
+
for i in index:
|
|
289
|
+
ax.scatter(x[i], y[i], c=sign_marker_color, alpha=alpha, edgecolors="none", **kwargs)
|
|
290
|
+
|
|
291
|
+
# Add GWAS significant lines
|
|
292
|
+
if "color" in hline_kws:
|
|
293
|
+
hline_kws.pop("color")
|
|
294
|
+
|
|
295
|
+
sign_line_cols = sign_line_cols.split(",") if "," in sign_line_cols else sign_line_cols
|
|
296
|
+
if suggestiveline is not None:
|
|
297
|
+
ax.axhline(y=-np.log10(suggestiveline) if logp else suggestiveline, color=sign_line_cols[0], **hline_kws)
|
|
298
|
+
if genomewideline is not None:
|
|
299
|
+
ax.axhline(y=-np.log10(genomewideline) if logp else genomewideline, color=sign_line_cols[1], **hline_kws)
|
|
300
|
+
|
|
301
|
+
# Plotting the Top SNP for each significant block
|
|
302
|
+
if is_annotate_topsnp:
|
|
303
|
+
sign_top_snp = _find_top_snp(sign_snp_sites, ld_block_size=ld_block_size, is_get_biggest=logp)
|
|
304
|
+
if sign_top_snp: # not empty
|
|
305
|
+
texts = [ax.text(_x, _y, _text) for _x, _y, _text in sign_top_snp]
|
|
306
|
+
adjust_text(texts, ax=ax, **text_kws)
|
|
307
|
+
|
|
308
|
+
if CHR is None:
|
|
309
|
+
|
|
310
|
+
if xtick_label_set is not None:
|
|
311
|
+
ax.set_xticks([v for c, v in xs_by_id if c in xtick_label_set])
|
|
312
|
+
ax.set_xticklabels([c for c, v in xs_by_id if c in xtick_label_set], **xticklabel_kws)
|
|
313
|
+
else:
|
|
314
|
+
ax.set_xticks([v for c, v in xs_by_id])
|
|
315
|
+
ax.set_xticklabels([c for c, v in xs_by_id], **xticklabel_kws)
|
|
316
|
+
|
|
317
|
+
else:
|
|
318
|
+
# show the whole chromosomal position without scientific notation
|
|
319
|
+
# if you are just interesting in this chromosome.
|
|
320
|
+
ax.get_xaxis().get_major_formatter().set_scientific(False)
|
|
321
|
+
|
|
322
|
+
ax.set_xlim(0, x[-1])
|
|
323
|
+
ax.set_ylim(ymin=min(y), ymax=1.2 * max(y))
|
|
324
|
+
|
|
325
|
+
if title:
|
|
326
|
+
ax.set_title(title)
|
|
327
|
+
if xlabel:
|
|
328
|
+
ax.set_xlabel(xlabel)
|
|
329
|
+
if ylabel:
|
|
330
|
+
ax.set_ylabel(ylabel)
|
|
331
|
+
|
|
332
|
+
ax.spines["top"].set_visible(False)
|
|
333
|
+
ax.spines["right"].set_visible(False)
|
|
334
|
+
return ax
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def _find_top_snp(sign_snp_data, ld_block_size, is_get_biggest=True):
|
|
338
|
+
"""
|
|
339
|
+
:param sign_snp_data: A 2D array: [[xpos1, yvalue1, text1], [xpos2, yvalue2, text2], ...]
|
|
340
|
+
"""
|
|
341
|
+
top_snp = []
|
|
342
|
+
tmp_cube = []
|
|
343
|
+
for i, (_x, _y, text) in enumerate(sign_snp_data):
|
|
344
|
+
if i == 0:
|
|
345
|
+
tmp_cube.append([_x, _y, text])
|
|
346
|
+
continue
|
|
347
|
+
|
|
348
|
+
if _x > tmp_cube[-1][0] + ld_block_size:
|
|
349
|
+
# Sorted by y_value in increase/decrease order and only get the first value [0], which is the TopSNP.
|
|
350
|
+
top_snp.append(sorted(tmp_cube, key=(lambda x: x[1]), reverse=is_get_biggest)[0])
|
|
351
|
+
tmp_cube = []
|
|
352
|
+
|
|
353
|
+
tmp_cube.append([_x, _y, text])
|
|
354
|
+
|
|
355
|
+
if tmp_cube: # deal the last one
|
|
356
|
+
top_snp.append(sorted(tmp_cube, key=(lambda x: x[1]), reverse=True)[0])
|
|
357
|
+
|
|
358
|
+
return top_snp
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def _sign_snp_regions(sign_snp_data, ld_block_size):
|
|
362
|
+
"""Create region according to the coordinate of sign_snp_data."""
|
|
363
|
+
regions = []
|
|
364
|
+
for i, (_x, _y, _t) in enumerate(sign_snp_data):
|
|
365
|
+
if i == 0:
|
|
366
|
+
regions.append([_x - ld_block_size, _x])
|
|
367
|
+
continue
|
|
368
|
+
|
|
369
|
+
if _x > regions[-1][1] + ld_block_size:
|
|
370
|
+
regions[-1][1] += ld_block_size
|
|
371
|
+
regions.append([_x - ld_block_size, _x])
|
|
372
|
+
else:
|
|
373
|
+
regions[-1][1] = _x
|
|
374
|
+
|
|
375
|
+
# The last
|
|
376
|
+
if regions:
|
|
377
|
+
regions[-1][1] += ld_block_size
|
|
378
|
+
|
|
379
|
+
return regions
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def _find_SNPs_which_overlap_sign_neighbour_region(sign_snp_neighbour_region, x):
|
|
383
|
+
"""
|
|
384
|
+
"""
|
|
385
|
+
x_size = len(x)
|
|
386
|
+
reg_size = len(sign_snp_neighbour_region)
|
|
387
|
+
index = []
|
|
388
|
+
tmp_index = 0
|
|
389
|
+
for i in range(x_size):
|
|
390
|
+
_x = x[i]
|
|
391
|
+
|
|
392
|
+
is_overlap = False
|
|
393
|
+
iter_index = range(tmp_index, reg_size)
|
|
394
|
+
for j in iter_index:
|
|
395
|
+
if _x > sign_snp_neighbour_region[j][1]: continue
|
|
396
|
+
if _x < sign_snp_neighbour_region[j][0]: break
|
|
397
|
+
|
|
398
|
+
tmp_index = j
|
|
399
|
+
is_overlap = True
|
|
400
|
+
break
|
|
401
|
+
|
|
402
|
+
if is_overlap:
|
|
403
|
+
index.append(i)
|
|
404
|
+
|
|
405
|
+
# return the index
|
|
406
|
+
return index
|