Source code for rnaglib.drawing.rna_layout
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
[docs]def rescale_layout(pos, scale=1):
"""
Return scaled position array to (-scale, scale) in all axes.
The function acts on NumPy arrays which hold position information.
Each position is one row of the array. The dimension of the space
equals the number of columns. Each coordinate in one column.
To rescale, the mean (center) is subtracted from each axis separately.
Then all values are scaled so that the largest magnitude value
from all axes equals `scale` (thus, the aspect ratio is preserved).
The resulting NumPy Array is returned (order of rows unchanged).
Parameters
----------
pos : numpy array
positions to be scaled. Each row is a position.
scale : number (default: 1)
The size of the resulting extent in all directions.
Returns
-------
pos : numpy array
scaled positions. Each row is a position.
"""
# Find max length over all dimensions
lim = 0 # max coordinate for all axes
for i in range(pos.shape[1]):
pos[:, i] -= pos[:, i].mean()
lim = max(abs(pos[:, i]).max(), lim)
# rescale to (-scale, scale) in all directions, preserves aspect
if lim > 0:
for i in range(pos.shape[1]):
pos[:, i] *= scale / lim
return pos
def _process_params(G, center, dim):
# Some boilerplate code.
import numpy as np
if not isinstance(G, nx.Graph):
empty_graph = nx.Graph()
empty_graph.add_nodes_from(G)
G = empty_graph
if center is None:
center = np.zeros(dim)
else:
center = np.asarray(center)
if len(center) != dim:
msg = "length of center coordinates must match dimension of layout"
raise ValueError(msg)
return G, center
[docs]def circular_layout(G, scale=1, center=None, dim=2):
# dim=2 only
"""
Position nodes on a circle.
Parameters
----------
G : NetworkX graph or list of nodes
A position will be assigned to every node in G.
scale : number (default: 1)
Scale factor for positions.
center : array-like or None
Coordinate pair around which to center the layout.
dim : int
Dimension of layout.
If dim>2, the remaining dimensions are set to zero
in the returned positions.
Returns
-------
pos : dict
A dictionary of positions keyed by node
Examples
--------
>>> G = nx.path_graph(4)
>>> pos = nx.circular_layout(G)
Notes
-----
This algorithm currently only works in two dimensions and does not
try to minimize edge crossings.
"""
import numpy as np
G, center = _process_params(G, center, dim)
paddims = max(0, (dim - 2))
if len(G) == 0:
pos = {}
elif len(G) == 1:
pos = {nx.utils.arbitrary_element(G): center}
else:
# Discard the extra angle since it matches 0 radians.
theta = np.linspace(0, 1, len(G) + 1)[:-1] * 2 * np.pi
theta = theta.astype(np.float32)
pos = np.column_stack([np.cos(theta), np.sin(theta),
np.zeros((len(G), paddims))])
pos = rescale_layout(pos, scale=scale) + center
try:
sorted_n = sorted(G, key=lambda x: x.split(".")[2], reverse=True)
except:
sorted_n = sorted(G)
pos = dict(zip(sorted_n, pos))
return pos
if __name__ == "__main__":
G = nx.Graph()
G.add_nodes_from([('A', 2), ('A', 3), ('A', 1), ('A', 5)])
G.add_edges_from([(('A', 2), ('A', 5))])
pos = circular_layout(G)
nx.draw_networkx(G, pos)
plt.show()