GraphGroup is specialized on managing and handling graph-related data.
The group defines a graph via data groups and data containers that store nodes, edges, and optionally their properties.
GraphGroup holds the following, customizable variables that describe in which containers or attributes to find the info on the nodes and edges:
_GG_node_container = "nodes": The name of the container or group (
node_container) containing the node data
_GG_edge_container = "edges": The name of the container or group (
edge_container) containing the edge data
_GG_attr_directed = "directed": The
GraphGroupattribute (boolean) describing whether the graph is directed or not
_GG_attr_parallel = "parallel": The
GraphGroupattribute (boolean) describing whether the graph allows for parallel edges or not
_GG_attr_edge_container_is_transposed = "edge_container_is_transposed": The
GraphGroupattribute (boolean) describing whether the edge container is transposed, i.e., has the shape
_GG_attr_keep_dim = "keep_dim": The
GraphGroupattribute (iterable) describing which dimensions are not to be squeezed during data selection.
If you do not change anything, the default values are taken.
GraphGroup only holds and manages graph data but itself is not a graph, in the sense that no functionality such as finding the neighborhood of a node is implemented there.
GraphGroup uses the networkx library and its interface for creating
In the following, an overview is given how graphs can be created from a
GraphGroup contains the
create_graph() method that creates a graph from the containers and groups that are part of the
GraphGroup together with information provided by the
However, the function also allows you to explicitly set graph properties such as whether the graph should be directed or allow for parallel edges.
The function returns a networkx graph object corresponding to the provided data and information.
create_graph() function further allows you to optionally set node and edge properties by specifying
Any data can be pre-selected using the
The selectors are applied to all data involved, i.e., to node, edge, as well as property data.
It is also possible to provide both
isel as long as the intersection of both key-sets is empty.
Invalid keys in
isel are ignored silently. This means that the node, edge, and property data need not have the same set of dimensions in order to apply a selection.
Moreover, all dimensions of size 1 are squeezed, hence no selection has to be specified in such scenarios, i.e. when the selection is unambiguous.
If you have node/edge data that changes over time, you can select along the
time dimension directly via the
at_times or the
This sets or overwrites the respective entry in the
The following example demonstrates the graph creation: Let us assume that we have a graph with static nodes and dynamic edges, each with dynamic properties.
The dynamic data, stored as
TimeSeriesGroup, is given for two points in time.
The resulting data tree looks as follows:
# graph_group <GraphGroup, 4 members, 2 attributes> # └┬ nodes <XrDataContainer, ..., shape (10,), 0 attributes> # ├ some_node_prop <XrDataContainer, ..., shape (2,10), 0 attributes> # ├ edges <TimeSeriesGroup, 2 members, 0 attributes> # └┬ 0 <XrDataContainer, ..., shape (9,2), 0 attributes> # └ 10 <XrDataContainer, ..., shape (6,2), 0 attributes> # ├ some_edge_prop <TimeSeriesGroup, 2 members, 0 attributes> # └┬ 0 <XrDataContainer, ..., shape (9,), 0 attributes> # └ 10 <XrDataContainer, ..., shape (6,), 0 attributes> # └ other_edge_prop <XrDataContainer, ..., shape (6,), 0 attributes>
Let’s now create a graph from the
# Create the initial graph from the graph group without node/edge properties g = graph_group.create_graph(at_time=0) # time specified by value # Now, create the final graph with `some_node_prop` as node property and # `some_edge_prop` as edge property. g = graph_group.create_graph(at_time_idx=-1, # time specified via index node_props=["some_node_prop"], edge_props=["some_edge_prop"])
Graph creation might fail for graphs with a single node (edge) due to the node (edge) dimension (of size 1) being squeezed out. It is therefore strongly recommended to specify the node and edge dimension names in the
_GG_attr_keep_dim group attribute. Alternatively, they can be specified via the
keep_dim argument in
data stored inside the
GraphGroup: Here, the
nameargument specifies the name of the data container or group which stores the property.
external data: see Loading External Data as Graph Property
In both cases,
name will be the name of the node or edge property in the
Again, the data can be pre-selected using the
In the example below, the
other_edge_prop data stored inside the graph group is added as edge property.
Note that time specification is required here, even though
other_edge_prop is one-dimensional, because
edge_container contains edge data for multiple times.
# Set the edge property manually from the `other_edge_prop` data container # and select the data of the last time step graph_group.set_edge_property(g=g, name="other_edge_prop", at_time_idx=-1)
Node properties can be added analogously.
Node (edge) properties can only be added for those nodes (edges) that are available in the
By default, property data is assumed to be aligned with the
GraphGroups node (edge) data.
However, it can be aligned with the latter via xarray.align by setting
The indexes of the
edge_container) are used for the alignment in each dimension.
If the class variable
_GG_WARN_UPON_BAD_ALIGN is set to
True), warnings on possible pitfalls are given.
If you want to add a graph property from data that is not stored inside the
GraphGroup (e.g., you have pre-processed some data), this can be realized in two different ways:
- Loading the external data directly by passing it via the
dataargument in the respective
nameargument then sets the name of the property.
- Loading the external data directly by passing it via the
Have a look at a small example where some external data
ext_data is added to the graph as a node property:
# Make the external data available in the graph group under the given key graph_group.register_property_map("my_ext_node_prop", data=ext_data) # Use the newly created key to set the external data as node property graph_group.set_node_property(g=g, name="my_ext_node_prop") # Alternatively, load the external data directly via the `data` argument graph_group.set_node_property(g=g, name="my_ext_node_prop", data=ext_data)