spatial_graph_algorithms.metrics
Evaluate reconstruction quality and graph structural properties.
Metric interpretation guide
| Metric | Range | Excellent | Good | Poor |
|---|---|---|---|---|
| CPD | [0, 1] | > 0.95 | > 0.85 | < 0.7 |
| KNN | [0, 1] | > 0.7 | > 0.5 | < 0.3 |
| Distortion* | [0, 1] | < 0.05 | < 0.20 | > 0.40 |
* Distortion is not computed by default — pass compute_distortion=True to enable it.
Scale-aligns the reconstruction to ground-truth before scoring; 0.0 = perfect.
All metrics are rotation-, reflection-, and translation-invariant.
Usage
from spatial_graph_algorithms.metrics import evaluate, quality_table
m = evaluate(sg_reconstructed, k_neighbors=10)
print(m["cpd"], m["knn"])
# Include distortion (opt-in, O(n²)):
m = evaluate(sg_reconstructed, compute_distortion=True)
# Optional: save to CSV
evaluate(sg_reconstructed, output_csv="quality.csv")
# Compare multiple reconstructions side-by-side (Jupyter-friendly DataFrame):
qt = quality_table({"MDS": sg_mds, "STRND": sg_strnd})
API Reference
spatial_graph_algorithms.metrics.evaluate(sn, *, k_neighbors=15, compute_distortion=False, output_csv=None)
Compute graph structure properties and reconstruction quality metrics.
Always computes structural properties from the adjacency matrix. When
both :attr:~spatial_graph_algorithms.network.SpatialGraph.positions and
:attr:~spatial_graph_algorithms.network.SpatialGraph.reconstructed_positions are
set, also computes reconstruction quality metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sn
|
SpatialGraph
|
Input graph. Should have reconstructed_positions set (via
:func: |
required |
k_neighbors
|
int
|
Number of neighbours used in the KNN metric. Default 10. |
15
|
compute_distortion
|
bool
|
If |
False
|
output_csv
|
str or Path
|
If given, the result dictionary is written as a one-row CSV to this path. Parent directories are created if needed. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Flat dictionary with the following keys: Graph structure
Reconstruction quality (
|
Examples:
>>> from spatial_graph_algorithms.simulate import generate
>>> from spatial_graph_algorithms.reconstruct import reconstruct
>>> from spatial_graph_algorithms.metrics import evaluate
>>> sn = generate(n=300, seed=42)
>>> sn_rec = reconstruct(sn, method="mds", seed=42)
>>> m = evaluate(sn_rec)
>>> m["cpd"] > 0.7
True
Source code in src/spatial_graph_algorithms/metrics/__init__.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
spatial_graph_algorithms.metrics.evaluate_denoising(sg, *, scores=None, method=None)
Evaluate denoising quality against ground-truth is_false labels.
Compares the is_removed column (set by
:class:~spatial_graph_algorithms.denoise.EdgeFilterer) against the
is_false column (set by
:func:~spatial_graph_algorithms.simulate.generate) to compute binary
classification metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sg
|
SpatialGraph
|
Graph after denoising. Must have |
required |
scores
|
dict
|
Continuous edge scores from
:class: |
None
|
method
|
str
|
Scoring method that produced scores. Required when scores is
provided. Score polarity is looked up in
:data: |
None
|
Returns:
| Type | Description |
|---|---|
dict or None
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If scores is provided without method, or method is unknown. |
Examples:
>>> from spatial_graph_algorithms.simulate import generate
>>> from spatial_graph_algorithms.denoise import denoise
>>> from spatial_graph_algorithms.metrics import evaluate_denoising
>>> sg = generate(n=200, false_edges_fraction=0.10, seed=42)
>>> sg_clean = denoise(sg, method="jaccard", fraction_to_remove=0.10)
>>> report = evaluate_denoising(sg_clean)
>>> report is not None and "f1" in report
True
Source code in src/spatial_graph_algorithms/metrics/denoise_quality.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | |
spatial_graph_algorithms.metrics.graph_report(sg)
Return a GraphReport characterizing the given SpatialGraph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sg
|
SpatialGraph
|
Input graph. May or may not have ground-truth positions. |
required |
Returns:
| Type | Description |
|---|---|
GraphReport
|
Report with topology properties always populated and spatial
properties populated when |
Examples:
>>> from spatial_graph_algorithms.simulate import generate
>>> from spatial_graph_algorithms.metrics import graph_report
>>> sg = generate(n=200, seed=0)
>>> r = graph_report(sg)
>>> r.n_nodes
200
Source code in src/spatial_graph_algorithms/metrics/report.py
spatial_graph_algorithms.metrics.GraphReport
Structural and spatial characterization of a SpatialGraph.
Instantiation computes all fast properties immediately. Expensive metrics
(diameter, average path length, betweenness) are lazy and cached on first
access via :func:functools.cached_property.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sg
|
SpatialGraph
|
Input graph. May or may not have ground-truth positions. |
required |
Examples:
>>> from spatial_graph_algorithms.simulate import generate
>>> from spatial_graph_algorithms.metrics import graph_report
>>> sg = generate(n=200, seed=0)
>>> r = graph_report(sg)
>>> r.n_nodes
200
>>> r.edge_length_stats["mean"] > 0
True
Source code in src/spatial_graph_algorithms/metrics/report.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | |
Attributes
diameter
cached
property
Diameter of the largest connected component.
O(n²) — may be slow for large graphs.
average_path_length
cached
property
Mean shortest-path length in the largest connected component.
O(n²) — may be slow for large graphs.
betweenness_centrality_stats
cached
property
Min / max / mean betweenness centrality over all nodes.
O(n · m) — may be slow for large graphs.
Returns:
| Type | Description |
|---|---|
dict
|
Keys: |
Functions
to_dict()
Return a flat dictionary of all default properties.
Returns:
| Type | Description |
|---|---|
dict
|
Topology keys are always present. Spatial keys are |
Source code in src/spatial_graph_algorithms/metrics/report.py
plot_degree_distribution(*, log_scale=False, **kwargs)
Return a bar chart of the degree distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
log_scale
|
bool
|
If |
False
|
**kwargs
|
Passed through to :func: |
{}
|
Returns:
| Type | Description |
|---|---|
Figure
|
|
Source code in src/spatial_graph_algorithms/metrics/report.py
plot_edge_length_distribution(*, log_scale=False, **kwargs)
Return a histogram of edge lengths.
Requires ground-truth positions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
log_scale
|
bool
|
If |
False
|
**kwargs
|
Passed through to :func: |
{}
|
Returns:
| Type | Description |
|---|---|
Figure
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the graph has no ground-truth positions. |
Source code in src/spatial_graph_algorithms/metrics/report.py
spatial_graph_algorithms.metrics.graph_summary(sn)
Return a high-level structural summary of the graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sn
|
SpatialGraph
|
Input graph. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary with keys:
|
Examples:
>>> from spatial_graph_algorithms.simulate import generate
>>> from spatial_graph_algorithms.metrics import graph_summary
>>> sn = generate(n=200, seed=0)
>>> s = graph_summary(sn)
>>> s["n_nodes"]
200
Source code in src/spatial_graph_algorithms/metrics/graph_properties.py
spatial_graph_algorithms.metrics.degree_sequence(sn)
Return the per-node degree sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sn
|
SpatialGraph
|
Input graph. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Float array of shape |
Source code in src/spatial_graph_algorithms/metrics/graph_properties.py
spatial_graph_algorithms.metrics.quality_table(reconstructions, *, k_neighbors=15)
Build a quality-metrics table for one or more reconstructions.
Calls :func:evaluate on each entry in reconstructions and collects
CPD, KNN, and Distortion into a tidy DataFrame indexed by method label.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reconstructions
|
dict[str, SpatialGraph]
|
Mapping of method label → reconstructed
:class: |
required |
k_neighbors
|
int
|
Passed to :func: |
15
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with columns |
Examples:
>>> from spatial_graph_algorithms.simulate import generate
>>> from spatial_graph_algorithms.reconstruct import reconstruct
>>> from spatial_graph_algorithms.metrics import quality_table
>>> sg = generate(n=300, seed=42)
>>> qt = quality_table({"MDS": reconstruct(sg, method="mds", seed=42)})
>>> qt.columns.tolist()
['CPD', 'KNN', 'Distortion']
Source code in src/spatial_graph_algorithms/metrics/__init__.py
spatial_graph_algorithms.metrics.degree_distribution(sn)
Compute the degree distribution as counts and proportions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sn
|
SpatialGraph
|
Input graph. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
A dictionary with two sub-dicts:
|
Examples:
>>> from spatial_graph_algorithms.simulate import generate
>>> from spatial_graph_algorithms.metrics import degree_distribution
>>> sn = generate(n=100, seed=0)
>>> dist = degree_distribution(sn)
>>> sum(dist["proportions"].values())
1.0