Esempio n. 1
0
def test_tensor_input():
    X = np.random.normal(size=(100, 5, 5))
    mds = ClassicalMDS(n_components=3, dissimilarity="euclidean")
    mds.fit(X)

    assert_equal(mds.dissimilarity_matrix_.shape, (100, 100))

    X_transformed = mds.fit_transform(X)
    assert_equal(X_transformed.shape, (100, 3))
Esempio n. 2
0
    def use_fit_transform():
        A = np.ones((4, 4)) - np.identity(4)

        mds = ClassicalMDS(n_components=3, dissimilarity="precomputed")
        B = mds.fit_transform(A)

        Ahat = _compute_dissimilarity(B)

        # Checks up to 7 decimal points
        assert_almost_equal(A, Ahat)
Esempio n. 3
0
    def use_fit():
        A = np.ones((4, 4)) - np.identity(4)

        mds = ClassicalMDS(n_components=3, dissimilarity="precomputed")
        mds.fit(A)
        B = np.dot(mds.components_, np.diag(mds.singular_values_))

        Ahat = _compute_dissimilarity(B)

        # Checks up to 7 decimal points
        assert_almost_equal(A, Ahat)
Esempio n. 4
0
    def use_euclidean():
        A = np.array([
            [-7.62291243e-17, 6.12372436e-01, 4.95031815e-16],
            [-4.97243701e-01, -2.04124145e-01, -2.93397401e-01],
            [5.02711453e-01, -2.04124145e-01, -2.83926977e-01],
            [-5.46775198e-03, -2.04124145e-01, 5.77324378e-01],
        ])

        mds = ClassicalMDS(dissimilarity="euclidean")
        B = mds.fit_transform(A)

        target = np.ones((4, 4)) - np.identity(4)
        assert_almost_equal(mds.dissimilarity_matrix_, target)
