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

Possible to change FD "threshold" in .html for QA purposes? #633

Open
ryanw412 opened this issue Mar 5, 2021 · 2 comments
Open

Possible to change FD "threshold" in .html for QA purposes? #633

ryanw412 opened this issue Mar 5, 2021 · 2 comments
Labels
effort:medium Estimated medium effort task help wanted impact:medium Estimated medium impact task plotting

Comments

@ryanw412
Copy link

ryanw412 commented Mar 5, 2021

When opening the .html file showing visual reports of the output, the FD shows a seemingly arbitrary bar that doesn't correspond to the default .5mm threshold. For example, one subject's .html shows a FD bar at .48mm, and another shows at .41mm. It would be convenient to have this bar be constant for all subjects for quality assessment across subjects. I know that there are commands to censor volumes that are FD>.5mm, but I'm more concerned about the visual inspection aspect. Is there any way to set this to be the same (preferably .5mm) for all subjects?

Thanks!

@julfou81
Copy link

julfou81 commented Mar 8, 2021

Hi,
Good question! I don't know how is calculated this line in FMRIPREP report.
For QA purposes, you may use MRIQC where you can see stats of number of volumes above a certain FD threshold (number and percentage of volumes above a certain threshold). But there as well, there is not bar with the visual threshold visible on the reports (as far as I know, I didn't try the latest version of MRIQC). Also, there is still one unresolved issue regarding this visual inspection in MRIQC: https://github.com/poldracklab/mriqc/issues/790

I agree, it would be nice to have a visual display similar to what is done with denoiser :

Capture d’écran 2021-03-08 à 18 11 28

@oesteban oesteban transferred this issue from nipreps/fmriprep May 7, 2021
@oesteban
Copy link
Member

oesteban commented May 7, 2021

Thanks @ryanw412 and @julfou81 for this suggestion. I think this would be very useful.

I'm transferring the issue to nipreps/niworkflows, which is where the code to generate that plot lives:

def confoundplot(
tseries,
gs_ts,
gs_dist=None,
name=None,
units=None,
tr=None,
hide_x=True,
color="b",
nskip=0,
cutoff=None,
ylims=None,
):
import seaborn as sns
# Define TR and number of frames
notr = False
if tr is None:
notr = True
tr = 1.0
ntsteps = len(tseries)
tseries = np.array(tseries)
# Define nested GridSpec
gs = mgs.GridSpecFromSubplotSpec(
1, 2, subplot_spec=gs_ts, width_ratios=[1, 100], wspace=0.0
)
ax_ts = plt.subplot(gs[1])
ax_ts.grid(False)
# Set 10 frame markers in X axis
interval = max((ntsteps // 10, ntsteps // 5, 1))
xticks = list(range(0, ntsteps)[::interval])
ax_ts.set_xticks(xticks)
if not hide_x:
if notr:
ax_ts.set_xlabel("time (frame #)")
else:
ax_ts.set_xlabel("time (s)")
labels = tr * np.array(xticks)
ax_ts.set_xticklabels(["%.02f" % t for t in labels.tolist()])
else:
ax_ts.set_xticklabels([])
if name is not None:
if units is not None:
name += " [%s]" % units
ax_ts.annotate(
name,
xy=(0.0, 0.7),
xytext=(0, 0),
xycoords="axes fraction",
textcoords="offset points",
va="center",
ha="left",
color=color,
size=8,
bbox={
"boxstyle": "round",
"fc": "w",
"ec": "none",
"color": "none",
"lw": 0,
"alpha": 0.8,
},
)
for side in ["top", "right"]:
ax_ts.spines[side].set_color("none")
ax_ts.spines[side].set_visible(False)
if not hide_x:
ax_ts.spines["bottom"].set_position(("outward", 20))
ax_ts.xaxis.set_ticks_position("bottom")
else:
ax_ts.spines["bottom"].set_color("none")
ax_ts.spines["bottom"].set_visible(False)
# ax_ts.spines["left"].set_position(('outward', 30))
ax_ts.spines["left"].set_color("none")
ax_ts.spines["left"].set_visible(False)
# ax_ts.yaxis.set_ticks_position('left')
ax_ts.set_yticks([])
ax_ts.set_yticklabels([])
nonnan = tseries[~np.isnan(tseries)]
if nonnan.size > 0:
# Calculate Y limits
valrange = nonnan.max() - nonnan.min()
def_ylims = [nonnan.min() - 0.1 * valrange, nonnan.max() + 0.1 * valrange]
if ylims is not None:
if ylims[0] is not None:
def_ylims[0] = min([def_ylims[0], ylims[0]])
if ylims[1] is not None:
def_ylims[1] = max([def_ylims[1], ylims[1]])
# Add space for plot title and mean/SD annotation
def_ylims[0] -= 0.1 * (def_ylims[1] - def_ylims[0])
ax_ts.set_ylim(def_ylims)
# Annotate stats
maxv = nonnan.max()
mean = nonnan.mean()
stdv = nonnan.std()
p95 = np.percentile(nonnan, 95.0)
else:
maxv = 0
mean = 0
stdv = 0
p95 = 0
stats_label = (
r"max: {max:.3f}{units} $\bullet$ mean: {mean:.3f}{units} "
r"$\bullet$ $\sigma$: {sigma:.3f}"
).format(max=maxv, mean=mean, units=units or "", sigma=stdv)
ax_ts.annotate(
stats_label,
xy=(0.98, 0.7),
xycoords="axes fraction",
xytext=(0, 0),
textcoords="offset points",
va="center",
ha="right",
color=color,
size=4,
bbox={
"boxstyle": "round",
"fc": "w",
"ec": "none",
"color": "none",
"lw": 0,
"alpha": 0.8,
},
)
# Annotate percentile 95
ax_ts.plot((0, ntsteps - 1), [p95] * 2, linewidth=0.1, color="lightgray")
ax_ts.annotate(
"%.2f" % p95,
xy=(0, p95),
xytext=(-1, 0),
textcoords="offset points",
va="center",
ha="right",
color="lightgray",
size=3,
)
if cutoff is None:
cutoff = []
for i, thr in enumerate(cutoff):
ax_ts.plot((0, ntsteps - 1), [thr] * 2, linewidth=0.2, color="dimgray")
ax_ts.annotate(
"%.2f" % thr,
xy=(0, thr),
xytext=(-1, 0),
textcoords="offset points",
va="center",
ha="right",
color="dimgray",
size=3,
)
ax_ts.plot(tseries, color=color, linewidth=0.8)
ax_ts.set_xlim((0, ntsteps - 1))
if gs_dist is not None:
ax_dist = plt.subplot(gs_dist)
sns.displot(tseries, vertical=True, ax=ax_dist)
ax_dist.set_xlabel("Timesteps")
ax_dist.set_ylim(ax_ts.get_ylim())
ax_dist.set_yticklabels([])
return [ax_ts, ax_dist], gs
return ax_ts, gs

Any suggestions in the form of PR (or patches, or anything) will be very welcome. Otherwise, we cannot really give any timeframe for the implementation of this feature. Please join our fMRIPrep bi-monthly meetings for more info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort:medium Estimated medium effort task help wanted impact:medium Estimated medium impact task plotting
Projects
None yet
Development

No branches or pull requests

3 participants