Skip to content

Models

This module contains the data models for building the network graph.

CustomCounter dataclass

Custom counter class built to emulate Counter from std lib.

This class utilizes a specific use case for this program, and uses 'reflexive tuple matching' to get synonymous pairs.

Parameters:

Name Type Description Default
lst list[tuple[str, str]]

A list of author-tuple pairs.

required

__post_init__(self, lst) special

Converts author pairs into counts of unique pairs.

After initialization, converts the list of tuple pairs into keys in a dictionary and increments the value by the count of the key.

Also sorts the pairs so that reflexive tuples are caught.

Stores the built dictionary in self.counts.

Parameters:

Name Type Description Default
lst list

A list of author-tuple pairs.

required
Source code in scholar_network/models.py
def __post_init__(self, lst: list[tuple[str, str]]):
    """Converts author pairs into counts of unique pairs.

    After initialization, converts the list of tuple pairs into keys
    in a dictionary and increments the value by the count of the key.

    Also sorts the pairs so that reflexive tuples are caught.

    Stores the built dictionary in `self.counts`.

    Parameters:
        lst (list[tuple[str, str]]): A list of author-tuple pairs.
    """
    result = defaultdict(int)
    for pair in lst:
        # by sorting we can ensure we catch the 'reflexive tuples'
        sorted_pair = tuple(sorted(pair))
        result[sorted_pair] += 1
    self.counts = result

most_common(self, limit=None)

Sorts and returns ordered tuple pairs.

Parameters:

Name Type Description Default
limit Optional[int]

Limit to return. Defaults to None.

None

Returns:

Type Description
list

list[tuple[tuple[str, str], int]]: Returns most common tuple pairs.

Source code in scholar_network/models.py
def most_common(
    self, limit: Union[int, None] = None
) -> list[tuple[tuple[str, str], int]]:
    """Sorts and returns ordered tuple pairs.

    Args:
        limit (Union[int, None], optional): Limit to return. Defaults to None.

    Returns:
        list[tuple[tuple[str, str], int]]: Returns most common tuple pairs.
    """
    ordered_keys = sorted(self.counts, key=lambda x: self.counts[x], reverse=True)
    ordered_result: list[tuple[tuple[str, str], int]] = []
    for item in ordered_keys:
        ordered_result.append((item, self.counts[item]))
    return ordered_result[:limit] if limit else ordered_result

Digraph dataclass

Directed graph class.

This class utilizes Node and Edge to store graph connections.

Attributes:

Name Type Description
edges dict[Node, list[Node]]

Connections stored as a dict of src node mapped to a list of connected nodes. Repeats allowed.

add_edge(self, edge)

Adds a new edge/connection to the graph.

Parameters:

Name Type Description Default
edge Edge

Edge to add to the graph

required

Exceptions:

Type Description
ValueError

Raises ValueError if either src or dest Nodes not in graph.

Source code in scholar_network/models.py
def add_edge(self, edge: Edge):
    """Adds a new edge/connection to the graph.

    Args:
        edge (Edge): Edge to add to the graph

    Raises:
        ValueError: Raises ValueError if either src or dest Nodes not in graph.
    """
    if not (edge.src in self.edges and edge.dest in self.edges):
        raise ValueError("Node not in graph")
    self.edges[edge.src].append(edge.dest)

add_node(self, node)

Adds a new node to the graph.

Parameters:

Name Type Description Default
node Node

New Node to add.

required
Source code in scholar_network/models.py
def add_node(self, node: Node):
    """Adds a new node to the graph.

    Args:
        node (Node): New Node to add.
    """
    if node not in self.edges:
        self.edges[node] = []
    else:
        pass

children(self, node)

Get's Nodes that node is linked to.

Parameters:

Name Type Description Default
node Node

Node to extract children from.

required

Returns:

Type Description
list

list[Node]: List of Nodes connected to the target node. Duplicates allowed.

Source code in scholar_network/models.py
def children(self, node: Node) -> list[Node]:
    """Get's Nodes that `node` is linked to.

    Args:
        node (Node): Node to extract children from.

    Returns:
        list[Node]: List of Nodes connected to the target node. Duplicates allowed.
    """
    return self.edges[node]

edge_count(self)

Counts all the edges in the graph. Duplicates are counted.

Returns:

Type Description
int

int: Number of edges/connections in the graph.

Source code in scholar_network/models.py
def edge_count(self) -> int:
    """Counts all the edges in the graph.  Duplicates are counted.

    Returns:
        int: Number of edges/connections in the graph.
    """
    return sum(len(self.children(node)) for node in self.edges)

edge_rank(self, vertex=None, limit=None)

Ranks the edges based on their weight.

Ranks are calculated either for the entire graph (default) or for the specified Node.

Parameters:

Name Type Description Default
vertex Optional[src.scholar_network.models.Node]

Node to run calculation on. Defaults to None.

None
limit Optional[int]

Limit for the number of edges returned. Defaults to None.

None

Returns:

Type Description
list

list[tuple[tuple[str, str], int]]: Returns a sorted (by weight) list of edges up to the limit parameter.

