Troubleshooting & FAQ

Common issues and solutions.

Installation Issues

Q: ImportError: No module named ‘mpspline’

A: Make sure mpspline is installed:

pip install mpspline

Or verify installation:

pip list | grep mpspline

Q: ModuleNotFoundError when importing

A: You may have multiple Python environments. Check you’re using the right one:

which python  # See which Python is active
python -m pip install mpspline

Q: Version conflicts with dependencies

A: Install in a clean virtual environment:

python -m venv venv
source venv/bin/activate
pip install mpspline

Data Input Issues

Q: KeyError: ‘horizons’

A: Your input doesn’t have a ‘horizons’ key. The correct structure is:

# ✗ Wrong - no 'horizons' key
data = {'cokey': 123, 'clay': 25}

# ✓ Correct - has 'horizons' key
data = {
    'cokey': 123,
    'horizons': [
        {'upper': 0, 'lower': 20, 'clay': 25}
    ]
}

Q: KeyError: ‘upper’ or ‘lower’

A: Your horizons don’t have recognized depth fields. Use one of these names:

# These all work:
{'upper': 0, 'lower': 20}      # Recommended
{'top': 0, 'bottom': 20}
{'start': 0, 'end': 20}
{'depth_min': 0, 'depth_max': 20}
{'hzdept_r': 0, 'hzdepb_r': 20}  # SSURGO standard

# This does NOT work:
{'depth': 0, 'lower': 20}      # 'depth' not recognized

Q: ValueError: Horizons must be ordered by depth

A: Your horizons have gaps, overlaps, or invalid depths. Check that:

# ✗ Wrong - overlapping
{'upper': 0, 'lower': 30}
{'upper': 20, 'lower': 50}

# ✓ Correct - sequential
{'upper': 0, 'lower': 20}
{'upper': 20, 'lower': 50}

# ✗ Wrong - inverted
{'upper': 20, 'lower': 10}

# ✓ Correct - ordered
{'upper': 10, 'lower': 20}

Q: TypeError: unhashable type: ‘dict’

A: You may have passed a single profile incorrectly. For a single profile, pass it directly (not in a list):

# ✓ Correct - single profile (dict)
result = mpspline(profile)

# ✗ Don't pass single profile in list
result = mpspline([profile])  # Returns DataFrame, not dict

Output Issues

Q: Output contains NaN values

A: This usually happens when the profile doesn’t extend to those depths:

# Profile only goes to 80cm
profile = {
    'horizons': [
        {'upper': 0, 'lower': 20, 'clay': 20},
        {'upper': 20, 'lower': 80, 'clay': 30},  # Stops at 80cm
    ]
}

result = mpspline(profile)
# Result will have NaN for 100-200cm because profile doesn't go that deep

Solution: Either extend your profile or use custom depths:

# Option 1: Only use depths your profile covers
result = mpspline(
    profile,
    target_depths=[(0, 5), (5, 15), (15, 30), (30, 60), (60, 80)]
)

# Option 2: Extend profile with lower horizon
profile['horizons'].append({
    'upper': 80,
    'lower': 120,
    'clay': 28,
})

Q: Predicted values seem unrealistic

A: You may need to add value constraints:

# ✗ Without constraints, clay might go above 100%
result = mpspline(profile)

# ✓ With constraints
result = mpspline(
    profile,
    var_name=['clay'],
    vlow=0.0,
    vhigh=100.0
)

Q: Some properties missing from output

A: Non-numeric properties are skipped. Check that your properties are numbers:

horizon = {
    'upper': 0,
    'lower': 20,
    'clay': 25.0,           # ✓ Numeric - included
    'texture': 'loam',      # ✗ String - skipped
    'sand': '40.0',         # ? String number - may or may not work
}

Solution: Convert to numeric or specify in var_name:

# Option 1: Ensure numeric
horizon['sand'] = float(horizon['sand'])

# Option 2: Specify what to process
result = mpspline(profile, var_name=['clay', 'sand'])

Processing Issues

Q: Processing is very slow

A: Enable parallel processing and optimize batch size:

# Enable parallel processing
df = mpspline(
    profiles,
    parallel=True,      # Use multiple cores
    batch_size=500,     # Tune batch size
    var_name=['clay'],  # Process only needed properties
)

Q: Memory error with large dataset

A: Reduce batch size or use parallel processing:

# Smaller batches = less memory
df = mpspline(
    profiles,
    batch_size=50,      # Reduce from default 100
    parallel=False,     # Single process
)

Q: Parallel processing doesn’t work on Windows

A: Wrap your code in if __name__ == ‘__main__’::

from mpspline import mpspline

if __name__ == '__main__':
    df = mpspline(profiles, parallel=True)

Q: Getting errors like “RuntimeError: An attempt has been made…”

A: This usually means the above issue on Windows. Use the if __name__ pattern.

Validation Errors

Q: What does “strict mode” mean?

A:

# Lenient mode (default, strict=False)
# Logs warnings, skips bad profiles, returns results for valid ones
df = mpspline(profiles, strict=False)

# Strict mode (strict=True)
# Raises exception on first error
df = mpspline(profiles, strict=True)

Use strict=True when debugging, strict=False for production.

Q: How do I see validation warnings?

A: Configure Python logging:

import logging
logging.basicConfig(level=logging.WARNING)

result = mpspline(profile, strict=False)

Advanced Issues

Q: Why are results slightly different between runs?

A: Due to floating-point arithmetic, tiny differences (~0.001%) are normal.

Q: How do I compare results with the R mpspline2?

A: Results should be nearly identical (within 0.01%). Small differences are due to: - Python vs R numerical differences - Different random seeds if parallel - Rounding differences in display

Q: What’s the meaning of the ‘lam’ parameter?

A: It’s the smoothing parameter in the spline algorithm. See Parameters for details.

Still Having Issues?

If you’ve tried the above solutions:

  1. Check the full documentation: https://py-mpspline.readthedocs.io

  2. Review the examples in the examples/ directory

  3. Look at the docstrings: help(mpspline.mpspline)

  4. Open an issue on GitHub: https://github.com/brownag/mpspline/issues

When reporting an issue, please include: - Python version: python –version - mpspline version: python -c “import mpspline; print(mpspline.__version__)” - Minimal code that reproduces the issue - Full error message and traceback