Skip to content

Commit

Permalink
added formatting, added resolution None error catch
Browse files Browse the repository at this point in the history
  • Loading branch information
AdnanAbouelela committed Dec 5, 2024
1 parent 7afdf21 commit 7e91fcd
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 78 deletions.
6 changes: 2 additions & 4 deletions scripts/shinymerfish.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def _generate_traces(self) -> None:
for resolution in self.resolution_keys:
cluster_dict = {}
for cluster_id in np.unique(self.gdf[resolution]):
cluster = self.gdf.loc[self.gdf[resolution] == cluster_id, 'geometry']
cluster = self.gdf.loc[self.gdf[resolution] == cluster_id, 'geometry'].copy()
cluster = cluster.geometry.buffer(3).union_all().buffer(-3)

x_coords, y_coords = extract_polygon_coords(cluster)
Expand All @@ -122,6 +122,7 @@ def _generate_traces(self) -> None:
traces['cells'] = {'x': cells_x_coords, 'y': cells_y_coords}

self.traces = traces
self.sdata['table'].uns['traces'] = self.traces

def _differential_expression(self, resolutions: list) -> None:
"""Perform differential expression analysis for each resolution key."""
Expand All @@ -131,8 +132,5 @@ def _differential_expression(self, resolutions: list) -> None:

def _export(self, output_path: str) -> None:
"""Export the processed data to the output path."""

with open(os.path.join(output_path, self.sample + '_traces.json'), 'w') as f:
json.dump(self.traces, f)

self.sdata['table'].write_h5ad(os.path.join(output_path, self.sample + '.h5ad'))
14 changes: 6 additions & 8 deletions src/spaceolotl/fct/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

def plot_gene_expression(input):

spatial_data = get_data(input)
adata = get_data(input)
plot_genes = list(input.select_gene_expression())

if spatial_data is None or not plot_genes:
if adata is None or not plot_genes:
return

plot_ex = sc.pl.dotplot(spatial_data['a'],
plot_ex = sc.pl.dotplot(adata,
var_names = plot_genes,
swap_axes = True,
groupby = input.select_resolution(),
Expand All @@ -26,13 +26,11 @@ def plot_gene_expression(input):

def plot_de(input):

spatial_data = get_data(input)

if spatial_data is None:
return
if not (adata := get_data(input)):
return None

plot_de = sc.pl.rank_genes_groups_dotplot(
spatial_data['a'],
adata,
n_genes = input.slider_n_genes(),
key = 'rank_' + input.select_resolution(),
min_logfoldchange=input.slider_lfc(),
Expand Down
22 changes: 10 additions & 12 deletions src/spaceolotl/fct/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
from spaceolotl._constants import *

def get_data(input):
name = input.select_dataset()
if not name:
return None

try:
adata = sc.read_h5ad(os.path.join(DATA_DIR, name + '.h5ad'))
with open(os.path.join(DATA_DIR, name + '_traces.json'), 'r') as f:
traces = json.load(f)
return {'a': adata, 't': traces}

except (FileNotFoundError, IOError):
print("File not found")
return None
if not (name := input.select_dataset()):
return None

try:
adata = sc.read_h5ad(os.path.join(DATA_DIR, name + '.h5ad'))
return adata

except (FileNotFoundError, IOError):
print("File not found")
return None
36 changes: 18 additions & 18 deletions src/spaceolotl/fct/spatial_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@

def plot_space(input):

if not (spatial_data := get_data(input)):
if not get_data(input):
return None

fig = go.Figure()

fig.update_layout(
template="plotly_dark",
showlegend=True,
Expand All @@ -20,12 +19,10 @@ def plot_space(input):
xaxis=dict(title="[mm]"),
yaxis=dict(title="[mm]")
)

fig.update_xaxes(
tickvals=[-1000, 0, 1000],
ticktext=[-1, 0, 1]
)

fig.update_yaxes(
tickvals=[-1000, 0, 1000],
ticktext=[-1, 0, 1]
Expand All @@ -35,19 +32,21 @@ def plot_space(input):

def add_space_clusters(input, widget):

if not (spatial_data := get_data(input)):
if not (adata := get_data(input)):
return None

if not input.select_resolution():
return None

p = widget
p.data = [trace for trace in p.data if not trace.name.isdigit()]
widget.data = [trace for trace in widget.data if not trace.name.isdigit()]

if input.switch_clusters():

cluster_traces = spatial_data['t'].get(input.select_resolution(), {})
cluster_traces = adata.uns['traces'].get(input.select_resolution(), {})
colors = glasbey.create_palette(palette_size=len(cluster_traces), lightness_bounds=(50, 100))

for color, (cluster_id, cluster_trace) in zip(colors, cluster_traces.items()):
p.add_trace(
widget.add_trace(
go.Scatter(
x=cluster_trace['x'],
y=cluster_trace['y'],
Expand All @@ -61,15 +60,17 @@ def add_space_clusters(input, widget):

def add_space_outlines(input, widget):

if not (spatial_data := get_data(input)):
adata = get_data(input)

if adata is None:
return None

p = widget
p.data = [trace for trace in p.data if trace.name != 'cells']

if input.switch_outlines():

cell_traces = spatial_data['t']['cells']
cell_traces = adata.uns['traces']['cells']
p.add_trace(
go.Scatter(
name='cells',
Expand All @@ -82,20 +83,19 @@ def add_space_outlines(input, widget):

def add_space_expression(input, widget):

if not (spatial_data := get_data(input)):
if not (adata := get_data(input)):
return None

p = widget
p.data = [trace for trace in p.data if trace.name not in GENES_LABEL]
widget.data = [trace for trace in widget.data if trace.name not in GENES_LABEL]

if input.switch_expression() and input.select_gene():

gene_name = input.select_gene().split('-')[1]
gene_expression = np.array(spatial_data['a'][:,input.select_gene()].X.flatten())
x_coords = spatial_data['a'].obs['x']
y_coords = spatial_data['a'].obs['y']
gene_expression = np.array(adata[:,input.select_gene()].X.flatten())
x_coords = adata.obs['x']
y_coords = adata.obs['y']

p.add_trace(
widget.add_trace(
go.Scatter(
name = gene_name,
x = x_coords,
Expand Down
58 changes: 30 additions & 28 deletions src/spaceolotl/fct/umap_widget.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from shiny import ui
from spaceolotl.fct.load import get_data
from spaceolotl._constants import GENES_LABEL

Expand All @@ -7,9 +8,7 @@

def plot_umap(input):

spatial_data = get_data(input)

if spatial_data is None:
if not get_data(input):
return None

fig = go.Figure()
Expand All @@ -18,25 +17,25 @@ def plot_umap(input):
showlegend=False,
autosize=True,
scene=dict(
xaxis=dict(showgrid=False, showticklabels=False, title='', zeroline=False),
yaxis=dict(showgrid=False, showticklabels=False, title='', zeroline=False),
zaxis=dict(showgrid=False, showticklabels=False, title='', zeroline=False))
xaxis=dict(showgrid=False, showticklabels=False, title='', zeroline=False),
yaxis=dict(showgrid=False, showticklabels=False, title='', zeroline=False),
zaxis=dict(showgrid=False, showticklabels=False, title='', zeroline=False))
)

return fig

def add_umap_clusters(input, widget):
spatial_data = get_data(input)

if spatial_data is None:
return

if not (adata := get_data(input)):
return None

if not input.select_resolution():
return None

p = widget
p.data = [trace for trace in p.data if not trace.name.isdigit()]
widget.data = [trace for trace in widget.data if not trace.name.isdigit()]

if input.switch_clusters():

adata = spatial_data['a']
cluster_ids = np.unique(adata.obs[input.select_resolution()])
colors = glasbey.create_palette(palette_size=len(cluster_ids), lightness_bounds=(50, 100))

Expand All @@ -46,7 +45,7 @@ def add_umap_clusters(input, widget):
y_coords = adata.obsm['X_umap'][adata.obs[input.select_resolution()] == cluster_id, 1]
z_coords = adata.obsm['X_umap'][adata.obs[input.select_resolution()] == cluster_id, 2]

p.add_trace(
widget.add_trace(
go.Scatter3d(
name = cluster_id,
x = x_coords,
Expand All @@ -61,24 +60,21 @@ def add_umap_clusters(input, widget):
)

def add_umap_expression(input, widget):
spatial_data = get_data(input)

if spatial_data is None:
return
if not (adata := get_data(input)):
return None

adata = spatial_data['a']
p = widget
p.data = [trace for trace in p.data if trace.name not in GENES_LABEL]
widget.data = [trace for trace in widget.data if trace.name not in GENES_LABEL]

if input.switch_expression() and input.select_gene():

gene_name = input.select_gene().split('-')[1]
gene_expression = np.array(adata[:,input.select_gene()].X.flatten())
x_coords = adata.obsm['X_umap'][:,0]
y_coords = adata.obsm['X_umap'][:,1]
z_coords = adata.obsm['X_umap'][:,2]
x_coords = adata.obsm['X_umap'][:, 0]
y_coords = adata.obsm['X_umap'][:, 1]
z_coords = adata.obsm['X_umap'][:, 2]

p.add_trace(
widget.add_trace(
go.Scatter3d(
name = gene_name,
x = x_coords,
Expand All @@ -88,9 +84,15 @@ def add_umap_expression(input, widget):
marker=dict(
color = gene_expression,
colorscale = 'Viridis',
size = input.slider_dotsize_umap()
),


showscale = True,
size = input.slider_dotsize_umap(),
colorbar=dict(
orientation = 'h',
lenmode='fraction',
len=0.25,
thickness=10,
y = 0.05,
x = 0.15)
)
)
)
6 changes: 6 additions & 0 deletions src/spaceolotl/js/_format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from shiny import ui

DROPDOWN_CONFIG = ui.js_eval(
'{option: function(item, escape) {return "<div style=\\"font-size: 12px; padding: 5px; display: flex; justify-content: space-between; align-items: center;\\">" + escape(item.label) + "<span style=\\"flex-grow: 1;\\"></span></div>";},'
+ 'item: function(item, escape) {return "<div style=\\"font-size: 12px; display: flex; justify-content: space-between; align-items: center;\\">" + escape(item.label) + "<span style=\\"flex-grow: 1;\\"></span></div>";}}'
)
46 changes: 38 additions & 8 deletions src/spaceolotl/mod/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from shinywidgets import output_widget

from spaceolotl._constants import DATA, GENES, LEIDEN_RESOLUTIONS
from spaceolotl.js._format import DROPDOWN_CONFIG

app_ui = ui.page_navbar(

Expand All @@ -17,24 +18,53 @@
# Sidebar
ui.page_sidebar(
ui.sidebar(
ui.input_selectize("select_dataset", "Select dataset", ['', *DATA], selected = None),
ui.input_selectize("select_resolution", "Cluster resolution", LEIDEN_RESOLUTIONS),
ui.input_selectize(
"select_dataset",
"Select dataset",
['', *DATA],
selected = None,
options={
"render": DROPDOWN_CONFIG
}
),
ui.input_selectize(
"select_resolution",
"Cluster resolution",
LEIDEN_RESOLUTIONS,
),
ui.input_switch("switch_outlines", "Show cell outlines", False),
ui.input_switch("switch_clusters", "Show clusters", True),
ui.input_selectize("select_gene", "Select gene", ['', *GENES], selected = None),
ui.input_selectize(
"select_gene",
"Select gene",
['', *GENES],
selected=None,
options={
"render": DROPDOWN_CONFIG
}
),
ui.input_switch("switch_expression", "Plot gene expression", False),
ui.input_slider("slider_dotsize_umap", "Slider UMAP", 1, 20, 2),
ui.input_slider("slider_dotsize_space", "Slider Space", 1, 20, 2),
ui.input_selectize("select_gene_expression", "Select genes", ['', *GENES], selected = None, multiple = True),
ui.input_selectize(
"select_gene_expression",
"Select genes",
['', *GENES],
selected=None,
multiple=True,
options={
"render": DROPDOWN_CONFIG
}
),
ui.input_slider("slider_n_genes", "Slider nGenes", 1, 10, 3),
ui.input_slider("slider_lfc", "Slider minLFC", 0.5, 2.5, 0.5, step = 0.1)

),
ui.layout_columns(
ui.card(
ui.card_header("UMAP Projection"),
output_widget('plot_umap'),
full_screen = True),
ui.card(
ui.card_header("UMAP Projection"),
output_widget('plot_umap'),
full_screen = True),
ui.card(
ui.card_header("Spatial plot"),
output_widget("plot_space"),
Expand Down

0 comments on commit 7e91fcd

Please sign in to comment.