Exemplo n.º 1
0
    def normalize_graph(self):
        import graspologic.utils as gu

        # By maximum edge weight
        if self.norm == 1:
            self.in_mat = thresholding.normalize(np.nan_to_num(self.in_mat))
        # Apply log10
        elif self.norm == 2:
            self.in_mat = np.log10(np.nan_to_num(self.in_mat))
        # Apply PTR simple-nonzero
        elif self.norm == 3:
            self.in_mat = gu.ptr.pass_to_ranks(np.nan_to_num(self.in_mat),
                                               method="simple-nonzero")
        # Apply PTR simple-all
        elif self.norm == 4:
            self.in_mat = gu.ptr.pass_to_ranks(np.nan_to_num(self.in_mat),
                                               method="simple-all")
        # Apply PTR zero-boost
        elif self.norm == 5:
            self.in_mat = gu.ptr.pass_to_ranks(np.nan_to_num(self.in_mat),
                                               method="zero-boost")
        # Apply standardization [0, 1]
        elif self.norm == 6:
            self.in_mat = thresholding.standardize(np.nan_to_num(self.in_mat))
        elif self.norm == 7:
            # Get hyperbolic tangent (i.e. fischer r-to-z transform) of matrix
            # if non-covariance
            self.in_mat = np.arctanh(self.in_mat)
        else:
            pass

        self.in_mat = thresholding.autofix(self.in_mat)
        self.G = nx.from_numpy_array(self.in_mat)

        return self.G
Exemplo n.º 2
0
    def __init__(self,
                 est_path,
                 prune,
                 norm,
                 out_fmt="gpickle",
                 remove_self_loops=True):
        import graspologic.utils as gu

        self.est_path = est_path
        self.prune = prune
        self.norm = norm
        self.out_fmt = out_fmt
        self.in_mat = None

        # Load and threshold matrix
        self.in_mat_raw = utils.load_mat(self.est_path)

        # De-diagnal and remove nan's and inf's, ensure edge weights are
        # positive
        self.in_mat = np.array(
            np.array(thresholding.autofix(np.array(np.abs(self.in_mat_raw)))))

        # Remove self-loops and ensure symmetry
        if remove_self_loops is True:
            self.in_mat = gu.remove_loops(gu.symmetrize(self.in_mat))
        else:
            self.in_mat = gu.symmetrize(self.in_mat)

        self.in_mat[np.where(np.isnan(self.in_mat)
                             | np.isinf(self.in_mat))] = 0

        # Create nx graph
        self.G = nx.from_numpy_array(self.in_mat)
