Ejemplo n.º 1
0
def compare_motifs(struct_mat, func_mat, name, bins=50, N=4):
    from pynets.stats.netmotifs import adaptivethresh
    from pynets.core.thresholding import standardize
    from scipy import spatial
    import pandas as pd
    from py3plex.core import multinet

    # Structural graph threshold window
    struct_mat = standardize(struct_mat)
    dims_struct = struct_mat.shape[0]
    struct_mat[range(dims_struct), range(dims_struct)] = 0
    tmin_struct = struct_mat.min()
    tmax_struct = struct_mat.max()
    threshes_struct = np.linspace(tmin_struct, tmax_struct, bins)

    # Functional graph threshold window
    func_mat = standardize(func_mat)
    dims_func = func_mat.shape[0]
    func_mat[range(dims_func), range(dims_func)] = 0
    tmin_func = func_mat.min()
    tmax_func = func_mat.max()
    threshes_func = np.linspace(tmin_func, tmax_func, bins)

    assert np.all(
        struct_mat == struct_mat.T), "Structural Matrix must be symmetric"
    assert np.all(
        func_mat == func_mat.T), "Functional Matrix must be symmetric"

    # list of
    mlib = ['1113', '1122', '1223', '2222', '2233', '3333']

    # Count motifs
    print("%s%s%s%s" % ('Mining ', N, '-node motifs: ', mlib))
    motif_dict = {}
    for thr_struct, thr_func in list(
            itertools.product(threshes_struct, threshes_func)):
        # Count
        at_struct = adaptivethresh(struct_mat, float(thr_struct), mlib, N)
        at_func = adaptivethresh(func_mat, float(thr_func), mlib, N)

        motif_dict["%s%s%s%s" % ('struct_', np.round(
            thr_struct, 4), '_func_', np.round(thr_func, 4))] = {}
        motif_dict["%s%s%s%s" % ('struct_', np.round(thr_struct, 4), '_func_',
                                 np.round(thr_func, 4))]['struct'] = at_struct
        motif_dict["%s%s%s%s" % ('struct_', np.round(
            thr_struct, 4), '_func_', np.round(thr_func, 4))]['func'] = at_func

        print("%s%s%s%s%s" %
              ('Layer 1 (structural) with absolute threshold of : ',
               thr_struct, ' yields ', np.sum(at_struct), ' total motifs'))
        print("%s%s%s%s%s" %
              ('Layer 2 (functional) with absolute threshold of : ', thr_func,
               ' yields ', np.sum(at_func), ' total motifs'))

    for k, v in list(motif_dict.items()):
        if np.sum(v['struct']) == 0 or np.sum(v['func']) == 0:
            del motif_dict[k]

    for k, v in list(motif_dict.items()):
        motif_dict[k]['dist'] = spatial.distance.cosine(v['struct'], v['func'])

    df = pd.DataFrame(motif_dict).T

    df['struct_func_3333'] = np.zeros(len(df))
    df['struct_func_2233'] = np.zeros(len(df))
    df['struct_func_2222'] = np.zeros(len(df))
    df['struct_func_1223'] = np.zeros(len(df))
    df['struct_func_1122'] = np.zeros(len(df))
    df['struct_func_1113'] = np.zeros(len(df))
    df['struct_3333'] = np.zeros(len(df))
    df['func_3333'] = np.zeros(len(df))
    df['struct_2233'] = np.zeros(len(df))
    df['func_2233'] = np.zeros(len(df))
    df['struct_2222'] = np.zeros(len(df))
    df['func_2222'] = np.zeros(len(df))
    df['struct_1223'] = np.zeros(len(df))
    df['func_1223'] = np.zeros(len(df))
    df['struct_1122'] = np.zeros(len(df))
    df['func_1122'] = np.zeros(len(df))
    df['struct_1113'] = np.zeros(len(df))
    df['func_1113'] = np.zeros(len(df))

    for idx in range(len(df)):
        df.set_value(df.index[idx], 'struct_3333', df['struct'][idx][-1])
        df.set_value(df.index[idx], 'func_3333', df['func'][idx][-1])

        df.set_value(df.index[idx], 'struct_2233', df['struct'][idx][-2])
        df.set_value(df.index[idx], 'func_2233', df['func'][idx][-2])

        df.set_value(df.index[idx], 'struct_2222', df['struct'][idx][-3])
        df.set_value(df.index[idx], 'func_2222', df['func'][idx][-3])

        df.set_value(df.index[idx], 'struct_1223', df['struct'][idx][-4])
        df.set_value(df.index[idx], 'func_1223', df['func'][idx][-4])

        df.set_value(df.index[idx], 'struct_1122', df['struct'][idx][-5])
        df.set_value(df.index[idx], 'func_1122', df['func'][idx][-5])

        df.set_value(df.index[idx], 'struct_1113', df['struct'][idx][-6])
        df.set_value(df.index[idx], 'func_1113', df['func'][idx][-6])

    df['struct_func_3333'] = np.abs(df['struct_3333'] - df['func_3333'])
    df['struct_func_2233'] = np.abs(df['struct_2233'] - df['func_2233'])
    df['struct_func_2222'] = np.abs(df['struct_2222'] - df['func_2222'])
    df['struct_func_1223'] = np.abs(df['struct_1223'] - df['func_1223'])
    df['struct_func_1122'] = np.abs(df['struct_1122'] - df['func_1122'])
    df['struct_func_1113'] = np.abs(df['struct_1113'] - df['func_1113'])

    df = df[(df.struct_3333 != 0) & (df.func_3333 != 0) & (df.struct_2233 != 0)
            & (df.func_2233 != 0) & (df.struct_2222 != 0) & (df.func_2222 != 0)
            & (df.struct_1223 != 0) & (df.func_1223 != 0) &
            (df.struct_1122 != 0) & (df.func_1122 != 0) & (df.struct_1113 != 0)
            & (df.func_1113 != 0)]

    df = df.sort_values(by=[
        'dist', 'struct_func_3333', 'struct_func_2233', 'struct_func_2222',
        'struct_func_1223', 'struct_func_1122', 'struct_func_1113',
        'struct_3333', 'func_3333', 'struct_2233', 'func_2233', 'struct_2222',
        'func_2222', 'struct_1223', 'func_1223', 'struct_1122', 'func_1122',
        'struct_1113', 'func_1113'
    ],
                        ascending=[
                            True, True, True, True, True, True, True, False,
                            False, False, False, False, False, False, False,
                            False, False, False, False
                        ])

    # Take the top 25th percentile
    df = df[df['dist'] < df['dist'].quantile(0.25)]
    best_threshes = []
    best_mats = []
    #best_graphs = []
    best_multigraphs = []
    for str in list(df.index):
        func_mat_tmp = func_mat.copy()
        struct_mat_tmp = struct_mat.copy()
        struct_thr = float(str.split('_')[1])
        func_thr = float(str.split('_')[3])
        best_threshes.append((struct_thr, func_thr))

        func_mat_tmp[func_mat_tmp < func_thr] = 0
        struct_mat_tmp[struct_mat_tmp < struct_thr] = 0
        best_mats.append((func_mat_tmp, struct_mat_tmp))

        G = build_nx_multigraph(func_mat, struct_mat, str)
        #best_graphs.append(G)

        B = multinet.multi_layer_network(network_type="multiplex",
                                         directed=False)
        B.add_edges([[x, 1, y, 2, z] for x, y, z in list(G.edges)],
                    input_type="list")
        best_multigraphs.append(B)

    mg_dict = dict(zip(best_threshes, best_multigraphs))

    return mg_dict
