Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Figures of components with index 0 get rendered now #793

Merged
merged 6 commits into from
Sep 14, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
216 changes: 132 additions & 84 deletions tedana/reporting/dynamic_figures.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import numpy as np
from math import pi

import numpy as np
import pandas as pd
from bokeh import events, models, plotting, transform
from sklearn.preprocessing import MinMaxScaler
from bokeh import (events, models, plotting, transform)

color_mapping = {'accepted': '#2ecc71',
'rejected': '#e74c3c',
'ignored': '#3498db'}
color_mapping = {"accepted": "#2ecc71", "rejected": "#e74c3c", "ignored": "#3498db"}

tap_callback_jscode = """
// Accessing the selected component ID
var data = source_comp_table.data;
var selected_idx = source_comp_table.selected.indices;
if(selected_idx > 0) {
console.log('Selected idx is ' + selected_idx)
if(selected_idx >= 0) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsalo This is the main contribution for what I recall.

// A component has been selected
// -----------------------------
var components = data['component']
Expand Down Expand Up @@ -68,56 +68,68 @@ def _create_data_struct(comptable_path, color_mapping=color_mapping):
cds: bokeh.models.ColumnDataSource
Data structure with all the fields to plot or hover over
"""
unused_cols = ['normalized variance explained',
'countsigFT2', 'countsigFS0',
'dice_FS0', 'countnoise', 'dice_FT2',
'signal-noise_t', 'signal-noise_p',
'd_table_score', 'kappa ratio',
'rationale', 'd_table_score_scrub']
unused_cols = [
"normalized variance explained",
"countsigFT2",
"countsigFS0",
"dice_FS0",
"countnoise",
"dice_FT2",
"signal-noise_t",
"signal-noise_p",
"d_table_score",
"kappa ratio",
"rationale",
"d_table_score_scrub",
]

df = pd.read_table(comptable_path)
n_comps = df.shape[0]

# remove space from column name
df.rename(columns={'variance explained': 'var_exp'}, inplace=True)
df.rename(columns={"variance explained": "var_exp"}, inplace=True)

# For providing sizes based on Var Explained that are visible
mm_scaler = MinMaxScaler(feature_range=(4, 20))
df['var_exp_size'] = mm_scaler.fit_transform(
df[['var_exp', 'normalized variance explained']])[:, 0]
df["var_exp_size"] = mm_scaler.fit_transform(
df[["var_exp", "normalized variance explained"]]
)[:, 0]

# Calculate Kappa and Rho ranks
df['rho_rank'] = df['rho'].rank(ascending=False).values
df['kappa_rank'] = df['kappa'].rank(ascending=False).values
df['var_exp_rank'] = df['var_exp'].rank(ascending=False).values
df["rho_rank"] = df["rho"].rank(ascending=False).values
df["kappa_rank"] = df["kappa"].rank(ascending=False).values
df["var_exp_rank"] = df["var_exp"].rank(ascending=False).values

# Remove unused columns to decrease size of final HTML
# set errors to 'ignore' in case some columns do not exist in
# a given data frame
df.drop(unused_cols, axis=1, inplace=True, errors='ignore')
df.drop(unused_cols, axis=1, inplace=True, errors="ignore")

# Create additional Column with colors based on final classification
df['color'] = [color_mapping[i] for i in df['classification']]
df["color"] = [color_mapping[i] for i in df["classification"]]

# Create additional column with component ID
df['component'] = np.arange(n_comps)
df["component"] = np.arange(n_comps)

# Compute angle and re-sort data for Pie plots
df['angle'] = df['var_exp'] / df['var_exp'].sum() * 2 * pi
df.sort_values(by=['classification', 'var_exp'], inplace=True)

cds = models.ColumnDataSource(data=dict(
kappa=df['kappa'],
rho=df['rho'],
varexp=df['var_exp'],
kappa_rank=df['kappa_rank'],
rho_rank=df['rho_rank'],
varexp_rank=df['var_exp_rank'],
component=[str(i) for i in df['component']],
color=df['color'],
size=df['var_exp_size'],
classif=df['classification'],
angle=df['angle']))
df["angle"] = df["var_exp"] / df["var_exp"].sum() * 2 * pi
df.sort_values(by=["classification", "var_exp"], inplace=True)

cds = models.ColumnDataSource(
data=dict(
kappa=df["kappa"],
rho=df["rho"],
varexp=df["var_exp"],
kappa_rank=df["kappa_rank"],
rho_rank=df["rho_rank"],
varexp_rank=df["var_exp_rank"],
component=[str(i) for i in df["component"]],
color=df["color"],
size=df["var_exp_size"],
classif=df["classification"],
angle=df["angle"],
)
)

return cds

Expand All @@ -137,28 +149,43 @@ def _create_kr_plt(comptable_cds):
Bokeh scatter plot of kappa vs. rho
"""
# Create Panel for the Kappa - Rho Scatter
kr_hovertool = models.HoverTool(tooltips=[('Component ID', '@component'),
('Kappa', '@kappa{0.00}'),
('Rho', '@rho{0.00}'),
('Var. Expl.', '@varexp{0.00}%')])
fig = plotting.figure(plot_width=400, plot_height=400,
tools=["tap,wheel_zoom,reset,pan,crosshair,save", kr_hovertool],
title="Kappa / Rho Plot")
diagonal = models.Slope(gradient=1, y_intercept=0, line_color='#D3D3D3')
kr_hovertool = models.HoverTool(
tooltips=[
("Component ID", "@component"),
("Kappa", "@kappa{0.00}"),
("Rho", "@rho{0.00}"),
("Var. Expl.", "@varexp{0.00}%"),
]
)
fig = plotting.figure(
plot_width=400,
plot_height=400,
tools=["tap,wheel_zoom,reset,pan,crosshair,save", kr_hovertool],
title="Kappa / Rho Plot",
)
diagonal = models.Slope(gradient=1, y_intercept=0, line_color="#D3D3D3")
fig.add_layout(diagonal)
fig.circle('kappa', 'rho', size='size', color='color', alpha=0.5, source=comptable_cds,
legend_group='classif')
fig.xaxis.axis_label = 'Kappa'
fig.yaxis.axis_label = 'Rho'
fig.circle(
"kappa",
"rho",
size="size",
color="color",
alpha=0.5,
source=comptable_cds,
legend_group="classif",
)
fig.xaxis.axis_label = "Kappa"
fig.yaxis.axis_label = "Rho"
fig.toolbar.logo = None
fig.legend.background_fill_alpha = 0.5
fig.legend.orientation = 'horizontal'
fig.legend.location = 'bottom_right'
fig.legend.orientation = "horizontal"
fig.legend.location = "bottom_right"
return fig


def _create_sorted_plt(comptable_cds, n_comps, x_var, y_var, title=None,
x_label=None, y_label=None):
def _create_sorted_plt(
comptable_cds, n_comps, x_var, y_var, title=None, x_label=None, y_label=None
):
"""
Create dynamic sorted plots

Expand Down Expand Up @@ -187,18 +214,26 @@ def _create_sorted_plt(comptable_cds, n_comps, x_var, y_var, title=None,
fig: bokeh.plotting.figure.Figure
Bokeh plot of components ranked by a given feature
"""
hovertool = models.HoverTool(tooltips=[('Component ID', '@component'),
('Kappa', '@kappa{0.00}'),
('Rho', '@rho{0.00}'),
('Var. Expl.', '@varexp{0.00}%')])
fig = plotting.figure(plot_width=400, plot_height=400,
tools=["tap,wheel_zoom,reset,pan,crosshair,save", hovertool],
title=title)
fig.line(x=np.arange(1, n_comps + 1),
y=comptable_cds.data[y_var].sort_values(ascending=False).values,
color='black')
fig.circle(x_var, y_var, source=comptable_cds,
size=5, color='color', alpha=0.7)
hovertool = models.HoverTool(
tooltips=[
("Component ID", "@component"),
("Kappa", "@kappa{0.00}"),
("Rho", "@rho{0.00}"),
("Var. Expl.", "@varexp{0.00}%"),
]
)
fig = plotting.figure(
plot_width=400,
plot_height=400,
tools=["tap,wheel_zoom,reset,pan,crosshair,save", hovertool],
title=title,
)
fig.line(
x=np.arange(1, n_comps + 1),
y=comptable_cds.data[y_var].sort_values(ascending=False).values,
color="black",
)
fig.circle(x_var, y_var, source=comptable_cds, size=5, color="color", alpha=0.7)
fig.xaxis.axis_label = x_label
fig.yaxis.axis_label = y_label
fig.x_range = models.Range1d(-1, n_comps + 1)
Expand All @@ -208,22 +243,34 @@ def _create_sorted_plt(comptable_cds, n_comps, x_var, y_var, title=None,


def _create_varexp_pie_plt(comptable_cds, n_comps):
fig = plotting.figure(plot_width=400, plot_height=400, title='Variance Explained View',
tools=['hover,tap,save'],
tooltips=[('Component ID', ' @component'),
('Kappa', '@kappa{0.00}'),
('Rho', '@rho{0.00}'),
('Var. Exp.', '@varexp{0.00}%')])
fig.wedge(x=0, y=1, radius=.9,
start_angle=transform.cumsum('angle', include_zero=True),
end_angle=transform.cumsum('angle'),
line_color="white",
fill_color='color', source=comptable_cds, fill_alpha=0.7)
fig = plotting.figure(
plot_width=400,
plot_height=400,
title="Variance Explained View",
tools=["hover,tap,save"],
tooltips=[
("Component ID", " @component"),
("Kappa", "@kappa{0.00}"),
("Rho", "@rho{0.00}"),
("Var. Exp.", "@varexp{0.00}%"),
],
)
fig.wedge(
x=0,
y=1,
radius=0.9,
start_angle=transform.cumsum("angle", include_zero=True),
end_angle=transform.cumsum("angle"),
line_color="white",
fill_color="color",
source=comptable_cds,
fill_alpha=0.7,
)
fig.axis.visible = False
fig.grid.visible = False
fig.toolbar.logo = None

circle = models.Circle(x=0, y=1, size=150, fill_color='white', line_color='white')
circle = models.Circle(x=0, y=1, size=150, fill_color="white", line_color="white")
fig.add_glyph(circle)

return fig
Expand All @@ -248,10 +295,14 @@ def _tap_callback(comptable_cds, div_content, io_generator):
CustomJS: bokeh.models.CustomJS
Javascript function that adds the tapping functionality
"""
return models.CustomJS(args=dict(source_comp_table=comptable_cds,
div=div_content,
outdir=io_generator.out_dir),
code=tap_callback_jscode)
return models.CustomJS(
args=dict(
source_comp_table=comptable_cds,
div=div_content,
outdir=io_generator.out_dir,
),
code=tap_callback_jscode,
)


def _link_figures(fig, comptable_ds, div_content, io_generator):
Expand Down Expand Up @@ -280,8 +331,5 @@ def _link_figures(fig, comptable_ds, div_content, io_generator):
its Tap event.

"""
fig.js_on_event(events.Tap,
_tap_callback(comptable_ds,
div_content,
io_generator))
fig.js_on_event(events.Tap, _tap_callback(comptable_ds, div_content, io_generator))
return fig
18 changes: 11 additions & 7 deletions tedana/reporting/html_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ def _generate_buttons(out_dir):
with open(str(buttons_template_path), "r") as buttons_file:
buttons_tpl = Template(buttons_file.read())

buttons_html = buttons_tpl.substitute(optcomdisp=optcom_nogsr_disp,
denoiseddisp=denoised_mir_disp,
accepteddisp=accepted_mir_disp,
optcomname=optcom_name,
denoisedname=denoised_name,
acceptedname=accepted_name)
buttons_html = buttons_tpl.substitute(
optcomdisp=optcom_nogsr_disp,
denoiseddisp=denoised_mir_disp,
accepteddisp=accepted_mir_disp,
optcomname=optcom_name,
denoisedname=denoised_name,
acceptedname=accepted_name,
)

return buttons_html

Expand All @@ -69,7 +71,9 @@ def _update_template_bokeh(bokeh_id, about, bokeh_js, buttons):
body_template_path = resource_path.joinpath(body_template_name)
with open(str(body_template_path), "r") as body_file:
body_tpl = Template(body_file.read())
body = body_tpl.substitute(content=bokeh_id, about=about, javascript=bokeh_js, buttons=buttons)
body = body_tpl.substitute(
content=bokeh_id, about=about, javascript=bokeh_js, buttons=buttons
)
return body


Expand Down