Exemplo n.º 3
0
def plot_all_struct(conn_matrix, conn_model, atlas, dir_path, ID, network, labels, roi, coords, thr,
                    node_size, edge_threshold, prune, uatlas, target_samples, norm, binary, track_type, directget,
                    max_length):
    """
    Plot adjacency matrix, connectogram, and glass brain for functional connectome.

    Parameters
    ----------
    conn_matrix : array
        NxN matrix.
    conn_model : str
       Connectivity estimation model (e.g. corr for correlation, cov for covariance, sps for precision covariance,
       partcorr for partial correlation). sps type is used by default.
    atlas : str
        Name of atlas parcellation used.
    dir_path : str
        Path to directory containing subject derivative data for given run.
    ID : str
        A subject id or other unique identifier.
    network : str
        Resting-state network based on Yeo-7 and Yeo-17 naming (e.g. 'Default') used to filter nodes in the study of
        brain subgraphs.
    labels : list
        List of string labels corresponding to ROI nodes.
    roi : str
        File path to binarized/boolean region-of-interest Nifti1Image file.
    coords : list
        List of (x, y, z) tuples corresponding to an a-priori defined set (e.g. a coordinate atlas).
    thr : float
        A value, between 0 and 1, to threshold the graph using any variety of methods
        triggered through other options.
    node_size : int
        Spherical centroid node size in the case that coordinate-based centroids
        are used as ROI's.
    edge_threshold : float
        The actual value, between 0 and 1, that the graph was thresholded (can differ from thr if target was not
        successfully obtained.
    prune : bool
        Indicates whether to prune final graph of disconnected nodes/isolates.
    uatlas : str
        File path to atlas parcellation Nifti1Image in MNI template space.
    target_samples : int
        Total number of streamline samples specified to generate streams.
    norm : int
        Indicates method of normalizing resulting graph.
    binary : bool
        Indicates whether to binarize resulting graph edges to form an
        unweighted graph.
    track_type : str
        Tracking algorithm used (e.g. 'local' or 'particle').
    directget : str
        The statistical approach to tracking. Options are: det (deterministic), closest (clos), boot (bootstrapped),
        and prob (probabilistic).
    max_length : int
        Maximum fiber length threshold in mm to restrict tracking.
    """
    import matplotlib
    matplotlib.use('agg')
    import os
    import os.path as op
    from matplotlib import pyplot as plt
    from nilearn import plotting as niplot
    import pkg_resources
    import networkx as nx
    from matplotlib import colors
    import seaborn as sns
    from pynets.core import thresholding
    from pynets.plotting import plot_gen, plot_graphs
    from pynets.stats.netstats import most_important, prune_disconnected
    try:
        import cPickle as pickle
    except ImportError:
        import _pickle as pickle

    ch2better_loc = pkg_resources.resource_filename("pynets", "templates/ch2better.nii.gz")

    coords = list(coords)
    labels = list(labels)
    if len(coords) > 0:
        dpi_resolution = 500
        if '\'b' in atlas:
            atlas = atlas.decode('utf-8')
        if (prune == 1 or prune == 2) and len(coords) == conn_matrix.shape[0]:
            G_pre = nx.from_numpy_matrix(np.abs(conn_matrix))
            if prune == 1:
                [G, pruned_nodes] = prune_disconnected(G_pre)
            elif prune == 2:
                [G, pruned_nodes] = most_important(G_pre)
            else:
                G = G_pre
                pruned_nodes = []
            pruned_nodes.sort(reverse=True)
            coords_pre = list(coords)
            labels_pre = list(labels)
            if len(pruned_nodes) > 0:
                for j in pruned_nodes:
                    labels_pre.pop(j)
                    coords_pre.pop(j)
                conn_matrix = nx.to_numpy_array(G)
                labels = labels_pre
                coords = coords_pre
            else:
                print('No nodes to prune for plot...')

        coords = list(tuple(x) for x in coords)

        namer_dir = dir_path + '/figures'
        if not os.path.isdir(namer_dir):
            os.makedirs(namer_dir, exist_ok=True)

        # Plot connectogram
        if len(conn_matrix) > 20:
            try:
                plot_gen.plot_connectogram(conn_matrix, conn_model, atlas, namer_dir, ID, network, labels)
            except RuntimeWarning:
                print('\n\n\nWarning: Connectogram plotting failed!')
        else:
            print('Warning: Cannot plot connectogram for graphs smaller than 20 x 20!')

        # Plot adj. matrix based on determined inputs
        if not node_size or node_size == 'None':
            node_size = 'parc'
        plot_graphs.plot_conn_mat_struct(conn_matrix, conn_model, atlas, namer_dir, ID, network, labels, roi, thr,
                                         node_size, target_samples, track_type, directget, max_length)

        # Plot connectome
        out_path_fig = "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (namer_dir, '/', ID, '_modality-dwi_',
                                                                     '%s' % ("%s%s%s" % ('rsn-', network, '_') if
                                                                             network is not None else ''),
                                                                     '%s' % ("%s%s%s" % ('roi-',
                                                                                         op.basename(roi).split(
                                                                                             '.')[0],
                                                                                         '_') if roi is not
                                                                                                 None else ''),
                                                                     'est-', conn_model, '_',
                                                                     '%s' % (
                                                                         "%s%s%s" % ('nodetype-spheres-', node_size,
                                                                                     'mm_')
                                                                         if ((node_size != 'parc') and
                                                                             (node_size is not None))
                                                                         else 'nodetype-parc_'),
                                                                     "%s" % ("%s%s%s" % (
                                                                         'samples-', int(target_samples),
                                                                         'streams_')
                                                                             if float(target_samples) > 0 else '_'),
                                                                     'tt-', track_type, '_dg-', directget,
                                                                     '_ml-', max_length,
                                                                     '_thr-', thr, '_glass_viz.png')
        if roi:
            # Save coords to pickle
            coord_path = "%s%s%s%s" % (namer_dir, '/coords_', op.basename(roi).split('.')[0], '_plotting.pkl')
            with open(coord_path, 'wb') as f:
                pickle.dump(coords, f, protocol=2)

            # Save labels to pickle
            labels_path = "%s%s%s%s" % (namer_dir, '/labelnames_', op.basename(roi).split('.')[0], '_plotting.pkl')
            with open(labels_path, 'wb') as f:
                pickle.dump(labels, f, protocol=2)
        else:
            # Save coords to pickle
            coord_path = "%s%s" % (namer_dir, '/coords_plotting.pkl')
            with open(coord_path, 'wb') as f:
                pickle.dump(coords, f, protocol=2)

            # Save labels to pickle
            labels_path = "%s%s" % (namer_dir, '/labelnames_plotting.pkl')
            with open(labels_path, 'wb') as f:
                pickle.dump(labels, f, protocol=2)

        connectome = niplot.plot_connectome(np.zeros(shape=(1, 1)), [(0, 0, 0)], node_size=0.0001, black_bg=True)
        connectome.add_overlay(ch2better_loc, alpha=0.45, cmap=plt.cm.gray)
        #connectome.add_overlay(ch2better_loc, alpha=0.35, cmap=plt.cm.gray)
        conn_matrix = np.array(np.array(thresholding.autofix(conn_matrix)))
        [z_min, z_max] = -np.abs(conn_matrix).max(), np.abs(conn_matrix).max()
        if node_size == 'parc':
            node_size_plot = int(6)
        else:
            node_size_plot = int(node_size)
        if len(coords) != conn_matrix.shape[0]:
            raise RuntimeWarning('\nWARNING: Number of coordinates does not match conn_matrix dimensions.')
        else:
            norm = colors.Normalize(vmin=-1, vmax=1)
            clust_pal = sns.color_palette("Blues_r", conn_matrix.shape[0])
            clust_colors = colors.to_rgba_array(clust_pal)
            fa_path = dir_path + '/../reg_dmri/dmri_tmp/DSN/Warped.nii.gz'
            if os.path.isfile(fa_path):
                connectome.add_overlay(img=fa_path,
                                       threshold=0.01, alpha=0.25, cmap=plt.cm.copper)

            connectome.add_graph(conn_matrix, coords, edge_threshold=edge_threshold, edge_cmap=plt.cm.binary,
                                 edge_vmax=float(z_max), edge_vmin=float(z_min), node_size=node_size_plot,
                                 node_color=clust_colors)
            connectome.savefig(out_path_fig, dpi=dpi_resolution)
    else:
        raise RuntimeError('\nERROR: no coordinates to plot! Are you running plotting outside of pynets\'s internal '
                           'estimation schemes?')

    plt.close('all')

    return
