OBAnalyser
OBAnalyser is a Python package for analysing open beam build data, with support for OBF and OBP workflows.
It can be used to:
- extract build-level information such as layer timing, recoating data, and energy-related summaries
- analyse OBP geometry and melt area information
- rasterize full builds into per-layer image stacks
- export JSON outputs that can be used in downstream processing pipelines
Installation
Install from PyPI:
pip install OBPAnalyser
For local development in a virtual environment:
python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
Minimum example
import obanalyser.analyse_build as analyse_build
import obanalyser.plotters.plot_build_data as plot_build_data
path = r"tests\input\cubes_test\buildInfo.json"
build = analyse_build.analyse_build(path)
build.to_json(r"tests\output\build_info.json")
plot_build_data.plot_build_data(build)
This reads the build structure, analyses the layer content, writes a JSON summary, and plots the build data.
Export layer images
The package writes one grayscale PNG per layer directly into the output folder,
named layer_0000.png, layer_0001.png, and so on:
- Black (0): melted regions
- Gray (190): sintered-only regions
- Light gray (225): unscanned powder inside the build cylinder, when a radius is set
- White (255): outside the cylinder (or empty space when no radius is set)
Melted regions stay black where scans overlap, regardless of scan order. No per-file images, subfolders, or metadata sidecars are generated. Each PNG embeds its pixel size, image dimensions in pixels and millimeters, physical bounds, zero-based layer index, Z step, cumulative Z height, and cylinder radius when supplied. Standard PNG physical resolution is also stored for image software that supports it.
from obanalyser.analyse_obf_geometry import write_obf_image_stack
build_path = r"tests\input\cubes_test\buildInfo.json"
output_dir = r"tests\output\layer_image_stack"
write_obf_image_stack(
build_path,
output_dir,
pixel_um=200,
close_gap_um=50,
sinter_close_gap_um="auto",
cylinder_radius_mm=50,
)
cylinder_radius_mm is optional and centers the cylinder at (0, 0) in build
coordinates. The square image covers its diameter, rounded up to whole pixels;
scans outside the circle are clipped. For example, a 50 mm radius with 200 µm
pixels produces a 500 × 500 image covering 100 × 100 mm. Omitting the radius
fits the image to the scanned regions as before.
Z context comes from layerFeed.buildPistonDistance in the build JSON, honoring
layer defaults and per-layer overrides (or build.layerfeed.build_piston_distance
in YAML). z_step_mm is the negative of the signed piston movement;
z_height_mm accumulates these steps, with Z=0 before the first layer feed.
For example, piston movements of -0.1 mm produce layer heights of 0.1, 0.2,
0.3 mm, etc. Zero steps and movements in the opposite direction retain their
sign. These are planned relative build heights from the input, rather than
measured absolute machine coordinates. Missing or invalid movement data stops
export with an error instead of assigning an assumed height.
Sintered regions use automatic gap closing by default. The estimate uses the typical spacing between parallel preheat tracks (including rotated and reversed tracks), or nearest-neighbor spacing with a diagonal allowance for point scans, and the beam focus size. It includes a pixel-rounding allowance and caps the inferred spacing at four focus diameters to limit bridging between separate regions. Patterns with too few neighbors for an estimate retain their original coverage. This is a geometric representation of the sintered footprint, without an energy or thermal model.
Set sinter_close_gap_um to a number for manual control, 0 to disable sinter
closing, or None to reuse close_gap_um. close_gap_um continues to control
melt closing independently. Automatic closing can fill intentional gaps similar
in size to the hatch spacing; use the manual override for those builds.
To read the embedded information with Pillow:
import json
from PIL import Image
with Image.open(r"tests\output\layer_image_stack\layer_0000.png") as image:
info = json.loads(image.info["obanalyser"])
print(info["pixel_size_um"], info["image_size_px"], info["image_size_mm"])
print(info["layer_index"], info["z_step_mm"], info["z_height_mm"])
Example scripts
The repository includes runnable examples in the docs folder:
docs/examples.pydocs/example_create_image_stack.py
Notes
- Spatial raster resolution for image stacks is controlled with
pixel_um. - Melt gap closing is controlled with
close_gap_um; sinter gap closing usessinter_close_gap_um(default"auto"). write_obf_image_stackreturns the image stack after saving the PNG files.analyse_obf_geomreturns a single-channeluint8stack with shape[layer, row, col]; part colors and scan order do not affect pixel values.
Metadata
Release files for OBPAnalyser 0.0.14
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| obpanalyser-0.0.14.tar.gz | 27.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| obpanalyser-0.0.14-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.8 kB
Release files / obpanalyser-0.0.14.tar.gz
| Download URL | obpanalyser-0.0.14.tar.gz |
|---|---|
| Size | 27.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
606ad2ba8319d573f26523cac92f2f472cc6190421c60e8f61d3a9195f53b2a3
|
|
BLAKE2b-256 checksum How to use checksums |
20c8cca7260f7cceb6bbc8150b28105fe48f4047b44e3d398fc60a9c44a20d63
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.5
|
Release files / obpanalyser-0.0.14-py3-none-any.whl
| Download URL | obpanalyser-0.0.14-py3-none-any.whl |
|---|---|
| Size | 27.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c2e4fd78847b978a036a68c768b8c2ca5883e1d6e84746848a8e9b937a48d31e
|
|
BLAKE2b-256 checksum How to use checksums |
ff6defc166174b9ca51d981af22017a40a40e93d6deb34f375111444aec78ed8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.5
|