Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return networkx graph #41

Merged
merged 15 commits into from
Mar 23, 2022
51 changes: 51 additions & 0 deletions src/snkit/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
import numpy as np
import pandas
import shapely.errors
try:
import networkx as nx
USE_NX = True
except ImportError:
USE_NX = False

from geopandas import GeoDataFrame
from shapely.geometry import Point, MultiPoint, LineString, GeometryCollection, shape, mapping
Expand Down Expand Up @@ -603,3 +608,49 @@ def set_precision(geom, precision):
geom_mapping = mapping(geom)
geom_mapping['coordinates'] = np.round(np.array(geom_mapping['coordinates']), precision)
return shape(geom_mapping)


def to_networkx(network):
"""Return a networkx graph
"""
if USE_NX is True:
# init graph
G = nx.Graph()
# get nodes from network data
G.add_nodes_from(network.nodes.id.to_list())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to edges, can we add node attributes to the graph here?

# get edges from network data
edges_as_list = list(zip(network.edges.from_id,network.edges.to_id))
# add edges to graph
G.add_weighted_edges_from(edges_as_list)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we pass in a column to use as weight here?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thinking about this - it would be generally useful to add all the edge attributes here, including geometry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed this part to extract nodal positions and edge weights (https://github.com/amanmajid/snkit/blob/e55bc44c4aa848fb9f1724f8db504a3c6a7ad114/src/snkit/network.py#L613-L639). I'm not sure how to go about efficiently adding all edge attributes when defining the graph?

return G
else:
raise ImportError('No module named networkx')


def get_connected_components(network):
''' Get connected components within network and id to each individual graph
'''
if USE_NX is True:
G = to_networkx(network)
return sorted(nx.connected_components(G), key = len, reverse=True)
else:
raise ImportError('No module named networkx')


def add_component_ids(network,id_col='component_id'):
''' Add column of component IDs to network edge data
'''
# get connected components
connected_parts = get_connected_components(network)
# add unique id to each graph
count = 1
network.edges[id_col] = 0 # init id_col
for part in connected_parts:
network.edges.loc[ (network.edges.from_id.isin(list(part))) | \
(network.edges.to_id.isin(list(part))), id_col ] = count
# adjust counter
count = count + 1
# return
return Network(
nodes=network.nodes,
edges=network.edges