Skip to content

Commit c4f4dc4

Browse files
committed
first commit
1 parent faade3b commit c4f4dc4

File tree

7 files changed

+3698
-0
lines changed

7 files changed

+3698
-0
lines changed

setup.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# builtin
2+
import setuptools
3+
4+
def get_long_description():
5+
with open("README.md", "r") as readme_file:
6+
long_description = readme_file.read()
7+
return long_description
8+
9+
10+
def get_requirements():
11+
with open('requirements.txt') as f:
12+
required = f.read().splitlines()
13+
return required
14+
15+
16+
def create_pip_wheel():
17+
requirements = get_requirements()
18+
setuptools.setup(
19+
name="acore",
20+
version="0.1.0",
21+
license="MIT",
22+
description="An open-source Python package for Statistical Analysis of Omics datasets",
23+
long_description=get_long_description(),
24+
long_description_content_type="text/markdown",
25+
author="Multi-omics Network Analytics lab",
26+
author_email="[email protected]",
27+
url="",
28+
project_urls={
29+
"Multi-omics Network Analytics": "",
30+
"GitHub": "",
31+
"ReadTheDocs": "",
32+
"PyPi": "",
33+
"Scientific paper": "https://www.nature.com/articles/s41587-021-01145-6",
34+
},
35+
keywords=["statistics", "bioinformatics", "multi-omics",],
36+
classifiers=[
37+
"Intended Audience :: Science/Research",
38+
"License :: OSI Approved :: MIT License",
39+
"Operating System :: OS Independent",
40+
"Programming Language :: Python :: 3",
41+
"Topic :: Scientific :: Bioinformatics",
42+
],
43+
packages=[
44+
"acore",
45+
],
46+
include_package_data=True,
47+
entry_points={},
48+
install_requires=requirements,
49+
python_requires=">=3.9,<4",
50+
)
51+
52+
53+
if __name__ == "__main__":
54+
create_pip_wheel()

vcore/Dendrogram.py

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
import numpy as np
2+
import scipy as scp
3+
from collections import OrderedDict
4+
import plotly.graph_objs as go
5+
6+
def plot_dendrogram(Z_dendrogram, cutoff_line=True, value=15, orientation='bottom', hang=30, hide_labels=False, labels=None,
7+
colorscale=None, hovertext=None, color_threshold=None):
8+
"""
9+
Modified version of Plotly _dendrogram.py that returns a dendrogram Plotly figure object with cutoff line.
10+
11+
:param Z_dendrogram: Matrix of observations as array of arrays
12+
:type Z_dendrogram: ndarray
13+
:param cutoff_line: plot distance cutoff line
14+
:type cutoff_line: boolean
15+
:param value: dendrogram distance for cutoff line
16+
:type value: float or int
17+
:param orientation: 'top', 'right', 'bottom', or 'left'
18+
:type orientation: str
19+
:param hang: dendrogram distance of leaf lines
20+
:type hang: float
21+
:param hide_labels: show leaf labels
22+
:type hide_labels: boolean
23+
:param labels: List of axis category labels(observation labels)
24+
:type labels: list
25+
:param colorscale: Optional colorscale for dendrogram tree
26+
:type colorscale: list
27+
:param hovertext: List of hovertext for constituent traces of dendrogram
28+
clusters
29+
:type hovertext: list[list]
30+
:param color_threshold: Value at which the separation of clusters will be made
31+
:type color_threshold: double
32+
:return: Plotly figure object
33+
34+
Example::
35+
36+
figure = plot_dendrogram(dendro_tree, hang=0.9, cutoff_line=False)
37+
"""
38+
39+
dendrogram = Dendrogram(Z_dendrogram, orientation, hang, hide_labels, labels, colorscale, hovertext=hovertext, color_threshold=color_threshold)
40+
41+
if cutoff_line == True:
42+
dendrogram.layout.update({'shapes':[{'type':'line',
43+
'xref':'paper',
44+
'yref':'y',
45+
'x0':0, 'y0':value,
46+
'x1':1, 'y1':value,
47+
'line':{'color':'red'}}]})
48+
49+
figure = dict(data=dendrogram.data, layout=dendrogram.layout)
50+
figure['layout']['template'] = 'plotly_white'
51+
52+
return figure
53+
54+
class Dendrogram(object):
55+
"""Refer to plot_dendrogram() for docstring."""
56+
def __init__(self, Z_dendrogram, orientation='bottom', hang=1, hide_labels=False, labels=None, colorscale=None, hovertext=None,
57+
color_threshold=None, width=np.inf, height=np.inf, xaxis='xaxis', yaxis='yaxis'):
58+
self.orientation = orientation
59+
self.labels = labels
60+
self.xaxis = xaxis
61+
self.yaxis = yaxis
62+
self.data = []
63+
self.leaves = []
64+
self.sign = {self.xaxis: 1, self.yaxis: 1}
65+
self.layout = {self.xaxis: {}, self.yaxis: {}}
66+
67+
if self.orientation in ['left', 'bottom']:
68+
self.sign[self.xaxis] = 1
69+
else:
70+
self.sign[self.xaxis] = -1
71+
72+
if self.orientation in ['right', 'bottom']:
73+
self.sign[self.yaxis] = 1
74+
else:
75+
self.sign[self.yaxis] = -1
76+
77+
(dd_traces, xvals, yvals,
78+
ordered_labels, leaves) = self.get_dendrogram_traces(Z_dendrogram, hang, colorscale,
79+
hovertext,
80+
color_threshold)
81+
82+
self.labels = ordered_labels
83+
self.leaves = leaves
84+
yvals_flat = yvals.flatten()
85+
xvals_flat = xvals.flatten()
86+
87+
self.zero_vals = []
88+
89+
for i in range(len(yvals_flat)):
90+
if yvals_flat[i] == 0.0 and xvals_flat[i] not in self.zero_vals:
91+
self.zero_vals.append(xvals_flat[i])
92+
93+
if len(self.zero_vals) > len(yvals) + 1:
94+
l_border = int(min(self.zero_vals))
95+
r_border = int(max(self.zero_vals))
96+
correct_leaves_pos = range(l_border,
97+
r_border + 1,
98+
int((r_border - l_border) / len(yvals)))
99+
self.zero_vals = [v for v in correct_leaves_pos]
100+
101+
self.zero_vals.sort()
102+
self.layout = self.set_figure_layout(width, height, hide_labels=hide_labels)
103+
self.data = dd_traces
104+
105+
def get_color_dict(self, colorscale):
106+
"""
107+
Returns colorscale used for dendrogram tree clusters.
108+
109+
:param colorscale: colors to use for the plot in rgb format
110+
:type colorscale: list
111+
:return (dict): default colors mapped to the user colorscale
112+
"""
113+
114+
# These are the color codes returned for dendrograms
115+
# We're replacing them with nicer colors
116+
d = {'r': 'red',
117+
'g': 'green',
118+
'b': 'blue',
119+
'c': 'cyan',
120+
'm': 'magenta',
121+
'y': 'yellow',
122+
'k': 'black',
123+
'w': 'white'}
124+
default_colors = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
125+
126+
if colorscale is None:
127+
colorscale = [
128+
'rgb(0,116,217)', # blue
129+
'rgb(35,205,205)', # cyan
130+
'rgb(61,153,112)', # green
131+
'rgb(40,35,35)', # black
132+
'rgb(133,20,75)', # magenta
133+
'rgb(255,65,54)', # red
134+
'rgb(255,255,255)', # white
135+
'rgb(255,220,0)'] # yellow
136+
137+
for i in range(len(default_colors.keys())):
138+
k = list(default_colors.keys())[i] # PY3 won't index keys
139+
if i < len(colorscale):
140+
default_colors[k] = colorscale[i]
141+
142+
return default_colors
143+
144+
def set_axis_layout(self, axis_key, hide_labels):
145+
"""
146+
Sets and returns default axis object for dendrogram figure.
147+
148+
:param axis_key: E.g., 'xaxis', 'xaxis1', 'yaxis', yaxis1', etc.
149+
:type axis_key: str
150+
:return (dict): An axis_key dictionary with set parameters.
151+
"""
152+
axis_defaults = {
153+
'type': 'linear',
154+
'ticks': 'outside',
155+
'mirror': 'allticks',
156+
'rangemode': 'tozero',
157+
'showticklabels': True,
158+
'zeroline': False,
159+
'showgrid': False,
160+
'showline': True,
161+
}
162+
163+
if len(self.labels) != 0:
164+
axis_key_labels = self.xaxis
165+
if self.orientation in ['left', 'right']:
166+
axis_key_labels = self.yaxis
167+
if axis_key_labels not in self.layout:
168+
self.layout[axis_key_labels] = {}
169+
self.layout[axis_key_labels]['tickvals'] = \
170+
[zv*self.sign[axis_key] for zv in self.zero_vals]
171+
self.layout[axis_key_labels]['ticktext'] = self.labels
172+
self.layout[axis_key_labels]['tickmode'] = 'array'
173+
174+
self.layout[axis_key].update(axis_defaults)
175+
176+
if hide_labels == True:
177+
self.layout[axis_key].update({'showticklabels': False})
178+
else: pass
179+
180+
return self.layout[axis_key]
181+
182+
def set_figure_layout(self, width, height, hide_labels):
183+
"""
184+
Sets and returns default layout object for dendrogram figure.
185+
186+
:param width: plot width
187+
:type width: int
188+
:param height: plot height
189+
:type height: int
190+
:param hide_labels: show leaf labels
191+
:type hide_labels: boolean
192+
:return: Plotly layout
193+
"""
194+
self.layout.update({
195+
'showlegend': False,
196+
'autosize': False,
197+
'hovermode': 'closest',
198+
'width': width,
199+
'height': height
200+
})
201+
202+
self.set_axis_layout(self.xaxis, hide_labels=hide_labels)
203+
self.set_axis_layout(self.yaxis, hide_labels=False)
204+
205+
return self.layout
206+
207+
208+
def get_dendrogram_traces(self, Z_dendrogram, hang, colorscale, hovertext, color_threshold):
209+
"""
210+
Calculates all the elements needed for plotting a dendrogram.
211+
212+
:param Z_dendrogram: Matrix of observations as array of arrays
213+
:type Z_dendrogram: ndarray
214+
:param hang: dendrogram distance of leaf lines
215+
:type hang: float
216+
:param colorscale: Color scale for dendrogram tree clusters
217+
:type colorscale: list
218+
:param hovertext: List of hovertext for constituent traces of dendrogram
219+
:type hovertext: list
220+
:return (tuple): Contains all the traces in the following order:
221+
222+
a. trace_list: List of Plotly trace objects for dendrogram tree
223+
b. icoord: All X points of the dendrogram tree as array of arrays with length 4
224+
c. dcoord: All Y points of the dendrogram tree as array of arrays with length 4
225+
d. ordered_labels: leaf labels in the order they are going to appear on the plot
226+
e. Z_dendrogram['leaves']: left-to-right traversal of the leaves
227+
"""
228+
icoord = scp.array(Z_dendrogram['icoord'])
229+
dcoord = scp.array(Z_dendrogram['dcoord'])
230+
ordered_labels = scp.array(Z_dendrogram['ivl'])
231+
color_list = scp.array(Z_dendrogram['color_list'])
232+
colors = self.get_color_dict(colorscale)
233+
234+
trace_list = []
235+
236+
for i in range(len(icoord)):
237+
if self.orientation in ['top', 'bottom']:
238+
xs = icoord[i]
239+
else:
240+
xs = dcoord[i]
241+
242+
if self.orientation in ['top', 'bottom']:
243+
ys = dcoord[i]
244+
else:
245+
ys = icoord[i]
246+
color_key = color_list[i]
247+
hovertext_label = None
248+
if hovertext:
249+
hovertext_label = hovertext[i]
250+
251+
coord = [list(a) for a in zip(xs, ys)]
252+
x_coord = []
253+
y_coord = []
254+
y_at_x = {}
255+
for n, seg in enumerate(coord):
256+
x, y = seg
257+
if y > 0 and y < y_at_x.get(x, np.inf):
258+
y_at_x[x] = y
259+
for n, seg in enumerate(coord):
260+
x, y = seg
261+
if y == 0:
262+
y = max(0, y_at_x.get(x, 0) - hang)
263+
x_coord.append(x)
264+
y_coord.append(y)
265+
266+
trace = dict(
267+
type='scattergl',
268+
x=np.multiply(self.sign[self.xaxis], x_coord),
269+
y=np.multiply(self.sign[self.yaxis], y_coord),
270+
mode='lines',
271+
marker=dict(color='rgb(40,35,35)'),
272+
line=dict(color='rgb(40,35,35)', width=1), #dict(color=colors[color_key]),
273+
text=hovertext_label,
274+
hoverinfo='text')
275+
276+
try:
277+
x_index = int(self.xaxis[-1])
278+
except ValueError:
279+
x_index = ''
280+
281+
try:
282+
y_index = int(self.yaxis[-1])
283+
except ValueError:
284+
y_index = ''
285+
286+
trace['xaxis'] = 'x' + x_index
287+
trace['yaxis'] = 'y' + y_index
288+
289+
trace_list.append(trace)
290+
291+
return trace_list, icoord, dcoord, ordered_labels, Z_dendrogram['leaves']

vcore/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)