cvmcore 1.0.1__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.
- cvmcore-1.0.1/PKG-INFO +29 -0
- cvmcore-1.0.1/README.md +6 -0
- cvmcore-1.0.1/cvmcore/__init__.py +10 -0
- cvmcore-1.0.1/cvmcore/cvmcore.py +515 -0
- cvmcore-1.0.1/cvmcore/inputdir/CPF_RS14355.fasta +260 -0
- cvmcore-1.0.1/cvmcore/inputdir/CPF_RS14360.fasta +449 -0
- cvmcore-1.0.1/cvmcore/inputdir/CPF_RS14365.fasta +491 -0
- cvmcore-1.0.1/cvmcore/test.py +4 -0
- cvmcore-1.0.1/cvmcore.egg-info/PKG-INFO +29 -0
- cvmcore-1.0.1/cvmcore.egg-info/SOURCES.txt +14 -0
- cvmcore-1.0.1/cvmcore.egg-info/dependency_links.txt +1 -0
- cvmcore-1.0.1/cvmcore.egg-info/requires.txt +7 -0
- cvmcore-1.0.1/cvmcore.egg-info/top_level.txt +1 -0
- cvmcore-1.0.1/requirements.txt +7 -0
- cvmcore-1.0.1/setup.cfg +4 -0
- cvmcore-1.0.1/setup.py +70 -0
cvmcore-1.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cvmcore
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: SZQ lab data analysis core function
|
|
5
|
+
Home-page: https://github.com/hbucqp/cvmcore
|
|
6
|
+
Author: Qingpo Cui
|
|
7
|
+
Author-email: cqp@cau.edu.cn
|
|
8
|
+
License: MIT Licence
|
|
9
|
+
Keywords: pip,mlst,cgmlst,plot
|
|
10
|
+
Platform: any
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
cvmcore
|
|
23
|
+
===
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
## Introduction
|
|
27
|
+
The core function of data analysis used by SZQ lab from China Agricultural University
|
|
28
|
+
|
|
29
|
+
|
cvmcore-1.0.1/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# -*- coding:utf-8 -*-
|
|
2
|
+
|
|
3
|
+
__title__ = 'cvmbcore'
|
|
4
|
+
__description__ = 'core function of data analysis used by SZQ lab from China Agricultural University'
|
|
5
|
+
__url__ = 'https://github.com/hbucqp/cvmcore'
|
|
6
|
+
__version__ = "1.0.1"
|
|
7
|
+
__author__ = 'Qingpo Cui'
|
|
8
|
+
__author_email__ = 'cqp@cau.edu.cn'
|
|
9
|
+
__license__ = 'MIT'
|
|
10
|
+
__copyright__ = 'Copyright 2023 Qingpo Cui'
|
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# data process
|
|
5
|
+
import dask.array as aa
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pandas as pd
|
|
8
|
+
from scipy.cluster.hierarchy import linkage, dendrogram, complete, to_tree
|
|
9
|
+
from scipy.spatial.distance import squareform
|
|
10
|
+
from tabulate import tabulate
|
|
11
|
+
|
|
12
|
+
# from Bio.Blast import NCBIWWW
|
|
13
|
+
from Bio import SeqIO
|
|
14
|
+
from Bio.Seq import Seq
|
|
15
|
+
from Bio.SeqRecord import SeqRecord
|
|
16
|
+
from Bio.Blast import NCBIXML
|
|
17
|
+
from Bio.Blast.Applications import NcbiblastnCommandline
|
|
18
|
+
from Bio.Blast.Applications import NcbimakeblastdbCommandline
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# matplotlib
|
|
22
|
+
from matplotlib import pyplot as plt
|
|
23
|
+
from matplotlib.lines import Line2D
|
|
24
|
+
from matplotlib.patches import Patch
|
|
25
|
+
from matplotlib.transforms import Affine2D
|
|
26
|
+
|
|
27
|
+
from typing import Optional, List, Dict, Union, Tuple
|
|
28
|
+
|
|
29
|
+
plt.rcParams['font.family'] = 'sans-serif'
|
|
30
|
+
plt.rcParams['font.sans-serif'] = ['Arial']
|
|
31
|
+
plt.rcParams['svg.fonttype'] = 'none'
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class cvmbox():
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def single_cgmlst2ref(files_dir: str, outpath: str):
|
|
39
|
+
"""
|
|
40
|
+
Create cgMLST reference sequences using fasta files downloaded from "https://www.cgmlst.org/"
|
|
41
|
+
"""
|
|
42
|
+
files_dir = os.path.abspath(files_dir)
|
|
43
|
+
new_records = []
|
|
44
|
+
for file in os.listdir(files_dir):
|
|
45
|
+
# print(file)
|
|
46
|
+
if file.endswith('.fasta'):
|
|
47
|
+
file_base = file.split('.')[0]
|
|
48
|
+
# print(file_base)
|
|
49
|
+
file = os.path.join(files_dir, file)
|
|
50
|
+
records = SeqIO.parse(file, 'fasta')
|
|
51
|
+
for record in records:
|
|
52
|
+
record.id = file_base + "_" + record.id
|
|
53
|
+
record.name = file_base + "_" + record.name
|
|
54
|
+
record.description = ''
|
|
55
|
+
# print(record.id)
|
|
56
|
+
# print(record)
|
|
57
|
+
new_records.append(record)
|
|
58
|
+
|
|
59
|
+
# check if outpath exists
|
|
60
|
+
outdir = os.path.abspath(outpath)
|
|
61
|
+
if not os.path.exists(outdir):
|
|
62
|
+
os.makedirs(outdir, exist_ok=True)
|
|
63
|
+
|
|
64
|
+
# Specify the output file name
|
|
65
|
+
output_file = "reference.fa"
|
|
66
|
+
output_file = os.path.join(outdir, output_file)
|
|
67
|
+
# Write the modified sequences to the new fasta file
|
|
68
|
+
with open(output_file, "w") as output_handle:
|
|
69
|
+
SeqIO.write(new_records, output_handle, "fasta")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class cvmplot():
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
def circulartree(Z2,
|
|
76
|
+
fontsize: float=8,
|
|
77
|
+
open_angle: float=0,
|
|
78
|
+
start_angle: float=0,
|
|
79
|
+
figsize: Optional[Tuple]=None,
|
|
80
|
+
addpoints: bool=False,
|
|
81
|
+
pointsize: float=15,
|
|
82
|
+
point_colors: Optional[dict]=None,
|
|
83
|
+
point_legend_title: str='Category',
|
|
84
|
+
palette: str="gist_rainbow",
|
|
85
|
+
addlabels: bool=True,
|
|
86
|
+
label_colors: Optional[dict]=None,
|
|
87
|
+
show: bool=True,
|
|
88
|
+
branch_color: bool=False,
|
|
89
|
+
sample_classes: Optional[dict]=None,
|
|
90
|
+
|
|
91
|
+
colorlabels: Optional[dict]=None,
|
|
92
|
+
colorlabels_legend: Optional[dict]=None) -> plt.Axes:
|
|
93
|
+
"""
|
|
94
|
+
Drawing a radial dendrogram from a scipy dendrogram output.
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
Z2 : dictionary
|
|
98
|
+
A dictionary returned by scipy.cluster.hierarchy.dendrogram
|
|
99
|
+
fontsize : float
|
|
100
|
+
A float to specify the font size
|
|
101
|
+
figsize : (x, y) tuple-like
|
|
102
|
+
1D tuple-like of floats to specify the figure size
|
|
103
|
+
palette : string
|
|
104
|
+
Matplotlib colormap name.
|
|
105
|
+
branch_color: bool
|
|
106
|
+
whether or not render branch with colors.
|
|
107
|
+
add_points: bool
|
|
108
|
+
whether or not render leaf point with colors.
|
|
109
|
+
point_colors: dict
|
|
110
|
+
A dictionary to set the color of the leaf point. The Key is the name of the leaflabel.
|
|
111
|
+
The value is the hex color.
|
|
112
|
+
e.g., {'label1':{'#ffffff':'Category1'}, 'label2':{'##f77124':'Catogory2'}...}
|
|
113
|
+
point_legend_title: str
|
|
114
|
+
The title of leaf point legend.
|
|
115
|
+
pointsize: float
|
|
116
|
+
A float to specify the leaf point size
|
|
117
|
+
sample_classes : dict
|
|
118
|
+
A dictionary that contains lists of sample subtypes or classes. These classes appear
|
|
119
|
+
as color labels of each leaf. Colormaps are automatically assigned. Not compatible
|
|
120
|
+
with options "colorlabels" and "colorlabels_legend".
|
|
121
|
+
e.g., {"color1":["Class1","Class2","Class1","Class3", ....]}
|
|
122
|
+
start_angle : float
|
|
123
|
+
The angle of the start point of the circular plot.
|
|
124
|
+
e.g., range from 0 to 360.
|
|
125
|
+
open_angle : float
|
|
126
|
+
The angle of the endpoint of the circular plot.
|
|
127
|
+
e.g., range from 0 to 360.
|
|
128
|
+
addlabels: bool
|
|
129
|
+
A bool to choose if labels are shown.
|
|
130
|
+
label_colors: dict
|
|
131
|
+
A dictionary to set the color of the leaf label. The Key is the name of the leaflabel.
|
|
132
|
+
The value is the hex color.
|
|
133
|
+
e.g., {'label1':'#ffffff', 'label2':'##f77124'...}
|
|
134
|
+
colorlabels_legend : dict
|
|
135
|
+
A nested dictionary to generate the legends of color labels. The key is the name of
|
|
136
|
+
the color label. The value is a dictionary that has two keys "colors" and "labels".
|
|
137
|
+
The value of "colors" is the list of RGB color codes, each corresponds to the class of a leaf.
|
|
138
|
+
e.g., {"color1":{"colors":[[1,0,0,1], ....], "labels":["label1","label2",...]}}
|
|
139
|
+
show : bool
|
|
140
|
+
Whether or not to show the figure.
|
|
141
|
+
Returns
|
|
142
|
+
-------
|
|
143
|
+
Raises
|
|
144
|
+
------
|
|
145
|
+
Notes
|
|
146
|
+
-----
|
|
147
|
+
References
|
|
148
|
+
----------
|
|
149
|
+
See Also
|
|
150
|
+
--------
|
|
151
|
+
Examples
|
|
152
|
+
--------
|
|
153
|
+
"""
|
|
154
|
+
if figsize == None and colorlabels != None:
|
|
155
|
+
figsize = [7, 5]
|
|
156
|
+
elif figsize == None and sample_classes != None:
|
|
157
|
+
figsize = [7, 5]
|
|
158
|
+
elif figsize == None:
|
|
159
|
+
figsize = [10, 10]
|
|
160
|
+
linewidth = 0.5
|
|
161
|
+
R = 1
|
|
162
|
+
width = R * 0.1
|
|
163
|
+
space = R * 0.05
|
|
164
|
+
if colorlabels != None:
|
|
165
|
+
offset = width * len(colorlabels) / R + space * \
|
|
166
|
+
(len(colorlabels) - 1) / R + 0.05
|
|
167
|
+
print(offset)
|
|
168
|
+
elif sample_classes != None:
|
|
169
|
+
offset = width * len(sample_classes) / R + \
|
|
170
|
+
space * (len(sample_classes) - 1) / R + 0.05
|
|
171
|
+
print(offset)
|
|
172
|
+
else:
|
|
173
|
+
offset = 0
|
|
174
|
+
|
|
175
|
+
xmax = np.amax(Z2['icoord'])
|
|
176
|
+
ymax = np.amax(Z2['dcoord'])
|
|
177
|
+
|
|
178
|
+
ucolors = sorted(set(Z2["color_list"]))
|
|
179
|
+
# print(ucolors)
|
|
180
|
+
#cmap = cm.gist_rainbow(np.linspace(0, 1, len(ucolors)))
|
|
181
|
+
cmp = plt.get_cmap(palette, len(ucolors))
|
|
182
|
+
# print(cmp)
|
|
183
|
+
if type(cmp) == matplotlib.colors.LinearSegmentedColormap:
|
|
184
|
+
cmap = cmp(np.linspace(0, 1, len(ucolors)))
|
|
185
|
+
else:
|
|
186
|
+
cmap = cmp.colors
|
|
187
|
+
fig, ax = plt.subplots(figsize=figsize)
|
|
188
|
+
i = 0
|
|
189
|
+
label_coords = []
|
|
190
|
+
leaf_coords = []
|
|
191
|
+
# Z2["color_list"] = list(np.full(149, 'black'))
|
|
192
|
+
for x, y, c in sorted(zip(Z2['icoord'], Z2['dcoord'], Z2["color_list"])):
|
|
193
|
+
# if not branch_color:
|
|
194
|
+
# _color='black'
|
|
195
|
+
# else:
|
|
196
|
+
# _color=cmap[ucolors.index(c)]
|
|
197
|
+
_color = 'black'
|
|
198
|
+
|
|
199
|
+
# np.abs(_xr1)<0.000000001 and np.abs(_yr1) <0.000000001:
|
|
200
|
+
if c == "C0":
|
|
201
|
+
# print('test')
|
|
202
|
+
_color = "black"
|
|
203
|
+
|
|
204
|
+
# transforming original x coordinates into relative circumference positions and y into radius
|
|
205
|
+
# the rightmost leaf is going to [1, 0]
|
|
206
|
+
r = R * (1 - np.array(y) / ymax)
|
|
207
|
+
# _x=np.cos(2*np.pi*np.array([x[0],x[2]])/xmax) # transforming original x coordinates into x circumference positions
|
|
208
|
+
_x = np.cos((2 * np.pi * (360 - open_angle) / 360)
|
|
209
|
+
* np.array([x[0], x[2]]) / xmax)
|
|
210
|
+
_xr0 = _x[0] * r[0]
|
|
211
|
+
_xr1 = _x[0] * r[1]
|
|
212
|
+
_xr2 = _x[1] * r[2]
|
|
213
|
+
_xr3 = _x[1] * r[3]
|
|
214
|
+
# _y=np.sin(2*np.pi*np.array([x[0],x[2]])/xmax) # transforming original x coordinates into y circumference positions
|
|
215
|
+
# transforming original x coordinates into y circumference positions
|
|
216
|
+
_y = np.sin(2 * np.pi * (360 - open_angle) /
|
|
217
|
+
360 * np.array([x[0], x[2]]) / xmax)
|
|
218
|
+
_yr0 = _y[0] * r[0]
|
|
219
|
+
_yr1 = _y[0] * r[1]
|
|
220
|
+
_yr2 = _y[1] * r[2]
|
|
221
|
+
_yr3 = _y[1] * r[3]
|
|
222
|
+
|
|
223
|
+
# calculate the new coordinate
|
|
224
|
+
new_xr0, new_yr0 = rotate_point(_xr0, _yr0, start_angle)
|
|
225
|
+
new_xr1, new_yr1 = rotate_point(_xr1, _yr1, start_angle)
|
|
226
|
+
new_xr2, new_yr2 = rotate_point(_xr2, _yr2, start_angle)
|
|
227
|
+
new_xr3, new_yr3 = rotate_point(_xr3, _yr3, start_angle)
|
|
228
|
+
|
|
229
|
+
# plotting radial lines
|
|
230
|
+
ax.plot([new_xr0, new_xr1], [new_yr0, new_yr1],
|
|
231
|
+
c=_color, linewidth=linewidth, rasterized=True)
|
|
232
|
+
ax.plot([new_xr2, new_xr3], [new_yr2, new_yr3],
|
|
233
|
+
c=_color, linewidth=linewidth, rasterized=True)
|
|
234
|
+
|
|
235
|
+
# plotting circular links between nodes
|
|
236
|
+
if new_yr1 > 0 and new_yr2 > 0:
|
|
237
|
+
link = np.sqrt(
|
|
238
|
+
r[1]**2 - np.linspace(new_xr1, new_xr2, 10000)**2)
|
|
239
|
+
ax.plot(np.linspace(new_xr1, new_xr2, 10000), link,
|
|
240
|
+
c=_color, linewidth=linewidth, rasterized=True)
|
|
241
|
+
elif new_yr1 < 0 and new_yr2 < 0:
|
|
242
|
+
link = -np.sqrt(r[1]**2 -
|
|
243
|
+
np.linspace(new_xr1, new_xr2, 10000)**2)
|
|
244
|
+
|
|
245
|
+
ax.plot(np.linspace(new_xr1, new_xr2, 10000), link,
|
|
246
|
+
c=_color, linewidth=linewidth, rasterized=True)
|
|
247
|
+
elif new_yr1 > 0 and new_yr2 < 0:
|
|
248
|
+
_r = r[1]
|
|
249
|
+
if new_xr1 < 0 or new_xr2 < 0:
|
|
250
|
+
_r = -_r
|
|
251
|
+
link = -np.sqrt(r[1]**2 -
|
|
252
|
+
np.linspace(new_yr1, new_yr2, 10000)**2)
|
|
253
|
+
# print(link)
|
|
254
|
+
# print(dict(zip(np.linspace(_xr1, _r, 10000), link)))
|
|
255
|
+
ax.plot(link, np.linspace(new_yr1, new_yr2, 10000),
|
|
256
|
+
c=_color, linewidth=linewidth, rasterized=True)
|
|
257
|
+
else:
|
|
258
|
+
link = np.sqrt(
|
|
259
|
+
r[1]**2 - np.linspace(new_yr1, new_yr2, 10000)**2)
|
|
260
|
+
ax.plot(link, np.linspace(new_yr1, new_yr2, 10000),
|
|
261
|
+
c=_color, linewidth=linewidth, rasterized=True)
|
|
262
|
+
|
|
263
|
+
# Calculating the x, y coordinates and rotation angles of labels and the leaf points coordinates
|
|
264
|
+
|
|
265
|
+
if y[0] == 0:
|
|
266
|
+
label_coords.append(
|
|
267
|
+
[(1.05 + offset) * new_xr0, (1.05 + offset) * new_yr0, (360 - open_angle) * x[0] / xmax])
|
|
268
|
+
leaf_coords.append([new_xr0, new_yr0])
|
|
269
|
+
#plt.text(1.05*_xr0, 1.05*_yr0, Z2['ivl'][i],{'va': 'center'},rotation_mode='anchor', rotation=360*x[0]/xmax)
|
|
270
|
+
i += 1
|
|
271
|
+
# print('Label_coords')
|
|
272
|
+
# print(label_coords)
|
|
273
|
+
if y[3] == 0:
|
|
274
|
+
label_coords.append(
|
|
275
|
+
[(1.05 + offset) * new_xr3, (1.05 + offset) * new_yr3, (360 - open_angle) * x[2] / xmax])
|
|
276
|
+
leaf_coords.append([new_xr3, new_yr3])
|
|
277
|
+
#plt.text(1.05*_xr3, 1.05*_yr3, Z2['ivl'][i],{'va': 'center'},rotation_mode='anchor', rotation=360*x[2]/xmax)
|
|
278
|
+
i += 1
|
|
279
|
+
# print(label_coords)
|
|
280
|
+
|
|
281
|
+
# print(label_coords)
|
|
282
|
+
if addlabels == True:
|
|
283
|
+
assert len(Z2['ivl']) == len(label_coords), "Internal error, label numbers " + \
|
|
284
|
+
str(len(Z2['ivl'])) + " and " + \
|
|
285
|
+
str(len(label_coords)) + " must be equal!"
|
|
286
|
+
if label_colors != None:
|
|
287
|
+
assert len(Z2['ivl']) == len(label_colors), "Internal error, label numbers " + str(
|
|
288
|
+
len(Z2['ivl'])) + " and " + str(len(label_colors)) + " must be equal!"
|
|
289
|
+
# Adding labels
|
|
290
|
+
for (_x, _y, _rot), label in zip(label_coords, Z2['ivl']):
|
|
291
|
+
ax.text(_x, _y, label, {'va': 'center'}, rotation_mode='anchor', color=list(
|
|
292
|
+
label_colors[label].keys())[0], rotation=_rot + start_angle, fontsize=fontsize)
|
|
293
|
+
else:
|
|
294
|
+
for (_x, _y, _rot), label in zip(label_coords, Z2['ivl']):
|
|
295
|
+
ax.text(_x, _y, label, {
|
|
296
|
+
'va': 'center'}, rotation_mode='anchor', rotation=_rot + start_angle, fontsize=fontsize)
|
|
297
|
+
if addpoints == True:
|
|
298
|
+
assert len(Z2['ivl']) == len(label_coords), "Internal error, point numbers " + \
|
|
299
|
+
str(len(Z2['ivl'])) + " and " + \
|
|
300
|
+
str(len(label_coords)) + " must be equal!"
|
|
301
|
+
if point_colors != None:
|
|
302
|
+
assert len(Z2['ivl']) == len(point_colors), "Internal error, label numbers " + str(
|
|
303
|
+
len(Z2['ivl'])) + " and " + str(len(point_colors)) + " must be equal!"
|
|
304
|
+
for (_x, _y), label in zip(leaf_coords, Z2['ivl']):
|
|
305
|
+
point = ax.scatter(_x, _y, color=list(
|
|
306
|
+
point_colors[label].keys())[0], s=pointsize)
|
|
307
|
+
legend_elements = point_legend(point_colors, fontsize + 2)
|
|
308
|
+
plt.legend(handles=legend_elements,
|
|
309
|
+
loc='upper left',
|
|
310
|
+
bbox_to_anchor=(1.04, 1),
|
|
311
|
+
title=point_legend_title,
|
|
312
|
+
fontsize=fontsize + 2, title_fontsize=fontsize + 3, frameon=False)
|
|
313
|
+
plt.gca().add_artist(point)
|
|
314
|
+
|
|
315
|
+
else:
|
|
316
|
+
for (_x, _y), label in zip(leaf_coords, Z2['ivl']):
|
|
317
|
+
point = ax.scatter(_x, _y, size=pointsize)
|
|
318
|
+
plt.gca().add_artist(point)
|
|
319
|
+
|
|
320
|
+
# plt.draw()
|
|
321
|
+
# # Plot strip
|
|
322
|
+
# num_samples = 150
|
|
323
|
+
# open_angle = 30
|
|
324
|
+
# num_remove = math.floor(num_samples * open_angle /(360-open_angle))
|
|
325
|
+
|
|
326
|
+
# all_samples = num_samples+num_remove
|
|
327
|
+
# all_samples
|
|
328
|
+
|
|
329
|
+
# ax.pie(np.ones(all_samples),radius=1.3,startangle=0)
|
|
330
|
+
# circle = plt.Circle((0,0),1.2, fc='white', rasterized=True)
|
|
331
|
+
# plt.gca().add_patch(circle)
|
|
332
|
+
|
|
333
|
+
# if colorlabels != None:
|
|
334
|
+
# assert len(Z2['ivl'])==len(label_coords), "Internal error, label numbers "+str(len(Z2['ivl'])) +" and "+str(len(label_coords))+" must be equal!"
|
|
335
|
+
|
|
336
|
+
# j=0
|
|
337
|
+
# outerrad=R*1.05+width*len(colorlabels)+space*(len(colorlabels)-1)
|
|
338
|
+
# # print(outerrad)
|
|
339
|
+
# #sort_index=np.argsort(Z2['icoord'])
|
|
340
|
+
# #print(sort_index)
|
|
341
|
+
# intervals=[]
|
|
342
|
+
# for i in range(len(label_coords)):
|
|
343
|
+
# _xl,_yl,_rotl =label_coords[i-1]
|
|
344
|
+
# _x,_y,_rot =label_coords[i]
|
|
345
|
+
# if i==len(label_coords)-1:
|
|
346
|
+
# _xr,_yr,_rotr =label_coords[0]
|
|
347
|
+
# else:
|
|
348
|
+
# _xr,_yr,_rotr =label_coords[i+1]
|
|
349
|
+
# d=((_xr-_xl)**2+(_yr-_yl)**2)**0.5
|
|
350
|
+
# intervals.append(d)
|
|
351
|
+
# colorpos=intervals#np.ones([len(label_coords)])
|
|
352
|
+
# labelnames=[]
|
|
353
|
+
# for labelname, colorlist in colorlabels.items():
|
|
354
|
+
# colorlist=np.array(colorlist)[Z2['leaves']]
|
|
355
|
+
# if j!=0:
|
|
356
|
+
# outerrad=outerrad-width-space
|
|
357
|
+
# innerrad=outerrad-width
|
|
358
|
+
# patches, texts =plt.pie(colorpos, colors=colorlist,
|
|
359
|
+
# radius=outerrad,
|
|
360
|
+
# counterclock=True,
|
|
361
|
+
# startangle=label_coords[0][2]*0.5)
|
|
362
|
+
# circle=plt.Circle((0,0),innerrad, fc='white')
|
|
363
|
+
# plt.gca().add_patch(circle)
|
|
364
|
+
# labelnames.append(labelname)
|
|
365
|
+
# j+=1
|
|
366
|
+
|
|
367
|
+
# if colorlabels_legend!=None:
|
|
368
|
+
# for i, labelname in enumerate(labelnames):
|
|
369
|
+
# print(colorlabels_legend[labelname]["colors"])
|
|
370
|
+
# colorlines=[]
|
|
371
|
+
# for c in colorlabels_legend[labelname]["colors"]:
|
|
372
|
+
# colorlines.append(Line2D([0], [0], color=c, lw=4))
|
|
373
|
+
# leg=plt.legend(colorlines,
|
|
374
|
+
# colorlabels_legend[labelname]["labels"],
|
|
375
|
+
# bbox_to_anchor=(1.5+0.3*i, 1.0),
|
|
376
|
+
# title=labelname)
|
|
377
|
+
# plt.gca().add_artist(leg)
|
|
378
|
+
# elif sample_classes!=None:
|
|
379
|
+
# assert len(Z2['ivl'])==len(label_coords), "Internal error, label numbers "+str(len(Z2['ivl'])) +" and "+str(len(label_coords))+" must be equal!"
|
|
380
|
+
|
|
381
|
+
# j=0
|
|
382
|
+
# outerrad=R*1.05+width*len(sample_classes)+space*(len(sample_classes)-1)
|
|
383
|
+
# print(f'outerrad: {outerrad}')
|
|
384
|
+
# #sort_index=np.argsort(Z2['icoord'])
|
|
385
|
+
# #print(sort_index)
|
|
386
|
+
# intervals=[]
|
|
387
|
+
# for i in range(len(label_coords)):
|
|
388
|
+
# _xl,_yl,_rotl =label_coords[i-1]
|
|
389
|
+
# _x,_y,_rot =label_coords[i]
|
|
390
|
+
# if i==len(label_coords)-1:
|
|
391
|
+
# _xr,_yr,_rotr =label_coords[0]
|
|
392
|
+
# else:
|
|
393
|
+
# _xr,_yr,_rotr =label_coords[i+1]
|
|
394
|
+
# d=((_xr-_xl)**2+(_yr-_yl)**2)**0.5
|
|
395
|
+
# intervals.append(d)
|
|
396
|
+
# print(f'intervals:{intervals}')
|
|
397
|
+
# print(f'label_coord:{label_coords}')
|
|
398
|
+
# colorpos=intervals#np.ones([len(label_coords)])
|
|
399
|
+
# labelnames=[]
|
|
400
|
+
# colorlabels_legend={}
|
|
401
|
+
# for labelname, colorlist in sample_classes.items():
|
|
402
|
+
# ucolors=sorted(list(np.unique(colorlist)))
|
|
403
|
+
# type_num=len(ucolors)
|
|
404
|
+
# _cmp=plt.get_cmap(colormap_list[j])
|
|
405
|
+
# _colorlist=[_cmp(ucolors.index(c)/(type_num-1)) for c in colorlist]
|
|
406
|
+
# # print(f'_colorlist0:{_colorlist}')
|
|
407
|
+
# #rearange colors based on leaf index
|
|
408
|
+
# _colorlist=np.array(_colorlist)[Z2['leaves']]
|
|
409
|
+
# # print(f'_colorlist:{_colorlist}')
|
|
410
|
+
# if j!=0:
|
|
411
|
+
# outerrad=outerrad-width-space
|
|
412
|
+
# innerrad=outerrad-width
|
|
413
|
+
# # print(outerrad, innerrad)
|
|
414
|
+
# patches, texts =plt.pie(colorpos, colors=_colorlist,
|
|
415
|
+
# radius=outerrad,
|
|
416
|
+
# counterclock=True,
|
|
417
|
+
# startangle=label_coords[0][2]*0.5)
|
|
418
|
+
# circle=plt.Circle((0,0),innerrad, fc='white')
|
|
419
|
+
# plt.gca().add_patch(circle)
|
|
420
|
+
# labelnames.append(labelname)
|
|
421
|
+
# colorlabels_legend[labelname]={}
|
|
422
|
+
# colorlabels_legend[labelname]["colors"]=_cmp(np.linspace(0, 1, type_num))
|
|
423
|
+
# colorlabels_legend[labelname]["labels"]=ucolors
|
|
424
|
+
# j+=1
|
|
425
|
+
|
|
426
|
+
# if colorlabels_legend!=None:
|
|
427
|
+
# for i, labelname in enumerate(labelnames):
|
|
428
|
+
# print(colorlabels_legend[labelname]["colors"])
|
|
429
|
+
# colorlines=[]
|
|
430
|
+
# for c in colorlabels_legend[labelname]["colors"]:
|
|
431
|
+
# colorlines.append(Line2D([0], [0], color=c, lw=4))
|
|
432
|
+
# leg=plt.legend(colorlines,
|
|
433
|
+
# colorlabels_legend[labelname]["labels"],
|
|
434
|
+
# bbox_to_anchor=(1.1, 1.0-0.3*i),
|
|
435
|
+
# title=labelname)
|
|
436
|
+
# plt.gca().add_artist(leg)
|
|
437
|
+
# breakf
|
|
438
|
+
ax.spines.right.set_visible(False)
|
|
439
|
+
ax.spines.top.set_visible(False)
|
|
440
|
+
ax.spines.left.set_visible(False)
|
|
441
|
+
ax.spines.bottom.set_visible(False)
|
|
442
|
+
ax.set_rasterization_zorder(None)
|
|
443
|
+
plt.xticks([])
|
|
444
|
+
plt.yticks([])
|
|
445
|
+
|
|
446
|
+
if colorlabels != None:
|
|
447
|
+
maxr = R * 1.05 + width * \
|
|
448
|
+
len(colorlabels) + space * (len(colorlabels) - 1)
|
|
449
|
+
elif sample_classes != None:
|
|
450
|
+
maxr = R * 1.05 + width * \
|
|
451
|
+
len(sample_classes) + space * (len(sample_classes) - 1)
|
|
452
|
+
else:
|
|
453
|
+
maxr = R * 1.05
|
|
454
|
+
plt.xlim(-maxr, maxr)
|
|
455
|
+
plt.ylim(-maxr, maxr)
|
|
456
|
+
# plt.legend(loc="upper right")
|
|
457
|
+
plt.subplots_adjust(left=0.05, right=0.85)
|
|
458
|
+
plt.show()
|
|
459
|
+
return ax
|
|
460
|
+
|
|
461
|
+
def rotate_point(x: float, y: float, theta: float):
|
|
462
|
+
"""
|
|
463
|
+
rotate the given point a angle based on origin (0,0)
|
|
464
|
+
Parameters
|
|
465
|
+
----------
|
|
466
|
+
x: float
|
|
467
|
+
The x value
|
|
468
|
+
y: float
|
|
469
|
+
The y value
|
|
470
|
+
theta: float
|
|
471
|
+
The rotate angle, range is (0, 360).
|
|
472
|
+
"""
|
|
473
|
+
angle = 2 * np.pi * theta / 360
|
|
474
|
+
|
|
475
|
+
new_x = x * np.cos(angle) - y * np.sin(angle)
|
|
476
|
+
new_y = x * np.sin(angle) + y * np.cos(angle)
|
|
477
|
+
return new_x, new_y
|
|
478
|
+
|
|
479
|
+
def point_legend(point_colors: Optional[dict]=None,
|
|
480
|
+
markersize: float=10):
|
|
481
|
+
"""
|
|
482
|
+
Return legend elements.
|
|
483
|
+
Parameters
|
|
484
|
+
----------
|
|
485
|
+
point_colors: dict
|
|
486
|
+
A dictionary to set the color of the leaf point. The Key is the name of the leaflabel.
|
|
487
|
+
The value is the hex color.
|
|
488
|
+
e.g., {'label1':{'#ffffff':'Category1'}, 'label2':{'##f77124':'Catogory2'}...}
|
|
489
|
+
markersize: float
|
|
490
|
+
A float to specify the markerpoint size.
|
|
491
|
+
Returns
|
|
492
|
+
-------
|
|
493
|
+
Raises
|
|
494
|
+
------
|
|
495
|
+
Notes
|
|
496
|
+
-----
|
|
497
|
+
References
|
|
498
|
+
----------
|
|
499
|
+
See Also
|
|
500
|
+
--------
|
|
501
|
+
Examples
|
|
502
|
+
--------
|
|
503
|
+
"""
|
|
504
|
+
df = pd.DataFrame.from_dict(point_colors, orient='columns')
|
|
505
|
+
new_df = df.melt(var_name='Labels', value_name='Cate',
|
|
506
|
+
ignore_index=False)
|
|
507
|
+
new_df.index.name = 'Color'
|
|
508
|
+
new_df.reset_index(inplace=True)
|
|
509
|
+
new_df.dropna(inplace=True)
|
|
510
|
+
new_df.drop_duplicates(subset=['Color', 'Cate'], inplace=True)
|
|
511
|
+
# print(new_df)
|
|
512
|
+
Cate_dict = dict(zip(new_df['Cate'], new_df['Color']))
|
|
513
|
+
legend_element = [Line2D([0], [0], marker='o', color='w', markerfacecolor=Cate_dict[key],
|
|
514
|
+
label=key, markersize=markersize) for key in Cate_dict.keys()]
|
|
515
|
+
return legend_element
|