Source code for topologic.projection.vertex_projections
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
import networkx as nx
from typing import Callable, List, Optional
from ._common import ATTRIBUTES, metadata_to_dict
__all__ = ["vertex_with_collection_metadata", "vertex_with_single_metadata"]
[docs]def vertex_with_collection_metadata(
headers: List[str],
vertex_id_index: int,
ignored_values: Optional[List[str]] = None
) -> Callable[[nx.Graph], Callable[[List[str]], None]]:
"""
This function is an unlikely function to use; if you have vertex metadata you wish to load into the networkx.Graph
where the vertex_id is repeated, it would be a better choice for you to compact those into a single record
with a specific, string representable format of multiple metadata entries. However, this function can be used
when you aren't sure what you have. Like the edge_with_collection_metadata projection, this function will
create a List of dictionaries for each instance of metadata it sees for a given vertex_id.
Note: If the vertex_id for a given row does not exist in the graph, NO METADATA WILL BE RETAINED.
See package docstrings for more details on these currying functions.
:param List[str] headers: Headers from a CSV row to use as metadata attribute keys
:param int vertex_id_index: The index in the CSV data row to use as the vertex id in this graph
:param Optional[List[str]] ignored_values: Optional. A list of values to ignore if present in the row, such as
"NULL" or ""
:return: A partially applied function that partially applies yet more arguments prior to the final operation
function
:rtype: Callable[[networkx.Graph], Callable[[List[str]], None]]
"""
if not ignored_values:
ignored_values = []
def _configure_graph(
graph: nx.Graph
) -> Callable[[List[str]], None]:
def _vertex_with_collection_metadata(row: List[str]):
vertex_id = row[vertex_id_index]
# don't add anything if the vertex isn't even in the graph.
if vertex_id in graph:
row_metadata = metadata_to_dict(
row,
[vertex_id_index],
ignored_values,
headers
)
if not graph.nodes[vertex_id].get(ATTRIBUTES):
graph.nodes[vertex_id][ATTRIBUTES] = []
previous_metadata = graph.nodes[vertex_id][ATTRIBUTES]
previous_metadata.append(row_metadata)
return _vertex_with_collection_metadata
return _configure_graph
[docs]def vertex_with_single_metadata(
headers: List[str],
vertex_id_index: int,
ignored_values: List[str] = None
) -> Callable[[nx.Graph], Callable[[List[str]], None]]:
"""
Function will project vertex metadata into the graph. If prior data exists for the vertex_id, the later instance
of data for the vertex_id will clobber it.
Note: If the vertex_id for a given row does not exist in the graph, NO METADATA WILL BE RETAINED.
See package docstrings for more details on these currying functions and on the attributes datastructure.
:param List[str] headers: Headers from a CSV row to use as metadata attribute keys
:param int vertex_id_index: The index in the CSV data row to use as the vertex id in this graph
:param Optional[List[str]] ignored_values: Optional. A list of values to ignore if present in the row, such as
"NULL" or ""
:return: A partially applied function that partially applies yet more arguments prior to the final operation
function
:rtype: Callable[[networkx.Graph], Callable[[List[str]], None]]
"""
if not ignored_values:
ignored_values = []
def _configure_graph(
graph: nx.Graph
) -> Callable[[List[str]], None]:
def _vertex_with_single_metadata(row: List[str]):
vertex_id = row[vertex_id_index]
if vertex_id in graph:
current_vertex_metadata = metadata_to_dict(
row,
[vertex_id_index],
ignored_values,
headers
)
# clobber the existing attributes
graph.nodes[vertex_id][ATTRIBUTES] = [current_vertex_metadata]
return _vertex_with_single_metadata
return _configure_graph