Source code for thema.multiverse.universe.stars.pyballStar
# File: multiverse/universe/stars/pyballStar.py
# Last Updated: 11-19-25
# Updated By: JW
import networkx as nx
from pyballmapper import BallMapper
from ..star import Star
from ..utils.starGraph import starGraph
from ..utils.starHelpers import (
convert_keys_to_alphabet,
mapper_pseudo_laplacian,
mapper_unclustered_items,
)
[docs]
def initialize():
"""Returns pyballStar class from module."""
return pyballStar
[docs]
class pyballStar(Star):
"""
PyBall Mapper Star Class
Generates a graph representation of projection using PyBall Mapper.
See: https://github.com/dioscuri-tda/pyBallMapper
Members
------
data: pd.DataFrame
a pandas dataframe of raw data
clean: pd.DataFrame
a pandas dataframe of complete, scaled, and encoded data
projection: np.narray
a numpy array containing projection coordinates
EPS: float
epsilon parameter for BallMapper
mapper: pyballmapper.BallMapper
a BallMapper object
starGraph: thema.multiverse.universe.starGraph class
An expanded framework for analyzing networkx graphs
Functions
--------
get_data_path() -> str
returns path to raw data
get_clean_path() -> str
returns path to Moon object containing clean data
get_projection_path()-> str
returns path to Comet object containing projection data
fit() -> None
Computes a complex and corresponding starGraph
get_unclustered_items() -> list
returns list of unclustered items
save() -> None
Saves object as a .pkl file.
"""
def __init__(self, data_path, clean_path, projection_path, EPS=0.1):
super().__init__(
data_path=data_path,
clean_path=clean_path,
projection_path=projection_path,
)
self.EPS = EPS
[docs]
def fit(self):
self.mapper = BallMapper(X=self.projection, eps=self.EPS, verbose=False)
graph = self.mapper.Graph
self.complex = {"nodes": nx.get_node_attributes(graph, "membership")}
self.nodes = convert_keys_to_alphabet(self.complex["nodes"])
relabel_map = {
old: new
for old, new in zip(self.complex["nodes"].keys(), self.nodes.keys())
}
graph = nx.relabel_nodes(graph, relabel_map)
nx.set_node_attributes(graph, self.nodes, "membership")
# Update complex to use the new alphabetic keys (use copy to avoid reference issues)
self.complex["nodes"] = self.nodes.copy()
self.starGraph = starGraph(graph)
[docs]
def get_pseudoLaplacian(self, neighborhood="node"):
"""Calculates and returns a pseudo laplacian n by n matrix representing neighborhoods in the graph. Here, n corresponds to
the number of items (ie rows in the clean data - keep in mind some raw data rows may have been dropped in cleaning). Here,
the diagonal element A_ii represents the number of neighborhoods item i appears in. The element A_ij represent the number of
neighborhoods both item i and j belong to.
Parameters
----------
neighborhood: str
Specifies the type of neighborhood. For pyballStar, neighborhood options are 'node' or 'cc'
"""
if self.starGraph is None:
self.fit()
return mapper_pseudo_laplacian(
complex=self.complex,
n=len(self.clean),
components=self.starGraph.components,
neighborhood=neighborhood,
)
[docs]
def get_unclustered_items(self):
"""Returns the list of items that were not clustered in the mapper fitting.
Returns
-------
self._unclustered_item : list
A list of unclustered item ids
"""
return mapper_unclustered_items(len(self.clean), self.nodes)