diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 62bd4d6..0fe8be4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -6,7 +6,7 @@ body: id: version attributes: label: DiffractoKit version - placeholder: "0.4.1" + placeholder: "0.10.0" validations: required: true - type: input diff --git a/CHANGELOG.md b/CHANGELOG.md index 92121df..106c22b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,12 @@ # Changelog All notable changes to DiffractoKit. Versions are semantic (0.x: a minor release may change the API). The numbers each module -reproduces, and against what, are in `docs/parity.md`. +reproduces, and against what, are in `docs/parity.md`. From 0.11.0 on, release-please writes each entry from the +conventional-commit titles of the merged pull requests. The entries up to 0.10.0 use Keep a Changelog's sections (Added, Changed, Fixed, Removed, Migration). -## 0.10.0 (2026-10-22) — misorientation, orientation-relationship variants, ring-sequence assignment and the apps' kit asks +## [0.10.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.9.1...0.10.0) (2026-10-22) -ROADMAP task 35 and the asks of both apps' open items. Additive except one case in an error enum (see Migration). +Misorientation, orientation-relationship variants, ring-sequence assignment, and what the consuming applications asked of the kit. Additive except one case in an error enum (see Migration). ### Added - **Misorientation and orientation** (`DiffractoOrientation`, orix 0.15.0): `Misorientation(matrix, source:, target:)` with `equivalent(grainExchange:)` and `reduce()` / @@ -18,12 +19,12 @@ ROADMAP task 35 and the asks of both apps' open items. Additive except one case (planted truth; no Python reference computes the set). - **`LinearScale.assign`** (and `estimateAssigned`, `LinearScaleAssignment`, `LinearScaleAssignmentError`): which of the crystal's first shells is the first observed ring, from the sequence of rings, with named refusals; Al [001] reads {200} and delta q is exact (the old assumption of {111} read 13.4 % low). Moved from mac4DSTEM's `ShellAssignment`. -- **`LinearScale.fit`** (`LinearScaleFit`): delta q from several indexed rings by least squares with a standard error (macTEM ask 2). +- **`LinearScale.fit`** (`LinearScaleFit`): delta q from several indexed rings by least squares with a standard error. - **Single-pattern measurements:** `PatternCentre.find` (the unscattered beam's centre), `PatternRadialProfile.about` (ellipse-corrected radial profile), `PatternSpot.refine` (subpixel - spot centre); macTEM asks 1, 3 and 9. Planted truth, `validation: "none"`. + spot centre). Asked for by macTEM. Planted truth, `validation: "none"`. - `ReflectionFamily` has a public initialiser. `OrientationSymmetryError.differentSymmetry`. -### Diagnosed +### Changed: diagnosed, no number changed - The {111} ring fit reading 0.1 % low (macTEM open item): the cause is the tail of the neighbouring {200} ring inside the annulus, which the one-ring profile model absorbs. A single ring is exact to 3e-8 px; the bias is -0.041 px for the annulus 29 to 37, -0.003 px for 29 to 36 and -3e-6 px for 29 to 35, and linear in the neighbour's amplitude (`RingFitNeighbourTailTests`). No number changed: end the annulus before the neighbour's tail. @@ -34,7 +35,7 @@ ROADMAP task 35 and the asks of both apps' open items. Additive except one case `OrientationSymmetryError` has a new case, `differentSymmetry`: a `switch` over it that has no `default` must handle it. Nothing else changes for a consumer. mac4DSTEM can delete `ShellAssignment` (marked `delete at DiffractoKit 0.10.x`) and call `LinearScale.assign`; macTEM can delete its `refineSpot` interim. -## 0.9.1 (2026-10-21) +## [0.9.1](https://github.com/mac4DSTEM/DiffractoKit/compare/0.9.0...0.9.1) (2026-10-21) Tests, docs and one speed fix. No number, default or public symbol changes. @@ -46,7 +47,7 @@ Tests, docs and one speed fix. No number, default or public symbol changes. file: 67 ms (median), the 0.9.0 table's 351 ms. Still about 27 times pymatgen's parser, which does not detect symmetry; the rest is in `docs/open-items.md`, which now lists `cif_import` first with the measured cause. -### Tests (D17) +### Changed: tests - The 33 parity rows marked [S] (pins stricter than upstream): 31 loosened, 2 lost only the marker (see below). Loosened to the upstream tolerance stated in each row: rtol 1e-7 (with a 1e-12 floor for exact zeros) where upstream states none, `tol` 1e-5 for the Niggli reduction, orix's allclose (atol 1e-8, rtol 1e-5) for the orix rows, `symprec` 0.01 angstrom (as a fraction of the longest edge) for operation translations, @@ -56,7 +57,7 @@ Tests, docs and one speed fix. No number, default or public symbol changes. TrigonalSettingTests. No fixture moved. Two rows were not stricter and lost the marker only (P11's SciPy optimum; the P25 spot bound is [L], float32 upstream). Closure, orthogonality and the kit's own invariance checks keep their tight bounds. -### Docs +### Changed: docs - `docs/parity.md`: no [S] left; the three 0.9.0 numerics have rows (opt-in in-plane parabola refinement: partly, the vertex formula is py4DSTEM's but is applied to the kit's own correlation; the mirror flag and pattern-angle planes: partly, no Python counterpart; `minimumMatrixEvidence`: partly, no Python counterpart), the Summary counts follow (148 rows, 58 partly). @@ -68,7 +69,7 @@ Tests, docs and one speed fix. No number, default or public symbol changes. ### Migration None. -## 0.9.0 (2026-10-21) +## [0.9.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.8.1...0.9.0) (2026-10-21) The kit audit: the three diagnose-first items (phase matching, ACOM mirror and in-plane angle, CIF symmetry) diagnosed with the experiment named in each test, the parity table and the benchmark table rewritten against the Python sources on disk. @@ -93,7 +94,7 @@ import and a missed refusal into one. - A primitive C-centred monoclinic cell with beta = 90 (two right angles, like the conventional cell) was refused with its correct 4-operation list; the listed rotations (not diagonal in a primitive basis) now decide. -### Diagnosed, nothing changed by default (the experiments are tests) +### Changed: diagnosed, nothing changed by default (the experiments are tests) - Phase matching: `minimumVectors` = 2 is the paper's rule (one or no survivor is the matrix) and the survivor count cannot tell "the matrix explained everything" from "nothing was there" (`minimumMatrixEvidence` above). The completeness-aware cross-phase ranking loses at small noise (23 wrong of 400 against 0 at sigma 0.003 A^-1) and wins only near the pair radius (20 against @@ -110,7 +111,7 @@ Source-compatible except: (1) `CIFImportError` gains a case, so an exhaustive `s `ACOMMatcher(library:refinesInPlaneAngle: true)` for the scan. Phase maps: set `minimumMatrixEvidence = 1` to stop vacuum and stray-peak positions counting as matrix once a labelled scan has cleared it. -## 0.8.1 (2026-10-21) +## [0.8.1](https://github.com/mac4DSTEM/DiffractoKit/compare/0.8.0...0.8.1) (2026-10-21) ### Added - `OrientationMapAnalysis` in `DiffractoOrientation`: `eulerText`, `reliabilityThreshold(percentile:)`, `fractionOfMatched`, the per-position planes @@ -122,7 +123,7 @@ positions counting as matrix once a labelled scan has cleared it. mac4DSTEM (`OrientationMap`): forward its methods to `OrientationMapAnalysis` on `results`, wrapping the planes in `FloatImage` / `RGBAImage`. Not moved: the learned detector (Paul's decision), `ACOMCrystalSymmetry`'s test-only unreduced fallback; the open phase-matching, ACOM-mirror and CIF-symmetry items are diagnose-first. -## 0.8.0 (2026-10-21) +## [0.8.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.7.1...0.8.0) (2026-10-21) The one numeric piece mac4DSTEM still carried that belongs here. No existing number changes. @@ -139,11 +140,11 @@ mac4DSTEM: build `radiiPerPosition` from its Bragg vectors (distance of each pea Not moved, by design: `ACOMCrystalSymmetry` / `OrientationMap` / `MetalACOMMatcher` (app, by the app's own design); the open phase-matching, ACOM-mirror and CIF-symmetry items are diagnose-first behaviour questions, not missing code. -## 0.7.1 (2026-10-21) +## [0.7.1](https://github.com/mac4DSTEM/DiffractoKit/compare/0.7.0...0.7.1) (2026-10-21) The ImagoKit dependency accepts `"0.2.0"..<"1.0.0"` (was 0.2.x), so a consumer can take ImagoKit 0.4.0. Only `FFT1D` is used; the ACOM, phase and orientation tests pass against ImagoKit 0.4.0. -## 0.7.0 (2026-10-21) +## [0.7.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.6.0...0.7.0) (2026-10-21) The ACOM asks of the apps' kit switch: what mac4DSTEM still carries a copy of around `ACOMMatcher` and `ACOMTemplateLibrary`. No number changes: every addition is checked against the existing CPU route (`match`, `matchAll(peaks:)`), which stays the reference. @@ -170,7 +171,7 @@ number changes: every addition is checked against the existing CPU route (`match - `ACOMError` has a new case `cancelled`: an exhaustive `switch` over it needs one more branch. - The generic `match`/`matchAll` overloads accept everything the array forms did; no call site changes. -## 0.6.0 (2026-10-20) +## [0.6.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.5.0...0.6.0) (2026-10-20) Orientation symmetry beyond the three app classes, pinned to orix; the py4DSTEM direction families; the preset crystals, the Materials Project models and the phase model that the two apps carry. @@ -246,7 +247,7 @@ Materials Project models and the phase model that the two apps carry. `PhaseModel.orientationClass`; the apps' `.identity` is `nil`, and the kit also reduces tetragonal, orthorhombic, cubic m-3, trigonal and 6/m cells that the apps called unreduced). -## 0.5.0 (2026-10-20) +## [0.5.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.4.1...0.5.0) (2026-10-20) ACOM matching over a whole scan, so the apps can drop their own scan loop (mac4DSTEM `OrientationMatching.matchAll`, CPU path). @@ -268,7 +269,7 @@ mapping (a Bragg-vector lattice fit with no crystal in it; it belongs to CuboKit Additive: a consumer of 0.4.1 recompiles unchanged. mac4DSTEM replaces its CPU `matchAll` loop and `ACOMScanSelection` with the kit's; the Metal path and the `OrientationMap` presentation stay. -## 0.4.1 (2026-10-16) +## [0.4.1](https://github.com/mac4DSTEM/DiffractoKit/compare/0.4.0...0.4.1) (2026-10-16) Dependency range only; no API, source or number changes. @@ -277,7 +278,7 @@ Dependency range only; no API, source or number changes. ### Migration None for consumers of 0.4.0 beyond re-pinning to 0.4.1. A consumer may now use any ImagoKit 0.2.x. -## 0.4.0 (2026-10-16) +## [0.4.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.3.1...0.4.0) (2026-10-16) Orientation symmetry for all eleven Laue classes, the ACOM matcher, the Materials Project cell import, and helpers for application front ends (crystal loading, ring overlay, indexing display, ring scale). @@ -314,12 +315,12 @@ non-lattice rotations) is included in this tag. patterns; one 2/m pattern returns a different beam direction (127 degrees). - Dependency: ImagoKit 0.2.0 (exact), for `FFT1D` (ImagoFFT), used by DiffractoOrientation only. -### Conventions +### Changed: conventions - py4DSTEM's direction-family reduction is not ported (returns families, not a rotation). Neither the minimum-angle rotation nor the native direction fold substitutes for Python's family array. See `docs/orientation-symmetry.md`. - Additive API; no orientation-map container added. -## 0.3.1 (2026-10-15) +## [0.3.1](https://github.com/mac4DSTEM/DiffractoKit/compare/0.3.0...0.3.1) (2026-10-15) ### Fixed - Symmetry detection: a CIF whose operation loop lists rotations that are not symmetries of the cell's lattice (the 48 signed @@ -329,7 +330,7 @@ non-lattice rotations) is included in this tag. class and the atoms decide it. Reflections are unchanged on every pinned structure; `SymmetryDetection.Result.candidates` no longer lists such a rotation. - Not a change: hcp written in a cell with γ = 60° is read as 6/mmm (it is hcp); 0.1.0's 2/m was the metric not being recognised. -## 0.3.0 +## [0.3.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.1.1...0.3.0) (2026-10-15) One release for two steps (there is no separate 0.2.0 tag): the generality pass, where every policy is a parameter with the previous value as its documented default, the platform floor is lowered and the docs stand alone (the default path is bit @@ -400,7 +401,7 @@ identical to 0.1.1 on 31,725 outputs); and vector-matched phase mapping with the and loosening coverage needs both `RingCalibration.Policy.minimumOccupiedAngularBins` and the ellipse policy's `degeneracyBoundBins`; removing the `ReflectionList.Policy` caps removes the memory and time protection (a k_max of 100 reached 10 GB). Error texts quote the default bounds. A kinematic pattern cannot tell +c from −c on a polar structure: no consumer may -claim a polarity from a kinematic match. Earlier per-release migration notes are archived (see the 0.1.0 entry) and in git history. +claim a polarity from a kinematic match. **Phase mapping.** An application that carried its own vector matching can delete it when it adopts the kit's. For code moving from such an implementation: `Crystal` becomes `CrystalStructure` (`PhaseDefinition.crystal`); a structure the kit refuses throws `PhaseReferenceLibrary.Failure.structureRefused`; `BraggVectors` becomes `scan:scanWidth:scanHeight:` with @@ -410,15 +411,17 @@ throws; a scan whose position count is not width × height gives nil (or `[]`) f `matrixEntryIndex` makes `map` return nil; a cancelled `build` throws `CancellationError`. The decision rule of `.knownVariants` and its two constants follow Thronsen et al., Ultramicroscopy 255 (2024) 113861 (CC BY 4.0; NOTICE). No other number moves. -## 0.1.1 +## [0.1.1](https://github.com/mac4DSTEM/DiffractoKit/compare/0.1.0...0.1.1) (2026-10-15) Niggli reduction, the conventional cell in both settings, the Cartesian symmetry tolerance, detection on a cell list; the CI type-check fixes. -## 0.1.0 +## [0.1.0](https://github.com/mac4DSTEM/DiffractoKit/compare/0.0.3...0.1.0) (2026-10-15) Cells of the seven systems, symmetry from the atoms, CIF import, reflections, absences, orbits and rings; electron scattering factors and structure factors; the wavelength, ring and ellipse calibration, camera length, indexing and zone axes; error texts; progress and cancellation of the fits. -Consumer notes for 0.0.1 to 0.3.0 are archived. +## [0.0.3](https://github.com/mac4DSTEM/DiffractoKit/releases/tag/0.0.3) (2026-10-15) + +Pre-releases (0.0.1 to 0.0.3): the first cells, reflections, scattering factors and ring fits, before the API settled. See the git history. diff --git a/CITATION.cff b/CITATION.cff index ed75d24..5831a4c 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -6,7 +6,8 @@ abstract: "A Swift library for crystallography and electron diffraction: unit ce authors: - family-names: Lobpreis given-names: Paul - # TODO(Paul): add orcid: "https://orcid.org/…" and affiliation: "…" here +version: 0.10.0 # x-release-please-version +date-released: 2026-10-22 license: GPL-3.0-only repository-code: "https://github.com/mac4DSTEM/DiffractoKit" keywords: @@ -34,3 +35,8 @@ references: authors: - name: "The pyxem developers" url: "https://github.com/pyxem/pyxem" + - type: software + title: "orix" + authors: + - name: "The pyxem developers" + url: "https://github.com/pyxem/orix" diff --git a/NOTICE b/NOTICE index 2f47fae..ede090d 100644 --- a/NOTICE +++ b/NOTICE @@ -21,7 +21,8 @@ The cell, lattice and reflection-list code, the CIF parser with its written-precision expansion and its refusals, the family (ring) rule and the monoclinic orbit convention are ported from mac4DSTEM (commit 7448401b: mac4DSTEM/Core/Crystal/Crystal.swift, CrystalModel.swift, CIFImport.swift) and -macTEM (commit a58c84c: Sources/TEMCore/Analysis/DSpacingIndexing.swift, and its design notes), generalised to the seven crystal systems. +macTEM before v1.0.0 (history squashed: Sources/TEMCore/Analysis/DSpacingIndexing.swift, +and its design notes), generalised to the seven crystal systems. The CIF fixtures under Tests/DiffractoCoreTests/Fixtures come from mac4DSTEM's tests at the same commit, each with its provenance in a comment line. @@ -29,9 +30,10 @@ Later parts were read at mac4DSTEM 7d6fdbd1 (structure factors and the |F| cut, Crystal.swift and ScatteringFactors.swift; EllipseCalibration.swift with ADR 069; the ellipse transform of Calibration.swift; the zone axes of PhaseReferenceLibrary.swift, OrientationPlan.swift and OrientationResult.swift) -and macTEM 9482831 (RingCalibration.swift, RingCalibration+Fit.swift and -DSpacingIndexing.swift). The ring-fit tests port those applications' plants and their -renderer at those commits. +and macTEM before v1.0.0 (history squashed: RingCalibration.swift, +RingCalibration+Fit.swift and DSpacingIndexing.swift). The ring-fit tests port +those applications' plants and their renderer at those versions. macTEM's public +history starts at v1.0.0, so its earlier commits are named by version, not hash. mac4DSTEM - https://github.com/mac4DSTEM/mac4DSTEM macTEM - https://github.com/mac4DSTEM/macTEM @@ -109,4 +111,34 @@ plot_orientation_maps (GPL-3.0); its automatic sector bases are generated by calling that version's orientation_plan. pymatgen PointGroup (2026.9.24 / core 2026.9.23, MIT) is an oracle for all eleven proper rotation tables; SciPy Rotation is an oracle for the minimum-angle representative. No orix or -MTEX code is copied or executed. tools/symmetry/pins.py records provenance. +MTEX code is copied into the library. tools/symmetry/pins.py records provenance. + +================================================================================ +orix (used as a reference for checking; no code copied) +================================================================================ + +tools/orix/*-pins.py run orix 0.15.0 as the oracle for the IPF colour key, +direction reduction, disorientation and misorientation (docs/parity.md P26 and +P36); their output is committed as Tests/DiffractoOrientationTests/Fixtures/ +orix-*-pins.json. No orix code is copied into the library. + + orix - https://github.com/pyxem/orix + Copyright (C) The pyxem developers + Licensed under the GNU General Public License v3.0 + +================================================================================ +Materials Project (test fixtures) +================================================================================ + +Tests/DiffractoCoreTests/Fixtures/mp-import/input-*.json are decoder inputs in +the Materials Project API's response format, copied from the applications' tests: +input-aluminium-v3.json is a recorded API response for mp-134, and the +magnesium and silicon files are smaller records in the same format. They are +credited as Materials Project data, licensed CC BY 4.0 +(https://creativecommons.org/licenses/by/4.0/). Changes: none to the recorded +response; the other two were written by hand in its format. + + Source: The Materials Project, https://materialsproject.org + A. Jain et al., "Commentary: The Materials Project: A materials genome + approach to accelerating materials innovation", APL Materials 1, 011002 + (2013), doi:10.1063/1.4812323 diff --git a/README.md b/README.md index c163ab1..790e399 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ # DiffractoKit +[![CI](https://github.com/mac4DSTEM/DiffractoKit/actions/workflows/ci.yml/badge.svg)](https://github.com/mac4DSTEM/DiffractoKit/actions/workflows/ci.yml) +[![Docs](https://github.com/mac4DSTEM/DiffractoKit/actions/workflows/docs.yml/badge.svg)](https://mac4dstem.github.io/DiffractoKit/) + Crystallography and electron diffraction as a Swift package: the numbers a scientist reads, never UI. DiffractoKit is the Swift counterpart of the crystallography parts of **pymatgen**, **py4DSTEM** and **pyxem**: the unit cell and its reciprocal lattice, symmetry found from the atoms, CIF import, d-spacings and the list of reflections with systematic @@ -9,8 +12,10 @@ absences, electron scattering factors and kinematic structure factors, rings and diffraction pattern (wavelength, camera length, reciprocal-space pixel size, the ring and ellipse fit). It is built to be imported by tagged version into applications. -Swift 6 strict concurrency, `Foundation`, `simd` and `CryptoKit` (no Python). Headless, one SwiftPM product per module. -Where a path is accelerated (none yet), it will keep a CPU reference path with a stated tolerance. +Swift 6 strict concurrency on `Foundation`, `simd`, `CryptoKit`, Metal (the ACOM matcher's optional GPU path) and +[ImagoKit](https://github.com/mac4DSTEM/ImagoKit) (its FFT, on Accelerate); no Python. Headless, one SwiftPM product per +module. The one accelerated path, `ACOMMatcher.matchAll(..., backend: .metal)`, keeps the CPU path as its reference and is +checked against it. **Status: 0.x** ([semantic versioning](https://semver.org): a minor release may change the API, and every release has a `CHANGELOG.md` entry with a migration note where needed). Pin an exact tag and bump on purpose. @@ -23,17 +28,17 @@ One SwiftPM product per module; a module imports only the ones above it in this | Module | Holds | Since | |---|---|---| -| `DiffractoCore` | `UnitCell` (all seven crystal systems: real and reciprocal lattice, metric, volume, d and g of an hkl, the angle between planes), `SymmetryOperation` and `PointSymmetry` (the eleven Laue classes, `LaueClass`, `CrystalSystem`), symmetry found from the atom sites (`SymmetryDetection`, `CrystalStructure`), `CIFImport` (CIF text to `CrystalStructure`, with named refusals), `ReflectionList` (every hkl up to a k_max with its systematic-absence flag), orbits and families (rings) with their names | 0.1.0; Niggli reduction, the conventional cell and a Cartesian symmetry tolerance since 0.1.1 | +| `DiffractoCore` | `UnitCell` (all seven crystal systems: real and reciprocal lattice, metric, volume, d and g of an hkl, the angle between planes), `SymmetryOperation` and `PointSymmetry` (the eleven Laue classes, `LaueClass`, `CrystalSystem`), symmetry found from the atom sites (`SymmetryDetection`, `CrystalStructure`), `CIFImport` (CIF text to `CrystalStructure`, with named refusals), `ReflectionList` (every hkl up to a k_max with its systematic-absence flag), orbits and families (rings) with their names, `CrystalPresets`, the Materials Project import | 0.1.0; Niggli reduction, the conventional cell and a Cartesian symmetry tolerance 0.1.1; presets and Materials Project import 0.6.0 | | `DiffractoScattering` | `ElectronScatteringFactors` (Lobato and Van Dyck, the table of py4DSTEM, Z = 1 to 103), `StructureFactors` (F(hkl) in A^-2), `CrystalStructure.kinematicReflections(kMax:)`: the reflections after an \|F\| cut, and their rings with the summed \|F\|^2 | 0.1.0 | -| `DiffractoGeometry` | `ElectronWavelength` (relativistic, CODATA 2018), `RingCalibration` (camera length, reciprocal-space pixel size from one ring of known d, with the refusals that say when a ring must not be calibrated from; `fit` runs the whole chain on a pattern), `EllipseCalibration` and `EllipseTransform` (the ring and detector-ellipse fit, py4DSTEM's model), `RingIndexing` (which family a measured \|q\| belongs to, and when it must not be named), `ZoneAxis` (beam directions, the detector basis, excitation errors) | 0.1.0 | -| `DiffractoOrientation` | Phase reference libraries and vector matching, Euler angles and orientation-result values; `CrystalOrientationSymmetry` (minimum-angle reduction for all 11 Laue classes), direction sampling and explicit `.py4DSTEM` / `.native` IPF colour keys | phase mapping and orientation results 0.3.0; orientation symmetry and the ACOM matcher 0.4.0; [conventions](docs/orientation-symmetry.md), parity P17–P19 | +| `DiffractoGeometry` | `ElectronWavelength` (relativistic, CODATA 2018), `RingCalibration` (camera length, reciprocal-space pixel size from one ring of known d, with the refusals that say when a ring must not be calibrated from; `fit` runs the whole chain on a pattern), `EllipseCalibration` and `EllipseTransform` (the ring and detector-ellipse fit, py4DSTEM's model), `RingIndexing` (which family a measured \|q\| belongs to, and when it must not be named), `ZoneAxis` (beam directions, the detector basis, excitation errors), `LinearScale` (delta q from rings: estimate, assign, fit), single-pattern measurements (`PatternCentre`, `PatternRadialProfile`, `PatternSpot`) | 0.1.0; `LinearScale.estimate` 0.8.0; `LinearScale.assign` and `fit` and the pattern measurements 0.10.0 | +| `DiffractoOrientation` | Phase reference libraries and vector matching, Euler angles and orientation-result values; `CrystalOrientationSymmetry` (minimum-angle reduction for all 11 Laue classes), direction sampling and explicit `.py4DSTEM` / `.native` / `.orix` IPF colour keys, the ACOM matcher and scan (CPU and Metal), `OrientationMapAnalysis`, `PhaseModel`, `Misorientation` and `Orientation`, orientation-relationship variants | phase mapping and orientation results 0.3.0; orientation symmetry and the ACOM matcher 0.4.0; ACOM scans 0.5.0; the orix key, disorientation, `PhaseModel` and the Metal backend 0.6.0; map analysis 0.8.1; misorientation and variants 0.10.0; [conventions](docs/orientation-symmetry.md) | ## Install ```swift // Package.swift dependencies: [ - .package(url: "https://github.com/mac4DSTEM/DiffractoKit", exact: "0.4.1"), + .package(url: "https://github.com/mac4DSTEM/DiffractoKit", exact: "0.10.0"), // x-release-please-version ], targets: [ .target(name: "MyApp", dependencies: [ @@ -44,8 +49,9 @@ targets: [ ] ``` -The package needs macOS 15 or iOS 18 and a Swift 6.2 toolchain (`swift-tools-version: 6.2`). Its only dependency is -[ImagoKit](https://github.com/mac4DSTEM/ImagoKit), used by `DiffractoOrientation` alone (its `FFT1D`). It carries no unsafe +The package needs macOS 15 or iOS 18 and a Swift 6.2 toolchain (`swift-tools-version: 6.2`). Its only package dependency is +[ImagoKit](https://github.com/mac4DSTEM/ImagoKit), used by `DiffractoOrientation` alone (its `FFT1D`, on Accelerate); +the system frameworks are Foundation, simd, CryptoKit and, for the optional GPU matcher, Metal. It carries no unsafe flags: your build compiles it optimised itself; a Debug build of the reflection loops and of the ring fit is slow. `DiffractoGeometry` depends on the other two, but each file that names a type of a module should import that module itself (`MemberImportVisibility` is on in this package). @@ -249,9 +255,10 @@ and ported from: pymatgen, spglib, py4DSTEM and, for the orientation work, pyxem - Nothing here is validated on a real diffraction pattern; the ring-fit evidence is measured on synthetic plants only. - No database CIF (COD, ICSD) is read yet. -- theta'-Al2Cu in the slice 4 pins is a test structure (Al4Cu2 body-centred, a 4.04 A, c 5.80 A), not checked against a published CIF. +- theta'-Al2Cu in the orientation pins is a test structure (Al4Cu2 body-centred, a 4.04 A, c 5.80 A), not checked against a published CIF. - With py4DSTEM's patterns the ACOM matcher finds 17 of 18 planted orientations within 4 degrees; one 2/m pattern matches another beam direction. -- `testRinglessFitOnARealMeanPatternFallsBackToTheConic` is disabled by name until the owner's Ni65Cu35 mean pattern has a manifest line. +- One real-data test (`testRinglessFitOnARealMeanPatternFallsBackToTheConic`, a Ni65Cu35 mean pattern) is disabled until that + dataset is published with the tests. - Policies not yet parameters (profile-fit plausibility bounds, cell volume 1e-6) remain. - The open list, worst first, with causes: `docs/open-items.md`; timings against Python: `docs/benchmarks.md`. diff --git a/Sources/DiffractoCore/ReflectionList.swift b/Sources/DiffractoCore/ReflectionList.swift index cbfc8fb..288c436 100644 --- a/Sources/DiffractoCore/ReflectionList.swift +++ b/Sources/DiffractoCore/ReflectionList.swift @@ -3,7 +3,7 @@ // Role: every (h, k, l) with 0 < |g| ≤ k_max, its d, whether the space-group operations allow it, and the rings // (families) the list falls into. The enumeration is reference commit 7448401b `Crystal.reflections` without the // structure factor (the per-axis index bound, DEVIATION of 2026-09-14, complete for oblique cells); the absence -// rule is the general reflection condition; the family rule is reference commit a58c84c `DSpacingIndexing.families`. +// rule is the general reflection condition; the family rule is macTEM before v1.0.0 (history squashed) `DSpacingIndexing.families`. // import Foundation diff --git a/Sources/DiffractoGeometry/ElectronWavelength.swift b/Sources/DiffractoGeometry/ElectronWavelength.swift index beadef0..5c39d68 100644 --- a/Sources/DiffractoGeometry/ElectronWavelength.swift +++ b/Sources/DiffractoGeometry/ElectronWavelength.swift @@ -1,7 +1,7 @@ // // ElectronWavelength.swift // Role: the one electron wavelength of the kit, the relativistic de Broglie wavelength at an accelerating voltage. -// Ported from reference commit 9482831 `RingCalibration.wavelengthAngstroms` +// Ported from macTEM before v1.0.0 (history squashed) `RingCalibration.wavelengthAngstroms` // with the same arithmetic order, so the results are bit identical. // // λ = hc / √(eV (2 m₀c² + eV)), V in volts, λ in Å. diff --git a/Sources/DiffractoGeometry/RingCalibration+Fit.swift b/Sources/DiffractoGeometry/RingCalibration+Fit.swift index fd81f14..41c0dac 100644 --- a/Sources/DiffractoGeometry/RingCalibration+Fit.swift +++ b/Sources/DiffractoGeometry/RingCalibration+Fit.swift @@ -3,7 +3,7 @@ // Role: the fit-driven calibration: a ring of known d fitted in a pattern, the fit's numbers checked against every // refusal, and Δq and the camera length computed from the fitted radius only when nothing refuses them. // -// SEED: reference commit 9482831 `Sources/TEMCore/Analysis/RingCalibration+Fit.swift`, logic unchanged. The one difference is the +// SEED: macTEM before v1.0.0 (history squashed) `Sources/TEMCore/Analysis/RingCalibration+Fit.swift`, logic unchanged. The one difference is the // fit it runs: the reference implementation's own `EllipseCalibration` copy there is the pre-ADR-069 file; this runs the kit's // `EllipseCalibration` (reference commit 7d6fdbd1, with ADR 069's two starts and the 0.30 px ring-width floor), so the numbers // the reference implementation measured on its copy move when it imports the kit. diff --git a/Sources/DiffractoGeometry/RingCalibration.swift b/Sources/DiffractoGeometry/RingCalibration.swift index 983361e..6d727d8 100644 --- a/Sources/DiffractoGeometry/RingCalibration.swift +++ b/Sources/DiffractoGeometry/RingCalibration.swift @@ -1,7 +1,7 @@ // // RingCalibration.swift // Role: the calibration a diffraction ring of known d gives (Δq in 1/Å per pixel, and the camera length) as closed forms, -// and the decision of when a ring is NOT to be calibrated from. Ported from reference commit 9482831 `RingCalibration.swift` with every formula, constant, +// and the decision of when a ring is NOT to be calibrated from. Ported from macTEM before v1.0.0 (history squashed) `RingCalibration.swift` with every formula, constant, // NaN rule, refusal order and message kept. The fit that fills a `FitReport` is in `RingCalibration+Fit.swift`. // // THE FORMULAS (exact; nothing here is a small-angle form): diff --git a/Sources/DiffractoGeometry/RingIndexing.swift b/Sources/DiffractoGeometry/RingIndexing.swift index 0a6289d..7e42287 100644 --- a/Sources/DiffractoGeometry/RingIndexing.swift +++ b/Sources/DiffractoGeometry/RingIndexing.swift @@ -1,7 +1,7 @@ // // RingIndexing.swift // Role: the (hkl) family a measured |q| belongs to, against a ring list (DiffractoScattering's `KinematicFamily`, or DiffractoCore's -// `ReflectionFamily`), and the decision of when it is NOT to be named. The decision is reference commit 9482831 +// `ReflectionFamily`), and the decision of when it is NOT to be named. The decision is macTEM before v1.0.0 (history squashed) // `DSpacingIndexing.index` (macTEM ADR 022 and ADR 024), generalised: the list is DiffractoCore's family rule over any // crystal system ("RingIndexing"), so the lattice, orbit and // family-construction code of the seed is not ported and `unsupportedLattice` / `unsupportedElement` cannot occur diff --git a/Sources/DiffractoGeometry/ZoneAxis.swift b/Sources/DiffractoGeometry/ZoneAxis.swift index 3614137..6e7611f 100644 --- a/Sources/DiffractoGeometry/ZoneAxis.swift +++ b/Sources/DiffractoGeometry/ZoneAxis.swift @@ -2,7 +2,7 @@ // ZoneAxis.swift // Role: zone-axis primitives ("ZoneAxis"): the 49 low-index beam // directions, a direction [u v w] as a Cartesian unit vector of a cell, the detector basis of a beam direction, -// and the projection of a reflection list onto it with the excitation error. Seeds, read at reference commit 7d6fdbd1 +// and the projection of a reflection list onto it with the excitation error. Seeds, read at mac4DSTEM 7d6fdbd1 // by `git show`: `PhaseReferenceLibrary.lowIndexZoneAxes` and `cartesianZoneAxis`, `ACOMOrientation.detectorBasis` // (Core/Analysis/OrientationResult.swift), `OrientationPlan.project` (Core/Crystal/OrientationPlan.swift). // Units: Å⁻¹ without 2π, as the rest of the kit. diff --git a/Tests/DiffractoGeometryTests/Fixtures/.keep b/Tests/DiffractoGeometryTests/Fixtures/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/Tests/DiffractoGeometryTests/RingCalibrationTests.swift b/Tests/DiffractoGeometryTests/RingCalibrationTests.swift index ad24cfb..982803e 100644 --- a/Tests/DiffractoGeometryTests/RingCalibrationTests.swift +++ b/Tests/DiffractoGeometryTests/RingCalibrationTests.swift @@ -1,7 +1,7 @@ // // RingCalibrationTests.swift // The closed forms (λ, 2θ, L_px, Δq, L_mm) against hand arithmetic, -// and every refusal by its own name. Ported from reference commit 9482831 Tests/RingCalibrationTests.swift (30 tests, same +// and every refusal by its own name. Ported from macTEM before v1.0.0 (history squashed) Tests/RingCalibrationTests.swift (30 tests, same // names, literals unchanged) to Swift Testing. No fit, no Python at run time: the expected numbers below were worked once, // by hand, in 60-digit decimal arithmetic from the CODATA 2018 constants stated in ElectronWavelength.swift (h and c and e // exact, m₀ = 9.1093837015e-31 kg) and are typed here as literals. The many-case parity with a 60-digit decimal script is diff --git a/Tests/DiffractoGeometryTests/RingFitCalibrationTests.swift b/Tests/DiffractoGeometryTests/RingFitCalibrationTests.swift index 8f71722..111afa3 100644 --- a/Tests/DiffractoGeometryTests/RingFitCalibrationTests.swift +++ b/Tests/DiffractoGeometryTests/RingFitCalibrationTests.swift @@ -1,7 +1,7 @@ // // RingFitCalibrationTests.swift // The fit-driven calibration (`RingCalibration.fit`) on rings planted here, in Swift, with their truth -// known. Ported from reference commit 9482831 Tests/RingFitCalibrationTests.swift (8 tests, same names, same plant, same bands), +// known. Ported from macTEM before v1.0.0 (history squashed) Tests/RingFitCalibrationTests.swift (8 tests, same names, same plant, same bands), // RUN ON THE KIT'S FIT, which is reference commit 7d6fdbd1's `EllipseCalibration` (ADR 069: two starts and the 0.30 px floor guard); // the reference implementation's own copy there is the pre-ADR-069 file. No number of these eight moved: every assertion holds as the reference implementation wrote it // (said they might, the measured values are in tools/slice-3b/README.md). diff --git a/Tests/DiffractoGeometryTests/RingIndexingTests.swift b/Tests/DiffractoGeometryTests/RingIndexingTests.swift index 04bd6a2..9e0e2b3 100644 --- a/Tests/DiffractoGeometryTests/RingIndexingTests.swift +++ b/Tests/DiffractoGeometryTests/RingIndexingTests.swift @@ -1,7 +1,7 @@ // // RingIndexingTests.swift // The indexing decision ("RingIndexing", "Truth"), on the kit's own ring -// lists (DiffractoScattering's `kinematicReflections(kMax: 1.2).families`). It ports every test of reference commit 9482831 +// lists (DiffractoScattering's `kinematicReflections(kMax: 1.2).families`). It ports every test of macTEM before v1.0.0 (history squashed) // `DSpacingIndexingTests` (28) and `MonoclinicIndexingTests` (13) that concerns the decision or the family lists, // re-expressed on the kit's rings; the ones that test what DiffractoCore and DiffractoScattering own are mapped to a comment at the end. // The dyadic lists are the kit's rings of an exactly-scaled orthorhombic cell (a 2, b 1, c 1/2 Å: g = h/2, k, 2 l, so diff --git a/Tests/DiffractoKitParityTests/Geometry/RingCalibrationPinsTests.swift b/Tests/DiffractoKitParityTests/Geometry/RingCalibrationPinsTests.swift index 906a7e4..8d7c7cc 100644 --- a/Tests/DiffractoKitParityTests/Geometry/RingCalibrationPinsTests.swift +++ b/Tests/DiffractoKitParityTests/Geometry/RingCalibrationPinsTests.swift @@ -4,7 +4,7 @@ // pins tools/slice-3/ring-pins.py writes (Fixtures/slice-3-ring-pins.json): the closed forms evaluated in 60-digit decimal // arithmetic, 320 cases, the refusal decision from the documented thresholds (68 plants), the Bragg limit (18 plants) and the // radius (10 plants). Band 1e-7 relative (the reference's tolerance since 0.9.1; it was 1e-12); a difference is a failure of the port, never a band to widen. -// Ported from reference commit 9482831 tools/ring-calibration-parity/main.swift. The fixture is read by #filePath (the Fixtures folder +// Ported from macTEM before v1.0.0 (history squashed) tools/ring-calibration-parity/main.swift. The fixture is read by #filePath (the Fixtures folder // is excluded from the target). // diff --git a/Tests/Fixtures/README.md b/Tests/Fixtures/README.md index 2ca6cfd..400aabc 100644 --- a/Tests/Fixtures/README.md +++ b/Tests/Fixtures/README.md @@ -1,9 +1,9 @@ # Test fixtures One row per committed fixture file under `Tests/*/Fixtures/`: size, the script under `tools/` that names it (the generator or its -pin script; a few scripts write a whole directory; a script found only by file-name prefix, tool-folder name or test module is marked so), and a note where the origin is not the kit's own pinned reference. 55 files. +pin script; a few scripts write a whole directory; a script found only by file-name prefix, tool-folder name or test module is marked so), and a note where the origin is not the kit's own pinned reference. 56 files. -Licence: every fixture is generated from this kit's own code and the pinned Python reference (named in the README) and ships under the kit's GPL-3.0-or-later licence, except the rows marked *third party*. No fixture is a copy of a real dataset: the committed text fixtures carry no local path or personal name (checked by search), and real datasets are read from `$MACEM_DATA` and never copied into the repo. +Licence: every fixture is generated from this kit's own code and the pinned Python reference (named in the README) and ships under the kit's GPL-3.0-only licence, except the rows marked *third party*. No fixture is a copy of a real dataset: the committed text fixtures carry no local path or personal name (checked by search), and real datasets are read from `$MACEM_DATA` and never copied into the repo. ## Third party @@ -24,9 +24,9 @@ Licence: every fixture is generated from this kit's own code and the pinned Pyth | `DiffractoCoreTests/Fixtures/ideal_hcp_P1.cif` | 504 B | `tools/slice-1/pins.py` | | | `DiffractoCoreTests/Fixtures/magnesium_P63mmc.cif` | 401 B | `tools/slice-4/pins.py` | | | `DiffractoCoreTests/Fixtures/magnesium_P63mmc_24ops.cif` | 896 B | `tools/slice-1/pins.py` | | -| `DiffractoCoreTests/Fixtures/mp-import/input-aluminium-v3.json` | 1.6 KB | `tools/mp-import/pins.py` | third party: Materials Project export; licence terms to be confirmed by Paul | -| `DiffractoCoreTests/Fixtures/mp-import/input-magnesiumJSON.json` | 1.1 KB | `tools/mp-import/pins.py` | third party: Materials Project export; licence terms to be confirmed by Paul | -| `DiffractoCoreTests/Fixtures/mp-import/input-siliconJSON.json` | 2.9 KB | `tools/mp-import/pins.py` | third party: Materials Project export; licence terms to be confirmed by Paul | +| `DiffractoCoreTests/Fixtures/mp-import/input-aluminium-v3.json` | 1.6 KB | `tools/mp-import/pins.py` | third party: Materials Project data, CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/), source https://materialsproject.org; credited in `NOTICE` | +| `DiffractoCoreTests/Fixtures/mp-import/input-magnesiumJSON.json` | 1.1 KB | `tools/mp-import/pins.py` | third party: Materials Project data, CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/), source https://materialsproject.org; credited in `NOTICE` | +| `DiffractoCoreTests/Fixtures/mp-import/input-siliconJSON.json` | 2.9 KB | `tools/mp-import/pins.py` | third party: Materials Project data, CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/), source https://materialsproject.org; credited in `NOTICE` | | `DiffractoCoreTests/Fixtures/mp-import/pymatgen-pins.json` | 6.3 KB | `tools/mp-import/pins.py` | | | `DiffractoCoreTests/Fixtures/presets-pins.json` | 21.1 KB | `tools/presets/pins.py` | | | `DiffractoCoreTests/Fixtures/pyrite_Pa-3.cif` | 1.1 KB | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | @@ -60,6 +60,7 @@ Licence: every fixture is generated from this kit's own code and the pinned Pyth | `DiffractoOrientationTests/Fixtures/orix-direction-pins.json` | 1.5 MB | `tools/orix/direction-pins.py` | | | `DiffractoOrientationTests/Fixtures/orix-disorientation-pins.json` | 1.5 MB | `tools/orix/disorientation-pins.py` | | | `DiffractoOrientationTests/Fixtures/orix-ipf-pins.json` | 484.0 KB | `tools/orix/ipf-pins.py` | | +| `DiffractoOrientationTests/Fixtures/orix-misorientation-pins.json` | 896.0 KB | `tools/orix/misorientation-pins.py` | | | `DiffractoOrientationTests/Fixtures/py4dstem-family-pins.json` | 1005.7 KB | `tools/symmetry/family-pins.py` | | | `DiffractoOrientationTests/Fixtures/py4dstem-family-real-pins.json` | 3.7 MB | `tools/symmetry/family-real-pins.py` | | | `DiffractoOrientationTests/Fixtures/slice-4-apps.json` | 12.9 MB | `tools/slice-4/apps-parity/main.swift`, `tools/slice-4/apps-parity/run.sh` | | diff --git a/release-please-config.json b/release-please-config.json index f4d6bc8..a12a8ef 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -7,7 +7,11 @@ "packages": { ".": { "package-name": "DiffractoKit", - "changelog-path": "CHANGELOG.md" + "changelog-path": "CHANGELOG.md", + "extra-files": [ + "CITATION.cff", + "README.md" + ] } } } diff --git a/tools/slice-2/README.md b/tools/slice-2/README.md index 6f2abe9..abf130a 100644 --- a/tools/slice-2/README.md +++ b/tools/slice-2/README.md @@ -11,7 +11,7 @@ tools/slice-2/apps-parity/run.sh # about 4 s - `pins.py` writes `Tests/DiffractoScatteringTests/Fixtures/slice-2-pins.json` (about 1.7 MB): the versions, the table's sha256 and the 103 x 10 table as `np.loadtxt` reads it, `f_e` at g2 in {0, 0.25, 1, 4} for Z = 1..103, 20 structures (the - apps' presets Au, Al, Si, Mg, WS2; Cu3Au-occ and Weak-cut from macTEM a58c84c; ideal hcp; the extra non-centrosymmetric + apps' presets Au, Al, Si, Mg, WS2; Cu3Au-occ and Weak-cut from macTEM before v1.0.0 (history squashed); ideal hcp; the extra non-centrosymmetric zincblende GaAs; beta'' and ten slice-1 CIF fixtures), each with every reflection above 1e-6 in |F|, the kept count, the rings after the cut, the ring counts on the operation-allowed and on all reflections, the operation-absent check; the mutation-moves; pymatgen's X-ray pattern per peak with the explicit half-space members; the diff --git a/tools/slice-2/fetch-table.sh b/tools/slice-2/fetch-table.sh index 9c57bea..4355d9b 100755 --- a/tools/slice-2/fetch-table.sh +++ b/tools/slice-2/fetch-table.sh @@ -1,5 +1,5 @@ #!/bin/zsh -# PROVENANCE: macTEM a58c84c tools/lib/fetch-py4dstem-scattering.sh adapted +# PROVENANCE: macTEM before v1.0.0 (history squashed) tools/lib/fetch-py4dstem-scattering.sh adapted # Adapted: the same py4DSTEM lock commit and the same sha256, the destination is this kit's gitignored References/ (the # script sits one level deeper than macTEM's, tools/slice-2/, and the root is still two levels up). # END PROVENANCE diff --git a/tools/slice-2/pins.py b/tools/slice-2/pins.py index 11ba329..8d41f73 100644 --- a/tools/slice-2/pins.py +++ b/tools/slice-2/pins.py @@ -360,7 +360,7 @@ def sites_of(z, positions, occ=1.0): def preset_structures(table): - """The apps' presets (Crystal.swift 7d6fdbd1) in the apps' site order, plus macTEM a58c84c's two disordered cases and + """The apps' presets (Crystal.swift 7d6fdbd1) in the apps' site order, plus the two disordered cases of macTEM before v1.0.0 and the ideal hcp. Returns [(name, cell, sites, note)].""" a_hcp = 3.2094 q = weak_cut_occupancy(table) @@ -392,7 +392,7 @@ def preset_structures(table): def weak_cut_occupancy(table): - """macTEM a58c84c: q solved so that the lowest odd-sum reflection (1 0 0), |g| = 1/3, has |F| = 2.5e-4: + """macTEM before v1.0.0 (history squashed): q solved so that the lowest odd-sum reflection (1 0 0), |g| = 1/3, has |F| = 2.5e-4: F = (1 - q) f_e(29, g^2) / V, V = 27.""" a = 3.0 return float(1 - 2.5e-4 * a ** 3 / float(f_e(table, 29, (1 / a) ** 2))) diff --git a/tools/slice-3/README.md b/tools/slice-3/README.md index aaaa858..8ebeab2 100644 --- a/tools/slice-3/README.md +++ b/tools/slice-3/README.md @@ -15,13 +15,13 @@ the Swift and the pins is a failure of the port, never a band to widen. (3 % ellipticity, either axis major); the literals of `RingCalibrationTests` recomputed in decimal (`truth`); the mutation list. - The oracle is 60-digit `decimal` (arcsin by its power series, tan 2 theta by the identity 2 s sqrt(1 - s^2) / (1 - 2 s^2), so no trigonometric library is trusted), with NumPy 2.5.4 routes beside it that must agree to 1e-14. It is written from the - definitions, ported from macTEM 9482831 `tools/ring-calibration-parity/reference.py` (read by `git show`). + definitions, ported from macTEM before v1.0.0 (history squashed) `tools/ring-calibration-parity/reference.py`. - Exit 0: every self-check holds. 1: a self-check failed. Includes: each mutation (small angle, q = 2/d, Angstrom read as nm, pitch in um, non-relativistic lambda, kV as V, V defaulted, radius = a) moves its target quantity by more than 1e-6, so a mutation that moves nothing cannot be mistaken for a proof. - `RingCalibrationPinsTests` (Swift Testing) reads the fixture by `#filePath` and holds every number to 1e-12 relative, every refusal by name and in order, `withholdsDeltaQ` as registered. `RingCalibrationTests` are the 30 hand-arithmetic tests of - macTEM 9482831, converted. + macTEM before v1.0.0 (history squashed), converted. - One literal to know: the typed L_px of Au {111}, R 150 px, 200 kV (14082.307097295722, macTEM's test and `RingCalibrationTests`) is one ulp (1.3e-16 relative) from the correctly rounded decimal result (14082.307097295723). It is far inside the 1e-12 band; the generator holds the typed literals to 1e-15 relative and says so. @@ -35,7 +35,7 @@ failure of the port, never a tolerance to widen. ../References/python/orix/bin/python -I -B tools/slice-3/index-pins.py # about 2 s, deterministic: writes slice-3-index-pins.json ``` -- `index-pins.py` ports macTEM 9482831 `tools/indexing-parity/reference.py` (read by `git show`) onto the KIT's ring lists: +- `index-pins.py` ports macTEM before v1.0.0 (history squashed) `tools/indexing-parity/reference.py` onto the KIT's ring lists: the families after the |F| cut that slice 2 pinned in `Tests/DiffractoScatteringTests/Fixtures/slice-2-pins.json` (so `tools/slice-2/pins.py` runs first), at k_max 1.2: Au, Al, Si, Mg, ideal hcp, Weak-cut (macTEM's six) and beta''. - The decision is NumPy written from the definition in `RingIndexing.swift`'s header, with a plain-Python scalar re-implementation that must agree on diff --git a/tools/slice-3/index-pins.py b/tools/slice-3/index-pins.py index 21e609a..f68534d 100644 --- a/tools/slice-3/index-pins.py +++ b/tools/slice-3/index-pins.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Pins for RingIndexing. -Port of macTEM 9482831 tools/indexing-parity/reference.py (read by `git show`) onto the KIT's own ring lists: the families +Port of macTEM before v1.0.0 (history squashed) tools/indexing-parity/reference.py onto the KIT's own ring lists: the families after the |F| cut that slice 2 pinned (Tests/DiffractoScatteringTests/Fixtures/slice-2-pins.json, written by tools/slice-2/pins.py), at k_max 1.2. The decision is written here from its definition in DiffractoGeometry/RingIndexing.swift's header (NumPy, plus a plain-Python scalar re-implementation that must agree on every plant), NOT from any Swift: diff --git a/tools/slice-3/ring-pins.py b/tools/slice-3/ring-pins.py index 154fb08..8ec425f 100644 --- a/tools/slice-3/ring-pins.py +++ b/tools/slice-3/ring-pins.py @@ -5,8 +5,8 @@ ../References/python/orix/bin/python -I -B tools/slice-3/ring-pins.py [out.json] It writes Tests/DiffractoGeometryTests/Fixtures/slice-3-ring-pins.json BEFORE the Swift tests read it. Deterministic: no -clock, no random numbers; two runs give the same bytes. Ported from macTEM 9482831 tools/ring-calibration-parity/ -reference.py (read by `git show`), which was written from the definitions and not from any Swift. +clock, no random numbers; two runs give the same bytes. Ported from macTEM before v1.0.0 (history squashed) tools/ring-calibration-parity/ +reference.py, which was written from the definitions and not from any Swift. Constants, CODATA 2018 (Tiesinga, Mohr, Newell, Taylor, Rev. Mod. Phys. 93, 025010 (2021)): h = 6.626 070 15e-34 J s exact (the SI 2019 definition) diff --git a/tools/slice-3b/README.md b/tools/slice-3b/README.md index 360d4b4..543354a 100644 --- a/tools/slice-3b/README.md +++ b/tools/slice-3b/README.md @@ -2,7 +2,7 @@ Seeds, from the apps' history before they were public: mac4DSTEM `7d6fdbd1` (`EllipseCalibration.swift`, `DiffractionPattern.swift`, `Calibration.swift`, the noisy, stop-rule and row-29 tests, the -`tools/ellipse-calibration-test` sweep) and macTEM `9482831` (`RingCalibration+Fit.swift`, its 8 tests). +`tools/ellipse-calibration-test` sweep) and macTEM before v1.0.0 (history squashed) (`RingCalibration+Fit.swift`, its 8 tests). - `apps-parity/run.sh` (+ `main.swift`): compiles the apps' own `EllipseCalibration.swift` and `DiffractionPattern.swift` at 7d6fdbd1 with `swiftc -O`, renders 35 planted rings (3 + 4 noisy, the 4 stop-rule rings, 20 clean sweep rings, 4 sparse rings) with the