Exemplo n.º 4
0
def plot_all_func(conn_matrix, conn_model, atlas, dir_path, ID, network, labels, roi, coords, thr,
                  node_size, edge_threshold, smooth, prune, uatlas, c_boot, norm, binary, hpass):
    """
    Plot adjacency matrix, connectogram, and glass brain for functional connectome.

    Parameters
    ----------
    conn_matrix : array
        NxN matrix.
    conn_model : str
       Connectivity estimation model (e.g. corr for correlation, cov for covariance, sps for precision covariance,
       partcorr for partial correlation). sps type is used by default.
    atlas : str
        Name of atlas parcellation used.
    dir_path : str
        Path to directory containing subject derivative data for given run.
    ID : str
        A subject id or other unique identifier.
    network : str
        Resting-state network based on Yeo-7 and Yeo-17 naming (e.g. 'Default') used to filter nodes in the study of
        brain subgraphs.
    labels : list
        List of string labels corresponding to ROI nodes.
    roi : str
        File path to binarized/boolean region-of-interest Nifti1Image file.
    coords : list
        List of (x, y, z) tuples corresponding to an a-priori defined set (e.g. a coordinate atlas).
    thr : float
        A value, between 0 and 1, to threshold the graph using any variety of methods
        triggered through other options.
    node_size : int
        Spherical centroid node size in the case that coordinate-based centroids
        are used as ROI's.
    edge_threshold : float
        The actual value, between 0 and 1, that the graph was thresholded (can differ from thr if target was not
        successfully obtained.
    smooth : int
        Smoothing width (mm fwhm) to apply to time-series when extracting signal from ROI's.
    prune : bool
        Indicates whether to prune final graph of disconnected nodes/isolates.
    uatlas : str
        File path to atlas parcellation Nifti1Image in MNI template space.
    c_boot : int
        Number of bootstraps if user specified circular-block bootstrapped resampling of the node-extracted time-series.
    norm : int
        Indicates method of normalizing resulting graph.
    binary : bool
        Indicates whether to binarize resulting graph edges to form an
        unweighted graph.
    hpass : bool
        High-pass filter values (Hz) to apply to node-extracted time-series.
    """
    import os
    import os.path as op
    import matplotlib
    matplotlib.use('agg')
    from matplotlib import pyplot as plt
    from nilearn import plotting as niplot
    import pkg_resources
    import networkx as nx
    from pynets.core import thresholding
    from pynets.plotting import plot_gen, plot_graphs
    from pynets.stats.netstats import most_important, prune_disconnected
    try:
        import cPickle as pickle
    except ImportError:
        import _pickle as pickle

    ch2better_loc = pkg_resources.resource_filename("pynets", "templates/ch2better.nii.gz")

    coords = list(coords)
    labels = list(labels)
    if len(coords) > 0:
        dpi_resolution = 500
        if '\'b' in atlas:
            atlas = atlas.decode('utf-8')
        if (prune == 1 or prune == 2) and len(coords) == conn_matrix.shape[0]:
            G_pre = nx.from_numpy_matrix(np.abs(conn_matrix))
            if prune == 1:
                [G, pruned_nodes] = prune_disconnected(G_pre)
            elif prune == 2:
                [G, pruned_nodes] = most_important(G_pre)
            else:
                G = G_pre
                pruned_nodes = []
            pruned_nodes.sort(reverse=True)
            print('(Display)')
            coords_pre = list(coords)
            labels_pre = list(labels)
            if len(pruned_nodes) > 0:
                for j in pruned_nodes:
                    labels_pre.pop(j)
                    coords_pre.pop(j)
                conn_matrix = nx.to_numpy_array(G)
                labels = labels_pre
                coords = coords_pre
            else:
                print('No nodes to prune for plot...')

        coords = list(tuple(x) for x in coords)

        namer_dir = dir_path + '/figures'
        if not os.path.isdir(namer_dir):
            os.makedirs(namer_dir, exist_ok=True)

        # Plot connectogram
        if len(conn_matrix) > 20:
            try:
                plot_gen.plot_connectogram(conn_matrix, conn_model, atlas, namer_dir, ID, network, labels)
            except RuntimeWarning:
                print('\n\n\nWarning: Connectogram plotting failed!')
        else:
            print('Warning: Cannot plot connectogram for graphs smaller than 20 x 20!')

        # Plot adj. matrix based on determined inputs
        if not node_size or node_size == 'None':
            node_size = 'parc'
        plot_graphs.plot_conn_mat_func(conn_matrix, conn_model, atlas, namer_dir, ID, network, labels, roi, thr,
                                       node_size, smooth, c_boot, hpass)

        # Plot connectome
        out_path_fig = "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (namer_dir, '/', ID, '_modality-func_',
                                                             '%s' % ("%s%s%s" % ('rsn-', network, '_') if
                                                                     network is not None else ''),
                                                             '%s' % ("%s%s%s" % ('roi-', op.basename(roi).split('.')[0],
                                                                                 '_') if roi is not None else ''),
                                                             'est-', conn_model, '_',
                                                             '%s' % (
                                                                 "%s%s%s" % ('nodetype-spheres-', node_size, 'mm_') if
                                                                 ((node_size != 'parc') and (node_size is not None))
                                                                 else 'nodetype-parc_'),
                                                             "%s" % ("%s%s%s" % ('boot-', int(c_boot), 'iter_') if
                                                                     float(c_boot) > 0 else ''),
                                                             "%s" % ("%s%s%s" % ('smooth-', smooth, 'fwhm_') if
                                                                     float(smooth) > 0 else ''),
                                                             "%s" % ("%s%s%s" % ('hpass-', hpass, 'Hz_') if
                                                                     hpass is not None else ''),
                                                             '_thr-', thr, '_glass_viz.png')
        if roi:
            # Save coords to pickle
            coord_path = "%s%s%s%s" % (namer_dir, '/coords_', op.basename(roi).split('.')[0], '_plotting.pkl')
            with open(coord_path, 'wb') as f:
                pickle.dump(coords, f, protocol=2)

            # Save labels to pickle
            labels_path = "%s%s%s%s" % (namer_dir, '/labelnames_', op.basename(roi).split('.')[0], '_plotting.pkl')
            with open(labels_path, 'wb') as f:
                pickle.dump(labels, f, protocol=2)

        else:
            # Save coords to pickle
            coord_path = "%s%s" % (namer_dir, '/coords_plotting.pkl')
            with open(coord_path, 'wb') as f:
                pickle.dump(coords, f, protocol=2)

            # Save labels to pickle
            labels_path = "%s%s" % (namer_dir, '/labelnames_plotting.pkl')
            with open(labels_path, 'wb') as f:
                pickle.dump(labels, f, protocol=2)

        connectome = niplot.plot_connectome(np.zeros(shape=(1, 1)), [(0, 0, 0)], node_size=0.0001, black_bg=True)
        connectome.add_overlay(ch2better_loc, alpha=0.45, cmap=plt.cm.gray)
        #connectome.add_overlay(ch2better_loc, alpha=0.35, cmap=plt.cm.gray)
        conn_matrix = np.array(np.array(thresholding.autofix(conn_matrix)))
        [z_min, z_max] = -np.abs(conn_matrix).max(), np.abs(conn_matrix).max()
        if node_size == 'parc':
            node_size_plot = int(6)
        else:
            node_size_plot = int(node_size)
        if len(coords) != conn_matrix.shape[0]:
            raise RuntimeWarning('\nWARNING: Number of coordinates does not match conn_matrix dimensions. If you are '
                                 'using disparity filtering, try relaxing the α threshold.')
        else:
            color_theme = 'Blues'
            #color_theme = 'Greens'
            #color_theme = 'Reds'
            node_color = 'auto'
            connectome.add_graph(conn_matrix, coords, edge_threshold=edge_threshold, edge_cmap=color_theme,
                                 edge_vmax=float(z_max), edge_vmin=float(z_min), node_size=node_size_plot,
                                 node_color='auto')
            connectome.savefig(out_path_fig, dpi=dpi_resolution)
    else:
        raise RuntimeError('\nERROR: no coordinates to plot! Are you running plotting outside of pynets\'s internal '
                           'estimation schemes?')

    plt.close('all')

    return
