decipher.cluster
Generic feature clustering: standardise → PCA → HDBSCAN → noise reassignment.
decipher.cluster.ClusterResult @dataclass
class ClusterResult:
labels: np.ndarray # raw HDBSCAN labels; -1 = noise
labels_assigned: np.ndarray # noise rows reassigned to nearest centroid
n_clusters: int
features_reduced: np.ndarray # PCA-projected matrix, (N, n_pca_dims)
centroids: np.ndarray # per-cluster centroid in PCA space Use labels_assigned for downstream symbol streams; it has
no -1 holes.
decipher.cluster.cluster_features def cluster_features(
X: np.ndarray,
*,
min_cluster_size: int = 10,
min_samples: int = 3,
n_pca_dims: int = 20,
cluster_selection_epsilon: float = 0.3,
cluster_selection_method: str = "eom",
metric: str = "euclidean",
) -> ClusterResult Standardise → PCA → HDBSCAN. The noise-reassignment step is
load-bearing: downstream symbol-stream analyses need a complete
sequence with no -1 holes.
Defaults: the defaults match the values that appeared identically in two independent paper reproductions (paper #001 hand-rolled mel-patch features and paper #002 AVES SSL features). Override at the call site rather than forking the primitive.