Source code for AFQ.viz.plot

import math

import matplotlib.pyplot as plt
import pandas as pd

from AFQ.viz.utils import display_string, gen_color_dict

__all__ = ["visualize_tract_profiles"]


def _plot_tract(ax, df, tract_name, metric, color, label=None):
    sub = df[df["tractID"] == tract_name].sort_values("nodeID")
    if sub.empty:
        return
    ax.plot(
        sub["nodeID"],
        sub[metric],
        color=color,
        linewidth=1.8,
        label=label or tract_name,
    )


def _split_hemisphere(tract_id):
    if tract_id.endswith(("_L_R", "_R_L")):
        return None, None
    for prefix, hemi in (("Left ", "Left"), ("Right ", "Right")):
        if tract_id.startswith(prefix):
            return tract_id[len(prefix) :], hemi
    for suffix, hemi in (("_L", "Left"), ("_R", "Right")):
        if tract_id.endswith(suffix):
            return tract_id[: -len(suffix)], hemi
    return None, None


[docs] def visualize_tract_profiles( tract_profiles, scalar="dti_fa", file_name=None, fontsize=14, ): """ Visualize all tract profiles for a scalar in one plot Parameters ---------- tract_profiles : string Path to CSV containing tract_profiles. scalar : string, optional Scalar to use in plots. Default: "dti_fa". file_name : string, optional File name to save figure to if not None. Default: None fontsize : int, optional Font size for figure. Default: 14 Returns ------- Matplotlib figure and axes. """ df = pd.read_csv(tract_profiles) color_dict = gen_color_dict(df["tractID"].unique()) bilateral = {} callosal = [] for tt in df["tractID"].unique(): base, hemi = _split_hemisphere(tt) if base is None: callosal.append(tt) else: bilateral.setdefault(base, {})[hemi] = tt bilateral_bases = sorted(bilateral) callosal = sorted(callosal) n_bilateral = len(bilateral_bases) n_panels = n_bilateral + len(callosal) n_cols = math.ceil(math.sqrt(n_panels)) n_rows = math.ceil(n_panels / n_cols) fig1, axes1 = plt.subplots( n_rows, n_cols, figsize=(n_cols * 4, n_rows * 4), sharex=False, sharey=False, squeeze=False, ) flat_axes = axes1.ravel() def _style_axis(ax, ylabel): ax.set_ylabel(ylabel, fontsize=fontsize - 2, labelpad=4) ax.set_xlabel("Node", fontsize=fontsize) ax.tick_params(labelsize=fontsize - 4) ax.spines[["top", "right"]].set_visible(False) ax.legend(fontsize=fontsize, loc="best", frameon=False) for idx, base in enumerate(bilateral_bases): ax = flat_axes[idx] for hemi in ("Left", "Right"): full_name = bilateral[base].get(hemi) if full_name is None: continue _plot_tract( ax, df, full_name, scalar, color_dict[full_name], hemi, ) _style_axis(ax, base + " " + display_string(scalar)) for ii, tract in enumerate(callosal): ax = flat_axes[n_bilateral + ii] sub = df[df["tractID"] == tract].sort_values("nodeID") ax.plot( sub["nodeID"], sub[scalar], color=color_dict[tract], linewidth=1.8, label=tract.replace("Callosum ", ""), ) _style_axis(ax, tract + " " + display_string(scalar)) for ax in flat_axes[n_panels:]: ax.set_visible(False) fig1.suptitle(display_string(scalar), fontsize=fontsize + 2, fontweight="bold") fig1.tight_layout(rect=[0, 0, 1, 0.97]) if file_name is not None: fig1.savefig(file_name, dpi=300, bbox_inches="tight") return fig1, axes1