Exemplo n.º 5
0
    def _gen_mat_data(n: int=20, m: int=20, p: int=0.50,
                      mat_type: str='sb', binary: bool=False,
                      asfile: bool=True, n_graphs: int=1,
                      lcc: bool=False, modality: str='func'):
        if binary is True:
            wt = 1
        else:
            wt = np.random.uniform

        mat_list = []
        mat_file_list = []

        if n_graphs > 0:
            for nm in range(n_graphs):
                if mat_type == 'er':
                    mat = symmetrize(
                        remove_loops(er_nm(n, m, wt=np.random.uniform,
                                           wtargs=dict(low=0, high=1))))
                elif mat_type == 'sb':
                    if p is None:
                        raise ValueError(
                            f"for mat_type {mat_type}, p cannot be None")
                    mat = symmetrize(
                        remove_loops(sbm(np.array([n]), np.array([[p]]),
                                         wt=wt, wtargs=dict(low=0,
                                                            high=1))))
                else:
                    raise ValueError(f"mat_type {mat_type} not recognized!")

                if lcc is True:
                    mat = largest_connected_component(mat)

                mat_list.append(autofix(mat))

                if asfile is True:
                    path_tmp = tempfile.NamedTemporaryFile(mode='w+',
                                                           suffix='.npy',
                                                           delete=False)
                    mat_path_tmp = str(path_tmp.name)
                    out_folder = f"{str(Path.home())}/test_mats"
                    os.makedirs(out_folder, exist_ok=True)

                    if modality == 'func':
                        mat_path = f"{out_folder}/graph_sub-999_modality-func_" \
                        f"model-corr_template-" \
                        f"MNI152_2mm_" \
                        f"parc_tol-6fwhm_hpass-" \
                        f"0Hz_" \
                        f"signal-mean_thrtype-prop_thr-" \
                        f"{round(random.uniform(0, 1),2)}.npy"
                    elif modality == 'dwi':
                        mat_path = f"{out_folder}/graph_sub-999_modality-func_" \
                        f"model-csa_template-" \
                        f"MNI152_2mm_tracktype-local_" \
                        f"traversal-det_minlength-30_" \
                        f"tol-5_thrtype-prop_thr-" \
                        f"{round(random.uniform(0, 1),2)}.npy"

                    shutil.copyfile(mat_path_tmp, mat_path)
                    np.save(mat_path, mat)
                    mat_file_list.append(mat_path)
                    path_tmp.close()

        return {'mat_list': mat_list, 'mat_file_list': mat_file_list}
