Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@

<div class="wrap">
<section class="hero">
<p class="eyebrow">Version 5.0.1 — available now</p>
<p class="eyebrow">Version 5.1.1 — available now</p>

<div class="hero-head">
<img class="hero-logo" src="/assets/icon-512.png" alt="" width="512" height="512">
Expand All @@ -148,11 +148,11 @@ <h1 class="wordmark">mac<em>4D</em>STEM</h1>
<a class="get-btn" href="https://github.com/mac4DSTEM/mac4DSTEM/releases/latest/download/mac4DSTEM.dmg">
<span aria-hidden="true">↓</span> Download for macOS
</a>
<p class="get-meta">Version 5.0.1 · 11.6 MB · signed and notarized</p>
<p class="get-meta">Version 5.1.1 · 17.7 MB · signed and notarized</p>
</div>

<ul class="specs">
<li>macOS 27+</li>
<li>macOS 26+</li>
<li>Apple silicon</li>
<li>Metal &amp; Neural Engine</li>
<li>GPL-3.0</li>
Expand Down Expand Up @@ -357,12 +357,12 @@ <h2 class="section-label" id="availability-h">Availability</h2>

<ol class="steps">
<li data-state="done">
<h3>Version 5.0.1 complete</h3>
<h3>Version 5.1 complete</h3>
<p>The analysis workflow is finished and covered by automated tests, including parity harnesses measured against py4DSTEM on experimental data.</p>
</li>
<li data-state="done">
<h3>Download</h3>
<p>Version 5.0.1 is <a href="https://github.com/mac4DSTEM/mac4DSTEM/releases/latest/download/mac4DSTEM.dmg">available as a signed, notarized disk image</a>. Open it and drag mac4DSTEM to your Applications folder — it launches without a security warning, and needs nothing else installed.</p>
<p>Version 5.1.1 is <a href="https://github.com/mac4DSTEM/mac4DSTEM/releases/latest/download/mac4DSTEM.dmg">available as a signed, notarized disk image</a>. Open it and drag mac4DSTEM to your Applications folder — it launches without a security warning, and needs nothing else installed.</p>
</li>
<li data-state="done">
<h3>Source release</h3>
Expand All @@ -375,7 +375,7 @@ <h3>Distribution</h3>
</ol>

<p class="band-note">
Requires macOS 27 or later on Apple silicon (for macOS 14–26, <a href="https://github.com/mac4DSTEM/mac4DSTEM/releases/tag/v3.0.0">version 3.0.0</a> remains available). No external runtime, toolchain, or library
Requires macOS 26 or later on Apple silicon (for macOS 14–25, <a href="https://github.com/mac4DSTEM/mac4DSTEM/releases/tag/v3.0.0">version 3.0.0</a> remains available). No external runtime, toolchain, or library
installation is needed — all dependencies are contained within the application. The Merlin
MIB and EMPAD RAW readers are preview-grade pending further vendor data.
</p>
Expand Down Expand Up @@ -417,10 +417,10 @@ <h2 id="contact-h">Enquiries, issue reports, and collaboration</h2>
"name": "mac4DSTEM",
"url": "https://mac4dstem.com/",
"applicationCategory": "ScientificApplication",
"operatingSystem": "macOS 27 or later, Apple silicon",
"softwareVersion": "5.0.1",
"operatingSystem": "macOS 26 or later, Apple silicon",
"softwareVersion": "5.1.1",
"downloadUrl": "https://github.com/mac4DSTEM/mac4DSTEM/releases/latest/download/mac4DSTEM.dmg",
"fileSize": "11.6 MB",
"fileSize": "17.7 MB",
"license": "https://www.gnu.org/licenses/gpl-3.0.html",
"description": "A free, native macOS application for interactive 4D-STEM analysis: virtual imaging, Bragg disk detection, strain and orientation mapping, and phase reconstruction, computed natively on Apple silicon.",
"screenshot": "https://mac4dstem.com/assets/workspace.png",
Expand Down
12 changes: 6 additions & 6 deletions mactem/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