Esempio n. 5
0
def _omni_embed(pop_array, atlas, graph_path_list, ID,
                subgraph_name="all_nodes", n_components=None, norm=1):
    """
    Omnibus embedding of arbitrary number of input graphs with matched vertex
    sets.

    Given :math:`A_1, A_2, ..., A_m` a collection of (possibly weighted)
    adjacency matrices of a collection :math:`m` undirected graphs with
    matched vertices.
    Then the :math:`(mn \times mn)` omnibus matrix, :math:`M`, has the
    subgraph where :math:`M_{ij} = \frac{1}{2}(A_i + A_j)`. The omnibus
    matrix is then embedded using adjacency spectral embedding.


    Parameters
    ----------
    pop_array : list of nx.Graph or ndarray, or ndarray
        If list of nx.Graph, each Graph must contain same number of nodes.
        If list of ndarray, each array must have shape (n_vertices,
        n_vertices).
        If ndarray, then array must have shape (n_graphs, n_vertices,
        n_vertices).
    atlas : str
        The name of an atlas (indicating the node definition).
    graph_pathlist : list
        List of file paths to graphs in pop_array.
    ID : str
        An arbitrary subject identifier.
    subgraph_name : str

    Returns
    -------
    out_path : str
        File path to .npy file containing omni embedding tensor.

    References
    ----------
    .. [1] Levin, K., Athreya, A., Tang, M., Lyzinski, V., & Priebe, C. E.
      (2017, November). A central limit theorem for an omnibus embedding of
      multiple random dot product graphs. In Data Mining Workshops (ICDMW),
      2017 IEEE International Conference on (pp. 964-967). IEEE.
    .. [2] Chung, J., Pedigo, B. D., Bridgeford, E. W., Varjavand, B. K.,
      Helm, H. S., & Vogelstein, J. T. (2019). Graspy: Graph statistics in
      python. Journal of Machine Learning Research.

    """
    import os
    import networkx as nx
    import numpy as np
    from pynets.core.utils import flatten
    from graspologic.embed.omni import OmnibusEmbed
    from graspologic.embed.mds import ClassicalMDS
    from joblib import dump
    from pynets.stats.netstats import CleanGraphs

    dir_path = str(Path(os.path.dirname(graph_path_list[0])).parent)

    namer_dir = f"{dir_path}/embeddings"
    if os.path.isdir(namer_dir) is False:
        os.makedirs(namer_dir, exist_ok=True)

    clean_mats = []
    i = 0
    for graph_path in graph_path_list:
        cg = CleanGraphs(None, None, graph_path, 0, norm)

        if float(norm) >= 1:
            G = cg.normalize_graph()
            mat_clean = nx.to_numpy_array(G)
        else:
            mat_clean = pop_array[i]

        mat_clean[np.where(np.isnan(mat_clean) | np.isinf(mat_clean))] = 0
        if np.isnan(np.sum(mat_clean)) == False:
            clean_mats.append(mat_clean)
        i += 1

    clean_mats = [i for i in clean_mats if np.isfinite(i).all()]

    if len(clean_mats) > 0:
        # Omnibus embedding
        print(
            f"{'Embedding unimodal omnetome for atlas: '}{atlas} and "
            f"{subgraph_name}{'...'}"
        )
        omni = OmnibusEmbed(n_components=n_components, check_lcc=False)
        mds = ClassicalMDS(n_components=n_components)
        omni_fit = omni.fit_transform(clean_mats)

        # Transform omnibus tensor into dissimilarity feature
        mds_fit = mds.fit_transform(omni_fit.reshape(omni_fit.shape[1],
                                                     omni_fit.shape[2],
                                                     omni_fit.shape[0]))

        out_path = (
            f"{namer_dir}/gradient-OMNI_{atlas}_{subgraph_name}_"
            f"{os.path.basename(graph_path_list[0]).split('_thrtype')[0]}.npy"
        )

        # out_path_est_omni = f"{namer_dir}/gradient-OMNI_{atlas}_" \
        #                     f"{subgraph_name}_" \
        #                     f"{os.path.basename(graph_path).split(
        #                     '_thrtype')[0]}" \
        #                     f"_MDS.joblib"
        # out_path_est_mds = f"{namer_dir}/gradient-OMNI_{atlas}_" \
        #                    f"{subgraph_name}_" \
        #                    f"{os.path.basename(graph_path).split(
        #                    '_thrtype')[0]}" \
        #                    f"_MDS.joblib"

        # dump(omni, out_path_est_omni)
        # dump(omni, out_path_est_mds)

        print("Saving...")
        np.save(out_path, mds_fit)
        del mds, mds_fit, omni, omni_fit
    else:
        # Add a null tmp file to prevent pool from breaking
        out_path = f"{namer_dir}/gradient-OMNI" \
                   f"_{atlas}_{subgraph_name}_" \
                   f"{os.path.basename(graph_path_list[0])}_NULL"
        if not os.path.exists(out_path):
            os.mknod(out_path)
    return out_path
Esempio n. 6
0
def test_input():
    X = np.random.normal(0, 1, size=(10, 3))

    # X cannot be tensor when precomputed dissimilarity
    with pytest.raises(ValueError):
        tensor = np.random.normal(0, 1, size=(10, 3, 3))
        mds = ClassicalMDS(n_components=3, dissimilarity="precomputed")
        mds.fit(tensor)

    with pytest.raises(ValueError):
        one_dimensional = np.random.normal(size=10)
        mds = ClassicalMDS(n_components=2, dissimilarity="euclidean")
        mds.fit(one_dimensional)

    # n_components > n_samples
    with pytest.raises(ValueError):
        mds = ClassicalMDS(n_components=100)
        mds.fit(X)

    # Invalid n_components
    with pytest.raises(ValueError):
        mds = ClassicalMDS(n_components=-2)

    with pytest.raises(TypeError):
        mds = ClassicalMDS(n_components="1")

    # Invalid dissimilarity
    with pytest.raises(ValueError):
        mds = ClassicalMDS(dissimilarity="abc")

    # Invalid input for fit function
    with pytest.raises(ValueError):
        mds = ClassicalMDS(n_components=3, dissimilarity="precomputed")
        mds.fit(X="bad_input")

    # Must be square and symmetric matrix if precomputed dissimilarity
    with pytest.raises(ValueError):
        mds = ClassicalMDS(n_components=3, dissimilarity="precomputed")
        mds.fit(X)
Esempio n. 7
0
 def test_sklearn_conventions(self):
     check_estimator(ClassicalMDS())