Exemplo n.º 6
0
 def test_autofix(x, thr, cp):
     x[1][1] = np.inf
     x[2][1] = np.nan
     s = thresholding.autofix(x)
     assert (np.nan not in s) and (np.inf not in s)
Exemplo n.º 7
0
def motif_matching(
    paths,
    ID,
    atlas,
    namer_dir,
    name_list,
    metadata_list,
    multigraph_list_all,
    graph_path_list_all,
    rsn=None,
):
    import networkx as nx
    import numpy as np
    import glob
    import pickle
    from pynets.core import thresholding
    from pynets.stats.netmotifs import compare_motifs
    from sklearn.metrics.pairwise import cosine_similarity
    from pynets.stats.netstats import community_resolution_selection
    from graspy.utils import remove_loops, symmetrize, get_lcc
    from pynets.core.nodemaker import get_brainnetome_node_attributes

    [struct_graph_path, func_graph_path] = paths
    struct_mat = np.load(struct_graph_path)
    func_mat = np.load(func_graph_path)

    [struct_coords, struct_labels, struct_label_intensities] = \
        get_brainnetome_node_attributes(glob.glob(
        f"{str(Path(struct_graph_path).parent.parent)}/nodes/*.json"),
        struct_mat.shape[0])

    [func_coords, func_labels, func_label_intensities] = \
        get_brainnetome_node_attributes(glob.glob(
        f"{str(Path(func_graph_path).parent.parent)}/nodes/*.json"),
        func_mat.shape[0])

    # Find intersecting nodes across modalities (i.e. assuming the same
    # parcellation, but accomodating for the possibility of dropped nodes)
    diff1 = list(set(struct_label_intensities) - set(func_label_intensities))
    diff2 = list(set(func_label_intensities) - set(struct_label_intensities))
    G_struct = nx.from_numpy_array(struct_mat)
    G_func = nx.from_numpy_array(func_mat)

    bad_idxs = []
    for val in diff1:
        bad_idxs.append(struct_label_intensities.index(val))
        bad_idxs = sorted(list(set(bad_idxs)), reverse=True)
        if type(struct_coords) is np.ndarray:
            struct_coords = list(tuple(x) for x in struct_coords)
    for j in bad_idxs:
        G_struct.remove_node(j)
        print(f"Removing: {(struct_labels[j], struct_coords[j])}...")
        del struct_labels[j], struct_coords[j]

    bad_idxs = []
    for val in diff2:
        bad_idxs.append(func_label_intensities.index(val))
        bad_idxs = sorted(list(set(bad_idxs)), reverse=True)
        if type(func_coords) is np.ndarray:
            func_coords = list(tuple(x) for x in func_coords)
    for j in bad_idxs:
        G_func.remove_node(j)
        print(f"Removing: {(func_labels[j], func_coords[j])}...")
        del func_labels[j], func_coords[j]

    struct_mat = nx.to_numpy_array(G_struct)
    func_mat = nx.to_numpy_array(G_func)

    struct_mat = thresholding.autofix(symmetrize(remove_loops(struct_mat)))

    func_mat = thresholding.autofix(symmetrize(remove_loops(func_mat)))

    if func_mat.shape == struct_mat.shape:
        func_mat[~struct_mat.astype("bool")] = 0
        struct_mat[~func_mat.astype("bool")] = 0
        print(
            "Edge disagreements after matching: ",
            sum(sum(abs(func_mat - struct_mat))),
        )

        metadata = {}
        assert (
            len(struct_coords)
            == len(struct_labels)
            == len(func_coords)
            == len(func_labels)
            == func_mat.shape[0]
        )
        metadata["coords"] = struct_coords
        metadata["labels"] = struct_labels
        metadata_list.append(metadata)

        struct_mat = np.maximum(struct_mat, struct_mat.T)
        func_mat = np.maximum(func_mat, func_mat.T)
        struct_mat = thresholding.standardize(struct_mat)
        func_mat = thresholding.standardize(func_mat)

        struct_node_comm_aff_mat = community_resolution_selection(
            nx.from_numpy_matrix(np.abs(struct_mat))
        )[1]

        func_node_comm_aff_mat = community_resolution_selection(
            nx.from_numpy_matrix(np.abs(func_mat))
        )[1]

        struct_comms = []
        for i in np.unique(struct_node_comm_aff_mat):
            struct_comms.append(struct_node_comm_aff_mat == i)

        func_comms = []
        for i in np.unique(func_node_comm_aff_mat):
            func_comms.append(func_node_comm_aff_mat == i)

        sims = cosine_similarity(struct_comms, func_comms)
        try:
            struct_comm = struct_comms[np.argmax(sims, axis=0)[0]]
        except BaseException:
            print('Matching by structural communities failed...')
            struct_comm = struct_mat
        try:
            func_comm = func_comms[np.argmax(sims, axis=0)[0]]
        except BaseException:
            print('Matching by functional communities failed...')
            func_comm = func_mat

        comm_mask = np.equal.outer(struct_comm, func_comm).astype(bool)

        try:
            assert comm_mask.shape == struct_mat.shape == func_mat.shape
        except AssertionError as e:
            e.args += (comm_mask, comm_mask.shape, struct_mat,
                       struct_mat.shape, func_mat, func_mat.shape)

        try:
            struct_mat[~comm_mask] = 0
        except BaseException:
            print('Skipping community masking...')
        try:
            func_mat[~comm_mask] = 0
        except BaseException:
            print('Skipping community masking...')

        struct_name = struct_graph_path.split("/rawgraph_"
                                              )[-1].split(".npy")[0]
        func_name = func_graph_path.split("/rawgraph_")[-1].split(".npy")[0]
        name = f"sub-{ID}_{atlas}_mplx_Layer-1_{struct_name}_" \
               f"Layer-2_{func_name}"
        name_list.append(name)
        struct_mat = np.maximum(struct_mat, struct_mat.T)
        func_mat = np.maximum(func_mat, func_mat.T)
        try:
            [mldict, g_dict] = compare_motifs(
                struct_mat, func_mat, name, namer_dir)
        except BaseException:
            print(f"Adaptive thresholding by motif comparisons failed "
                  f"for {name}. This usually happens when no motifs are found")
            return [], [], [], []

        multigraph_list_all.append(list(mldict.values())[0])
        graph_path_list = []
        for thr in list(g_dict.keys()):
            multigraph_path_list_dict = {}
            [struct, func] = g_dict[thr]
            struct_out = f"{namer_dir}/struct_{atlas}_{struct_name}.npy"
            func_out = f"{namer_dir}/struct_{atlas}_{func_name}_" \
                       f"motif-{thr}.npy"
            np.save(struct_out, struct)
            np.save(func_out, func)
            multigraph_path_list_dict[f"struct_{atlas}_{thr}"] = struct_out
            multigraph_path_list_dict[f"func_{atlas}_{thr}"] = func_out
            graph_path_list.append(multigraph_path_list_dict)
        graph_path_list_all.append(graph_path_list)
    else:
        print(
            f"Skipping {rsn} rsn, since structural and functional graphs are "
            f"not identical shapes."
        )

    return name_list, metadata_list, multigraph_list_all, graph_path_list_all
