Mass-preserving equal-area quadratic splines for depth harmonization of soil component profiles
Project description
mpspline
Python implementation of mass-preserving equal-area quadratic splines for harmonizing soil profiles to standard depth intervals.
Port of the mpspline2 R package by Lauren O'Brien, based on the method of Bishop et al. (1999), as generalized in Malone et al. (2009).
Installation
pip install mpspline
Quick Start
from mpspline import mpspline
# Single profile
result = mpspline({
'horizons': [
{'hzname': 'A', 'upper': 0, 'lower': 20, 'clay': 24.5},
{'hzname': 'B', 'upper': 20, 'lower': 50, 'clay': 35.2},
]
})
print(result) # {'clay_0_5': 21.4, 'clay_5_15': 27.8, ...}
# Multiple profiles
profiles = [...]
df = mpspline(profiles) # Returns DataFrame
Usage
Pass a dict for a single profile or a list for multiple profiles:
from mpspline import mpspline
# Single profile (returns dict)
result = mpspline({
'cokey': 12345,
'horizons': [
{'hzname': 'Ap', 'upper': 0, 'lower': 20, 'clay': 24.5},
{'hzname': 'Bt', 'upper': 20, 'lower': 50, 'clay': 35.2},
]
})
print(result['clay_0_5']) # 21.4
# Multiple profiles (returns DataFrame)
profiles = [
{
'cokey': 1001,
'horizons': [
{'hzname': 'A', 'upper': 0, 'lower': 15, 'clay': 18.5},
{'hzname': 'Bt1', 'upper': 15, 'lower': 45, 'clay': 35.0},
{'hzname': 'Bt2', 'upper': 45, 'lower': 80, 'clay': 32.5},
]
},
{
'cokey': 1002,
'horizons': [
{'hzname': 'Ap', 'upper': 0, 'lower': 20, 'clay': 15.2},
{'hzname': 'Bw', 'upper': 20, 'lower': 50, 'clay': 28.4},
{'hzname': 'C', 'upper': 50, 'lower': 100, 'clay': 25.0},
]
},
]
df = mpspline(profiles, var_name=['clay'], parallel=True)
print(df[['cokey', 'clay_0_5', 'clay_5_15', 'clay_15_30', 'clay_30_60']])
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
dict or list | Required | Profile(s) with a 'horizons' key |
var_name |
str or list | None | Properties to harmonize (all numeric if None) |
target_depths |
list | GlobalSoilMap | Depth intervals as (top, bottom). Default: [(0,5), (5,15), (15,30), (30,60), (60,100), (100,200)] |
lam |
float | 0.1 | Smoothing parameter (0.01=smooth, 1.0=fit data closely) |
vlow |
float | 0.0 | Minimum constraint for values |
vhigh |
float | 1000.0 | Maximum constraint for values |
parallel |
bool | False | Use multiprocessing for multiple profiles |
batch_size |
int | 100 | Profiles per batch |
strict |
bool | False | Raise exceptions on validation errors (False = skip) |
Horizon Input Format
Required fields:
- Depth:
upperandlower(ortopandbottom) in cm - Properties: numeric fields to harmonize
Optional:
hzname: horizon name
Example:
{
'hzname': 'Ap',
'upper': 0,
'lower': 20,
'clay': 24.5,
'sand': 42.3,
}
Examples
# Custom depth intervals
result = mpspline(profile, target_depths=[(0, 10), (10, 30), (30, 60)])
# Adjust smoothing (0.01=smooth, 1.0=closer to data)
result = mpspline(profile, lam=0.01)
# Constrain values to realistic ranges
result = mpspline(profile, var_name=['clay'], vlow=0, vhigh=100)
# Parallel processing for many profiles
df = mpspline(profiles, parallel=True, batch_size=500)
# Only process specific properties
df = mpspline(profiles, var_name=['clay', 'sand'])
# Error handling: skip bad profiles or raise errors
df = mpspline(profiles, strict=False) # Skip problematic profiles
try:
df = mpspline(profiles, strict=True) # Raise on errors
except ValueError as e:
print(f"Validation error: {e}")
Troubleshooting
Horizons not ordered by depth: Horizons must be sequential with no gaps or overlaps.
# Wrong
{'upper': 0, 'lower': 30}, {'upper': 20, 'lower': 50}
# Right
{'upper': 0, 'lower': 20}, {'upper': 20, 'lower': 50}
Values outside expected ranges: Use vlow and vhigh to constrain predictions:
result = mpspline(profile, vlow=0, vhigh=100)
Processing is slow: Enable parallel processing:
df = mpspline(profiles, parallel=True, batch_size=500)
How it works
The algorithm fits a mass-preserving equal-area quadratic spline to horizon data. This converts discrete observations at varying depths to standard depth intervals while preserving the average value across each depth range.
See the algorithm documentation for details.
References
- O'Brien, L. (2025). mpspline2: Mass-Preserving Spline Functions for Soil Data. R package version 0.1.9. https://doi.org/10.32614/CRAN.package.mpspline2
- Bishop, T.F.A., McBratney, A.B., & Laslett, G.M. (1999). Modelling soil attribute depth functions with equal-area quadratic smoothing splines. Geoderma, 89(3-4), 185-208. https://doi.org/10.1016/S0016-7061(99)00003-8
- Malone, B.P., McBratney, A.B., & Minasny, B. (2009). Mapping continuous depth functions of soil carbon storage and available water capacity. Geoderma, 154(3-4), 138-152. https://doi.org/10.1016/j.geoderma.2009.10.007
License
GPL 3.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mpspline-0.1.0.tar.gz.
File metadata
- Download URL: mpspline-0.1.0.tar.gz
- Upload date:
- Size: 38.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d1421c99663be84bff9a1189d7b29d43b53ee809f29cb6a4e6335ac48e0a31e
|
|
| MD5 |
103cac0102edbd7baf6be8bb20195123
|
|
| BLAKE2b-256 |
ff99cbde30bd23ba6161dce2c186773c606ee8b840dbe02b9d7e2d2430666d4e
|
Provenance
The following attestation bundles were made for mpspline-0.1.0.tar.gz:
Publisher:
pypi-release.yml on brownag/py-mpspline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mpspline-0.1.0.tar.gz -
Subject digest:
0d1421c99663be84bff9a1189d7b29d43b53ee809f29cb6a4e6335ac48e0a31e - Sigstore transparency entry: 815769561
- Sigstore integration time:
-
Permalink:
brownag/py-mpspline@db8c52c3bec7694de8d9e962f7f8ffcfcc67773b -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/brownag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@db8c52c3bec7694de8d9e962f7f8ffcfcc67773b -
Trigger Event:
release
-
Statement type:
File details
Details for the file mpspline-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mpspline-0.1.0-py3-none-any.whl
- Upload date:
- Size: 32.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5213336f8d160b677fb0f09251f544ba004a2ce583021e85bd6890c01948c9bb
|
|
| MD5 |
921a61ba19bd041f58b09e4dfd1442d2
|
|
| BLAKE2b-256 |
d983ac6e30a223d2cc1d5d957943e86faad4e8ddf6fb363e75e5f6734f640e63
|
Provenance
The following attestation bundles were made for mpspline-0.1.0-py3-none-any.whl:
Publisher:
pypi-release.yml on brownag/py-mpspline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mpspline-0.1.0-py3-none-any.whl -
Subject digest:
5213336f8d160b677fb0f09251f544ba004a2ce583021e85bd6890c01948c9bb - Sigstore transparency entry: 815769574
- Sigstore integration time:
-
Permalink:
brownag/py-mpspline@db8c52c3bec7694de8d9e962f7f8ffcfcc67773b -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/brownag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@db8c52c3bec7694de8d9e962f7f8ffcfcc67773b -
Trigger Event:
release
-
Statement type: