Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cdci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand Down
20 changes: 13 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ dynamic = ["version"]
description = "A Python package for plotting related to multimodal molecular data. Works with acore."
license = { text = "GNU General Public License v3" }
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.9,<3.13"
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
Expand All @@ -27,12 +27,16 @@ dependencies = [
"beautifulsoup4",
"requests",
"dash", # from dash import html
# "networkx",
"networkx",
"matplotlib",
# "cy-jupyterlab",
# "nltk",
# "webweb"
# "acore",
"kaleido",
"pyvis",
"wordcloud",
"cyjupyter",
"nltk",
"webweb",
"acore",
"dash-cytoscape",
]

[project.optional-dependencies]
Expand Down Expand Up @@ -64,5 +68,7 @@ Documentation = "https://analytics-core.readthedocs.io/"


[build-system]
requires = ["setuptools"]
requires = ["setuptools", "setuptools_scm>=8"]
build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
3 changes: 2 additions & 1 deletion src/vuecore/Dendrogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ def plot_dendrogram(
color_threshold=None,
):
"""
Modified version of Plotly _dendrogram.py that returns a dendrogram Plotly figure object with cutoff line.
Modified version of Plotly _dendrogram.py that
returns a dendrogram Plotly figure object with cutoff line.

:param Z_dendrogram: Matrix of observations as array of arrays
:type Z_dendrogram: ndarray
Expand Down
20 changes: 20 additions & 0 deletions src/vuecore/linkers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from io import StringIO

import requests


def get_clustergrammer_link(net, filename=None):
clustergrammer_url = "http://amp.pharm.mssm.edu/clustergrammer/matrix_upload/"
if filename is None:
file_string = net.write_matrix_to_tsv()
file_obj = StringIO(file_string)
if "filename" not in net.dat or net.dat["filename"] is None:
fake_filename = "Network.txt"
else:
fake_filename = net.dat["filename"]
r = requests.post(clustergrammer_url, files={"file": (fake_filename, file_obj)})
else:
file_obj = open(filename, "r")
r = requests.post(clustergrammer_url, files={"file": file_obj})
link = r.text
return link
20 changes: 20 additions & 0 deletions src/vuecore/translate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import base64
import io

from dash import html


def hex2rgb(color):
_hex = color.lstrip("#")
rgb = tuple(int(_hex[i : i + 2], 16) for i in (0, 2, 4))
rgba = rgb + (0.6,)
return rgba


def mpl_to_html_image(plot, width=800):
buf = io.BytesIO()
plot.savefig(buf, format="png")
data = base64.b64encode(buf.getbuffer()).decode("utf8")
figure = html.Img(src="data:image/png;base64,{}".format(data), width=f"{width}")

return figure
20 changes: 1 addition & 19 deletions src/vuecore/utils.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import base64
import io
import random
from collections import defaultdict
from urllib import error

import bs4 as bs
import dash_html_components as html
import networkx as nx
import pandas as pd
import requests
from Bio import Entrez, Medline
from dash import html
from networkx.readwrite import json_graph

# TODO: This should probably be changed to the email of the person installing ckg?
Expand All @@ -23,15 +21,6 @@ def check_columns(df, cols):
return True


def mpl_to_html_image(plot, width=800):
buf = io.BytesIO()
plot.savefig(buf, format="png")
data = base64.b64encode(buf.getbuffer()).decode("utf8")
figure = html.Img(src="data:image/png;base64,{}".format(data), width="800")

return figure


def generate_html(network):
"""
This method gets the data structures supporting the nodes, edges,
Expand Down Expand Up @@ -281,13 +270,6 @@ def __extract_style(el):
return getattr(html, name.title())(contents, style=style)


def hex2rgb(color):
hex = color.lstrip("#")
rgb = tuple(int(hex[i : i + 2], 16) for i in (0, 2, 4))
rgba = rgb + (0.6,)
return rgba


