A desktop and web application for loading and visualising semiconductor wafer map data. Built with Tauri v2 (Rust backend), a WASM parser for the browser, and wafermap (canvas rendering).
Questions, ideas, or want to show off a wafer map you built? Use GitHub Discussions.
- Open STDF, ATDF, CSV, JSON, and Parquet wafer map files, including
.gzand.zipcontainers - Filter files — point tsmap at a directory of hundreds of files and it scans only their header metadata (lot ID, part type, tester, wafer count, dates) into a sortable, filterable table, so you load just the handful you actually want. Mixed formats scan together, and a filter can be saved and reloaded
- Multi-wafer — all formats support multiple wafers; renders as a gallery automatically
- Stats & findings — yield, bin breakdown, ring/quadrant analysis, and spatial findings
- Coordinate-less dies — X/Y position is optional; a wafer with no reported position shows a CSV-exportable die list instead of a fabricated map, and a partly-positioned wafer shows both
- Charts & Insights — yield by wafer, bin pareto, per-test box plots and histograms, and a cross-test correlation matrix
- Wafer splits — attach a process corner or experiment group to each wafer, load and save the assignment as CSV, and group every chart by it
- Test selector — for files with many tests, a two-pass flow lets you choose which tests to import before the full parse; the Lot ▾ menu's "Filter tests…" re-opens the selector after load
- Open from a URL —
tsmap --url <url> --url-format <format>on desktop,?dataUrl=&dataFormat=on the browser build, or atsmap://open?url=…deep link from your own web page.--url-headers <file>covers data APIs that authenticate via a header. See Integrations and the live demo - File associations — Help → File associations… (desktop) registers tsmap as the default handler for
.stdf/.atdf/.parquet, so double-clicking one in a file manager opens it here - PNG export — save any wafer map from the toolbar
- Cross-platform — Linux (Wayland/X11), macOS, Windows 11; also runs in the browser via WASM
| Format | Parsing | Notes |
|---|---|---|
| STDF | Rust | Binary V4; MIR (lot meta), SDR (site map), WIR/WRR (wafer), PIR/PRR (die — hbin, sbin, x, y), PTR/FTR (parametric/functional test values) |
| ATDF | Rust | ASCII V4; MIR (lot meta), WIR/WRR (wafer), PIR/PRR (die — hbin, sbin, x, y), PTR/FTR (parametric/functional test values) |
| CSV | Rust | Column mapping step before render; supports wide and long (pivot) formats |
| JSON | Rust | Flat array or nested [{ wafer fields, results: [{die}] }]; same mapping step as CSV |
| Parquet | Rust | Typed, columnar; same mapping step as CSV/JSON with a type-mismatch hint. snappy/gzip/lz4/brotli on desktop and web; zstd desktop-only |
tsmap is free and open source, but its installers are not code-signed — signing certificates cost money and grant no extra safety, only a vendor's stamp. As a result, your OS may warn that the app is from an "unknown publisher" or is "possibly dangerous." This is expected. The steps below let you install anyway. If you'd rather avoid installing at all, the web version runs entirely in your browser with no download.
Running tsmap-<version>-windows-x64.msi (or the -setup.exe installer) triggers a blue "Windows protected your PC" SmartScreen dialog:
- Click More info.
- Click Run anyway.
The warning appears because the installer has no signature and no download reputation yet; it will fade as more people install the app.
macOS Gatekeeper blocks unsigned apps by default with "tsmap can't be opened because it is from an unidentified developer." To open it:
- In Finder, locate tsmap in Applications.
- Right-click (or Control-click) the app and choose Open.
- Click Open in the dialog that appears.
You only need to do this once — macOS remembers the choice.
If macOS instead says the app is "damaged and can't be opened" (common on Apple Silicon for downloaded unsigned apps), clear the quarantine flag in Terminal:
xattr -dr com.apple.quarantine /Applications/tsmap.app.AppImage, .deb, and .rpm builds run normally; any warning is just a browser download nag. For .AppImage, mark it executable first:
chmod +x tsmap-*-linux-x86_64.AppImage
./tsmap-*-linux-x86_64.AppImageTo verify a download is intact, compare its checksum against the one published on the releases page.
npm install
npm run tauri dev # full Tauri app (Rust + frontend)
npm run dev:web # web version at http://localhost:5301 (uses WASM parser)
cargo check # type-check Rust (run from src-tauri/)
npx tsc --noEmit # type-check TypeScript
cargo test # run parser tests (run from packages/parsers/)python3 scripts/generate_stdf.py /tmp/test.stdf # synthetic STDF — 3 wafers, 4 tests
python3 scripts/generate_stdf_large.py /tmp/large.stdf # large STDF — 25 wafers, 50 tests, ~10k dies/wafer (341 MB)
python3 scripts/generate_atdf.py /tmp/test.atdf # synthetic ATDF — same structureThe parsers compile to a shared crate (packages/parsers) that targets both native Tauri and WASM. The published npm package is @wafertools/testdata-parser.
Prerequisites: wasm-pack (cargo install wasm-pack) and the wasm32-unknown-unknown target (rustup target add wasm32-unknown-unknown).
cd packages/parsers
# Build
wasm-pack build --target web -s wafertools --no-default-features --features wasm
# Publish
cd pkg
npm publish --access publicAfter publishing a new version, update tsmap to use it:
# from repo root
npm install @wafertools/testdata-parser@latest
npx tsc --noEmit # verify types still resolvesrc/
main.ts — app entry: file open, two-pass test selector, renderWafers, chart view
platform.ts — platform adapter: Tauri IPC (desktop) or WASM-in-a-Worker (browser)
parserWorker.ts — web-only module worker running the WASM parsers off the UI thread
lib.ts — pure, DOM-free helpers extracted from main.ts for testability
types.ts — shared types: ParsedFile, WaferData, TestDef, LotMeta
mappingUI.ts — CSV/JSON/Parquet column mapping overlay
multiFileUI.ts — multi-file rename and append confirmation
testSelectorUI.ts — test selector overlay for large STDF/ATDF files
fileFilterUI.ts — "Filter files…": header-only metadata scan of a large batch
filterTable.ts — generic sortable/filterable table behind the file filter
fileAssociationsUI.ts — "File associations…" dialog (Tauri only)
splits.ts / splitsUI.ts — wafer splits: a user-assigned grouping axis over metadata
metadata.ts — faceting metadata: distinct wafer-provenance values to group by
recentFiles.ts — recently opened file sets on the empty state (desktop only)
anchoredMenu.ts — shared popup menu shell for the Recent / Help / Lot toolbar menus
menuSelect.ts — themed replacement for a grouped native <select> (WebKitGTK)
modal.ts — shared app modal: backdrop, header chrome, Esc/F, focus management
tooltip.ts — shared themed hover tooltip for tsmap's own chrome
theme.ts — theme selection, persistence, and re-render notification
icons.ts — shared Lucide icon set, aligned with wmap's own iconography
charts/ — yield heatmap, bin pareto, box plot, histogram charts
packages/parsers/ — shared Rust crate (native + WASM targets), published as
@wafertools/testdata-parser
src/types.rs — DieResult, WaferData, ParsedStdf, LotMeta, TestDef
src/parse_stdf.rs — STDF V4 binary parser; first-pass scan, filtered parse, file meta
src/parse_atdf.rs — ATDF ASCII parser; first-pass scan, filtered parse, file meta
src/parse_csv.rs — CSV/TSV parser with column mapping
src/parse_json.rs — JSON array parser with column mapping
src/parse_parquet.rs — Parquet parser with column mapping; row-oriented, no arrow dep
src/test_identity.rs — stable test numbering derived from test name / source column
src/read_file.rs — read_bytes / read_text, plus maybe_gunzip transparent .gz handling
src-tauri/src/
lib.rs — app setup: single-instance, tsmap:// scheme registration, and
--url resolution before the window opens
cli_files.rs — CLI parsing: positional paths, --list/--tests/--splits,
--url/--url-format/--url-headers, and the tsmap:// link form
commands/ — thin Tauri async wrappers over packages/parsers
parse_{stdf,atdf,csv,json,parquet}.rs — per-format parse + header commands
parse_{stdf,atdf}_filtered.rs — filtered parse for a chosen test subset
{stdf,atdf}_test_names.rs — first-pass test name scan
{stdf,atdf}_file_meta.rs — header-only metadata scan for Filter files
fetch_url.rs — fetch --url / tsmap:// data to a temp file before the window opens
file_associations.rs — register/unregister default handler (Windows registry, xdg-mime)
extract_archive.rs — extract_archive(path), cleanup_extract()
read_file.rs — re-exports the shared crate's read_bytes / read_text
read_text_file.rs — plain text file read for the frontend
last_dir.rs — remembers the last directory used in a file dialog
get_startup_files.rs — files passed on the command line at launch
respawn_new_instance.rs — relaunch for the single-instance handler
write_temp_html.rs — opens wmap HTML reports
scripts/
generate_*.py — synthetic STDF/ATDF/CSV/JSON/Parquet fixtures and benchmarks
capture-screenshots.mjs — drives the web build to regenerate the docs screenshots
run-scenario.mjs — deterministic, assertion-checked replay of a scripted investigation
check-*.js/.mjs — release guards: version sync, wmap/parser published, config drift
Seven npm runtime dependencies, and no bundled UI framework or third-party charting library.
Frontend (npm)
@wafertools/wafermap— wafer map rendering and analysis@wafertools/testdata-parser— the WASM build ofpackages/parsers, used by the browser build@tauri-apps/api— Tauri IPC@tauri-apps/plugin-dialog·plugin-fs·plugin-opener— JS bindings for the plugins belowfflate— zip extraction in the browser build
Rust — shared parser crate (packages/parsers, published to npm as @wafertools/testdata-parser; builds for both native and wasm32)
parquet— Parquet reader, used through its row-orientedrecordAPI (noarrowdependency, which keeps the wasm bundle small).zstdis enabled on native only, since its C library needs a cross-compiler toolchain the wasm build can't assumecsv— CSV/TSV readerflate2— transparent.gzdecompression (pure-Rust backend, so it builds for wasm)serde·serde_json·indexmap— data model and JSON parsingwasm-bindgen·serde-wasm-bindgen— the browser build's bridge
The STDF and ATDF parsers are written in this crate, not taken from a library — rust-stdf was the original STDF dependency but its ATDF support proved unusable, so both formats are now parsed here.
Rust — desktop shell (src-tauri)
tauriv2 — application shelltauri-plugin-dialog— native file open/save dialogs (all platforms). On Linux itsrfdbackend uses the XDG desktop portal, falling back tozenityif presenttauri-plugin-fs·tauri-plugin-opener— filesystem access and opening files/URLs in the OS default handlertauri-plugin-single-instance— forwards a second launch (file double-click, deep link) into the running windowtauri-plugin-deep-link— thetsmap://open?url=…URL schemereqwest— fetches--urldata (rustls, no OpenSSL system dependency). Deliberately used instead oftauri-plugin-http, whose scope system needs a pre-configured allow-list and can't express "fetch whatever URL the caller supplies"zip—.ziparchive extractionwinreg(Windows only) — file-association registration underHKEY_CURRENT_USER\Software\Classes
MIT — © 2026 Paul Robins. The shared parser crate published as
@wafertools/testdata-parser
is covered by the same licence.