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

Add section to reports that show system info, tedana call and version #747

Merged
merged 29 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f968eb4
Added function to get system info and save into json
eurunuela Jul 10, 2021
ccf832b
Add missing dependency
eurunuela Jul 10, 2021
8044a99
Info table almost ready, need to figure out how to save json
eurunuela Jul 10, 2021
5a53ced
Added system info output structure, only missing command now
eurunuela Jul 10, 2021
5140f42
First working version, style missing now
eurunuela Jul 10, 2021
6d377e8
Styled info table
eurunuela Jul 10, 2021
aded008
Changed where system info is saved and how it is displayed on report
eurunuela Jul 15, 2021
056ac84
Merge branch 'main' of https://github.com/ME-ICA/tedana into reports/…
eurunuela Jul 15, 2021
80f4e64
Remove import of unused library
eurunuela Jul 15, 2021
fcf54fc
Assess review comments
eurunuela Jul 15, 2021
05d9ac3
Correct silly mistake
eurunuela Jul 15, 2021
9f8467c
Update tedana/utils.py
eurunuela Jul 15, 2021
7c8e901
Merge remote-tracking branch 'upstream/main' into reports/info
eurunuela Aug 9, 2023
10c9eba
Added system info to report after merge with main removed it
eurunuela Aug 9, 2023
865a3c6
Increase spacing in info table
eurunuela Aug 9, 2023
cbd6801
Added tedana call file to reports and tedana call from Python to report
eurunuela Aug 9, 2023
acd594b
Only generate call.sh when cli is used.
eurunuela Aug 9, 2023
363bc46
Fix command in dictionary bug
eurunuela Aug 10, 2023
942377f
Add system info to ica_reclassify
eurunuela Aug 10, 2023
ed7ab14
Remove call from 3-echo results
eurunuela Aug 10, 2023
cc3dc8f
Add call to ica_reclassify tests
eurunuela Aug 10, 2023
ec69f75
Trigger tests
eurunuela Aug 14, 2023
b6fb863
Merge remote-tracking branch 'upstream/main' into reports/info
eurunuela Aug 14, 2023
e34b6d0
Ran black on repo
eurunuela Aug 14, 2023
0183e1d
Revert changes black made to selection_nodes.py
eurunuela Aug 14, 2023
69979c3
Remove unused import
eurunuela Aug 14, 2023
11b9701
Fixed artifacts path and did some style fixing too
eurunuela Aug 25, 2023
4d3ed72
Added highlighted code block
eurunuela Aug 28, 2023
83ffeff
Moved up the creation of the tedana command
eurunuela Aug 30, 2023
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
23 changes: 23 additions & 0 deletions tedana/reporting/data/html/report_body_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
margin-top: 50px;
height: 900px;
}
.info {
margin-left: 5%;
margin-right: 5%;
margin-bottom: 100px;
font-size: larger;
color: #505050;
}
.about {
position: relative;
top: -50px;
Expand All @@ -13,11 +20,27 @@
white-space: pre-line;
font-family: Arial, Helvetica, sans-serif;
font-size: larger;
color: #505050;
}
h1 {
color: #000000;
font-weight: 800;
}
.title {
color: #000000;
font-weight: 800;
}
td {
padding-right: 50px;
}
</style>
<div class="content">
$content
</div>
<div class="info">
<h1>Info</h1>
$info
</div>
<div class="about">
$about
</div>
Expand Down
39 changes: 39 additions & 0 deletions tedana/reporting/data/html/report_info_table_template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<div>
<p>
<span class="title">Tedana command used:</span> $command
</p>
<table>
<tr>
<td class="title">System:</td>
<td>$system</td>
</tr>
<tr>
<td class="title">Node:</td>
<td>$node</td>
</tr>
<tr>
<td class="title">Release:</td>
<td>$release</td>
</tr>
<tr>
<td class="title">System version:</td>
<td>$sysversion</td>
</tr>
<tr>
<td class="title">Machine:</td>
<td>$machine</td>
</tr>
<tr>
<td class="title">Processor:</td>
<td>$processor</td>
</tr>
<tr>
<td class="title">Python:</td>
<td>$python</td>
</tr>
<tr>
<td class="title">Tedana version:</td>
<td>$tedana</td>
</tr>
</table>
</div>
43 changes: 41 additions & 2 deletions tedana/reporting/html_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
from os.path import join as opj
from string import Template
from tedana.info import __version__
from tedana.io import load_json
from tedana.reporting import dynamic_figures as df


