API reference¶
The primary public API is the scikit-learn-compatible estimator.
SpatialDeformer ¶
SpatialDeformer(*, backend: str = 'mds', cost: str = 'travel_cost', missing_cost: str | Callable[[GeoDataFrame, ndarray], Any] = 'error', fallback_speed: float = 8.0, impute_by: str | None = None, source: str | None = 'source', target: str | None = 'target', scale: str | float = 'auto', geo_weight: float = 0.1, spatial_weight: str = 'uniform', spatial_bandwidth: float | None = None, directed: bool = False, directed_policy: str = 'mean', auto_project: bool = True, n_neighbors: int = 8, displacement_power: float = 2.0, node_precision: int = 9, max_iter: int = 300, tol: float = 1e-06, n_components: int = 2)
Bases: TransformerMixin, BaseEstimator
Deform a line network so map distance represents network travel cost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
('mds', 'isomap')
|
|
"mds"
|
cost
|
str
|
Edge column used as travel cost when |
"travel_cost"
|
missing_cost
|
('error', 'drop', 'length', 'median')
|
Policy for NaN or infinite edge costs. A callable receives |
"error"
|
fallback_speed
|
float
|
Working-CRS distance units per cost unit used by
|
8.0
|
impute_by
|
str or None
|
Optional column used for groupwise median imputation. Groups without a finite value fall back to the global median. |
None
|
source
|
str or None
|
Edge endpoint identifier columns. When absent, rounded geometry endpoints define node identity. |
'source'
|
target
|
str or None
|
Edge endpoint identifier columns. When absent, rounded geometry endpoints define node identity. |
'source'
|
scale
|
'auto' or float
|
Conversion from cost units to working-CRS units. Reuse a fitted
|
"auto"
|
geo_weight
|
float
|
Strength of preservation of the original node coordinates. |
0.1
|
spatial_weight
|
('uniform', 'gaussian', 'inverse')
|
Pair weighting in the MDS stress objective. |
"uniform"
|
spatial_bandwidth
|
float or None
|
Working-CRS bandwidth for non-uniform pair weights. The median geographic node distance is used when omitted. |
None
|
directed
|
bool
|
Whether edge costs form a directed graph. |
False
|
directed_policy
|
('mean', 'min', 'max')
|
How reciprocal directed shortest-path costs become a symmetric metric. |
"mean"
|
auto_project
|
bool
|
Automatically project a geographic CRS to an estimated local UTM CRS. |
True
|
n_neighbors
|
int
|
Nearby graph nodes used to interpolate displacement at line vertices. |
8
|
displacement_power
|
float
|
Inverse-distance interpolation power for non-node vertices. |
2.0
|
node_precision
|
int
|
Decimal precision used when geometry endpoints define node identity. |
9
|
max_iter
|
int
|
Maximum SMACOF iterations. |
300
|
tol
|
float
|
Relative stress convergence tolerance. |
1e-6
|
Attributes:
| Name | Type | Description |
|---|---|---|
embedding_ |
ndarray of shape (n_nodes, 2)
|
Deformed node coordinates in |
geographic_coordinates_ |
ndarray of shape (n_nodes, 2)
|
Original node coordinates in |
graph_distances_ |
ndarray of shape (n_nodes, n_nodes)
|
Symmetric shortest travel-cost distances. |
node_ids_ |
ndarray of shape (n_nodes,)
|
Node identifiers in embedding order. |
scale_ |
float
|
Fitted cost-to-map-unit scale. |
stress_ |
float
|
Final raw weighted stress. |
normalized_stress_ |
float
|
Stress divided by weighted squared target distances. |
costs_ |
ndarray of shape (n_edges,)
|
Resolved costs aligned with the input. Dropped positions remain NaN or
infinite and are excluded by |
edge_mask_ |
ndarray of shape (n_edges,)
|
Boolean mask of input edges used to fit the graph. |
imputed_edges_ |
list
|
Input index labels whose missing costs were imputed. |
dropped_edges_ |
list
|
Input index labels excluded by |
Source code in src/spatialdeform/_estimator.py
fit ¶
Fit the graph embedding from edge geometries and travel costs.
Source code in src/spatialdeform/_estimator.py
transform ¶
Apply the fitted smooth displacement field to line geometries.
Source code in src/spatialdeform/_estimator.py
get_nodes ¶
Return fitted deformed nodes as a GeoDataFrame.
By default nodes use the input CRS. Pass a CRS explicitly to override
that behavior; pass working_crs_ to inspect optimizer coordinates.
Source code in src/spatialdeform/_estimator.py
score ¶
Return negative normalized stress (higher is better).
Low-level constrained SMACOF¶
Large pipelines that already compute their own dissimilarity matrices can use the same optimization core directly. This is how the repository's landmark street-network pipeline shares SpatialDeform without constructing an infeasible all-pairs matrix for every one of its 19,000+ nodes.
spatial_smacof ¶
spatial_smacof(dissimilarities: Any, reference_coordinates: Any, *, pair_weights: Any | None = None, coordinate_weights: float | Any = 0.0, previous_coordinates: Any | None = None, temporal_weight: float = 0.0, init: Any | None = None, max_iter: int = 300, tol: float | None = 1e-06, backend: str = 'auto') -> tuple[np.ndarray, int]
Minimize weighted metric stress with coordinate constraints.
The optimized objective is
sum(i<j) w_ij (||x_i-x_j||-delta_ij)^2
+ sum(i) a_i ||x_i-g_i||^2
+ beta sum(i) ||x_i-p_i||^2.
backend="auto" uses the optional Rust kernel when installed and falls
back to NumPy/SciPy otherwise. Pass "rust" to require acceleration or
"python" for reproducible benchmarking. tol=None disables early
stopping, which is useful for callers that need a fixed iteration count.
Source code in src/spatialdeform/_smacof.py
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 | |
rust_available ¶
Fitted-state conventions¶
Calling fit replaces all learned attributes. Constructor parameters remain
unchanged, so sklearn.base.clone returns an unfitted estimator with the same
configuration.
from sklearn.base import clone
configured = SpatialDeformer(geo_weight=0.2, backend="mds")
fresh = clone(configured)
assert fresh.get_params() == configured.get_params()
transform and get_nodes call scikit-learn’s fitted-state validation and
raise NotFittedError when used before fit.