Python interface to TEM1D Fortran code for 1D transient electromagnetic forward modeling
Project description
pytem1d - Python Interface to TEM1D
Python wrapper for the TEM1D Fortran code that computes 1D transient electromagnetic (TEM) forward responses and derivatives for layered earth models.
Features
- Dual API: Functional and class-based interfaces
- Complete TEM1D functionality: Step/impulse responses, IP effects, polygonal loops, waveform convolution
- Derivatives: Jacobian matrix calculation for inversion
- Visualization: Built-in plotting functions
- I/O utilities: Save/load results, export to various formats
- Type-safe: Data classes with validation
- Parallel processing: Multiprocessing support for millions of forward models (see
examples/parallel_utils.py)
Installation
From source
# Clone the repository
git clone https://github.com/tem1d/tem1d.git
cd tem1d/python
# Build the Fortran shared library
make
# Install the Python package (editable mode for development)
pip install -e .
# Or install with development dependencies
pip install -e ".[dev]"
Requirements
- Python >= 3.8
- NumPy >= 1.20
- Matplotlib >= 3.3
- gfortran (or compatible Fortran compiler)
- make
Quick Start
Functional API (Simple)
import numpy as np
import matplotlib.pyplot as plt
from pytem1d import run_tem1d
# Simple 2-layer model: 100 Ω·m over 10 Ω·m halfspace
result = run_tem1d(
resistivities=[100, 10],
depths=[0, 50], # Interface at 50m depth
tx_area=314.16 # Circular loop, radius ~10m
)
# Plot response
plt.loglog(result.times * 1e3, np.abs(result.responses))
plt.xlabel('Time (ms)')
plt.ylabel('|dB/dt| (V/A·m²)')
plt.grid(True, alpha=0.3)
plt.show()
Class-Based API (Advanced)
from pytem1d import TEM1DModel
# Create model instance
tem = TEM1DModel()
# Configure layered earth
tem.set_earth_model(
resistivities=[100, 10, 50], # 3 layers
depths=[0, 30, 100] # Interfaces at 30m and 100m
)
# Configure instrument
tem.set_instrument(
tx_area=314.16,
tx_rx_separation=0.0 # Central loop
)
# Enable derivative calculation
tem.enable_derivatives(True)
# Run forward modeling
result = tem.run()
# Access results
print(f"Number of time gates: {len(result.times)}")
print(f"Derivative shape: {result.derivatives.shape}")
With IP Effects
from pytem1d import run_tem1d
result = run_tem1d(
resistivities=[100, 10, 50],
depths=[0, 30, 100],
tx_area=314.16,
# Cole-Cole IP parameters
ip_params={
'chargeabilities': [0.1, 0.3, 0.05],
'time_constants': [0.01, 0.05, 0.001],
'powers': [0.5, 0.4, 0.6]
}
)
Polygonal Loop
import numpy as np
from pytem1d import run_tem1d
# Square loop 100m x 100m
vertices = np.array([
[-50, -50],
[50, -50],
[50, 50],
[-50, 50]
])
result = run_tem1d(
resistivities=[100, 10],
depths=[0, 50],
polygon_vertices=vertices,
rx_position=(0, 0) # Receiver at center
)
Visualization
from pytem1d import run_tem1d, plot_response, plot_derivatives
# Run with derivatives
result = run_tem1d(
resistivities=[100, 10, 50],
depths=[0, 30, 100],
calculate_derivatives=True
)
# Plot response
plot_response(result)
# Plot Jacobian (sensitivities)
plot_derivatives(result, param_labels=['σ₁', 'σ₂', 'σ₃', 'h₁', 'h₂'])
API Reference
Main Functions
run_tem1d()- Functional interface for forward modelingTEM1DModel- Class-based interface with state management
Data Classes
EarthModel- Layered earth parametersIPModel- Induced polarization (Cole-Cole)Instrument- TX/RX configurationPolygonLoop- Arbitrary loop geometryTEM1DResult- Computation results
Utilities
plot_response()- Plot TEM responseplot_derivatives()- Plot Jacobian matrixplot_comparison()- Compare multiple responsessave_result()- Save results to fileload_result()- Load results from file
Examples
See the examples/ directory for more usage examples:
basic_usage.py- Simple functional APIclass_api.py- Advanced class-based APIplotting_demo.py- Visualization examplesbatch_random_models.py- Batch processing 1000 random models (compares both APIs)numerical_derivatives.py- Workaround for computing derivatives using finite differencesparallel_utils.py⚡ NEW - Parallel execution utilities for large-scale processingbatch_random_models_parallel.py⚡ NEW - Parallel benchmarking (7,000+ models/s on 128-core system)
Building from Source
The Python package requires a compiled Fortran shared library:
cd python
make # Build shared library
make clean # Clean build artifacts
The Makefile automatically detects your platform and builds the appropriate shared library (.so on Linux, .dll on Windows, .dylib on macOS).
Testing
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/
# With coverage
pytest --cov=pytem1d tests/
Troubleshooting
Library not found
If you get "Cannot load libtem1d.so" errors:
- Ensure you ran
makein thepython/directory - Check that
python/src/pytem1d/lib/libtem1d.soexists - Try reinstalling:
pip install -e .
Fortran compiler issues
If make fails:
- Linux: Install gfortran:
sudo apt-get install gfortran - macOS: Install via Homebrew:
brew install gcc - Windows: Install MinGW-w64
Results don't match TEMTEST
Small numerical differences are expected due to floating-point precision. Differences > 1% may indicate an issue.
License
See LICENSE file in the root directory.
Citation
If you use this code in publications, please cite:
- See
TEM1D_UserManual_20251219.pdffor proper citation
Contributing
Contributions are welcome! Please see the main repository for guidelines.
Links
Known Issues
Derivative Calculation
The Python interface supports derivative (Jacobian) calculation via the calculate_derivatives=True parameter. However, in the current version of the TEM1D Fortran code, derivatives may return all zeros. This is not a Python wrapper issue - the same behavior occurs with the original TEMTEST program when IDERIV=1.
To verify if derivatives are supported in your version:
cd examples/
# Check if example2 (with derivatives) produces non-zero values
./run_example.sh example2_3layer_with_derivatives.txt
grep -v "0.0000E+00" output_example2_3layer_with_derivatives/FORWRITE | wc -l
If you need derivatives for inversion, you may need to:
- Check the TEM1D user manual for derivative support status
- Implement numerical derivatives using finite differences
- Contact the TEM1D developers for the derivative-enabled version
The Python interface is ready and will work correctly once the Fortran code produces non-zero derivatives.
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 pytem1d-0.1.2.tar.gz.
File metadata
- Download URL: pytem1d-0.1.2.tar.gz
- Upload date:
- Size: 515.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae458742df157610ee13956fbc324ca7a5ba170d2e62d6eaa040e6fedcbab90e
|
|
| MD5 |
d5a044e23c8092efb0bfc92397922523
|
|
| BLAKE2b-256 |
ddb0f0bd3403484e01cfd67a33be72620aff0160c1ad47ff60972e1347521613
|
File details
Details for the file pytem1d-0.1.2-py3-none-any.whl.
File metadata
- Download URL: pytem1d-0.1.2-py3-none-any.whl
- Upload date:
- Size: 476.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4fccfeed6aaa0c27d8b06af99136b9d872ed0d02e542d3c16ace1e9be38cb20c
|
|
| MD5 |
6bd0b3a25e096ba7010d330b7dc48859
|
|
| BLAKE2b-256 |
09c99a04997422499631021f7d8e33a269923fe018ec021d9a0e8adfdf336994
|