Exemplo n.º 8
0
def create_gb_palette(mat,
                      edge_cmap,
                      coords,
                      labels,
                      node_size='auto',
                      node_cmap=None,
                      prune=True):
    """
    Create conectome color palatte based on topography.

    Parameters
    ----------
    mat : array
        NxN matrix.
    edge_cmap: colormap
        colormap used for representing the weight of the edges.
    coords : list
        List of (x, y, z) tuples corresponding to an a-priori defined set (e.g. a coordinate atlas).
    labels : list
        List of string labels corresponding to ROI nodes.
    node_size : int
        Spherical centroid node size in the case that coordinate-based centroids
        are used as ROI's.
    node_size: scalar or array_like
        size(s) of the nodes in points^2.
    node_cmap: colormap
        colormap used for representing the community assignment of the nodes.
    """
    import random
    import seaborn as sns
    import networkx as nx
    from pynets.core import thresholding
    from matplotlib import colors
    from sklearn.preprocessing import minmax_scale
    from pynets.stats.netstats import community_resolution_selection, prune_disconnected

    mat = np.array(np.array(thresholding.autofix(mat)))
    if prune is True:
        [G,
         pruned_nodes] = prune_disconnected(nx.from_numpy_matrix(np.abs(mat)))
        pruned_nodes.sort(reverse=True)
        coords_pre = list(coords)
        labels_pre = list(labels)
        if len(pruned_nodes) > 0:
            for j in pruned_nodes:
                del labels_pre[j], coords_pre[j]
            mat = nx.to_numpy_array(G)
            labels = labels_pre
            coords = coords_pre
        else:
            print('No nodes to prune for plotting...')
    else:
        G = nx.from_numpy_matrix(np.abs(mat))

    # Node centralities
    try:
        node_centralities = list(
            nx.algorithms.eigenvector_centrality_numpy(
                G, weight='weight').values())
    except:
        node_centralities = len(coords) * [1]
    max_node_size = (1 / mat.shape[0] *
                     1e3 if node_size == 'auto' else node_size)
    node_sizes = np.array(
        minmax_scale(node_centralities, feature_range=(1, max_node_size)))

    # Node communities
    _, node_comm_aff_mat, resolution, num_comms = community_resolution_selection(
        G)

    # Path lengths
    edge_lengths = []
    for edge_dict in [i[1] for i in nx.all_pairs_shortest_path_length(G)]:
        edge_lengths.extend(list(edge_dict.values()))

    edge_sizes = np.array(minmax_scale(edge_lengths, feature_range=(0.5, 2)))

    # Nodes
    if not node_cmap:
        # Generate as many randomly distinct colors as num_comms
        def random_color(n):
            ret = []
            r = int(random.random() * 256)
            g = int(random.random() * 256)
            b = int(random.random() * 256)
            step = 256 / n
            for i in range(n):
                r += step
                g += step
                b += step
                r = int(r) % 256
                g = int(g) % 256
                b = int(b) % 256
                ret.append((r, g, b))
            return ret

        flatui = [
            '#{:02x}{:02x}{:02x}'.format(i[0], i[1], i[2])
            for i in random_color(num_comms)
        ]

        try:
            ls_cmap = colors.LinearSegmentedColormap.from_list(
                node_comm_aff_mat, sns.color_palette(flatui,
                                                     n_colors=num_comms))
            matplotlib.cm.register_cmap("community", ls_cmap)
            clust_pal = sns.color_palette("community", n_colors=mat.shape[0])
        except:
            clust_pal = sns.color_palette("Set2", n_colors=mat.shape[0])
    else:
        clust_pal = sns.color_palette(node_cmap, n_colors=mat.shape[0])
    clust_pal_nodes = colors.to_rgba_array(clust_pal)

    # Edges
    z_min = np.percentile(mat[mat > 0], 10)
    z_max = np.percentile(mat[mat > 0], 90)
    edge_cmap_pl = sns.color_palette(edge_cmap)
    clust_pal_edges = colors.ListedColormap(edge_cmap_pl.as_hex())

    return mat, clust_pal_edges, clust_pal_nodes, node_sizes, edge_sizes, z_min, z_max, coords, labels
