コード例 #1
0
def random_simple_deg_seq(sequence, brain_size=[7., 7., 7.], seed=None,
                          tries=10):
    '''Wrapper function to get a SIMPLE (no parallel or self-loop edges) graph
    that has a given degree sequence.

    This graph is used conventionally as a control because it yields a random
    graph that accounts for degree distribution.

    Parameters:
        sequence: list of int
            Degree of each node to be added to the graph.
        brain_size: list of 3 floats
            Size of the brain to use when distributing  node locations.
            Added for convenience, but does not affect connectivity pattern.
        seed: hashable object for random seed
            Seed for the random number generator.
        tries: int
            Number of attempts at creating graph (function will retry if
            self-loops exist.
    Returns:
        Networkx graph object, adjacency matrix, and random distances'''

    G = nx.random_degree_sequence_graph(sequence=sequence, seed=seed,
                                        tries=tries)

    A = nx.adjacency_matrix(G)
    N = len(sequence)
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))
    D = aux_tools.dist_mat(centroids)

    return G, A, D
コード例 #2
0
ファイル: brain_subgraph.py プロジェクト: wronk/dbw
def cortex_distance_matrix(lm_dir=LINEAR_MODEL_DIRECTORY, 
                           cent_dir=STRUCTURE_DIRECTORY, in_mm=True):
    """Compute distance matrix from centroid data.
    
    Args:
        lm_dir: Directory containing linear model data
        cent_dir: Directory containing centroid data
        in_mm: Set to true to return dist matrix in mm instead of 100um units
    Returns:
        distance matrix, centroid matrix"""
    # Get labels
    _, _, labels = aux.load_W_and_P(data_dir=lm_dir)
    
    # Get mask of areas in cortex
    mask = aux.mask_specific_structures(labels, ['CTX'])
    
    # Get new labels
    labels = list(np.array(labels)[mask])
    
    # Load centroids
    centroids = aux.load_centroids(labels, data_dir=cent_dir, in_mm=in_mm)
    # Compute distance matrix
    dist_mat = aux_tools.dist_mat(centroids)
    
    return dist_mat, labels
コード例 #3
0
def ER_distance(N=bc.num_brain_nodes, p=bc.num_brain_edges_directed, brain_size=[7., 7., 7.]):
    """Create an directed Erdos-Renyi random graph in which each node is
    assigned a position in space, so that relative positions are represented
    by a distance matrix."""
    # Make graph & get adjacency matrix
    G = nx.erdos_renyi_graph(N, p, directed=True)
    A = nx.adjacency_matrix(G)
    # Randomly distribute nodes in space & compute distance matrix
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))
    D = aux_tools.dist_mat(centroids)

    return G, A.todense(), D
コード例 #4
0
def ER_distance(N=426, p=.086, brain_size=[7., 7., 7.]):
    """Create an Erdos-Renyi random graph in which each node is assigned a
    position in space, so that relative positions are represented by a distance
    matrix."""
    # Make graph & get adjacency matrix
    G = nx.erdos_renyi_graph(N, p)
    A = nx.adjacency_matrix(G)
    # Randomly distribute nodes in space & compute distance matrix
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))
    D = aux_tools.dist_mat(centroids)

    return G, A, D
コード例 #5
0
def random_directed_deg_seq(in_sequence,
                            out_sequence,
                            simplify,
                            brain_size=[7., 7., 7.],
                            create_using=None,
                            seed=None):
    '''Wrapper function to get a MULTIGRAPH (parallel or self-loop edges may
    exist) given degree sequence. Chance of parallel/multiedges diminish
    as graph has more nodes.

    This graph is used conventionally as a control because it yields a random
    graph that accounts for degree distribution.

    Parameters:
    -----------
        in_sequence: list of int
            In degree of each node to be added to the graph.
        out_sequence: list of int
            Out degree of each node to be added to the graph.
        simplify: bool
            Whether or not to remove  self-loops and parallel edges. Will
            change degree sequence slightly, but effect diminishes with
            increasing size of graphs.
        brain_size: list of 3 floats
            Size of the brain to use when distributing  node locations.
        create_using: graph, optional
            Return graph of this type. The instance will be cleared.
        seed: hashable object for random seed
            Seed for the random number generator.
    Returns:
    --------
        Networkx graph object, adjacency matrix, and random distances'''

    # Create configuration model using specified properties
    G = nx.directed_configuration_model(in_sequence,
                                        out_sequence,
                                        create_using=create_using,
                                        seed=seed)
    if simplify:
        G = nx.DiGraph(G)  # Remove parallel edges
        G.remove_edges_from(G.selfloop_edges())  # Remove self loops

    # Get adjacency info and create random spatial locations
    A = nx.adjacency_matrix(G)
    N = len(in_sequence)
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))
    D = aux_tools.dist_mat(centroids)

    return G, A, D
