Merge branch 'hier_low_data_cw-7275' into 'dev'
Clustering plots low data [CW-7275] See merge request epi2melabs/workflows/wf-transcriptomes!298
This commit is contained in:
commit
da5f78497e
@ -1,10 +1,10 @@
|
|||||||
"""Hierarchical clustering heatmap plots."""
|
"""Hierarchical clustering heatmap plots."""
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from bokeh.layouts import column as bokeh_column, row as bokeh_row
|
from bokeh.layouts import column as bokeh_column, row as bokeh_row
|
||||||
from bokeh.models import (
|
from bokeh.models import (
|
||||||
ColorBar,
|
ColorBar,
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
Div,
|
|
||||||
FixedTicker,
|
FixedTicker,
|
||||||
HoverTool,
|
HoverTool,
|
||||||
LinearColorMapper,
|
LinearColorMapper,
|
||||||
@ -122,19 +122,10 @@ def _dendrogram_source(linked, orientation):
|
|||||||
return ColumnDataSource({"xs": xs, "ys": ys})
|
return ColumnDataSource({"xs": xs, "ys": ys})
|
||||||
|
|
||||||
|
|
||||||
def _empty_plot(message):
|
|
||||||
"""Return a BokehPlot containing a message instead of a heatmap."""
|
|
||||||
plot = BokehPlot()
|
|
||||||
plot._fig = Div(text=message)
|
|
||||||
return plot
|
|
||||||
|
|
||||||
|
|
||||||
def _sample_pca(matrix, sample_names):
|
def _sample_pca(matrix, sample_names):
|
||||||
"""Project samples onto the first two principal components."""
|
"""Project samples onto the first two principal components."""
|
||||||
sample_matrix = np.asarray(matrix, dtype=float).T
|
sample_matrix = np.asarray(matrix, dtype=float).T
|
||||||
centered = sample_matrix - sample_matrix.mean(axis=0, keepdims=True)
|
centered = sample_matrix - sample_matrix.mean(axis=0, keepdims=True)
|
||||||
if centered.shape[0] < 2 or centered.shape[1] == 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
u, singular_values, _ = np.linalg.svd(centered, full_matrices=False)
|
u, singular_values, _ = np.linalg.svd(centered, full_matrices=False)
|
||||||
scores = u * singular_values
|
scores = u * singular_values
|
||||||
@ -543,6 +534,16 @@ def pca_plot(matrix, col_order, sample_names, sample_metadata, condition_column)
|
|||||||
return pca_and_legend
|
return pca_and_legend
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ClusteringResult:
|
||||||
|
"""Container for hierarchical clustering results."""
|
||||||
|
|
||||||
|
heatmap: object | None # noqa: NT001
|
||||||
|
pca: object | None # noqa: NT001
|
||||||
|
distance: object | None # noqa: NT001
|
||||||
|
error: str | None = None # noqa: NT001
|
||||||
|
|
||||||
|
|
||||||
def hierarchical(
|
def hierarchical(
|
||||||
data,
|
data,
|
||||||
id_column,
|
id_column,
|
||||||
@ -559,11 +560,15 @@ def hierarchical(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if log2_matrix.shape[0] < 2 or log2_matrix.shape[1] < 2:
|
if log2_matrix.shape[0] < 2 or log2_matrix.shape[1] < 2:
|
||||||
return _empty_plot(
|
return ClusteringResult(
|
||||||
"Hierarchical clustering requires at least two features and "
|
heatmap=None,
|
||||||
"two numeric sample columns."
|
pca=None,
|
||||||
|
distance=None,
|
||||||
|
error=(
|
||||||
|
"Generation of clustering plots requires at least two features "
|
||||||
|
"and two sample columns."
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
log2_matrix = np.log2(log2_matrix + 1)
|
log2_matrix = np.log2(log2_matrix + 1)
|
||||||
log2_matrix, labels = _top_variable_rows(log2_matrix, labels, top_n=top_n)
|
log2_matrix, labels = _top_variable_rows(log2_matrix, labels, top_n=top_n)
|
||||||
log2_z_matrix = _row_zscore(log2_matrix)
|
log2_z_matrix = _row_zscore(log2_matrix)
|
||||||
@ -601,4 +606,8 @@ def hierarchical(
|
|||||||
height=hm_height
|
height=hm_height
|
||||||
)
|
)
|
||||||
|
|
||||||
return heatmap_plt, pca_plt, distance_plt
|
return ClusteringResult(
|
||||||
|
heatmap=heatmap_plt,
|
||||||
|
pca=pca_plt,
|
||||||
|
distance=distance_plt
|
||||||
|
)
|
||||||
|
|||||||
@ -1054,17 +1054,21 @@ def main(args):
|
|||||||
_create_warning_banner(
|
_create_warning_banner(
|
||||||
"Cohort gene CPM table is missing or empty. ")
|
"Cohort gene CPM table is missing or empty. ")
|
||||||
else:
|
else:
|
||||||
heatmap, pca, dist = hierarchical(
|
hierarchical_result = hierarchical(
|
||||||
cohort_cpm["gene"],
|
cohort_cpm["gene"],
|
||||||
id_column="GENEID",
|
id_column="GENEID",
|
||||||
samples=cohort_samples,
|
samples=cohort_samples,
|
||||||
condition_column=condition_column,
|
condition_column=condition_column,
|
||||||
top_n=150,
|
top_n=150,
|
||||||
)
|
)
|
||||||
|
if hierarchical_result.error is not None:
|
||||||
|
_create_warning_banner(
|
||||||
|
hierarchical_result.error, level='warning')
|
||||||
|
else:
|
||||||
with div(cls="heatmap-table-grid"):
|
with div(cls="heatmap-table-grid"):
|
||||||
EZChart(heatmap, width="100%")
|
EZChart(hierarchical_result.heatmap, width="100%")
|
||||||
EZChart(pca, width="100%")
|
EZChart(hierarchical_result.pca, width="100%")
|
||||||
EZChart(dist, width="100%")
|
EZChart(hierarchical_result.distance, width="100%")
|
||||||
with div(cls="clustering-info"):
|
with div(cls="clustering-info"):
|
||||||
br()
|
br()
|
||||||
clustering_info('gene')
|
clustering_info('gene')
|
||||||
@ -1114,17 +1118,21 @@ def main(args):
|
|||||||
_create_warning_banner(
|
_create_warning_banner(
|
||||||
"Cohort transcript CPM table is missing or empty.")
|
"Cohort transcript CPM table is missing or empty.")
|
||||||
else:
|
else:
|
||||||
tx_heatmap, tx_pca, tx_dist = hierarchical(
|
hierarchical_result = hierarchical(
|
||||||
cohort_cpm["transcript"],
|
cohort_cpm["transcript"],
|
||||||
id_column="TXNAME",
|
id_column="TXNAME",
|
||||||
top_n=150,
|
top_n=150,
|
||||||
samples=cohort_samples,
|
samples=cohort_samples,
|
||||||
condition_column=condition_column
|
condition_column=condition_column
|
||||||
)
|
)
|
||||||
|
if hierarchical_result.error is not None:
|
||||||
|
_create_warning_banner(
|
||||||
|
hierarchical_result.error, level='warning')
|
||||||
|
else:
|
||||||
with div(cls="heatmap-table-grid"):
|
with div(cls="heatmap-table-grid"):
|
||||||
EZChart(tx_heatmap, width="100%")
|
EZChart(hierarchical_result.heatmap, width="100%")
|
||||||
EZChart(tx_pca, width="100%")
|
EZChart(hierarchical_result.pca, width="100%")
|
||||||
EZChart(tx_dist, width="100%")
|
EZChart(hierarchical_result.distance, width="100%")
|
||||||
with div(cls="clustering-info"):
|
with div(cls="clustering-info"):
|
||||||
br()
|
br()
|
||||||
clustering_info('transcript')
|
clustering_info('transcript')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user