Skip to content

Commit 6047084

Browse files
committed
updated calculate_semivariance() function
1 parent 8906833 commit 6047084

File tree

4 files changed

+99
-13
lines changed

4 files changed

+99
-13
lines changed

CHANGELOG.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Changes - from version >= 1.x
22
=============================
33

4+
2025-11-0
5+
----------
6+
7+
**version 1.2.0**
8+
9+
* [enhancement] `Blocks` has the new parameters `values` and `geometries`, that might be provided instead of `ds` parameter
10+
* [enhancement] `calculate_semivariance()` function has the new parameters `values` and `geometries`, that might be provided instead of `ds` parameter
11+
* [enhancement] `interpolate_points()` function has the new parameters `values` and `geometries`, that might be provided instead of `ds` parameter
12+
413
2025-10-11
514
----------
615

src/pyinterpolate/core/data_models/points.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from pydantic import field_validator, BaseModel, ConfigDict
1010
from shapely.geometry import Point
1111

12+
from transform.geo import join_geometry_and_values
13+
1214

1315
class RawPoints(BaseModel):
1416
"""
@@ -100,9 +102,19 @@ class VariogramPoints:
100102
def __init__(self,
101103
points: Union[
102104
List, Tuple, ndarray, GeoDataFrame, GeoSeries, DataFrame
103-
]
105+
] = None,
106+
geometries: Union[
107+
List, Tuple, ndarray, GeoDataFrame, GeoSeries, DataFrame
108+
] = None,
109+
values: Union[
110+
List, Tuple, ndarray, DataFrame, Series
111+
] = None
104112
):
105113

114+
if points is None:
115+
# Try to create points
116+
points = join_geometry_and_values(geometries, values)
117+
106118
# validate
107119
self.points = cast(RawPoints, points)
108120

@@ -119,9 +131,14 @@ def transform(self):
119131
if len(cols) == 2:
120132
ds = self.points.copy()
121133
# geometry | values
122-
ds['x'] = ds[cols[0]].x
123-
ds['y'] = ds[cols[0]].y
124-
self.points = ds[['x', 'y', cols[1]]].values
134+
try:
135+
ds['x'] = ds[cols[0]].x
136+
ds['y'] = ds[cols[0]].y
137+
self.points = ds[['x', 'y', cols[1]]].values
138+
except AttributeError:
139+
ds['x'] = ds[cols[1]].x
140+
ds['y'] = ds[cols[1]].y
141+
self.points = ds[['x', 'y', cols[0]]].values
125142
elif len(cols) == 3:
126143
self.points = self.points.values
127144
elif isinstance(self.points, DataFrame):

src/pyinterpolate/semivariogram/experimental/experimental_semivariogram.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import warnings
22
from typing import Union, List, Any, Dict
3+
from numpy.typing import ArrayLike
34

45
import numpy as np
56

@@ -16,21 +17,32 @@
1617
from pyinterpolate.semivariogram.lags.lags import get_lags
1718

1819

19-
def calculate_semivariance(ds: Union[np.ndarray, VariogramPoints],
20+
def calculate_semivariance(ds: Union[ArrayLike, VariogramPoints] = None,
21+
values: ArrayLike = None,
22+
geometries: ArrayLike = None,
2023
step_size: float = None,
2124
max_range: float = None,
2225
direction: float = None,
2326
tolerance: float = None,
24-
custom_bins: Union[np.ndarray, Any] = None,
25-
custom_weights: np.ndarray = None) -> np.ndarray:
27+
custom_bins: Union[ArrayLike, Any] = None,
28+
custom_weights: ArrayLike = None) -> np.ndarray:
2629
"""
2730
Calculates experimental semivariance.
2831
2932
Parameters
3033
----------
31-
ds : numpy array
34+
ds : ArrayLike, optional
3235
``[x, y, value]``
3336
37+
values : ArrayLike, optional
38+
Aggregated values of each block. Optional parameter, if not
39+
given then ``ds`` must be provided.
40+
41+
geometries : ArrayLike, optional
42+
Array or similar structure with geometries. It must have the same
43+
length as ``values``. Optional parameter, if not given then ``ds``
44+
must be provided. Those must be point geometries!
45+
3446
step_size : float
3547
The fixed distance between lags grouping point neighbors.
3648
@@ -58,17 +70,17 @@ def calculate_semivariance(ds: Union[np.ndarray, VariogramPoints],
5870
* The baseline point is at a center of the ellipse.
5971
* The ``tolerance == 1`` creates an omnidirectional semivariogram.
6072
61-
custom_bins : numpy array, optional
73+
custom_bins : ArrayLike, optional
6274
Custom bins for semivariance calculation. If provided, then parameter
6375
``step_size`` is ignored and ``max_range`` is set to the final bin
6476
distance.
6577
66-
custom_weights : numpy array, optional
78+
custom_weights : ArrayLike, optional
6779
Custom weights assigned to points.
6880
6981
Returns
7082
-------
71-
semivariance : numpy array
83+
semivariance : ArrayLike
7284
``[lag, semivariance, number of point pairs]``
7385
7486
Notes
@@ -184,10 +196,11 @@ def calculate_semivariance(ds: Union[np.ndarray, VariogramPoints],
184196
[ 1. 4.625 24. ]
185197
"""
186198

187-
# Validation
188199
# Validate points
189200
if not isinstance(ds, VariogramPoints):
190-
ds = VariogramPoints(points=ds)
201+
ds = VariogramPoints(points=ds,
202+
geometries=geometries,
203+
values=values)
191204

192205
# Validate bins
193206
validate_bins(step_size, max_range, custom_bins)

tests/test_semivariogram/test_experimental_semivariance.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,50 @@ def test_weighted_directional_semivariogram():
168168
)
169169

170170
assert isinstance(semivariance, np.ndarray)
171+
172+
173+
def test_omnidirectional_semivariogram_values_geometry_inputs():
174+
import geopandas as gpd
175+
176+
177+
REFERENCE_INPUT = np.array([
178+
[0, 0, 8],
179+
[1, 0, 6],
180+
[2, 0, 4],
181+
[3, 0, 3],
182+
[4, 0, 6],
183+
[5, 0, 5],
184+
[6, 0, 7],
185+
[7, 0, 2],
186+
[8, 0, 8],
187+
[9, 0, 9],
188+
[10, 0, 5],
189+
[11, 0, 6],
190+
[12, 0, 3]
191+
])
192+
STEP_SIZE = 1
193+
MAX_RANGE = 4
194+
195+
GEOMETRY = gpd.points_from_xy(
196+
x=REFERENCE_INPUT[:, 0], y=REFERENCE_INPUT[:, 1]
197+
)
198+
199+
semivariance = calculate_semivariance(
200+
ds=None,
201+
values=REFERENCE_INPUT[:, -1],
202+
geometries=GEOMETRY,
203+
step_size=STEP_SIZE,
204+
max_range=MAX_RANGE
205+
)
206+
207+
expected_output = np.array(
208+
[
209+
[1., 4.625, 24.],
210+
[2., 5.22727273, 22.],
211+
[3., 6., 20.]
212+
]
213+
)
214+
215+
assert isinstance(semivariance, np.ndarray)
216+
assert semivariance.shape == (3, 3)
217+
assert np.allclose(semivariance, expected_output)

0 commit comments

Comments
 (0)