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 adaptive mask plot to report #1073

Merged
merged 18 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 6 additions & 0 deletions tedana/reporting/data/html/report_body_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ <h1>Carpet plots</h1>
</div>
</div>
</div>
<div class="carpet-plots">
<h1>Adaptive mask</h1>
<div class="carpet-plots-image">
<img id="adaptiveMask" src="$adaptiveMask" class="brainplot" />
</div>
</div>
<div class="carpet-plots">
<h1>T2* and S0</h1>
<h2>T2*</h2>
Expand Down
4 changes: 4 additions & 0 deletions tedana/reporting/html_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ def _update_template_bokeh(bokeh_id, info_table, about, prefix, references, boke
# Initial carpet plot (default one)
initial_carpet = f"./figures/{prefix}carpet_optcom.svg"

# Adaptive mask image
adaptive_mask = f"./figures/{prefix}adaptive_mask.svg"

# T2* and S0 images
t2star_brain = f"./figures/{prefix}t2star_brain.svg"
t2star_histogram = f"./figures/{prefix}t2star_histogram.svg"
Expand All @@ -165,6 +168,7 @@ def _update_template_bokeh(bokeh_id, info_table, about, prefix, references, boke
about=about,
prefix=prefix,
initialCarpet=initial_carpet,
adaptiveMask=adaptive_mask,
t2starBrainPlot=t2star_brain,
t2starHistogram=t2star_histogram,
s0BrainPlot=s0_brain,
Expand Down
60 changes: 60 additions & 0 deletions tedana/reporting/static_figures.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,3 +616,63 @@ def plot_t2star_and_s0(
annotate=False,
output_file=os.path.join(io_generator.out_dir, "figures", s0_plot),
)


def plot_adaptive_mask(
*,
optcom: np.ndarray,
base_mask: np.ndarray,
io_generator: io.OutputGenerator,
):
"""Create a figure to show the adaptive mask.

Parameters
----------
optcom : (S x T) :obj:`numpy.ndarray`
Optimal combination of components
base_mask : (S,) :obj:`numpy.ndarray`
Base mask used in tedana
io_generator : :obj:`~tedana.io.OutputGenerator`
The output generator for this workflow
"""
from matplotlib.lines import Line2D
from nilearn import image

adaptive_mask_img = io_generator.get_name("adaptive mask img")
mean_optcom_img = io.new_nii_like(io_generator.reference_img, np.mean(optcom, axis=1))

# Concatenate the three masks used in tedana to treat as a probabilistic atlas
base_mask = io.new_nii_like(io_generator.reference_img, base_mask)
mask_denoise = image.math_img("(img >= 1).astype(np.uint8)", img=adaptive_mask_img)
mask_clf = image.math_img("(img >= 3).astype(np.uint8)", img=adaptive_mask_img)
all_masks = image.concat_imgs((base_mask, mask_denoise, mask_clf))
# Set values to 0.5 for probabilistic atlas plotting
all_masks = image.math_img("img * 0.5", img=all_masks)

cmap = plt.cm.gist_rainbow
discrete_cmap = cmap.resampled(3) # colors matching the mask lines in the image
color_dict = {
"Base": discrete_cmap(0),
"Optimal combination": discrete_cmap(0.4),
"Classification": discrete_cmap(0.9),
}

ob = plotting.plot_prob_atlas(
maps_img=all_masks,
bg_img=mean_optcom_img,
view_type="contours",
threshold=0.2,
annotate=False,
draw_cross=False,
cmap=cmap,
)

legend_elements = []
for k, v in color_dict.items():
line = Line2D([0], [0], color=v, label=k, markersize=10)
legend_elements.append(line)

ob.frame_axes.legend(handles=legend_elements, facecolor="white", ncols=3, loc="lower center")
fig = ob.frame_axes.get_figure()
adaptive_mask_plot = f"{io_generator.prefix}adaptive_mask.svg"
fig.savefig(os.path.join(io_generator.out_dir, "figures", adaptive_mask_plot))
1 change: 1 addition & 0 deletions tedana/tests/data/cornell_three_echo_outputs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ desc-adaptiveGoodSignal_mask.nii.gz
desc-denoised_bold.nii.gz
desc-optcom_bold.nii.gz
figures
figures/adaptive_mask.svg
figures/carpet_optcom.svg
figures/carpet_denoised.svg
figures/carpet_accepted.svg
Expand Down
1 change: 1 addition & 0 deletions tedana/tests/data/fiu_four_echo_outputs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ sub-01_echo-4_desc-Rejected_bold.nii.gz
sub-01_report.txt
sub-01_tedana_report.html
figures
figures/sub-01_adaptive_mask.svg
figures/sub-01_carpet_optcom.svg
figures/sub-01_carpet_denoised.svg
figures/sub-01_carpet_accepted.svg
Expand Down
1 change: 1 addition & 0 deletions tedana/tests/data/nih_five_echo_outputs_verbose.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ sub-01_references.bib
sub-01_report.txt
sub-01_tedana_report.html
figures
figures/sub-01_adaptive_mask.svg
figures/sub-01_carpet_optcom.svg
figures/sub-01_carpet_denoised.svg
figures/sub-01_carpet_accepted.svg
Expand Down
10 changes: 8 additions & 2 deletions tedana/workflows/tedana.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,12 +595,13 @@
t2s_limited_sec = utils.reshape_niimg(t2smap)
t2s_limited = utils.sec2millisec(t2s_limited_sec)
t2s_full = t2s_limited.copy()
mask = utils.reshape_niimg(mask)
mask = utils.reshape_niimg(mask).astype(int)

Check warning on line 598 in tedana/workflows/tedana.py

View check run for this annotation

Codecov / codecov/patch

tedana/workflows/tedana.py#L598

Added line #L598 was not covered by tests
mask[t2s_limited == 0] = 0 # reduce mask based on T2* map
else:
LGR.info("Computing EPI mask from first echo")
first_echo_img = io.new_nii_like(io_generator.reference_img, catd[:, 0, :])
mask = compute_epi_mask(first_echo_img)
mask = compute_epi_mask(first_echo_img).get_fdata()
mask = utils.reshape_niimg(mask).astype(int)
RepLGR.info(
"An initial mask was generated from the first echo using "
"nilearn's compute_epi_mask function."
Expand Down Expand Up @@ -899,6 +900,11 @@

dn_ts, hikts, lowkts = io.denoise_ts(data_oc, mmix, mask_denoise, comptable)

reporting.static_figures.plot_adaptive_mask(
optcom=data_oc,
base_mask=mask,
io_generator=io_generator,
)
reporting.static_figures.carpet_plot(
optcom_ts=data_oc,
denoised_ts=dn_ts,
Expand Down