Skip to main content

stsckm

stsckm is an extensible Python framework for graph-regularized spatio-temporal clustering of point observations. Its STSCKM estimator combines separately weighted spatial and temporal centroid distances with a soft label-disagreement penalty on a sparse neighborhood graph.

The method was introduced in:

Idris, M. A., Aidi, M. N., and Djuraidah, A. (2026). Performance Evaluation of ST-DBSCAN and Spatio-Temporal Spatially Constrained K-Means (ST-SCKM) for Wildfire Risk Zoning and Resilience Analysis. Journal of Safety Science and Resilience. https://doi.org/10.1016/j.jnlssr.2026.100357

The package generalizes the reference implementation into reusable graph, diagnostic, and selection components. It is not limited to wildfire data.

What the package provides

  • a scikit-learn-style STSCKM estimator for aligned spatial and temporal matrices;
  • directed, union, or mutual K-nearest-neighbor graphs and radius graphs;
  • caller-supplied dense or SciPy sparse weighted adjacency matrices;
  • sequential or synchronous label-update schemes;
  • graph disagreement, connected-component, and fragmentation diagnostics;
  • deterministic parameter-grid summaries and repeated-fit stability checks;
  • conventional silhouette, Calinski-Harabasz, and Davies-Bouldin indices;
  • explicit separation between clustering variables and post hoc profile variables; and
  • a synthetic dataset, tests, documentation, examples, and complete replication archive.

The graph penalty is soft. It encourages neighboring observations to share a label but does not guarantee that every cluster is connected. Use a strict regionalization method when connected regions are mandatory.

Installation

Install the published package from PyPI:

python -m pip install stsckm

Optional plotting support is available with:

python -m pip install "stsckm[plot]"

For an editable development installation from the repository root:

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.txt

On Windows, use .venv\Scripts\activate.

Quick start

import numpy as np

from stsckm import (
    STSCKM,
    add_default_features,
    evaluate_labels,
    load_sample_wildfire,
    standardize_features,
)

events = add_default_features(load_sample_wildfire())
X_spatial, spatial_scaler = standardize_features(
    events, ["x_proj", "y_proj"]
)
X_temporal, temporal_scaler = standardize_features(events, ["time_days"])

model = STSCKM(
    n_clusters=4,
    spatial_weight=0.5,
    temporal_weight=1.5,
    lambda_spatial=1.0,
    graph_type="knn",
    n_neighbors=5,
    graph_symmetrize="union",
    random_state=42,
).fit(X_spatial, X_temporal)

metrics = evaluate_labels(
    np.column_stack([X_spatial, X_temporal]), model.labels_
)
print(metrics)
print(model.graph_diagnostics_)

The fitted object stores labels_, separate spatial and temporal centroids, the original sparse adjacency_, the symmetric regularization_adjacency_, an objective history, and graph diagnostics. transform() returns unregularized weighted distances to the fitted centroids. The package deliberately does not define out-of-sample predict() because prediction requires an explicit rule for connecting new observations to the fitted graph.

Radius and custom graphs

from stsckm import STSCKM, spatial_graph

radius_model = STSCKM(
    n_clusters=4,
    graph_type="radius",
    radius=0.20,
    lambda_spatial=1.0,
    random_state=42,
).fit(X_spatial, X_temporal)

adjacency = spatial_graph(
    X_spatial,
    graph_type="knn",
    n_neighbors=8,
    symmetrize="mutual",
)
custom_model = STSCKM(n_clusters=4, random_state=42).fit(
    X_spatial,
    X_temporal,
    adjacency=adjacency,
)

Non-negative edge weights in a custom graph enter the disagreement penalty. Diagonal entries are removed during validation. A complete asymmetric six-observation example is available in examples/custom_weighted_graph.py.

Parameter selection and stability

from stsckm import STSCKM, fit_stability, parameter_search

search = parameter_search(
    X_spatial,
    X_temporal,
    {
        "n_clusters": [3, 4],
        "lambda_spatial": [0.0, 0.5, 1.0, 2.0],
        "graph_symmetrize": ["union"],
    },
    estimator=STSCKM(n_neighbors=5, random_state=42),
)

stability = fit_stability(
    STSCKM(n_clusters=4, graph_symmetrize="union"),
    X_spatial,
    X_temporal,
    seeds=(0, 1, 2, 3, 4),
)
print(search)
print(stability.mean_adjusted_rand)

Internal separation and graph coherence quantify different properties. A parameter choice should therefore consider both, together with domain checks when available.

The package does not replace all spatial clustering tools:

Software or method Main mechanism Prefer it when
scikit-learn K-means Unconstrained centroid clustering No graph preference is required
scikit-learn connectivity-constrained Ward Only connected clusters may merge A hierarchical partition under a connectivity graph is appropriate
st-dbscan Spatial and temporal density thresholds Noise detection and an unknown cluster count are central
PySAL spopt Strict regionalization algorithms Areal units must form connected regions
R ClustGeo Feature and geographic dissimilarities A Ward-like hierarchy with soft geographic dissimilarity is preferred
R adespatial::constr.hclust Contiguity-constrained agglomeration Spatial or chronological contiguity must restrict each merge
stsckm Soft graph disagreement plus spatial-temporal centroids Point data need fixed K, separate space-time weights, and tunable graph coherence

The JSS manuscript gives full citations, a feature comparison, limitations, and a shared-data empirical illustration.

Reproducing the manuscript

The review archive is self-contained. After installing its submitted source distribution, run all commands from the replication folder:

cd replication
python -m pip install -r requirements.txt
python run_all.py

run_all.py executes the manuscript listings, runs the independently callable examples/run_example.py, recreates all numerical tables and data-driven figures, records dependency versions, and checks platform-invariant results against the archived CSVs in expected/. It also regenerates a small scaling benchmark without comparing wall times for exact equality. See replication/README.md for the exact reviewer workflow and output map.

For a single end-to-end script that prepares the bundled data, fits the model, writes diagnostics, screens a transparent parameter grid, and saves auditable outputs, run python replication/worked_analysis.py from the replication folder.

Tests, documentation, and build

python -m pytest
python -m ruff check src tests replication
python -m sphinx -W -b html docs docs/_build/html
python -m build
python -m twine check dist/*

License and author

stsckm is released under the MIT license, which is GPL-compatible.

Muh Akbar Idris, IPB University
ORCID: https://orcid.org/0009-0000-2995-1975

Metadata

Release files for stsckm 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for stsckm 2.0.0
File Size Uploaded
stsckm-2.0.0.tar.gz 119.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for stsckm 2.0.0
File Interpreter ABI Platform
stsckm-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 215.6 kB

Release files / stsckm-2.0.0.tar.gz

Download URL stsckm-2.0.0.tar.gz
Size 119.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6922cd76fb27fefc4f4439a20dd7ebda17654b057377f9e7cf96407887f18b6c
BLAKE2b-256 checksum
How to use checksums
fe8aef6385f4257583e6fd22b5d45168c557cc4760672c87717f6fd9b7f18b98
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.

Transparency log

Release files / stsckm-2.0.0-py3-none-any.whl

Download URL stsckm-2.0.0-py3-none-any.whl
Size 95.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c8b2499a9f58b9d40a807a435bf1d4996fcb1bcac251199ffdd8bcc80867769
BLAKE2b-256 checksum
How to use checksums
d6b1a23444cb5a78e92f6bfab4c2297b46e5240d38f60cab476d54a838a903ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.

Transparency log

Release history Release notifications | RSS feed

2.1.0

2 release files

This release

2.0.0 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page