def _update_template_bokeh(bokeh_id, about, bokeh_js):
def _update_template_bokeh(bokeh_id, info_table, about, bokeh_js):
"""
Populate a report with content.

Parameters
----------
bokeh_id : str
HTML div created by bokeh.embed.components
info_table : str
HTML div created by _generate_info_table()
about : str
Reporting information for a given run
bokeh_js : str
Expand All @@ -31,6 +34,7 @@ def _update_template_bokeh(bokeh_id, about, bokeh_js):
with open(str(body_template_path), 'r') as body_file:
body_tpl = Template(body_file.read())
body = body_tpl.substitute(content=bokeh_id,
info=info_table,
about=about,
javascript=bokeh_js)
return body
Expand All @@ -55,6 +59,34 @@ def _save_as_html(body):
return html


def _generate_info_table(info_dict):
"""Generate a table with relevant information about the
system and tedana.
"""
resource_path = Path(__file__).resolve().parent.joinpath('data', 'html')

info_template_name = 'report_info_table_template.html'
info_template_path = resource_path.joinpath(info_template_name)
with open(str(info_template_path), 'r') as info_file:
info_tpl = Template(info_file.read())

info_dict = info_dict["GeneratedBy"][0]
command = info_dict["Command"]
version_python = info_dict["Python"]
info_dict = info_dict["Node"]

info_html = info_tpl.substitute(command=command,
system=info_dict["System"],
node=info_dict["Name"],
release=info_dict["Release"],
sysversion=info_dict["Version"],
machine=info_dict["Machine"],
processor=info_dict["Processor"],
python=version_python,
tedana=__version__)
return info_html


def generate_report(io_generator, tr):
"""
Parameters
Expand Down Expand Up @@ -114,7 +146,14 @@ def generate_report(io_generator, tr):
with open(opj(io_generator.out_dir, 'report.txt'), 'r+') as f:
about = f.read()

body = _update_template_bokeh(kr_div, about, kr_script)
# Read info table
data_descr_path = io_generator.get_name("data description json")
data_descr_dict = load_json(data_descr_path)

# Create info table
info_table = _generate_info_table(data_descr_dict)

body = _update_template_bokeh(kr_div, info_table, about, kr_script)
html = _save_as_html(body)
with open(opj(io_generator.out_dir, 'tedana_report.html'), 'wb') as f:
f.write(html.encode('utf-8'))
52 changes: 52 additions & 0 deletions tedana/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
import logging
import os.path as op
import platform

import numpy as np
import nibabel as nib
Expand Down Expand Up @@ -384,3 +385,54 @@ def get_resource_path():
Based on function by Yaroslav Halchenko used in Neurosynth Python package.
"""
return op.abspath(op.join(op.dirname(__file__), "resources") + op.sep)


def get_system_info():
"""Return information about the system tedana is being run on.

Returns
-------
dict
Info about system where tedana is run on.
"""
system_info = platform.uname()

system_dict = {
"System": system_info.system,
"Node": system_info.node,
"Release": system_info.release,
"Version": system_info.version,
"Machine": system_info.machine,
"Processor": system_info.processor,
}

return system_dict


def write_tedana_command(arg_vals):
Copy link
Member

Choose a reason for hiding this comment

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

Following up from https://github.com/eurunuela/pySPFM/pull/28- I think it would be better if we could use the CLI commands directly, and not compile a tedana command when users don't use the CLI. WDYT of swapping out this function with the changes I proposed in pySPFM?

"""Write a CLI-style command with the arguments given to run tedana.

Parameters
----------
arg_vals : dict
Dictionary with arguments and values of passed to the tedana function.

Returns
-------
str
Arguments given to tedana and their values formatted in CLI-style.
"""
# Deleta frame from dictionary
del arg_vals["frame"]

command = "tedana"

for key, val in arg_vals.items():
# Data and TE are lists
if type(val) is list:
values = " ".join(str(x) for x in val)
else:
values = val
command += f" <b>--{key}</b> {values}"

return command
23 changes: 22 additions & 1 deletion tedana/workflows/tedana.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Run the "canonical" TE-Dependent ANAlysis workflow.
"""
import inspect
import json
import os
import sys
Expand Down Expand Up @@ -340,6 +341,9 @@ def tedana_workflow(data, tes, out_dir='.', mask=None,
generated by this workflow, please visit
https://tedana.readthedocs.io/en/latest/outputs.html
"""
frame = inspect.currentframe()
_, _, _, arg_values = inspect.getargvalues(frame)

out_dir = op.abspath(out_dir)
if not op.isdir(out_dir):
os.mkdir(out_dir)
Expand Down Expand Up @@ -421,6 +425,10 @@ def tedana_workflow(data, tes, out_dir='.', mask=None,
verbose=verbose,
)

# Save system info to json
info_dict = utils.get_system_info()
info_dict["Python"] = sys.version

n_samp, n_echos, n_vols = catd.shape
LGR.debug('Resulting data shape: {}'.format(catd.shape))

Expand Down Expand Up @@ -679,6 +687,9 @@ def tedana_workflow(data, tes, out_dir='.', mask=None,
if verbose:
io.writeresults_echoes(catd, mmix, mask, comptable, io_generator)

# Generate tedana command with all API values
tedana_command = utils.write_tedana_command(arg_values)

# Write out BIDS-compatible description file
derivative_metadata = {
"Name": "tedana Outputs",
Expand All @@ -692,7 +703,17 @@ def tedana_workflow(data, tes, out_dir='.', mask=None,
"A denoising pipeline for the identification and removal "
"of non-BOLD noise from multi-echo fMRI data."
),
"CodeURL": "https://github.com/ME-ICA/tedana"
"CodeURL": "https://github.com/ME-ICA/tedana",
"Node": {
"Name": info_dict["Node"],
"System": info_dict["System"],
"Machine": info_dict["Machine"],
"Processor": info_dict["Processor"],
"Release": info_dict["Release"],
"Version": info_dict["Version"]
},
"Python": info_dict["Python"],
"Command": tedana_command
Copy link
Member

Choose a reason for hiding this comment

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

When users use the Python function instead of the CLI, perhaps we could have the function call instead? I don't know if that's an easy thing to do though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That would be cool! I guess we could just write a silly function that turns the function call into a string as part of our utils file.

}
]
}
Expand Down