def get_rgb_colors(n):
colors = []
r = int(random.random() * 256)
Expand Down
55 changes: 29 additions & 26 deletions src/vuecore/viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
import plotly.io as pio
import plotly.subplots as tools
import plotly.tools as tls
from ckg.analytics_core import utils
from ckg.analytics_core.analytics import analytics, wgcnaAnalysis
from ckg.analytics_core.viz import Dendrogram, wgcnaFigures
from acore import network_analysis, wgcna_analysis
from cyjupyter import Cytoscape
from dash import dash_table, dcc, html
from networkx.readwrite import json_graph
Expand All @@ -33,6 +31,10 @@
from webweb import Web
from wordcloud import STOPWORDS, WordCloud

from . import dendrogram, utils, wgcna
from .linkers import get_clustergrammer_link
from .translate import hex2rgb, mpl_to_html_image

# matplotlib.use("Agg")


Expand Down Expand Up @@ -99,6 +101,7 @@ def get_markdown(text, args={}):
"""
Converts a given text into a Dash Markdown component. It includes a syntax for things
like bold text and italics, links, inline code snippets, lists, quotes, and more.

For more information visit https://dash.plot.ly/dash-core-components/markdown.

:param str text: markdown string (or array of strings) that adhreres to the CommonMark spec.
Expand Down Expand Up @@ -663,7 +666,7 @@ def get_scatterplot_matrix(data, identifier, args):
for g in data[group].unique():
gdata = data[data[group] == g].dropna()
gfig = get_simple_scatterplot(gdata, identifier + "_" + str(g), args)
trace = gfig.figure["data"].pop()
trace = gfig["data"].pop()
trace.name = g
fig.append_trace(trace, r, c)

Expand All @@ -688,7 +691,7 @@ def get_scatterplot_matrix(data, identifier, args):
dict(xref="paper", yref="paper", showarrow=False, text="")
]

return dcc.Graph(id=identifier, figure=fig)
return fig


def get_simple_scatterplot(data, identifier, args):
Expand Down Expand Up @@ -779,7 +782,7 @@ def get_simple_scatterplot(data, identifier, args):
template="plotly_white",
)

return dcc.Graph(id=identifier, figure=figure)
return figure


def get_scatterplot(data, identifier, args):
Expand Down Expand Up @@ -914,7 +917,7 @@ def get_scatterplot(data, identifier, args):
template="plotly_white",
)

return dcc.Graph(id=identifier, figure=figure)
return figure


def get_density(x: np.ndarray, y: np.ndarray):
Expand Down Expand Up @@ -1716,7 +1719,7 @@ def get_network(data, identifier, args):
max_node_size = max(degrees.values())
nx.set_node_attributes(graph, degrees, "radius")

clusters = analytics.get_network_communities(graph, args)
clusters = network_analysis.get_network_communities(graph, args)
col = utils.get_hex_colors(len(set(clusters.values())))
colors = {n: col[clusters[n]] for n in clusters}
nx.set_node_attributes(graph, colors, "color")
Expand Down Expand Up @@ -1984,7 +1987,7 @@ def get_pca_plot(data, identifier, args):
figure = {}
traces = []
annotations = []
sct = get_scatterplot(pca_data, identifier, args).figure
sct = get_scatterplot(pca_data, identifier, args)
traces.extend(sct["data"])
figure["layout"] = sct["layout"]
factor = 50
Expand Down Expand Up @@ -2033,7 +2036,7 @@ def get_pca_plot(data, identifier, args):
figure["layout"].annotations = annotations
figure["layout"]["template"] = "plotly_white"

return dcc.Graph(id=identifier, figure=figure)
return figure


def get_sankey_plot(
Expand Down Expand Up @@ -2128,7 +2131,7 @@ def get_sankey_plot(
label=nodes,
color=[
(
"rgba" + str(utils.hex2rgb(node_colors[c]))
"rgba" + str(hex2rgb(node_colors[c]))
if node_colors[c].startswith("#")
else node_colors[c]
)
Expand All @@ -2140,7 +2143,7 @@ def get_sankey_plot(
target=[list(nodes).index(i) for i in data[args["target"]].tolist()],
value=data[args["weight"]].tolist(),
color=[
"rgba" + str(utils.hex2rgb(c)) if c.startswith("#") else c
"rgba" + str(hex2rgb(c)) if c.startswith("#") else c
for c in data[args["source_colors"]].tolist()
],
label=hover_data,
Expand Down Expand Up @@ -2413,7 +2416,7 @@ def get_clustergrammer_plot(data, identifier, args):
)
clustergrammer_net.load_df(data)

link = utils.get_clustergrammer_link(clustergrammer_net, filename=None)
link = get_clustergrammer_link(clustergrammer_net, filename=None)

iframe = html.Iframe(src=link, width=1000, height=900)

Expand Down Expand Up @@ -2510,7 +2513,7 @@ def get_WGCNAPlots(data, identifier):
) = data
plots = []
plots.append(
wgcnaFigures.plot_complex_dendrogram(
wgcna.plot_complex_dendrogram(
dissTOM,
moduleColors,
title="Co-expression: dendrogram and module colors",
Expand All @@ -2537,7 +2540,7 @@ def get_WGCNAPlots(data, identifier):
)
)
plots.append(
wgcnaFigures.plot_labeled_heatmap(
wgcna.plot_labeled_heatmap(
moduleTraitCor,
textMatrix,
title="Module-Clinical variable relationships",
Expand All @@ -2547,11 +2550,11 @@ def get_WGCNAPlots(data, identifier):
height=800,
)
)
dendro_tree = wgcnaAnalysis.get_dendrogram(
dendro_tree = wgcna_analysis.get_dendrogram(
METDiss, METDiss.index, distfun=None, linkagefun="ward", div_clusters=False
)
if dendro_tree is not None:
dendrogram = Dendrogram.plot_dendrogram(
dendrogram_ = dendrogram.plot_dendrogram(
dendro_tree, hang=0.9, cutoff_line=False
)

Expand All @@ -2563,8 +2566,8 @@ def get_WGCNAPlots(data, identifier):
xaxis=dict(
domain=[0, 1],
range=[
np.min(dendrogram["layout"]["xaxis"]["tickvals"]) - 6,
np.max(dendrogram["layout"]["xaxis"]["tickvals"]) + 4,
np.min(dendrogram_["layout"]["xaxis"]["tickvals"]) - 6,
np.max(dendrogram_["layout"]["xaxis"]["tickvals"]) + 4,
],
showgrid=False,
zeroline=True,
Expand Down Expand Up @@ -2611,24 +2614,24 @@ def get_WGCNAPlots(data, identifier):
)
)
):
df = wgcnaAnalysis.get_percentiles_heatmap(
df = wgcna_analysis.get_percentiles_heatmap(
METcor, dendro_tree, bydendro=True, bycols=False
).T
else:
df = wgcnaAnalysis.df_sort_by_dendrogram(
wgcnaAnalysis.df_sort_by_dendrogram(METcor, dendro_tree).T,
df = wgcna_analysis.df_sort_by_dendrogram(
wgcna_analysis.df_sort_by_dendrogram(METcor, dendro_tree).T,
dendro_tree,
)

heatmap = wgcnaFigures.get_heatmap(
heatmap = wgcna.get_heatmap(
df,
colorscale=[[0, "#67a9cf"], [0.5, "#f7f7f7"], [1, "#ef8a62"]],
color_missing=False,
)

figure = tools.make_subplots(rows=2, cols=1, print_grid=False)

for i in list(dendrogram["data"]):
for i in list(dendrogram_["data"]):
figure.append_trace(i, 1, 1)
for j in list(heatmap["data"]):
figure.append_trace(j, 2, 1)
Expand Down Expand Up @@ -3271,7 +3274,7 @@ def get_km_plot(data, identifier, args):
plot.set_xlabel(xlabel)
plot.set_ylabel(ylabel)
if environment == "app":
figure = utils.mpl_to_html_image(plot.figure, width=800)
figure = mpl_to_html_image(plot.figure, width=800)
result = html.Div(id=identifier, children=[figure])
else:
result = plot.figure
Expand Down Expand Up @@ -3311,7 +3314,7 @@ def get_cumulative_hazard_plot(data, identifier, args):
plot.set_xlabel(xlabel)
plot.set_ylabel(ylabel)
if environment == "app":
figure = utils.mpl_to_html_image(plot.figure, width=800)
figure = mpl_to_html_image(plot.figure, width=800)
result = html.Div(id=identifier, children=[figure])
else:
result = plot.figure
Expand Down
Loading
Loading