コード例 #6
0
def random_directed_deg_seq(in_sequence, out_sequence, simplify,
                            brain_size=[7., 7., 7.], create_using=None,
                            seed=None):
    '''Wrapper function to get a MULTIGRAPH (parallel or self-loop edges may
    exist) given degree sequence. Chance of parallel/multiedges diminish
    as graph has more nodes.

    This graph is used conventionally as a control because it yields a random
    graph that accounts for degree distribution.

    Parameters:
    -----------
        in_sequence: list of int
            In degree of each node to be added to the graph.
        out_sequence: list of int
            Out degree of each node to be added to the graph.
        simplify: bool
            Whether or not to remove  self-loops and parallel edges. Will
            change degree sequence slightly, but effect diminishes with
            increasing size of graphs.
        brain_size: list of 3 floats
            Size of the brain to use when distributing  node locations.
        create_using: graph, optional
            Return graph of this type. The instance will be cleared.
        seed: hashable object for random seed
            Seed for the random number generator.
    Returns:
    --------
        Networkx graph object, adjacency matrix, and random distances'''

    # Create configuration model using specified properties
    G = nx.directed_configuration_model(in_sequence, out_sequence,
                                        create_using=create_using, seed=seed)
    if simplify:
        G = nx.DiGraph(G)  # Remove parallel edges
        G.remove_edges_from(G.selfloop_edges())  # Remove self loops

    # Get adjacency info and create random spatial locations
    A = nx.adjacency_matrix(G)
    N = len(in_sequence)
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))
    D = aux_tools.dist_mat(centroids)

    return G, A, D
コード例 #7
0
def biophysical_reverse(N=bc.num_brain_nodes, N_edges=bc.num_brain_edges_directed,
                        L=np.inf, gamma=1.75, brain_size=[7., 7., 7.]):
    """Create a biophysically inspired graph. Connection probabilities depend
    on distance & degree.

    Args:
        N: how many nodes
        N_edges: how many edges
        L: length constant
        gamma: power to raise degree to
        brain_size: size of space in which nodes are randomly placed
    Returns:
        Networkx graph object, adjacency matrix, distance matrix"""
    # Pick node positions & calculate distance matrix
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))

    # Calculate distance matrix and distance decay matrix
    D = aux_tools.dist_mat(centroids)
    D_decay = np.exp(-D / L)

    # Initialize diagonal adjacency matrix
    A = np.eye(N, dtype=float)

    # Make graph object
    G = nx.DiGraph()
    G.add_nodes_from(np.arange(N))

    # Randomly add edges
    edge_ctr = 0
    while edge_ctr < N_edges:
        # Update degree list & degree-related probability vector
        indegs = A.sum(0).astype(float)
        outdegs = A.sum(1).astype(float)
        degs = indegs + outdegs
        degs_prob = degs.copy()

        # Pick random node to draw edge to
        to_idx = np.random.randint(low=0, high=N)

        # Skip this node if already fully connected
        if outdegs[to_idx] == N:
            continue

        # Find unavailable cxns and set their probability to zero
        unavail_mask = A[:, to_idx] > 0
        degs_prob[unavail_mask] = 0
        # Set self cxn probability to zero
        degs_prob[to_idx] = 0

        # Calculate cxn probabilities from degree & distance
        P = (degs_prob ** gamma) * D_decay[:, to_idx]
        # On the off changes that P == 0, skip
        if P.sum() == 0:
            continue
        # Otherwise keep going on
        P /= float(P.sum())  # Normalize probabilities to sum to 1

        # Sample node from distribution
        from_idx = np.random.choice(np.arange(N), p=P)

        # Add edge to graph
        if A[from_idx, to_idx] == 0:
            G.add_edge(from_idx, to_idx, {'d': D[from_idx, to_idx]})

        # Add edge to adjacency matrix
        A[from_idx, to_idx] += 1

        # Increment edge counter
        edge_ctr += 1

    # Set diagonals to zero
    np.fill_diagonal(A, 0)

    return G, A, D
コード例 #8
0
def source_growth_total_degree(N=bc.num_brain_nodes, N_edges=bc.num_brain_edges_directed,
                  L=np.inf, gamma=1., brain_size=(7., 7., 7.)):
    """Create a graph based in which source growth depends on total, not out-degree.

    Source selection probability is proportional to total degree^gamma, and
    target selection is either random or  dependent on distance (through length
    constant L).

    Parameters:
    -----------

        N: how many nodes
        N_edges: how many edges
        L: length constant
        gamma: power to raise degree to
        brain_size: size of space in which nodes are randomly placed

    Returns:
    --------
        G, A, D: Networkx graph object, adjacency matrix, distance matrix"""

    # Pick node positions & calculate distance matrix
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))

    # Calculate distance matrix and distance decay matrix
    D = aux_tools.dist_mat(centroids)
    D_decay = np.exp(-D / L)

    # Initialize diagonal adjacency matrix
    A = np.eye(N, dtype=float)

    # Make graph object
    G = nx.DiGraph()
    G.add_nodes_from(np.arange(N))
    G.centroids = centroids

    # Randomly add edges
    edge_ctr = 0
    while edge_ctr < N_edges:
        # Update degree list & degree-related probability vector
        outdegs = A.sum(1).astype(float)
        indegs = A.sum(0).astype(float)
        total_degs = outdegs + indegs
        total_degs_prob = total_degs.copy()

        # Calculate source node probability
        P = total_degs_prob ** gamma
        # On the off chance that P == 0, skip
        if P.sum() == 0:
            continue
        # Otherwise keep going on
        P /= float(P.sum())  # Normalize probabilities to sum to 1

        # Sample node from distribution
        src_idx = np.random.choice(np.arange(N), p=P)

        D_src = D_decay[src_idx, :]

        # Find unavailable cxns and set their probability to zero
        unavail_mask = A[src_idx, :] > 0
        D_src[unavail_mask] = 0

        # Set self-connection probability to 0
        D_src[src_idx] = 0

        D_src /= float(D_src.sum())

        # Pick random node to draw edge to
        targ_idx = np.random.choice(np.arange(N), p=D_src)

        # Skip this node if already fully connected
        if outdegs[src_idx] == N:
            continue

        # Add edge to graph
        if A[src_idx, targ_idx] == 0:
            G.add_edge(src_idx, targ_idx, {'d': D[src_idx, targ_idx]})

        # Add edge to adjacency matrix
        A[src_idx, targ_idx] += 1

        # Increment edge counter
        edge_ctr += 1

    # Set diagonals to zero
    np.fill_diagonal(A, 0)

    return G, A.astype(int), D
コード例 #9
0
def pure_geometric(N, N_edges, L, brain_size=[7., 7., 7.]):
    """
    Create a pure geometric model in which nodes are embedded in 3-D space and connect preferentially to
    physically nearby nodes.

    :param N: number of nodes
    :param N_edges: number of edges
    :param L: length constant
    :param brain_size: volume in which to distribute nodes in
    :return: graph, adjacency matrix, distance matrix
    """
    # randomly distribute nodes in space & compute distance matrix
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))
    D = aux_tools.dist_mat(centroids)

    # make an adjacency matrix and graph
    A = np.zeros((N, N), dtype=float)
    G = nx.Graph()
    G.add_nodes_from(range(N))

    # initialize some helper variables
    node_idxs = np.arange(N, dtype=int)
    degs = np.zeros((N, ), dtype=int)
    fully_connected = np.zeros((N, ), dtype=bool)

    # add edges
    edge_ctr = 0
    while edge_ctr < N_edges:

        # pick source randomly
        src = np.random.choice(node_idxs[fully_connected == False])

        # get distance-dependent probabilities to all available targets
        d_probs = np.exp(-D[src, :]/L)  # unnormalized

        # compute which nodes are available to connect to
        unavailable_targs = fully_connected.copy()  # no fully connected nodes
        unavailable_targs[src] = True  # can't connect to self
        unavailable_targs[A[src, :] == 1] = True  # can't connect to already connected nodes

        # set probability to zero if node unavailable
        d_probs[unavailable_targs] = 0.
        # normalize
        d_probs /= d_probs.sum()

        # randomly pick a target
        targ = np.random.choice(node_idxs, p=d_probs)

        # add edge to graph and adjacency matrix
        G.add_edge(src, targ)
        A[src, targ] = 1
        A[targ, src] = 1

        # update degrees
        degs[src] += 1
        degs[targ] += 1

        # update available_from
        if degs[src] == N:
            fully_connected[src] = False
        if degs[targ] == N:
            fully_connected[targ] = False

        edge_ctr += 1

    return G, A, D