<div class="wrap">
<section class="hero">
<p class="eyebrow">Version 1.0.0 · part of the macEM suite, beside <a class="u-link" href="/">mac4DSTEM</a></p>
<p class="eyebrow">Version 1.1.1 · part of the macEM suite, beside <a class="u-link" href="/">mac4DSTEM</a></p>

<div class="hero-head">
<h1 class="wordmark">mac<em>TEM</em></h1>
Expand All @@ -65,7 +65,7 @@ <h1 class="wordmark">mac<em>TEM</em></h1>
<a class="get-btn" href="https://github.com/mac4DSTEM/macTEM/releases/latest/download/macTEM.dmg">
<span aria-hidden="true">↓</span> Download for macOS
</a>
<p class="get-meta">Version 1.0.0 · 19.7 MB · signed and notarized · macOS 27+ on Apple silicon</p>
<p class="get-meta">Version 1.1.1 · 17.9 MB · signed and notarized · macOS 26+ on Apple silicon</p>
</div>

<ul class="specs">
Expand Down Expand Up @@ -155,7 +155,7 @@ <h2 class="section-label" id="validation-h">Provenance and validation</h2>
</div>

<dl class="facts">
<div><dt>Requires</dt><dd>macOS 27, Apple silicon</dd></div>
<div><dt>Requires</dt><dd>macOS 26, Apple silicon</dd></div>
<div><dt>Built on</dt><dd>FormatoKit, ImagoKit, DiffractoKit, SpectroKit</dd></div>
<div><dt>Runtime</dt><dd>Self-contained</dd></div>
<div><dt>Licence</dt><dd>GPL-3.0</dd></div>
Expand Down Expand Up @@ -195,10 +195,10 @@ <h2 id="contact-h">Questions, issues, collaboration</h2>
"name": "macTEM",
"url": "https://mac4dstem.com/mactem/",
"applicationCategory": "ScientificApplication",
"operatingSystem": "macOS 27 or later, Apple silicon",
"softwareVersion": "1.0.0",
"operatingSystem": "macOS 26 or later, Apple silicon",
"softwareVersion": "1.1.1",
"downloadUrl": "https://github.com/mac4DSTEM/macTEM/releases/latest/download/macTEM.dmg",
"fileSize": "19.7 MB",
"fileSize": "17.9 MB",
"license": "https://www.gnu.org/licenses/gpl-3.0.html",
"description": "A native macOS application for TEM: calibrated images and FFTs, EDS and EELS spectrum images with quantification, and electron diffraction, computed natively on Apple silicon.",
"offers": {
Expand Down
10 changes: 5 additions & 5 deletions suite/benchmarks.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ <h4>FFT work of 2026-10-22 (real-input transform, mixed radix): before and after
<h4>Backend decision per function</h4>
<p>Today every function above is CPU (Accelerate, Float64 reference plus Float32 where it exists). <strong>No function has a Metal path, so no Metal break-even has been measured</strong>; the column says what the CPU table implies and what a large-size run must measure. A guess is not recorded as a measurement.</p>
<div class="tablewrap"><table><thead><tr><th>function</th><th>backend today</th><th>decision</th></tr></thead><tbody><tr><td><code>fft2</code> Float32/Float64</td><td>CPU</td><td>CPU only at 128² to 512² (0.02 to 2 ms: a Metal dispatch cannot win). Float64 lengths of prime factors 2, 3, 5, 7 run on the mixed-radix plan. Work item: a Metal Float32 FFT prototype, break-even not measured yet (2048², 4096², 8192²)</td></tr><tr><td><code>rfft2</code>, <code>irfft2</code>, <code>butterworth</code>, masked registration</td><td>CPU</td><td>CPU; real-input transform since 2026-10-22 (0.7 ms Float64 at 512², 1.1 times NumPy); a Metal path would have to beat 0.4 to 0.7 ms at 512², which a dispatch cannot, so the break-even is again a question for 2048² and up, not measured yet</td></tr><tr><td><code>gaussian_filter</code>, <code>uniform_filter</code>, <code>difference_of_gaussians</code></td><td>CPU</td><td>CPU only at 128² to 512² (1 to 4 ms, memory bound). Metal candidate above 2048² for large sigma; not measured yet</td></tr><tr><td><code>shift</code> order 1</td><td>CPU</td><td>CPU only: 0.65 ms at 512²</td></tr><tr><td><code>shift</code> order 3 (prefilter plus taps)</td><td>CPU</td><td>CPU; the prefilter is sequential along lines, the tap sum is the Metal-friendly part: candidate above 2048², not measured</td></tr><tr><td><code>phase_cross_correlation</code></td><td>CPU</td><td>CPU; FFT-bound, follows <code>fft2</code></td></tr><tr><td><code>profile_line</code></td><td>CPU</td><td>CPU: small arrays stay on the CPU</td></tr><tr><td><code>label</code></td><td>CPU</td><td>CPU: union-find is not a Metal workload</td></tr><tr><td><code>peak_local_max</code></td><td>CPU</td><td>CPU; the window maximum is a Metal candidate only above 4096²</td></tr></tbody></table></div>
<h2 id="diffractokit">DiffractoKit 0.11.0</h2>
<p><a class="u-link" href="https://github.com/mac4DSTEM/DiffractoKit/blob/0.11.0/docs/benchmarks.md">Full file and method</a></p>
<h2 id="diffractokit">DiffractoKit 0.12.0</h2>
<p><a class="u-link" href="https://github.com/mac4DSTEM/DiffractoKit/blob/0.12.0/docs/benchmarks.md">Full file and method</a></p>
<p>Measured 2026-10-21. Small and typical sizes only; the <strong>large</strong> rows are not measured yet (they run with <code>DIFFRACTO_BENCH_LARGE=1</code>). Best of five after one warm-up: the median is the figure, the spread (min-max) is in brackets. Same inputs on both sides (<code>tools/benchmarks/gen_inputs.py</code> writes them), Float64 unless the function is Float32 by design (ACOM, ellipse pattern pixels).</p>
<div class="tablewrap"><table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Machine</td><td>Apple M5 Pro, 64 GB, macOS 27.0.1 (Darwin 27.0.0)</td></tr><tr><td>Toolchain</td><td>Apple Swift 6.4, <code>swift build -c release</code> (separate package <code>tools/benchmarks</code>)</td></tr><tr><td>Python</td><td>3.12.14, NumPy 2.5.4, SciPy 1.18.1, in two virtual environments: py4DSTEM 0.14.19 in one; pymatgen-core 2026.10.16 (the code; its <code>pymatgen</code> metapackage dist-info reads 2026.9.24), orix 0.15.0 and spglib 2.8.0 in the other</td></tr><tr><td>Load</td><td><strong>10.5 on a 12-core machine while other builds ran</strong> (uptime 17:39): every figure carries that noise, the single-core rows least. Re-run when the machine is quiet before quoting a ratio.</td></tr><tr><td>Pin note</td><td>The orix environment runs pymatgen-core <strong>2026.10.16</strong> under a <code>pymatgen</code> 2026.9.24 metapackage; the fixtures record <code>pymatgen</code> 2026.9.24 and, except <code>cif-symmetry-pins.json</code> (generated 2026-10-21 on this install, byte-identical on regeneration), <code>pymatgen-core</code> 2026.9.23. Nothing here compares numbers, only time</td></tr><tr><td>0.9.1</td><td>The <code>symmetry_detection</code> and <code>cif_import</code> rows above are the 2026-10-21 measurement of 0.9.0. 0.9.1 replaced the closure check that took 95 % of them (see <code>docs/open-items.md</code>); measured in-process on the same <code>al_super2.cif</code> (machine load 3.6): <code>cif_import</code> typical median 67 ms (min 67, max 77), against 297 ms (one run at load 9) before the change and the table&#x27;s 351 ms. Not yet re-run through <code>run.sh</code></td></tr></tbody></table></div>
<div class="tablewrap"><table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Machine</td><td>Apple M5 Pro, 64 GB, macOS 27.0.1 (Darwin 27.0.0)</td></tr><tr><td>Toolchain</td><td>Apple Swift 6.4, <code>swift build -c release</code> (separate package <code>tools/benchmarks</code>)</td></tr><tr><td>Python</td><td>3.12.14, NumPy 2.5.4, SciPy 1.18.1, in two virtual environments: py4DSTEM 0.14.19 in one; pymatgen-core 2026.10.16 (the code; its <code>pymatgen</code> metapackage dist-info reads 2026.9.24), orix 0.15.0 and spglib 2.8.0 in the other</td></tr><tr><td>Load</td><td><strong>10.5 on a 12-core machine while other builds ran</strong> (uptime 17:39): every figure carries that noise, the single-core rows least. Re-run when the machine is quiet before quoting a ratio.</td></tr><tr><td>Pin note</td><td>The pymatgen environment runs pymatgen-core <strong>2026.10.16</strong> under a <code>pymatgen</code> 2026.9.24 metapackage, and every fixture that records pymatgen-core records 2026.10.16 (<code>tools/pins/requirements/pymatgen.txt</code>). Nothing here compares numbers, only time</td></tr><tr><td>0.9.1</td><td>The <code>symmetry_detection</code> and <code>cif_import</code> rows above are the 2026-10-21 measurement of 0.9.0. 0.9.1 replaced the closure check that took 95 % of them (see <code>docs/parity.md</code>, known limits); measured in-process on the same <code>al_super2.cif</code> (machine load 3.6): <code>cif_import</code> typical median 67 ms (min 67, max 77), against 297 ms (one run at load 9) before the change and the table&#x27;s 351 ms. Not yet re-run through <code>run.sh</code></td></tr></tbody></table></div>
<p>Re-run from a fresh clone of the kit, on a quiet Mac: <code>gen_inputs.py</code> writes the shared inputs, <code>run.sh</code> builds the benchmark package (<code>tools/benchmarks</code>, release) and prints the kit&#x27;s JSON lines, <code>bench_python.py</code> prints the Python lines, and <code>merge.py</code> turns them into the table below. Add <code>DIFFRACTO_BENCH_LARGE=1</code> to <code>run.sh</code> and <code>bench_python.py</code> for the large rows.</p>
<p>The raw lines of the run below are <code>tools/benchmarks/results/2026-10-21.jsonl</code>.</p>
<h4>Per-function table (ms per call; <code>acom_match_scan</code> is ms per pattern)</h4>
Expand All @@ -84,7 +84,7 @@ <h4>What the rows compare, and what they do not</h4>
<p><code>kinematic_reflections</code>: the kit&#x27;s <code>kinematicReflections(kMax:retainingAll:false)</code> against py4DSTEM&#x27;s</p>
<p><code>Crystal.calculate_structure_factors</code> on the same C2/m cell; the kit is 1.8 to 4.5 times faster. Both use the Lobato-Van Dyck table.</p>
<p><code>symmetry_detection</code> and <code>cif_import</code>: the kit&#x27;s <code>CIFImport.read</code> always detects the symmetry of the cell it reads;</p>
<p>pymatgen&#x27;s <code>CifParser</code> only parses and <code>SpacegroupAnalyzer</code> is spglib in C. On a 32-atom P1 cell (an fcc supercell with 1 536 operations) the kit took 361 ms against 13 ms, <strong>28 times slower</strong>; on a four-atom cell they are level. The cause was the closure check, not the symmetry search (<code>docs/open-items.md</code>); 0.9.1 made the check about five times faster, the rest stays listed there.</p>
<p>pymatgen&#x27;s <code>CifParser</code> only parses and <code>SpacegroupAnalyzer</code> is spglib in C. On a 32-atom P1 cell (an fcc supercell with 1 536 operations) the kit took 361 ms against 13 ms, <strong>28 times slower</strong>; on a four-atom cell they are level. The cause was the closure check, not the symmetry search (<code>docs/parity.md</code>, known limits); 0.9.1 made the check about five times faster, the rest stays listed there.</p>
<p><code>orientation_reduce</code>: the kit reduces one matrix at a time (24 proper operators); orix reduces a vectorised batch</p>
<p>(<code>Orientation.from_matrix</code> + <code>map_into_symmetry_reduced_zone</code>). The kit is 2.5 to 12 times faster at these sizes.</p>
<p><code>ellipse_fit_1d</code>: level with py4DSTEM&#x27;s <code>fit_ellipse_1D</code> (0.94 and 1.1).</p>
Expand All @@ -93,7 +93,7 @@ <h4>What the rows compare, and what they do not</h4>
<p><code>acom_match_scan</code>: the kit&#x27;s <code>matchAll</code> over the whole scan against py4DSTEM&#x27;s <code>match_single_pattern</code> per pattern (one</p>
<p>core; Python&#x27;s per-pattern time includes its own refinements, so this is a time, not a like-for-like algorithm). Per pattern the kit on one core is 14 times (8 x 8 scan) and 9 times (32 x 32) faster than py4DSTEM on one core, and on all cores 105 and 81 times.</p>
<h4>Backend decision per function</h4>
<div class="tablewrap"><table><thead><tr><th>Function</th><th>Backend</th><th>Why / break-even</th></tr></thead><tbody><tr><td><code>niggli_reduce</code>, <code>reflections</code>, <code>kinematic_reflections</code>, <code>symmetry_detection</code>, <code>cif_import</code></td><td>CPU only</td><td>small arrays, branchy integer logic, readers; the kit is already faster than Python except where <code>docs/open-items.md</code> lists it</td></tr><tr><td><code>orientation_reduce</code></td><td>CPU only</td><td>24 small matrix products per rotation; the batch (100 000 in 0.2 s) is bound by memory traffic, a GPU would pay the transfer for no gain at these sizes</td></tr><tr><td><code>ellipse_fit_1d</code></td><td>CPU only</td><td>one 1D least-squares fit per pattern; level with Python</td></tr><tr><td><code>acom_library</code></td><td>CPU only</td><td>built once per phase (60 ms for 600 axes), not per pattern</td></tr><tr><td><code>acom_match_scan</code></td><td><strong>CPU all cores; Metal not above any measured N</strong></td><td>Metal 0.294 ms per pattern at 64 patterns, 0.236 at 1 024, against 0.245 and 0.216 on all CPU cores: the break-even is <strong>not reached up to 1 024 patterns</strong> (the Metal path is 7 to 22 % slower); the 128 x 128 row (16 384 patterns) is not measured yet, and the Metal path stays an option (<code>ACOMBackend.metal</code>), not the default. A larger library (2 400 axes) is the other axis still to measure</td></tr></tbody></table></div>
<div class="tablewrap"><table><thead><tr><th>Function</th><th>Backend</th><th>Why / break-even</th></tr></thead><tbody><tr><td><code>niggli_reduce</code>, <code>reflections</code>, <code>kinematic_reflections</code>, <code>symmetry_detection</code>, <code>cif_import</code></td><td>CPU only</td><td>small arrays, branchy integer logic, readers; the kit is already faster than Python except where <code>docs/parity.md</code> (known limits) lists it</td></tr><tr><td><code>orientation_reduce</code></td><td>CPU only</td><td>24 small matrix products per rotation; the batch (100 000 in 0.2 s) is bound by memory traffic, a GPU would pay the transfer for no gain at these sizes</td></tr><tr><td><code>ellipse_fit_1d</code></td><td>CPU only</td><td>one 1D least-squares fit per pattern; level with Python</td></tr><tr><td><code>acom_library</code></td><td>CPU only</td><td>built once per phase (60 ms for 600 axes), not per pattern</td></tr><tr><td><code>acom_match_scan</code></td><td><strong>CPU all cores; Metal not above any measured N</strong></td><td>Metal 0.294 ms per pattern at 64 patterns, 0.236 at 1 024, against 0.245 and 0.216 on all CPU cores: the break-even is <strong>not reached up to 1 024 patterns</strong> (the Metal path is 7 to 22 % slower); the 128 x 128 row (16 384 patterns) is not measured yet, and the Metal path stays an option (<code>ACOMBackend.metal</code>), not the default. A larger library (2 400 axes) is the other axis still to measure</td></tr></tbody></table></div>
<p>Numbers in <code>docs/parity.md</code> are untouched by this table (time only).</p>
<h2 id="spectrokit">SpectroKit 0.13.2</h2>
<p><a class="u-link" href="https://github.com/mac4DSTEM/SpectroKit/blob/0.13.2/docs/benchmarks.md">Full file and method</a></p>
Expand Down
Loading
Loading