Automatic bedding measurement approximation for geological modeling
Loop-Autobedding is a Python package that addresses a critical challenge in implicit geological modeling: the lack of bedding measurements in many geological datasets. This package provides methods to approximate bedding orientations from various data sources when direct field measurements are not available.
Tools like LoopStructural and map2loop require bedding measurements (strike, dip, and dip direction) to perform implicit geological modeling. However, many geological datasets lack these critical measurements. This creates a significant barrier to:
- Broad-scale geological modeling
- Rapid prototyping of geological models
- Simulating large numbers of models for uncertainty analysis
- Working with legacy datasets that don't include structural measurements
Loop-Autobedding provides multiple methods to approximate bedding measurements from commonly available data:
- DEM-based approximation: Uses topographic gradients from Digital Elevation Models
- Contact-based approximation: Derives orientations from geological map contact lines
- Regional trend approximation: Applies known regional structural trends
- Interpolation: Densifies sparse measurements through spatial interpolation
Each method includes quality scoring to help users understand the reliability of approximated measurements.
git clone https://github.com/RichardScottOZ/Loop-Autobedding.git
cd Loop-Autobedding
pip install -e .- Python >= 3.8
- numpy >= 1.20.0
For development:
pip install -e ".[dev]"For running examples:
pip install -e ".[examples]"import numpy as np
from autobedding import AutobeddingEstimator
# Initialize estimator
estimator = AutobeddingEstimator()
# Example 1: Generate from regional trend
x = np.linspace(0, 1000, 20)
y = np.linspace(0, 1000, 20)
X, Y = np.meshgrid(x, y)
regional_data = estimator.add_regional_trend(
strike=45.0,
dip=30.0,
x_coords=X.flatten(),
y_coords=Y.flatten(),
name="regional"
)
print(f"Generated {len(regional_data)} measurements")
# Export to CSV for use with LoopStructural
estimator.export_to_csv(regional_data, "bedding_measurements.csv")Approximates bedding from topographic slopes, useful in areas with differential erosion:
dem_data = estimator.add_dem_estimates(
dem=elevation_array,
x_coords=x_coordinates,
y_coords=y_coordinates,
cell_size=30.0,
sample_spacing=10
)Derives bedding orientations from mapped geological contacts:
contact_points = [(x1, y1, z1), (x2, y2, z2), ...]
contact_data = estimator.add_contact_estimates(
contact_points=contact_points,
formation="Sandstone Formation"
)Applies uniform regional strike and dip across study area:
regional_data = estimator.add_regional_trend(
strike=45.0,
dip=30.0,
x_coords=x_array,
y_coords=y_array
)Densifies existing sparse measurements:
interpolated = estimator.interpolate_from_sparse(
known_dataset=sparse_measurements,
target_x=target_x_coords,
target_y=target_y_coords,
method="nearest"
)All measurements include quality scores (0-1) indicating reliability:
from autobedding.utils import quality_score, validate_measurements
# Get quality metrics
metrics = quality_score(dataset)
print(f"Mean quality: {metrics['mean_quality']:.2f}")
print(f"High quality measurements: {metrics['high_quality_count']}")
# Validate measurements
validation = validate_measurements(dataset)
print(f"Valid: {validation['valid_measurements']}")
print(f"Invalid: {validation['invalid_measurements']}")Combine multiple data sources with quality filtering:
# Combine all datasets with minimum quality threshold
combined = estimator.combine_datasets(min_quality=0.5)
# Filter by formation
formation_data = combined.filter_by_formation("Formation_1")
# Filter by quality
high_quality = combined.filter_by_quality(min_quality=0.7)See examples/basic_usage.py for a simple introduction:
cd examples
python basic_usage.pySee examples/advanced_workflow.py for a complete workflow including:
- Multiple data source integration
- Quality filtering and validation
- Formation-based filtering
- Export for LoopStructural/map2loop
cd examples
python advanced_workflow.pyMain class for generating and managing bedding measurements.
Methods:
add_dem_estimates(): Generate from DEM dataadd_contact_estimates(): Generate from geological contactsadd_regional_trend(): Generate from regional trendinterpolate_from_sparse(): Interpolate from sparse datacombine_datasets(): Combine multiple datasetsexport_to_csv(): Export to CSV file
Represents a single bedding measurement.
Attributes:
x,y,z: Coordinatesdip: Dip angle (0-90°)dip_direction: Dip direction (0-360°)formation: Formation name (optional)quality: Quality score (0-1)source: Data source identifier
Collection of bedding measurements.
Methods:
filter_by_quality(): Filter by quality thresholdfilter_by_formation(): Filter by formation nameto_arrays(): Convert to numpy arrays
DEMApproximator: DEM-based approximationContactApproximator: Contact-based approximationRegionalTrendApproximator: Regional trend approximationInterpolationApproximator: Interpolation-based approximation
validate_measurements(): Validate datasetquality_score(): Calculate quality metricscalculate_spatial_coverage(): Calculate spatial statisticsdetect_outliers(): Detect potential outliers
Generate bedding measurements across large areas using regional trends and DEM data:
# Regional trend for background
regional = estimator.add_regional_trend(strike=30, dip=25, ...)
# DEM refinement for local variations
dem_refined = estimator.add_dem_estimates(dem, ...)
# Combine with quality filtering
model_input = estimator.combine_datasets(min_quality=0.4)Add missing bedding measurements to legacy geological maps:
# Extract contacts from geological map
contacts = extract_contacts_from_map(geological_map)
# Generate bedding approximations
for formation, contact_line in contacts.items():
estimator.add_contact_estimates(contact_line, formation=formation)
combined = estimator.combine_datasets()Generate multiple realizations with varying parameters:
# Create multiple scenarios
for strike in [30, 35, 40, 45]:
for dip in [20, 25, 30]:
dataset = estimator.add_regional_trend(
strike=strike, dip=dip, ...,
name=f"scenario_s{strike}_d{dip}"
)
# Use each scenario for modelingInterpolate between sparse field measurements:
# Load sparse field measurements
known = load_field_measurements()
# Create dense grid
interpolated = estimator.interpolate_from_sparse(
known, target_x, target_y, method="nearest"
)Loop-Autobedding is designed to work seamlessly with Loop3D tools:
import pandas as pd
from LoopStructural import GeologicalModel
# Generate bedding measurements
estimator = AutobeddingEstimator()
# ... add various estimates ...
dataset = estimator.combine_datasets(min_quality=0.5)
# Export to CSV
estimator.export_to_csv(dataset, "bedding.csv")
# Load into LoopStructural
bedding_df = pd.read_csv("bedding.csv")
model = GeologicalModel(...)
model.add_orientation_data(bedding_df)-
DEM-based: 0.4-0.7 (depends on terrain)
- Best for areas with differential erosion
- Lower quality in heavily modified terrain
-
Contact-based: 0.6-0.8
- Good for clear geological contacts
- Assumes contacts parallel bedding
-
Regional trend: 0.3-0.6
- Useful for broad-scale modeling
- Lower quality due to lack of local variation
-
Interpolated: Quality degraded from source
- Useful for densification
- Quality decreases with distance from known points
- Combine multiple sources: Use different methods and filter by quality
- Validate results: Always check with
validate_measurements() - Use quality filtering: Set appropriate thresholds for your use case
- Check spatial coverage: Use
calculate_spatial_coverage()to ensure adequate sampling - Detect outliers: Use
detect_outliers()to identify suspicious measurements
Run the test suite:
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/
# Run with coverage
pytest --cov=autobedding tests/Contributions are welcome! Areas for improvement:
- Additional approximation methods (e.g., kriging, machine learning)
- Integration with geospatial file formats (GeoTIFF, Shapefiles)
- Visualization tools
- Additional quality metrics
- Performance optimizations
If you use Loop-Autobedding in your research, please cite:
Loop-Autobedding: Automatic bedding measurement approximation for geological modeling
https://github.com/RichardScottOZ/Loop-Autobedding
- LoopStructural - Implicit geological modeling
- map2loop - Map data extraction for geological modeling
- Loop3D - Open source 3D geological modeling platform
This package was developed to support the Loop3D project and the broader geological modeling community.
For questions, issues, or contributions, please use the GitHub issue tracker.