コード例 #10
0
ファイル: binary_directed.py プロジェクト: wronk/dbw
def biophysical_reverse_outdegree(N=bc.num_brain_nodes, N_edges=bc.num_brain_edges_directed,
                                  L=np.inf, gamma=1., brain_size=(7., 7., 7.)):
    """Create a biophysically inspired graph. Source probability depends on
    outdegree. Target probability depends on distance.

    Args:
        N: how many nodes
        N_edges: how many edges
        L: length constant
        gamma: power to raise degree to
        brain_size: size of space in which nodes are randomly placed
    Returns:
        Networkx graph object, adjacency matrix, distance matrix"""

    # Pick node positions & calculate distance matrix
    if brain_size == 'brain':
        centroids_dict = aux_random_graphs.get_coords()
        labels = centroids_dict.keys()
        centroids = np.zeros((N, 3))

        for ctr, label in enumerate(labels):
            centroids[ctr, :] = centroids_dict[label] / 10.0

    else:
        centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))

    # Calculate distance matrix and distance decay matrix
    D = aux_tools.dist_mat(centroids)
    D_decay = np.exp(-D / L)

    # Initialize diagonal adjacency matrix
    A = np.eye(N, dtype=float)

    # Make graph object
    G = nx.DiGraph()
    G.add_nodes_from(np.arange(N))
    G.centroids = centroids

    # Randomly add edges
    edge_ctr = 0
    while edge_ctr < N_edges:
        # Update degree list & degree-related probability vector
        outdegs = A.sum(1).astype(float)
        outdegs_prob = outdegs.copy()

        # Calculate source node probability
        P = outdegs_prob ** gamma
        # On the off chance that P == 0, skip
        if P.sum() == 0:
            continue
        # Otherwise keep going on
        P /= float(P.sum())  # Normalize probabilities to sum to 1

        # Sample node from distribution
        src_idx = np.random.choice(np.arange(N), p=P)

        D_src = D_decay[src_idx, :]

        # Find unavailable cxns and set their probability to zero
        unavail_mask = A[src_idx, :] > 0
        D_src[unavail_mask] = 0

        # Set self-connection probability to 0
        D_src[src_idx] = 0

        D_src /= float(D_src.sum())

        # Pick random node to draw edge to
        targ_idx = np.random.choice(np.arange(N), p=D_src)

        # Skip this node if already fully connected
        if outdegs[src_idx] == N:
            continue

        # Add edge to graph
        if A[src_idx, targ_idx] == 0:
            G.add_edge(src_idx, targ_idx, {'d': D[src_idx, targ_idx]})

        # Add edge to adjacency matrix
        A[src_idx, targ_idx] += 1

        # Increment edge counter
        edge_ctr += 1

    # Set diagonals to zero
    np.fill_diagonal(A, 0)

    return G, A, D
