Skip to content

Commit

Permalink
Remove melodic report (duplicate of AROMA report).
Browse files Browse the repository at this point in the history
  • Loading branch information
tsalo committed May 17, 2024
1 parent bcbd117 commit 07270ad
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 162 deletions.
208 changes: 62 additions & 146 deletions src/fmripost_aroma/interfaces/reportlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,87 +96,74 @@ def _generate_segment(self):
raise NotImplementedError


class _MELODICInputSpecRPT(nrb._SVGReportCapableInputSpec, fsl.model.MELODICInputSpec):
out_report = File(
'melodic_reportlet.svg',
usedefault=True,
desc='Filename for the visual report generated by Nipype.',
)
report_mask = File(
desc=(
'Mask used to draw the outline on the reportlet. '
'If not set the mask will be derived from the data.'
),
class SubjectSummaryInputSpec(BaseInterfaceInputSpec):
subject_id = Str(desc='Subject ID')
bold = InputMultiObject(
traits.Either(File(exists=True), traits.List(File(exists=True))),
desc='BOLD functional series',
)
std_spaces = traits.List(Str, desc='list of standard spaces')
nstd_spaces = traits.List(Str, desc='list of non-standard spaces')


class _MELODICOutputSpecRPT(
reporting.ReportCapableOutputSpec,
fsl.model.MELODICOutputSpec,
):
pass


class MELODICRPT(fsl.MELODIC):
"""Create a reportlet for MELODIC outputs."""

input_spec = _MELODICInputSpecRPT
output_spec = _MELODICOutputSpecRPT
_out_report = None

def __init__(self, generate_report=False, **kwargs):
"""Create the reportlet."""
super().__init__(**kwargs)
self.generate_report = generate_report

def _post_run_hook(self, runtime):
# Run _post_run_hook of super class
runtime = super()._post_run_hook(runtime)
# leave early if there's nothing to do
if not self.generate_report:
return runtime

NIWORKFLOWS_LOG.info('Generating report for MELODIC.')
_melodic_dir = runtime.cwd
if isdefined(self.inputs.out_dir):
_melodic_dir = self.inputs.out_dir
self._melodic_dir = os.path.abspath(_melodic_dir)

self._out_report = self.inputs.out_report
if not os.path.isabs(self._out_report):
self._out_report = os.path.abspath(os.path.join(runtime.cwd, self._out_report))

mix = os.path.join(self._melodic_dir, 'melodic_mix')
if not os.path.exists(mix):
NIWORKFLOWS_LOG.warning("MELODIC outputs not found, assuming it didn't converge.")
self._out_report = self._out_report.replace('.svg', '.html')
snippet = '<h4>MELODIC did not converge, no output</h4>'
with open(self._out_report, 'w') as fobj:
fobj.write(snippet)
return runtime

self._generate_report()
return runtime
class SubjectSummary(SummaryInterface):
input_spec = SubjectSummaryInputSpec
output_spec = SummaryOutputSpec

def _list_outputs(self):
try:
outputs = super()._list_outputs()
except NotImplementedError:
outputs = {}
if self._out_report is not None:
outputs['out_report'] = self._out_report
return outputs
def _generate_segment(self):
BIDS_NAME = re.compile(
r'^(.*\/)?'
'(?P<subject_id>sub-[a-zA-Z0-9]+)'
'(_(?P<session_id>ses-[a-zA-Z0-9]+))?'
'(_(?P<task_id>task-[a-zA-Z0-9]+))?'
'(_(?P<acq_id>acq-[a-zA-Z0-9]+))?'
'(_(?P<rec_id>rec-[a-zA-Z0-9]+))?'
'(_(?P<run_id>run-[a-zA-Z0-9]+))?'
)

def _generate_report(self):
from niworkflows.viz.utils import plot_melodic_components
# Add list of tasks with number of runs
bold_series = self.inputs.bold if isdefined(self.inputs.bold) else []
bold_series = [s[0] if isinstance(s, list) else s for s in bold_series]

plot_melodic_components(
melodic_dir=self._melodic_dir,
in_file=self.inputs.in_files[0],
tr=self.inputs.tr_sec,
out_file=self._out_report,
compress=self.inputs.compress_report,
report_mask=self.inputs.report_mask,
counts = Counter(
BIDS_NAME.search(series).groupdict()['task_id'][5:] for series in bold_series
)

tasks = ''
if counts:
header = '\t\t<ul class="elem-desc">'
footer = '\t\t</ul>'
lines = [
'\t\t\t<li>Task: {task_id} ({n_runs:d} run{s})</li>'.format(
task_id=task_id, n_runs=n_runs, s='' if n_runs == 1 else 's'
)
for task_id, n_runs in sorted(counts.items())
]
tasks = '\n'.join([header] + lines + [footer])

return SUBJECT_TEMPLATE.format(
subject_id=self.inputs.subject_id,
n_bold=len(bold_series),
tasks=tasks,
std_spaces=', '.join(self.inputs.std_spaces),
nstd_spaces=', '.join(self.inputs.nstd_spaces),
)


class AboutSummaryInputSpec(BaseInterfaceInputSpec):
version = Str(desc='FMRIPREP version')
command = Str(desc='FMRIPREP command')
# Date not included - update timestamp only if version or command changes


class AboutSummary(SummaryInterface):
input_spec = AboutSummaryInputSpec

def _generate_segment(self):
return ABOUT_TEMPLATE.format(
version=self.inputs.version,
command=self.inputs.command,
date=time.strftime('%Y-%m-%d %H:%M:%S %z'),
)


Expand Down Expand Up @@ -243,74 +230,3 @@ def _run_interface(self, runtime):
)
self._results['out_report'] = out_file
return runtime


class SubjectSummaryInputSpec(BaseInterfaceInputSpec):
subject_id = Str(desc='Subject ID')
bold = InputMultiObject(
traits.Either(File(exists=True), traits.List(File(exists=True))),
desc='BOLD functional series',
)
std_spaces = traits.List(Str, desc='list of standard spaces')
nstd_spaces = traits.List(Str, desc='list of non-standard spaces')


class SubjectSummary(SummaryInterface):
input_spec = SubjectSummaryInputSpec
output_spec = SummaryOutputSpec

def _generate_segment(self):
BIDS_NAME = re.compile(
r'^(.*\/)?'
'(?P<subject_id>sub-[a-zA-Z0-9]+)'
'(_(?P<session_id>ses-[a-zA-Z0-9]+))?'
'(_(?P<task_id>task-[a-zA-Z0-9]+))?'
'(_(?P<acq_id>acq-[a-zA-Z0-9]+))?'
'(_(?P<rec_id>rec-[a-zA-Z0-9]+))?'
'(_(?P<run_id>run-[a-zA-Z0-9]+))?'
)

# Add list of tasks with number of runs
bold_series = self.inputs.bold if isdefined(self.inputs.bold) else []
bold_series = [s[0] if isinstance(s, list) else s for s in bold_series]

counts = Counter(
BIDS_NAME.search(series).groupdict()['task_id'][5:] for series in bold_series
)

tasks = ''
if counts:
header = '\t\t<ul class="elem-desc">'
footer = '\t\t</ul>'
lines = [
'\t\t\t<li>Task: {task_id} ({n_runs:d} run{s})</li>'.format(
task_id=task_id, n_runs=n_runs, s='' if n_runs == 1 else 's'
)
for task_id, n_runs in sorted(counts.items())
]
tasks = '\n'.join([header] + lines + [footer])

return SUBJECT_TEMPLATE.format(
subject_id=self.inputs.subject_id,
n_bold=len(bold_series),
tasks=tasks,
std_spaces=', '.join(self.inputs.std_spaces),
nstd_spaces=', '.join(self.inputs.nstd_spaces),
)


class AboutSummaryInputSpec(BaseInterfaceInputSpec):
version = Str(desc='FMRIPREP version')
command = Str(desc='FMRIPREP command')
# Date not included - update timestamp only if version or command changes


class AboutSummary(SummaryInterface):
input_spec = AboutSummaryInputSpec

def _generate_segment(self):
return ABOUT_TEMPLATE.format(
version=self.inputs.version,
command=self.inputs.command,
date=time.strftime('%Y-%m-%d %H:%M:%S %z'),
)
18 changes: 2 additions & 16 deletions src/fmripost_aroma/workflows/aroma.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def init_ica_aroma_wf(

from fmripost_aroma.interfaces.confounds import ICAConfounds
from fmripost_aroma.interfaces.nilearn import MeanImage, MedianValue
from fmripost_aroma.interfaces.reportlets import ICAAROMARPT, MELODICRPT
from fmripost_aroma.interfaces.reportlets import ICAAROMARPT

workflow = Workflow(name=_get_wf_name(bold_file, 'aroma'))
workflow.__postdesc__ = f"""\
Expand Down Expand Up @@ -200,7 +200,7 @@ def init_ica_aroma_wf(

# ICA with MELODIC
melodic = pe.Node(
MELODICRPT(
fsl.MELODIC(
no_bet=True,
tr_sec=float(metadata['RepetitionTime']),
mm_thresh=0.5,
Expand All @@ -214,20 +214,6 @@ def init_ica_aroma_wf(
(smooth, melodic, [('smoothed_file', 'in_files')]),
]) # fmt:skip

ds_report_melodic = pe.Node(
DerivativesDataSink(
base_directory=config.execution.fmripost_aroma_dir,
source_file=bold_file,
datatype='figures',
desc='melodic',
dismiss_entities=('echo', 'den', 'res'),
),
name='ds_report_melodic',
run_without_submitting=True,
mem_gb=config.DEFAULT_MEMORY_MIN_GB,
)
workflow.connect([(melodic, ds_report_melodic, [('out_report', 'in_file')])])

select_melodic_files = pe.Node(
niu.Function(
function=_select_melodic_files,
Expand Down

0 comments on commit 07270ad

Please sign in to comment.