Skip to content

xarthurx/XelToFab

XelToFab

PyPI Python 3.13+ License: MIT

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.

Installation

# 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

Quick Start

# 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

2D → 3D extrusion

# 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.8

From 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")

Pipeline

Scalar Field → Preprocess → Extract → Smooth → Mesh/Contours
     (.npy)      threshold     marching    Taubin     (.stl/.obj)
                 + morphology  cubes/sq.   filter
  1. Preprocess — Gaussian smoothing, Heaviside thresholding, morphological cleanup, small component removal
  2. Extract — Marching cubes (3D) or marching squares (2D) via scikit-image
  3. Smooth — Taubin smoothing via trimesh (3D meshes only)

Python API

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")

Converting SDF to density

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).

Using Example Data

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)

Supported Input Formats

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

Development

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 demo

Project Structure

src/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.

Documentation

Full documentation is available at xeltofab.ethz.ch.

Requirements

  • Python 3.13+
  • uv for development

About

Post-process design fields into fabrication-ready meshes and contours.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors