-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added html template for report * doc: initial commit of reporting template * doc: save out html for testing * fix: add missing bokeh js script * fix: unescape HTML ugly way * fix: add missing cdn's * enh: switch to generate_report structure * sty: switch back to pure CSS from bootstrap * fix: differently update template for content * sty: add jupyter notebooks to git ignore * enh:initial commit of dynamic plots * fix: patch unpaired bracket * enh:modularized dynamic kappa/rho plots * enh:docstrings added to KappaRho_DynPlot.py * Force figures default, fold viz into reporting module * enh:TS and Spectrum are now dynamic plots * sty: initial refactor of dynamic figures * fix: re-introduce func to load comp_table * sty: finalize rough refactor * fix: patch linting errors * doc: continue refactor * Advanced on dynamic_figures * Made the refactored code work * fix: new year, new approach * tmp: non-functioning reporting code * Fixes bug * Fixes bug * Added new function to generate html report and removed tempita calls * Added FFT and time series plots * Made template subsitute work and updated necessary bokeh version * Changes html title * remove time series, fft plots * fix: remove unescapes * fix: patch incorrect imports * fix: add missing bokeh import * fix: spelling mistake 🤦 * fix: reflect reorg in get_coeffs call * fix: correct expected test outputs * fix: don't designate file path when saving report * fix: combine generate, html report functions * fix: ignore missing columns in df.drop, to better handle multiple params * Dynamic figures are now two rows, static figure is on the right. Removed the cute dog link and made adding report.txt text to bottom of report automatic * Added new line after References in report.txt * Removes BeautifulSoup dependency in favor of an object tag and changes some CSS styles * enh: switch to grid layout, style About section, add links to navbar * doc: update no-png to no-reports * modifiation of setup.py to properly install all reporting directories * Use relative path for static figures on report * Add version check for bokeh figures Co-authored-by: smoia <[email protected]> Co-authored-by: Javier Gonzalez-Castillo <[email protected]> Co-authored-by: eurunuela <[email protected]>
- Loading branch information
1 parent
03694bd
commit ddaa4d5
Showing
17 changed files
with
708 additions
and
408 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -104,4 +104,8 @@ ENV/ | |
.mypy_cache/ | ||
|
||
# vscode | ||
.vscode | ||
.vscode | ||
|
||
# jupyter notebooks | ||
.ipynb_checkpoints/ | ||
*.ipynb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ pandas | |
scikit-learn>=0.22 | ||
scipy>=1.3.3 | ||
threadpoolctl | ||
bokeh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
""" | ||
Reporting code for tedana | ||
""" | ||
|
||
from .html_report import generate_report | ||
from .static_figures import comp_figures | ||
|
||
__all__ = ['generate_report', 'comp_figures'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
This directory contains data required for tedana reporting. | ||
|
||
html/ : HTML templates |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<style type="text/css"> | ||
.content { | ||
padding: 35px 20px 10px 20px; | ||
margin-left: 50px; | ||
margin-top: 50px; | ||
height: 900px; | ||
} | ||
.about { | ||
position: relative; | ||
top: -50px; | ||
margin-left: 5%; | ||
margin-right: 5%; | ||
white-space: pre-line; | ||
font-family: Arial, Helvetica, sans-serif; | ||
font-size: larger; | ||
} | ||
</style> | ||
<div class="content"> | ||
$content | ||
</div> | ||
<div class="about"> | ||
$about | ||
</div> | ||
|
||
$javascript |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<title>tedana report</title> | ||
<meta name="viewport" content="width = device-width, initial-scale = 1" charset="UTF-8"> | ||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-2.0.1.min.js" | ||
crossorigin="anonymous"></script> | ||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.0.1.min.js" | ||
crossorigin="anonymous"></script> | ||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.0.1.min.js" | ||
crossorigin="anonymous"></script> | ||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/build/pure-min.css" | ||
integrity="sha384-oAOxQR6DkCoMliIh8yFnu25d7Eq/PHS21PClpwjOTeU2jRSq11vu66rf90/cZr47" crossorigin="anonymous"> | ||
<!-- CSS for the report --> | ||
<style type="text/css"> | ||
body { | ||
padding: 10px 20px 10px 20px; | ||
} | ||
</style> | ||
|
||
</head> | ||
|
||
<nav> | ||
<div class="pure-menu pure-menu-horizontal"> | ||
<a href="https://github.com/ME-ICA/tedana" class="pure-menu-heading pure-menu-link">tedana $version</a> | ||
<ul class="pure-menu-list"> | ||
<li class="pure-menu-item"> | ||
<a href="https://tedana.readthedocs.io" class="pure-menu-link">Reporting documentation</a> | ||
</li> | ||
</ul> | ||
</div> | ||
</nav> | ||
|
||
<body> | ||
$body | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
import numpy as np | ||
from math import pi | ||
import pandas as pd | ||
from sklearn.preprocessing import MinMaxScaler | ||
from bokeh import (events, models, plotting, transform) | ||
|
||
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) { | ||
// A component has been selected | ||
// ----------------------------- | ||
var components = data['component'] | ||
var selected = components[selected_idx] | ||
var selected_padded = '' + selected; | ||
while (selected_padded.length < 2) { | ||
selected_padded = '0' + selected_padded; | ||
} | ||
var selected_padded_forIMG = '0' + selected_padded | ||
var selected_padded_C = 'ica_' + selected_padded | ||
// Find color for selected component | ||
var colors = data['color'] | ||
var this_component_color = colors[selected_idx] | ||
// Image Below Plots | ||
div.text = "" | ||
var line = "<span><img src='./figures/comp_"+selected_padded_forIMG+".png'" + | ||
" alt='Component Map'><span>\\n"; | ||
console.log('Linea: ' + line) | ||
var text = div.text.concat(line); | ||
var lines = text.split("\\n") | ||
if (lines.length > 35) | ||
lines.shift(); | ||
div.text = lines.join("\\n"); | ||
} else { | ||
// No component has been selected | ||
// ------------------------------ | ||
// Set Component color to Black | ||
var this_component_color = '#000000' | ||
// Image Below Plots | ||
div.text = "" | ||
var line = "<p>Please select an individual component to view it in more detail</p>\\n" | ||
var text = div.text.concat(line); | ||
} | ||
""" | ||
|
||
|
||
def _create_data_struct(comptable_path, color_mapping=color_mapping): | ||
""" | ||
Create Bokeh ColumnDataSource with all info dynamic plots need | ||
Parameters | ||
---------- | ||
comptable: str | ||
file path to component table, JSON format | ||
Returns | ||
------- | ||
cds: bokeh.models.ColumnDataSource | ||
Data structure with all the fields to plot or hover over | ||
""" | ||
unused_cols = ['normalized variance explained', | ||
'countsigFR2', 'countsigFS0', | ||
'dice_FS0', 'countnoise', 'dice_FR2', | ||
'signal-noise_t', 'signal-noise_p', | ||
'd_table_score', 'kappa ratio', | ||
'rationale', 'd_table_score_scrub'] | ||
|
||
df = pd.read_json(comptable_path) | ||
df.drop('Description', axis=0, inplace=True) | ||
df.drop('Method', axis=1, inplace=True) | ||
df = df.T | ||
n_comps = df.shape[0] | ||
|
||
# remove space from column name | ||
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] | ||
|
||
# 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 | ||
|
||
# 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') | ||
|
||
# Create additional Column with colors based on final classification | ||
df['color'] = [color_mapping[i] for i in df['classification']] | ||
|
||
# Create additional column with component ID | ||
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'])) | ||
|
||
return cds | ||
|
||
|
||
def _create_kr_plt(comptable_cds): | ||
""" | ||
Create Dymamic Kappa/Rho Scatter Plot | ||
Parameters | ||
---------- | ||
comptable_cds: bokeh.models.ColumnDataSource | ||
Data structure containing a limited set of columns from the comp_table | ||
Returns | ||
------- | ||
fig: bokeh.plotting.figure.Figure | ||
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") | ||
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' | ||
return fig | ||
|
||
|
||
def _create_sorted_plt(comptable_cds, n_comps, x_var, y_var, title=None, | ||
x_label=None, y_label=None): | ||
""" | ||
Create dynamic sorted plots | ||
Parameters | ||
---------- | ||
comptable_ds: bokeh.models.ColumnDataSource | ||
Data structure containing a limited set of columns from the comp_table | ||
x_var: str | ||
Name of variable for the x-axis | ||
y_var: str | ||
Name of variable for the y-axis | ||
title: str | ||
Plot title | ||
x_label: str | ||
X-axis label | ||
y_label: str | ||
Y-axis label | ||
Returns | ||
------- | ||
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) | ||
fig.xaxis.axis_label = x_label | ||
fig.yaxis.axis_label = y_label | ||
fig.x_range = models.Range1d(-1, n_comps + 1) | ||
fig.toolbar.logo = None | ||
|
||
return fig | ||
|
||
|
||
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.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') | ||
fig.add_glyph(circle) | ||
|
||
return fig | ||
|
||
|
||
def _tap_callback(comptable_cds, div_content, out_dir): | ||
""" | ||
Javacript function to animate tap events and show component info on the right | ||
Parameters | ||
---------- | ||
CDS: bokeh.models.ColumnDataSource | ||
Data structure containing a limited set of columns from the comp_table | ||
div: bokeh.models.Div | ||
Target Div element where component images will be loaded | ||
Returns | ||
------- | ||
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=out_dir), code=tap_callback_jscode) | ||
|
||
|
||
def _link_figures(fig, comptable_ds, div_content, out_dir): | ||
""" | ||
Links figures and adds interaction on mouse-click. | ||
Parameters | ||
---------- | ||
fig : bokeh.plotting.figure | ||
Figure containing a given plot | ||
comptable_ds : bokeh.models.ColumnDataSource | ||
Data structure with a limited version of the comptable | ||
suitable for dynamic plot purposes | ||
div_content : bokeh.models.Div | ||
Div element for additional HTML content. | ||
out_dir : str | ||
Output directory of tedana results. | ||
Returns | ||
------- | ||
fig : bokeh.plotting.figure | ||
Same as input figure, but with a linked method to | ||
its Tap event. | ||
""" | ||
fig.js_on_event(events.Tap, | ||
_tap_callback(comptable_ds, | ||
div_content, | ||
out_dir)) | ||
return fig |
Oops, something went wrong.