コード例 #11
0
def biophysical_reverse(N=bc.num_brain_nodes,
                        N_edges=bc.num_brain_edges_directed,
                        L=np.inf,
                        gamma=1.75,
                        brain_size=[7., 7., 7.]):
    """Create a biophysically inspired graph. Connection probabilities depend
    on distance & degree.

    Args:
        N: how many nodes
        N_edges: how many edges
        L: length constant
        gamma: power to raise degree to
        brain_size: size of space in which nodes are randomly placed
    Returns:
        Networkx graph object, adjacency matrix, distance matrix"""
    # Pick node positions & calculate distance matrix
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))

    # Calculate distance matrix and distance decay matrix
    D = aux_tools.dist_mat(centroids)
    D_decay = np.exp(-D / L)

    # Initialize diagonal adjacency matrix
    A = np.eye(N, dtype=float)

    # Make graph object
    G = nx.DiGraph()
    G.add_nodes_from(np.arange(N))

    # Randomly add edges
    edge_ctr = 0
    while edge_ctr < N_edges:
        # Update degree list & degree-related probability vector
        indegs = A.sum(0).astype(float)
        outdegs = A.sum(1).astype(float)
        degs = indegs + outdegs
        degs_prob = degs.copy()

        # Pick random node to draw edge to
        to_idx = np.random.randint(low=0, high=N)

        # Skip this node if already fully connected
        if outdegs[to_idx] == N:
            continue

        # Find unavailable cxns and set their probability to zero
        unavail_mask = A[:, to_idx] > 0
        degs_prob[unavail_mask] = 0
        # Set self cxn probability to zero
        degs_prob[to_idx] = 0

        # Calculate cxn probabilities from degree & distance
        P = (degs_prob**gamma) * D_decay[:, to_idx]
        # On the off changes that P == 0, skip
        if P.sum() == 0:
            continue
        # Otherwise keep going on
        P /= float(P.sum())  # Normalize probabilities to sum to 1

        # Sample node from distribution
        from_idx = np.random.choice(np.arange(N), p=P)

        # Add edge to graph
        if A[from_idx, to_idx] == 0:
            G.add_edge(from_idx, to_idx, {'d': D[from_idx, to_idx]})

        # Add edge to adjacency matrix
        A[from_idx, to_idx] += 1

        # Increment edge counter
        edge_ctr += 1

    # Set diagonals to zero
    np.fill_diagonal(A, 0)

    return G, A, D
コード例 #12
0
def source_growth_total_degree(N=bc.num_brain_nodes,
                               N_edges=bc.num_brain_edges_directed,
                               L=np.inf,
                               gamma=1.,
                               brain_size=(7., 7., 7.)):
    """Create a graph based in which source growth depends on total, not out-degree.

    Source selection probability is proportional to total degree^gamma, and
    target selection is either random or  dependent on distance (through length
    constant L).

    Parameters:
    -----------

        N: how many nodes
        N_edges: how many edges
        L: length constant
        gamma: power to raise degree to
        brain_size: size of space in which nodes are randomly placed

    Returns:
    --------
        G, A, D: Networkx graph object, adjacency matrix, distance matrix"""

    # Pick node positions & calculate distance matrix
    centroids = np.random.uniform([0, 0, 0], brain_size, (N, 3))

    # Calculate distance matrix and distance decay matrix
    D = aux_tools.dist_mat(centroids)
    D_decay = np.exp(-D / L)

    # Initialize diagonal adjacency matrix
    A = np.eye(N, dtype=float)

    # Make graph object
    G = nx.DiGraph()
    G.add_nodes_from(np.arange(N))
    G.centroids = centroids

    # Randomly add edges
    edge_ctr = 0
    while edge_ctr < N_edges:
        # Update degree list & degree-related probability vector
        outdegs = A.sum(1).astype(float)
        indegs = A.sum(0).astype(float)
        total_degs = outdegs + indegs
        total_degs_prob = total_degs.copy()

        # Calculate source node probability
        P = total_degs_prob**gamma
        # On the off chance that P == 0, skip
        if P.sum() == 0:
            continue
        # Otherwise keep going on
        P /= float(P.sum())  # Normalize probabilities to sum to 1

        # Sample node from distribution
        src_idx = np.random.choice(np.arange(N), p=P)

        D_src = D_decay[src_idx, :]

        # Find unavailable cxns and set their probability to zero
        unavail_mask = A[src_idx, :] > 0
        D_src[unavail_mask] = 0

        # Set self-connection probability to 0
        D_src[src_idx] = 0

        D_src /= float(D_src.sum())

        # Pick random node to draw edge to
        targ_idx = np.random.choice(np.arange(N), p=D_src)

        # Skip this node if already fully connected
        if outdegs[src_idx] == N:
            continue

        # Add edge to graph
        if A[src_idx, targ_idx] == 0:
            G.add_edge(src_idx, targ_idx, {'d': D[src_idx, targ_idx]})

        # Add edge to adjacency matrix
        A[src_idx, targ_idx] += 1

        # Increment edge counter
        edge_ctr += 1

    # Set diagonals to zero
    np.fill_diagonal(A, 0)

    return G, A.astype(int), D