Getting Started#
This chapter provides everything you need to begin using LayTracer. It includes installation instructions including dependency management and general description of the package design.
Requirements#
LayTracer can be installed either with Conda or with standard Python pip.
For a reproducible full environment, we recommend using the miniforge Conda implementation.
Installation#
Dependencies#
LayTracer leverages numerous Python packages. Below are the key dependencies:
All dependencies are declared in pyproject.toml. The optional dev extra adds pytest and setuptools_scm, and the optional docs extra adds the packages used to build the documentation:
The authors are incredibly grateful to the developers of these packages.
Install using conda#
The best way to install is by creating a new conda environment. Its base, Python and pip, is defined in environment.yml:
conda env create -f environment.yml
Note: to speed up creation of the environment, use mamba instead of conda, which is a faster alternative.
Then activate the newly created environment:
conda activate laytracer
Finally, install the package in editable mode with the optional development dependencies defined in pyproject.toml:
python -m pip install -e ".[dev]"
For a minimal runtime-only installation, use python -m pip install -e . instead.
Install from PyPI (stable releases only)#
If you want the latest published stable release, install directly from PyPI:
python -m pip install --upgrade pip
pip install laytracer
Use this mode for stable releases. For development work or unreleased changes, install from the repository with pip install -e ..
Install using pip only#
If you prefer not to use Conda, you can install LayTracer into a standard virtual environment.
On Linux / macOS:
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -e .
On Windows (PowerShell):
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -e .
The pip-only approach is appropriate for package usage. In either workflow, add the optional extras for development (".[dev]"), documentation (".[docs]") or both (".[dev,docs]").
Install using script#
For quick installation, you can use the specially designed installation scripts which implement all of the above mentioned steps.
On Windows, in miniforge prompt run:
install.bat
On Linux / macOS, from the repository root run:
chmod +x install.sh
./install.sh
Limit NumPy’s BLAS threads#
When NumPy is imported, its OpenBLAS library may reserve a working buffer for every thread it can use. On Windows this memory is committed at once. With conda-forge’s OpenBLAS it is about 135 MB per thread, so on a machine with 22 logical CPUs a Python process commits about 3 GB before doing any work. LayTracer’s parallel workers already use one BLAS thread each, because ray tracing makes no BLAS calls (see laytracer.trace_rays). For your own Python process, limit the threads, for example to four:
conda env config vars set OPENBLAS_NUM_THREADS=4 -n laytracer
conda deactivate
conda activate laytracer
The setting applies whenever the environment is activated. Remove it with conda env config vars unset OPENBLAS_NUM_THREADS -n laytracer. Without Conda, set the environment variable OPENBLAS_NUM_THREADS before Python starts.
Build documentation using script#
Building the documentation needs the optional documentation dependencies defined in pyproject.toml:
python -m pip install -e ".[docs]"
To build and serve the documentation quickly, use the platform-specific scripts.
On Windows:
build-docs.bat
Build HTML + PDF on Windows:
build-docs.bat -pdf
On Linux / macOS:
chmod +x build-docs.sh
./build-docs.sh
Build HTML + PDF on Linux / macOS:
chmod +x build-docs.sh
./build-docs.sh -pdf
Build documentation using make#
If you prefer explicit Sphinx/Make commands, you can build the docs directly from the docs folder.
On Linux / macOS:
cd docs
make html
Build HTML + PDF on Linux / macOS:
cd docs
make html
make latexpdf
On Windows:
cd docs
make.bat html
Build HTML + PDF on Windows:
cd docs
make.bat html
make.bat latexpdf
Uninstall#
If you need to add/change packages, deactivate the environment first:
conda deactivate
Then remove the appropriate environment:
conda remove -n laytracer --all
Package Design#
LayTracer is structured as a Python package with a layered, modular architecture designed for numerical reliability, API clarity, and maintainability.
High-level architecture#
The implementation is separated into focused modules with clear responsibilities:
laytracer.modelDefines model-level data containers (for example,
LayerStack).Converts tabular velocity/depth input into solver-ready layer stacks.
laytracer.solverImplements the core two-point ray tracing algorithm (dimensionless-parameter Newton solver).
Computes per-ray kinematics such as travel time and ray geometry.
laytracer.amplitudeImplements amplitude-related physics (transmission/reflection coefficients, Brewster-angle analysis).
Provides reusable low-level functions independent of plotting/UI concerns.
laytracer.apiExposes high-level user workflows (for example, multi source-receiver tracing via
trace_rays).Handles batching, parallel execution, and result aggregation into user-facing containers.
laytracer.sensitivityComputes sparse fixed-topology derivatives of travel time and physical ray parameter.
Keeps model-layer indices explicit so the derivatives can be assembled into custom Jacobians.
laytracer.approximationSelects deterministic point-cloud anchors and traces their Cartesian product once.
Predicts nearby traveltimes from analytic endpoint derivatives while enforcing compatible ray topology.
laytracer.plotProvides visualization utilities (2-D profiles and 3-D interactive rendering).
Keeps visualization optional and decoupled from numerical core logic.
Public API surface#
The package root (laytracer.__init__) re-exports the primary classes/functions so typical user workflows stay concise while internal module boundaries remain explicit.
Approximate nearby traveltimes#
For a dense source-receiver table, exact rays can be retained at sparse anchors and nearby traveltimes predicted from their analytic endpoint derivatives. This is useful when many endpoints are close together and the velocity model and selected ray branch remain fixed.
import numpy as np
import pandas as pd
import laytracer
model = pd.DataFrame({
"Depth": [0.0, 700.0, 1400.0],
"Vp": [2600.0, 3400.0, 4300.0],
"Vs": [1450.0, 1950.0, 2500.0],
})
sources = np.column_stack([
np.arange(0.0, 2000.0, 50.0),
np.zeros(40),
np.full(40, 100.0),
])
receivers = np.array([
[2500.0, 0.0, 100.0],
[2750.0, 0.0, 100.0],
])
approximator = laytracer.TravelTimeApproximator.fit(
sources,
receivers,
model,
source_phase="P",
source_max_distance=150.0,
receiver_max_distance=None,
)
prediction = approximator.predict()
travel_times = prediction.travel_time_matrix
valid = prediction.valid_matrix
print(approximator.exact_ray_count, travel_times.shape)
Coordinates and anchor distances are in metres, and traveltimes are in
seconds. receiver_max_distance=None keeps every supplied receiver as an
exact anchor. Invalid local predictions are NaN; inspect
prediction.reason_matrix rather than assuming that every requested branch
can be extrapolated. See 06. Visualizing and using sensitivities
for visual error experiments and Methodology for the validity rules.
Design principles#
LayTracer follows several engineering principles:
Separation of concerns: numerical solvers, physical coefficients, API orchestration, and plotting are isolated.
Composability: low-level building blocks can be used independently in custom workflows.
Performance-aware implementation: vectorized NumPy operations and optional parallel execution for survey-scale runs.
Reproducibility: environment-driven dependency management and deterministic, test-backed numerical and anchor-selection behavior.
Extensibility: new physical attributes or workflow wrappers can be added without rewriting the solver core.
Typical execution flow#
Build a layered model from input data (
build_layer_stackor high-level API input).Solve one or many source-receiver ray paths (
solve/trace_rays).Optionally request sensitivities or attenuation/spreading/transmission attributes.
For dense nearby endpoints, fit a
TravelTimeApproximatorand predict a local traveltime table from exact anchor rays.Visualize outputs using
laytracer.plothelpers.