Exemplo n.º 9
0
def matching(
    paths,
    atlas,
    namer_dir,
):
    import glob
    import networkx as nx
    import numpy as np
    from pynets.core import thresholding
    from pynets.statistics.utils import parse_closest_ixs
    from graspologic.utils import remove_loops, symmetrize, \
        multigraph_lcc_intersection

    [dwi_graph_path, func_graph_path] = paths
    dwi_mat = np.load(dwi_graph_path)
    func_mat = np.load(func_graph_path)
    dwi_mat = thresholding.autofix(symmetrize(remove_loops(dwi_mat)))
    func_mat = thresholding.autofix(symmetrize(remove_loops(func_mat)))
    dwi_mat = thresholding.standardize(dwi_mat)
    func_mat = thresholding.standardize(func_mat)

    node_dict_dwi = parse_closest_ixs(
        glob.glob(f"{str(Path(dwi_graph_path).parent.parent)}"
                  f"/nodes/*.json"), dwi_mat.shape[0])[1]

    node_dict_func = parse_closest_ixs(
        glob.glob(f"{str(Path(func_graph_path).parent.parent)}"
                  f"/nodes/*.json"), func_mat.shape[0])[1]

    G_dwi = nx.from_numpy_array(dwi_mat)
    nx.set_edge_attributes(G_dwi, 'structural',
                           nx.get_edge_attributes(G_dwi, 'weight').values())
    nx.set_node_attributes(G_dwi, dict(node_dict_dwi), name='dwi')
    #G_dwi.nodes(data=True)

    G_func = nx.from_numpy_array(func_mat)
    nx.set_edge_attributes(G_func, 'functional',
                           nx.get_edge_attributes(G_func, 'weight').values())
    nx.set_node_attributes(G_func, dict(node_dict_func), name='func')
    #G_func.nodes(data=True)

    R = G_dwi.copy()
    R.remove_nodes_from(n for n in G_dwi if n not in G_func)
    R.remove_edges_from(e for e in G_dwi.edges if e not in G_func.edges)
    G_dwi = R.copy()

    R = G_func.copy()
    R.remove_nodes_from(n for n in G_func if n not in G_dwi)
    R.remove_edges_from(e for e in G_func.edges if e not in G_dwi.edges)
    G_func = R.copy()

    [G_dwi, G_func] = multigraph_lcc_intersection([G_dwi, G_func])

    def writeJSON(metadata_str, outputdir):
        import json
        import uuid
        modality = metadata_str.split('modality-')[1].split('_')[0]
        metadata_list = [
            i for i in metadata_str.split('modality-')[1].split('_')
            if '-' in i
        ]
        hash = str(uuid.uuid4())
        filename = f"{outputdir}/sidecar_modality-{modality}_{hash}.json"
        metadata_dict = {}
        for meta in metadata_list:
            k, v = meta.split('-')
            metadata_dict[k] = v
        with open(filename, 'w+') as jsonfile:
            json.dump(metadata_dict, jsonfile, indent=4)
        jsonfile.close()
        return hash

    dwi_name = dwi_graph_path.split("/")[-1].split(".npy")[0]
    func_name = func_graph_path.split("/")[-1].split(".npy")[0]

    dwi_hash = writeJSON(dwi_name, namer_dir)
    func_hash = writeJSON(func_name, namer_dir)

    name = f"{atlas}_mplx_layer1-dwi_ensemble-{dwi_hash}_" \
           f"layer2-func_ensemble-{func_hash}"

    dwi_opt, func_opt, best_mi = optimize_mutual_info(
        nx.to_numpy_array(G_dwi), nx.to_numpy_array(G_func), bins=50)

    func_mat_final = list(func_opt.values())[0]
    dwi_mat_final = list(dwi_opt.values())[0]
    G_dwi_final = nx.from_numpy_array(dwi_mat_final)
    G_func_final = nx.from_numpy_array(func_mat_final)

    G_multi = nx.OrderedMultiGraph(nx.compose(G_dwi_final, G_func_final))

    out_name = f"{name}_matchthr-{list(dwi_opt.keys())[0]}_" \
               f"{list(func_opt.keys())[0]}"
    mG = build_mx_multigraph(nx.to_numpy_array(G_func_final),
                             nx.to_numpy_array(G_dwi_final), out_name,
                             namer_dir)

    mG_nx = f"{namer_dir}/{out_name}.gpickle"
    nx.write_gpickle(G_multi, mG_nx)

    dwi_file_out = f"{namer_dir}/{dwi_name}.npy"
    func_file_out = f"{namer_dir}/{func_name}.npy"
    np.save(dwi_file_out, dwi_mat_final)
    np.save(func_file_out, func_mat_final)
    return mG_nx, mG, dwi_file_out, func_file_out