Ejemplo n.º 2
0
def compare_motifs(struct_mat, func_mat, name, namer_dir, bins=20, N=4):
    '''
    Compare motif structure and population across structural and functional
    graphs to achieve a homeostatic absolute threshold of each that optimizes
    multiplex community detection and analysis.

    Parameters
    ----------
    in_mat : ndarray
        M x M Connectivity matrix
    thr : float
        Absolute threshold [0, 1].
    mlib : list
        List of motif classes.

    Returns
    -------
    mf : ndarray
        1D vector listing the total motifs of size N for each
        class of mlib.

    References
    ----------
    .. [1] Battiston, F., Nicosia, V., Chavez, M., & Latora, V. (2017).
      Multilayer motif analysis of brain networks. Chaos.
      https://doi.org/10.1063/1.4979282

    '''
    from pynets.stats.netmotifs import adaptivethresh
    from pynets.core.thresholding import threshold_absolute
    from pynets.core.thresholding import standardize
    from scipy import spatial
    from nilearn.connectome import sym_matrix_to_vec
    import pandas as pd
    import gc

    mlib = ['1113', '1122', '1223', '2222', '2233', '3333']

    # Standardize structural graph
    struct_mat = standardize(struct_mat)
    dims_struct = struct_mat.shape[0]
    struct_mat[range(dims_struct), range(dims_struct)] = 0
    at_struct = adaptivethresh(struct_mat, float(0.0), mlib, N)
    print("%s%s%s" %
          ('Layer 1 (structural) has: ', np.sum(at_struct), ' total motifs'))

    # Functional graph threshold window
    func_mat = standardize(func_mat)
    dims_func = func_mat.shape[0]
    func_mat[range(dims_func), range(dims_func)] = 0
    tmin_func = func_mat.min()
    tmax_func = func_mat.max()
    threshes_func = np.linspace(tmin_func, tmax_func, bins)

    assert np.all(
        struct_mat == struct_mat.T), "Structural Matrix must be symmetric"
    assert np.all(
        func_mat == func_mat.T), "Functional Matrix must be symmetric"

    # Count motifs
    print("%s%s%s%s" % ('Mining ', N, '-node motifs: ', mlib))
    motif_dict = {}
    motif_dict['struct'] = {}
    motif_dict['func'] = {}

    mat_dict = {}
    mat_dict['struct'] = sym_matrix_to_vec(struct_mat, discard_diagonal=True)
    mat_dict['funcs'] = {}
    for thr_func in threshes_func:
        # Count
        at_func = adaptivethresh(func_mat, float(thr_func), mlib, N)
        motif_dict['struct']["%s%s" %
                             ('thr-', np.round(thr_func, 4))] = at_struct
        motif_dict['func']["%s%s" % ('thr-', np.round(thr_func, 4))] = at_func
        mat_dict['funcs']["%s%s" %
                          ('thr-', np.round(thr_func, 4))] = sym_matrix_to_vec(
                              threshold_absolute(func_mat, thr_func),
                              discard_diagonal=True)

        print("%s%s%s%s%s" %
              ('Layer 2 (functional) with absolute threshold of: ',
               np.round(thr_func,
                        2), ' yields ', np.sum(at_func), ' total motifs'))
        gc.collect()

    df = pd.DataFrame(motif_dict)

    for idx in range(len(df)):
        df.set_value(
            df.index[idx], 'motif_dist',
            spatial.distance.cosine(df['struct'][idx], df['func'][idx]))

    df = df[pd.notnull(df['motif_dist'])]

    for idx in range(len(df)):
        df.set_value(
            df.index[idx], 'graph_dist_cosine',
            spatial.distance.cosine(
                mat_dict['struct'].reshape(-1, 1),
                mat_dict['funcs'][df.index[idx]].reshape(-1, 1)))
        df.set_value(
            df.index[idx], 'graph_dist_correlation',
            spatial.distance.correlation(
                mat_dict['struct'].reshape(-1, 1),
                mat_dict['funcs'][df.index[idx]].reshape(-1, 1)))

    df['struct_func_3333'] = np.zeros(len(df))
    df['struct_func_2233'] = np.zeros(len(df))
    df['struct_func_2222'] = np.zeros(len(df))
    df['struct_func_1223'] = np.zeros(len(df))
    df['struct_func_1122'] = np.zeros(len(df))
    df['struct_func_1113'] = np.zeros(len(df))
    df['struct_3333'] = np.zeros(len(df))
    df['func_3333'] = np.zeros(len(df))
    df['struct_2233'] = np.zeros(len(df))
    df['func_2233'] = np.zeros(len(df))
    df['struct_2222'] = np.zeros(len(df))
    df['func_2222'] = np.zeros(len(df))
    df['struct_1223'] = np.zeros(len(df))
    df['func_1223'] = np.zeros(len(df))
    df['struct_1122'] = np.zeros(len(df))
    df['func_1122'] = np.zeros(len(df))
    df['struct_1113'] = np.zeros(len(df))
    df['func_1113'] = np.zeros(len(df))

    for idx in range(len(df)):
        df.set_value(df.index[idx], 'struct_3333', df['struct'][idx][-1])
        df.set_value(df.index[idx], 'func_3333', df['func'][idx][-1])

        df.set_value(df.index[idx], 'struct_2233', df['struct'][idx][-2])
        df.set_value(df.index[idx], 'func_2233', df['func'][idx][-2])

        df.set_value(df.index[idx], 'struct_2222', df['struct'][idx][-3])
        df.set_value(df.index[idx], 'func_2222', df['func'][idx][-3])

        df.set_value(df.index[idx], 'struct_1223', df['struct'][idx][-4])
        df.set_value(df.index[idx], 'func_1223', df['func'][idx][-4])

        df.set_value(df.index[idx], 'struct_1122', df['struct'][idx][-5])
        df.set_value(df.index[idx], 'func_1122', df['func'][idx][-5])

        df.set_value(df.index[idx], 'struct_1113', df['struct'][idx][-6])
        df.set_value(df.index[idx], 'func_1113', df['func'][idx][-6])

    df['struct_func_3333'] = np.abs(df['struct_3333'] - df['func_3333'])
    df['struct_func_2233'] = np.abs(df['struct_2233'] - df['func_2233'])
    df['struct_func_2222'] = np.abs(df['struct_2222'] - df['func_2222'])
    df['struct_func_1223'] = np.abs(df['struct_1223'] - df['func_1223'])
    df['struct_func_1122'] = np.abs(df['struct_1122'] - df['func_1122'])
    df['struct_func_1113'] = np.abs(df['struct_1113'] - df['func_1113'])

    df = df.drop(columns=['struct', 'func'])

    df = df.loc[~(df == 0).all(axis=1)]

    df = df.sort_values(by=[
        'motif_dist', 'graph_dist_cosine', 'graph_dist_correlation',
        'struct_func_3333', 'struct_func_2233', 'struct_func_2222',
        'struct_func_1223', 'struct_func_1122', 'struct_func_1113',
        'struct_3333', 'func_3333', 'struct_2233', 'func_2233', 'struct_2222',
        'func_2222', 'struct_1223', 'func_1223', 'struct_1122', 'func_1122',
        'struct_1113', 'func_1113'
    ],
                        ascending=[
                            True, True, False, False, False, False, False,
                            False, False, False, False, False, False, False,
                            False, False, False, False, False, False, False
                        ])

    # Take the top 25th percentile
    df = df.head(int(0.25 * len(df)))
    best_threshes = []
    best_mats = []
    best_multigraphs = []
    for key in list(df.index):
        func_mat_tmp = func_mat.copy()
        struct_mat_tmp = struct_mat.copy()
        struct_thr = float(key.split('-')[-1])
        func_thr = float(key.split('-')[-1])
        best_threshes.append(str(func_thr))

        func_mat_tmp[func_mat_tmp < func_thr] = 0
        struct_mat_tmp[struct_mat_tmp < struct_thr] = 0
        best_mats.append((func_mat_tmp, struct_mat_tmp))

        mG = build_mx_multigraph(func_mat, struct_mat, f"{name}_{key}",
                                 namer_dir)
        best_multigraphs.append(mG)

    mg_dict = dict(zip(best_threshes, best_multigraphs))
    g_dict = dict(zip(best_threshes, best_mats))

    return mg_dict, g_dict