def render_all(vols) -> dict:
"""Every image of the DTI QC report from :class:`tit.pre.qsi.dti_advisories.DtiVolumes`."""
from tit.pre.qsi import tensor_math as tm
lab = vols.labels
valid = vols.valid
w, v = tm.eig_desc(tm.sym(vols.t6w[valid]))
fa = np.clip(tm.fa_md(w)[0], 0, 1)
fa_vol = np.zeros(lab.shape, np.float32)
fa_vol[valid] = fa
rgb = np.zeros(lab.shape + (3,), np.float32)
rgb[valid] = np.abs(v[:, :, 0]) * fa[:, None]
del w, v
brain, wm, pial = np.isin(lab, (1, 2, 3)), lab == 1, np.isin(lab, (1, 2))
csf_t1, wm_t1 = vols.t1[lab == 3], vols.t1[wm]
lo = (
float(np.percentile(csf_t1, 40))
if csf_t1.size
else float(np.percentile(vols.t1, 5))
)
hi = (
float(np.percentile(wm_t1, 98))
if wm_t1.size
else float(np.percentile(vols.t1, 99))
)
t1n = np.clip((vols.t1 - lo) / max(hi - lo, 1e-6), 0, 1).astype(np.float32)
coord, is_mni = _coordinates(vols, pial)
box = sl.brain_box(brain, coord[..., 2])
def pick(axis: int, target: float) -> int:
return sl.pick_slice(axis, target, coord[..., axis], brain, box)
registration = {}
for plane, (axis, targets, letter) in REG_PLANES.items():
idx = [pick(axis, t) for t in targets]
def mosaic(vol, idx=idx, axis=axis):
return sl.mosaic([sl.oriented(vol, axis, i, box) for i in idx], 3)
t1_m, tile = mosaic(t1n)
contours = [
(mosaic(pial)[0], PIAL_COLOUR, 0.7),
(mosaic(wm)[0], WM_COLOUR, 0.9),
]
registration[plane] = {
"t1": sl.render(t1_m, contours),
"fa": sl.render(
np.clip(mosaic(fa_vol)[0] / FA_DISPLAY_MAX, 0, 1), contours
),
"labels": [f"{letter} = {t:+d}" for t in targets],
"cols": 3,
"tile": tile,
"shape": t1_m.shape[:2],
}
frames = [
sl.render(
np.clip(sl.oriented(rgb, 2, pick(2, z), box) * DEC_GAIN, 0, 1), quality=80
)
for z in DEC_STACK_Z
]
sphere, sphere_axes = orientation_sphere()
return {
"is_mni": is_mni,
"registration": registration,
"dec": {"z": list(DEC_STACK_Z), "frames": frames},
"sphere": sphere,
"sphere_axes": sphere_axes,
}