A design field post-processing pipeline that transforms continuous scalar fields from optimization solvers and neural networks into clean, fabrication-ready triangle meshes (3D) and contour representations (2D). The pipeline handles thresholding, smoothing, mesh extraction, quality improvement, visualization, and multi-format export.
# From PyPI (stable)
pip install xeltofab
# With optional format support
pip install "xeltofab[vtk,hdf5]"
# From source (development)
git clone https://github.com/xarthurx/XelToFab.git
cd XelToFab
uv sync# Process a 3D density field into an STL mesh
xtf process density.npy -o output.stl
# Process with custom parameters and save a comparison plot
xtf process density.npy -o output.stl --threshold 0.4 --sigma 1.5 --viz
# Visualize a 2D density field
xtf viz density_2d.npy -o comparison.png# Turn a 2D density field into a print-ready STL
xtf extrude density_2d.npy -o part.stl --thickness 10
# Printability cleanup: drop small islands + pre-smooth
xtf extrude beam.npy -o beam.stl -t 15 --min-component-area 20 --smooth-sigma 0.8From Python:
import numpy as np
import xeltofab as xtf
field = np.load("density_2d.npy")
mesh = xtf.extrude_2d(field, thickness=10)
mesh.export("part.stl")Scalar Field → Preprocess → Extract → Smooth → Mesh/Contours
(.npy) threshold marching Taubin (.stl/.obj)
+ morphology cubes/sq. filter
- Preprocess — Gaussian smoothing, Heaviside thresholding, morphological cleanup, small component removal
- Extract — Marching cubes (3D) or marching squares (2D) via scikit-image
- Smooth — Taubin smoothing via trimesh (3D meshes only)
import numpy as np
from xeltofab.state import PipelineState, PipelineParams
from xeltofab.pipeline import process
from xeltofab.io import save_mesh
# Create a scalar field (e.g., a sphere)
z, y, x = np.mgrid[-1:1:50j, -1:1:50j, -1:1:50j]
field = (x**2 + y**2 + z**2 < 0.5**2).astype(float)
# Run the pipeline
params = PipelineParams(threshold=0.5, smooth_sigma=1.0)
state = PipelineState(field=field, params=params)
result = process(state)
# Export
save_mesh(result, "sphere.stl")If you have an SDF array and want to feed it into the density-mode pipeline
(for example to share a density field with a downstream library such as
EngiBench), use sdf_to_density:
import numpy as np
from xeltofab import sdf_to_density, process, PipelineParams, PipelineState
# sdf_grid: ndarray, negative inside the shape, positive outside
density = sdf_to_density(sdf_grid, method="linear", bandwidth=1.0)
# direct_extraction=True skips the density preprocessor (Gaussian smooth +
# threshold + morphology) so the iso=0.5 surface of the converted field is
# preserved exactly. Drop it to run the full density pipeline instead.
params = PipelineParams(
field_type="density",
direct_extraction=True,
extraction_level=0.5,
)
result = process(PipelineState(field=density, params=params))Three methods are available:
| Method | Use when you want |
|---|---|
"heaviside" |
Binary density (no sub-voxel information). |
"linear" (default) |
Compact-support linear ramp — matches MC-at-0.5 behavior. |
"sigmoid" |
Smooth, differentiable profile — for gradient-based optimizers. |
bandwidth controls the transition width in the same units as the SDF (voxel
units when the SDF came from scipy.ndimage.distance_transform_edt, world
units when it came from an analytic SDF on a world-space grid).
Pre-computed topology optimization results are included in data/examples/ (sourced from IDEALLab EngiBench):
from xeltofab.io import load_field
from xeltofab.pipeline import process
state = load_field("data/examples/beams_2d_50x100_sample0.npy")
result = process(state)| Format | Extensions | Install |
|---|---|---|
| NumPy | .npy, .npz | Built-in |
| MATLAB | .mat | Built-in (via scipy) |
| CSV/Text | .csv, .txt | Built-in |
| VTK | .vtk, .vtr, .vti | pip install "xeltofab[vtk]" |
| HDF5/XDMF | .h5, .hdf5, .xdmf | pip install "xeltofab[hdf5]" |
| All formats | — | pip install "xeltofab[all-formats]" |
List available formats: xtf formats
uv sync # Install deps
uv run pytest tests/ -v # Run tests
uv run ruff check src/ tests/ # Lint
uv run ruff format src/ tests/ # Format
uv run marimo edit notebooks/demo.py # Interactive demosrc/xeltofab/
├── state.py Pipeline state + parameter models
├── preprocess.py Field preprocessing
├── extract.py Mesh/contour extraction
├── smooth.py Taubin smoothing
├── pipeline.py Orchestrator
├── io.py File I/O (multi-format load, mesh export)
├── loaders/ Format-specific loaders (numpy, matlab, csv, vtk, hdf5)
├── field_plots.py Matplotlib visualization
└── cli.py CLI (xtf)
See docs/ARCHITECTURE.md for detailed architecture documentation.
Full documentation is available at xeltofab.ethz.ch.
- Python 3.13+
- uv for development