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