Source code in scholar_network/models.py
def edge_rank(
    self, vertex: Union[Node, None] = None, limit: Union[int, None] = None
) -> list[tuple[tuple[str, str], int]]:
    """Ranks the edges based on their weight.

    Ranks are calculated either for the entire graph (default) or for
    the specified Node.

    Args:
        vertex (Union[Node, None], optional): Node to run calculation on. Defaults to None.
        limit (Union[int, None], optional): Limit for the number of edges returned. Defaults to None.

    Returns:
        list[tuple[tuple[str, str], int]]: Returns a sorted (by weight) list of edges up to the limit parameter.
    """
    if vertex:
        pairs = []
        for partner in self.edges[vertex]:
            pairs.append((vertex.name, partner.name))

        return (
            CustomCounter(pairs).most_common(limit)
            if limit
            else CustomCounter(pairs).most_common()
        )
    return (
        CustomCounter(self.node_pairs()).most_common(limit)
        if limit
        else CustomCounter(self.node_pairs()).most_common()
    )

get_node(self, name)

Gets a Node from the graph based on the Node's name attribute.

Parameters:

Name Type Description Default
name str

Name of the Node to return from the graph.

required

Exceptions:

Type Description
NameError

If no matching Node can be found.

Returns:

Type Description
Node

Node: The Node matching the search name.

Source code in scholar_network/models.py
def get_node(self, name: str) -> Node:
    """Gets a Node from the graph based on the Node's name attribute.

    Args:
        name (str): Name of the Node to return from the graph.

    Raises:
        NameError: If no matching Node can be found.

    Returns:
        Node: The Node matching the search name.
    """
    for n in self.edges:
        if n.name == name:
            return n
    raise NameError(name)

has_node(self, node)

Checks if the graph contains a given Node.

Parameters:

Name Type Description Default
node Node

Node to search the graph for.

required

Returns:

Type Description
bool

bool: True if the node exists, otherwise False.

Source code in scholar_network/models.py
def has_node(self, node: Node) -> bool:
    """Checks if the graph contains a given Node.

    Args:
        node (Node): Node to search the graph for.

    Returns:
        bool: True if the node exists, otherwise False.
    """
    return node in self.edges

node_pairs(self)

Generates pairs of nodes representing edge connections. Duplicates allowed.

Returns:

Type Description
list

list[tuple[str, str]]: List of node pairs.

Source code in scholar_network/models.py
def node_pairs(self) -> list[tuple[str, str]]:
    """Generates pairs of nodes representing edge connections.  Duplicates allowed.

    Returns:
        list[tuple[str, str]]: List of node pairs.
    """
    pairs = []
    for src in self.edges:
        for dest in self.edges[src]:
            pairs.append((src.name, dest.name))
    return pairs

vertex_count(self)

Counts the total number of Nodes in the graph.

Returns:

Type Description
int

int: Number of Nodes in the graph.

Source code in scholar_network/models.py
def vertex_count(self) -> int:
    """Counts the total number of Nodes in the graph.

    Returns:
        int: Number of Nodes in the graph.
    """
    return len(self.edges)

vertex_degree(self, vertex=None)

Calculates the number of Nodes connected to the target vertex.

If no target vertex provided, calculates connected Nodes for each Node in the graph.

Parameters:

Name Type Description Default
vertex Optional[src.scholar_network.models.Node]

Target vertex to search for. Defaults to None.

None

Returns:

Type Description
Union[int, list[int]]

Union[int, list[int]]: Either the degree of the target vertex or a list of the degrees of all the nodes.

Source code in scholar_network/models.py
def vertex_degree(self, vertex: Union[Node, None] = None) -> Union[int, list[int]]:
    """Calculates the number of Nodes connected to the target vertex.

    If no target vertex provided, calculates connected Nodes for each Node in the
    graph.

    Args:
        vertex (Union[Node, None], optional): Target vertex to search for. Defaults to None.

    Returns:
        Union[int, list[int]]: Either the degree of the target vertex or a list of the degrees of all the nodes.
    """
    if vertex:
        return len(self.children(vertex))
    return sorted([len(self.children(n)) for n in self.edges])

Edge dataclass

Edge connects Nodes that co-occur together in the same publication.

Edges are directed in a DiGraph and undirected in Graph. ^^ Both of these cases are handled by the (Di)Graph classes not the Edge itself.

Attributes:

Name Type Description
src Node

Source node for the connection.

dest Node

Destination node for the connection.

__str__(self) special

Makes the string representation an of the edge connection.

Returns:

Type Description
str

str: Connection being represented by the edge in string form.

Source code in scholar_network/models.py
def __str__(self) -> str:
    """Makes the string representation an of the edge connection.

    Returns:
        str: Connection being represented by the edge in string form.
    """
    return f"{self.src} -> {self.dest}"

Graph dataclass

Undirected sub-class of the Digraph.

add_edge(self, edge)

Adds both (directed) edges to the graph.

Source code in scholar_network/models.py
def add_edge(self, edge: Edge):
    """Adds both (directed) edges to the graph."""
    Digraph.add_edge(self, edge)
    rev = Edge(edge.dest, edge.src)
    Digraph.add_edge(self, rev)

Node dataclass

Node is a container to hold authors.

Attributes:

Name Type Description
name str

name of the author

__str__(self) special

Returns the name as the string.

Returns:

Type Description
str

str: Name attribute of the node.

Source code in scholar_network/models.py
def __str__(self) -> str:
    """Returns the name as the string.

    Returns:
        str: Name attribute of the node.
    """
    return self.name