recip-slice 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. recip_slice-0.4.1/AGENTS.md +178 -0
  2. recip_slice-0.4.1/CHANGELOG.md +212 -0
  3. recip_slice-0.4.1/CONTRIBUTING.md +65 -0
  4. recip_slice-0.4.1/MANIFEST.in +7 -0
  5. recip_slice-0.4.1/PKG-INFO +308 -0
  6. recip_slice-0.4.1/README.md +281 -0
  7. recip_slice-0.4.1/docs/algorithm.md +150 -0
  8. recip_slice-0.4.1/docs/architecture.md +61 -0
  9. recip_slice-0.4.1/docs/gui.md +306 -0
  10. recip_slice-0.4.1/docs/images/image.png +0 -0
  11. recip_slice-0.4.1/docs/installation.md +83 -0
  12. recip_slice-0.4.1/docs/npy_manifest_guide.md +220 -0
  13. recip_slice-0.4.1/docs/reproducibility.md +98 -0
  14. recip_slice-0.4.1/docs/roadmap.md +487 -0
  15. recip_slice-0.4.1/pyproject.toml +85 -0
  16. recip_slice-0.4.1/run.py +24 -0
  17. recip_slice-0.4.1/setup.cfg +4 -0
  18. recip_slice-0.4.1/setup.py +40 -0
  19. recip_slice-0.4.1/src/recip_slice/__init__.py +122 -0
  20. recip_slice-0.4.1/src/recip_slice/__main__.py +5 -0
  21. recip_slice-0.4.1/src/recip_slice/_version.py +3 -0
  22. recip_slice-0.4.1/src/recip_slice/assets/chevron-down-disabled.svg +3 -0
  23. recip_slice-0.4.1/src/recip_slice/assets/chevron-down.svg +3 -0
  24. recip_slice-0.4.1/src/recip_slice/assets/chevron-up-disabled.svg +3 -0
  25. recip_slice-0.4.1/src/recip_slice/assets/chevron-up.svg +3 -0
  26. recip_slice-0.4.1/src/recip_slice/cli.py +741 -0
  27. recip_slice-0.4.1/src/recip_slice/compat/__init__.py +1 -0
  28. recip_slice-0.4.1/src/recip_slice/compat/aliases.py +79 -0
  29. recip_slice-0.4.1/src/recip_slice/compat/dataset_discovery.py +23 -0
  30. recip_slice-0.4.1/src/recip_slice/compat/qt_slice_gui.py +5 -0
  31. recip_slice-0.4.1/src/recip_slice/compat/slice_viewer.py +60 -0
  32. recip_slice-0.4.1/src/recip_slice/compat/virtual_precession.py +51 -0
  33. recip_slice-0.4.1/src/recip_slice/core/__init__.py +1 -0
  34. recip_slice-0.4.1/src/recip_slice/core/calibration.py +344 -0
  35. recip_slice-0.4.1/src/recip_slice/core/common.py +247 -0
  36. recip_slice-0.4.1/src/recip_slice/core/dataset.py +699 -0
  37. recip_slice-0.4.1/src/recip_slice/core/frame_preview.py +143 -0
  38. recip_slice-0.4.1/src/recip_slice/core/geometry.py +1367 -0
  39. recip_slice-0.4.1/src/recip_slice/core/job_queue.py +401 -0
  40. recip_slice-0.4.1/src/recip_slice/core/options.py +75 -0
  41. recip_slice-0.4.1/src/recip_slice/core/preflight.py +545 -0
  42. recip_slice-0.4.1/src/recip_slice/core/project.py +139 -0
  43. recip_slice-0.4.1/src/recip_slice/core/result_management.py +248 -0
  44. recip_slice-0.4.1/src/recip_slice/core/settings.py +61 -0
  45. recip_slice-0.4.1/src/recip_slice/core/validation.py +193 -0
  46. recip_slice-0.4.1/src/recip_slice/core/workflow.py +385 -0
  47. recip_slice-0.4.1/src/recip_slice/gui/__init__.py +97 -0
  48. recip_slice-0.4.1/src/recip_slice/gui/canvas.py +555 -0
  49. recip_slice-0.4.1/src/recip_slice/gui/helpers.py +362 -0
  50. recip_slice-0.4.1/src/recip_slice/gui/viewer.py +279 -0
  51. recip_slice-0.4.1/src/recip_slice/gui/window.py +511 -0
  52. recip_slice-0.4.1/src/recip_slice/gui/window_comparison.py +1022 -0
  53. recip_slice-0.4.1/src/recip_slice/gui/window_dataset.py +702 -0
  54. recip_slice-0.4.1/src/recip_slice/gui/window_dependencies.py +203 -0
  55. recip_slice-0.4.1/src/recip_slice/gui/window_display.py +732 -0
  56. recip_slice-0.4.1/src/recip_slice/gui/window_interaction.py +529 -0
  57. recip_slice-0.4.1/src/recip_slice/gui/window_layout.py +1204 -0
  58. recip_slice-0.4.1/src/recip_slice/gui/window_measurement.py +1817 -0
  59. recip_slice-0.4.1/src/recip_slice/gui/window_process.py +603 -0
  60. recip_slice-0.4.1/src/recip_slice/gui/window_queue.py +538 -0
  61. recip_slice-0.4.1/src/recip_slice/gui/window_state.py +1878 -0
  62. recip_slice-0.4.1/src/recip_slice/gui/window_widgets.py +50 -0
  63. recip_slice-0.4.1/src/recip_slice/reconstruction/__init__.py +239 -0
  64. recip_slice-0.4.1/src/recip_slice/reconstruction/_accum_ext.c +32851 -0
  65. recip_slice-0.4.1/src/recip_slice/reconstruction/_accum_ext.pyx +1510 -0
  66. recip_slice-0.4.1/src/recip_slice/reconstruction/comparison.py +534 -0
  67. recip_slice-0.4.1/src/recip_slice/reconstruction/legacy.py +55 -0
  68. recip_slice-0.4.1/src/recip_slice/reconstruction/legacy_planes.py +370 -0
  69. recip_slice-0.4.1/src/recip_slice/reconstruction/legacy_volume.py +572 -0
  70. recip_slice-0.4.1/src/recip_slice/reconstruction/legacy_workflows.py +589 -0
  71. recip_slice-0.4.1/src/recip_slice/reconstruction/measurements.py +819 -0
  72. recip_slice-0.4.1/src/recip_slice/reconstruction/physical.py +239 -0
  73. recip_slice-0.4.1/src/recip_slice/reconstruction/physical_background.py +904 -0
  74. recip_slice-0.4.1/src/recip_slice/reconstruction/physical_io.py +454 -0
  75. recip_slice-0.4.1/src/recip_slice/reconstruction/physical_native.py +50 -0
  76. recip_slice-0.4.1/src/recip_slice/reconstruction/physical_pipeline.py +2016 -0
  77. recip_slice-0.4.1/src/recip_slice/reconstruction/physical_sampling.py +502 -0
  78. recip_slice-0.4.1/src/recip_slice/reconstruction/physical_tasks.py +299 -0
  79. recip_slice-0.4.1/src/recip_slice/reconstruction/results.py +1104 -0
  80. recip_slice-0.4.1/src/recip_slice/style.qss +738 -0
  81. recip_slice-0.4.1/src/recip_slice.egg-info/PKG-INFO +308 -0
  82. recip_slice-0.4.1/src/recip_slice.egg-info/SOURCES.txt +106 -0
  83. recip_slice-0.4.1/src/recip_slice.egg-info/dependency_links.txt +1 -0
  84. recip_slice-0.4.1/src/recip_slice.egg-info/entry_points.txt +3 -0
  85. recip_slice-0.4.1/src/recip_slice.egg-info/requires.txt +14 -0
  86. recip_slice-0.4.1/src/recip_slice.egg-info/top_level.txt +1 -0
  87. recip_slice-0.4.1/tests/test_calibration.py +159 -0
  88. recip_slice-0.4.1/tests/test_cli.py +245 -0
  89. recip_slice-0.4.1/tests/test_comparison.py +185 -0
  90. recip_slice-0.4.1/tests/test_coverage_semantics.py +133 -0
  91. recip_slice-0.4.1/tests/test_custom_planes.py +156 -0
  92. recip_slice-0.4.1/tests/test_dataset.py +134 -0
  93. recip_slice-0.4.1/tests/test_frame_preview.py +50 -0
  94. recip_slice-0.4.1/tests/test_gui_optional.py +1290 -0
  95. recip_slice-0.4.1/tests/test_job_queue.py +111 -0
  96. recip_slice-0.4.1/tests/test_measurements.py +156 -0
  97. recip_slice-0.4.1/tests/test_packaging.py +89 -0
  98. recip_slice-0.4.1/tests/test_preflight.py +138 -0
  99. recip_slice-0.4.1/tests/test_project.py +85 -0
  100. recip_slice-0.4.1/tests/test_project_cycle.py +111 -0
  101. recip_slice-0.4.1/tests/test_reconstruction.py +1009 -0
  102. recip_slice-0.4.1/tests/test_result_management.py +131 -0
  103. recip_slice-0.4.1/tests/test_results.py +310 -0
  104. recip_slice-0.4.1/tests/test_settings.py +70 -0
  105. recip_slice-0.4.1/tests/test_spot_validation.py +48 -0
  106. recip_slice-0.4.1/tests/test_workflow.py +138 -0
  107. recip_slice-0.4.1/tests/test_xds_plan.py +302 -0
  108. recip_slice-0.4.1/tools/project_cycle.py +678 -0
@@ -0,0 +1,178 @@
1
+ # Agent starting guide
2
+
3
+ This file is the starting point for coding agents working in this repository.
4
+ Read it before changing code, then read the documentation relevant to the
5
+ requested feature.
6
+
7
+ ## Start here
8
+
9
+ 1. Read `README.md` for the product and scientific scope.
10
+ 2. Read `docs/architecture.md` before moving responsibilities between modules.
11
+ 3. Read `docs/algorithm.md` before changing geometry, sampling, accumulation,
12
+ coverage, or detector processing.
13
+ 4. Read `docs/gui.md` before changing Qt behaviour or terminology.
14
+ 5. Read `docs/roadmap.md` for feature order and acceptance criteria.
15
+ 6. Read `docs/reproducibility.md` before changing manifests, reports, or saved
16
+ numerical products.
17
+
18
+ ## Canonical source and repository map
19
+
20
+ - `src/recip_slice/core/`: dataset discovery, settings, geometry, calibration,
21
+ validation, preflight, and workflow requests.
22
+ - `src/recip_slice/reconstruction/`: numerical reconstruction, native/fallback
23
+ accumulation, result manifests, and result loading.
24
+ - `src/recip_slice/gui/`: Qt layout, state, interactions, process management,
25
+ comparison, display, and canvas code.
26
+ - `src/recip_slice/compat/`: legacy import compatibility only.
27
+ - `tests/`: unit, integration, packaging, and optional headless GUI tests.
28
+ - `tools/project_cycle.py`: canonical compile/test/lint/type-check/build cycle.
29
+
30
+ Only edit the canonical files under `src/`, `tests/`, `docs/`, and repository
31
+ root. Never implement changes in generated `build/lib.*`, `dist/`,
32
+ `*.egg-info`, caches, wheelhouse output, or compiled `.pyd`/`.so` files.
33
+
34
+ ## Scientific invariants
35
+
36
+ - Detector images and XDS inputs are read-only.
37
+ - Display controls never mutate or rewrite saved arrays.
38
+ - `mean` is `sum / signal_coverage`; do not redefine coverage semantics.
39
+ - `geometry_coverage` is independent of intensity thresholding;
40
+ `signal_coverage` represents retained samples. The legacy `coverage` name is
41
+ a readable compatibility alias, not a new product.
42
+ - XDS frame exclusions, region/pixel masks, and detector distortion remain
43
+ explicit opt-ins and must be recorded in the manifest.
44
+ - Do not silently resample, register, normalize, interpolate, fill, mask, or
45
+ correct scientific data. Such operations require an explicit user choice and
46
+ provenance in a derived result.
47
+ - CLI and GUI reconstruction must use the same core settings and output-path
48
+ resolution.
49
+ - The GUI launches reconstruction through the installed module and keeps
50
+ numerical work outside the Qt event loop.
51
+ - Manifest paths stay within the result directory. NumPy loading uses
52
+ `allow_pickle=False`; axes, shapes, units, and manifest versions are
53
+ validated.
54
+ - Existing manifests and legacy three-axis results remain readable unless a
55
+ compatibility change is explicitly approved and documented.
56
+ - Geometry or accumulation changes require focused numerical tests. Preserve
57
+ deterministic frame order and verify native and NumPy-fallback semantics.
58
+
59
+ ## Cross-platform contract
60
+
61
+ The required interactive targets are native Linux, native Windows, and WSL.
62
+ WSL is a separate integration target because the Python process is Linux while
63
+ the visible desktop, clipboard, and file manager may belong to Windows.
64
+
65
+ ### General rules
66
+
67
+ - Use `pathlib.Path` for filesystem paths and `os.pathsep` for path lists.
68
+ - Do not parse paths by splitting on `/` or `\\`, and do not assume drive
69
+ letters, a home-directory layout, case sensitivity, or a particular mount
70
+ point.
71
+ - Paths with spaces and Unicode must work in dialogs, manifests, subprocesses,
72
+ exports, drag-and-drop, and project files.
73
+ - Use `sys.executable` for child Python processes.
74
+ - Pass subprocess arguments as a list. Do not build shell command strings or
75
+ rely on Bash, PowerShell, `cmd.exe`, `xdg-open`, or `explorer.exe` in shared
76
+ code.
77
+ - Prefer Qt abstractions such as `QFileDialog`, `QUrl.fromLocalFile`,
78
+ `QDesktopServices`, `QClipboard`, and `QStandardPaths` for desktop behaviour.
79
+ - When Qt does not cover a WSL host integration, isolate it in a small helper,
80
+ detect the required executable/capability, bound subprocess timeouts, and
81
+ retain a Linux-side fallback.
82
+ - Extend the existing WSL detection and clipboard bridge rather than creating
83
+ duplicate platform checks in unrelated widgets.
84
+ - Use explicit UTF-8 for project, report, manifest, and settings text files.
85
+ - Never write into the installed package directory at runtime. Use a selected
86
+ project/result directory, Qt standard writable location, or a temporary
87
+ directory as appropriate.
88
+
89
+ ### GUI rules
90
+
91
+ - Keep long work in a `QProcess`, worker thread, or pure background task; never
92
+ block the Qt event loop.
93
+ - Any platform-specific dialog or integration failure must leave scientific
94
+ reconstruction and saved results usable.
95
+ - Verify layouts at the current minimum window size and with normal Linux and
96
+ Windows font metrics.
97
+ - Important actions must have a visible entry point. Context menus and
98
+ shortcuts may duplicate an action but must not be its only discovery path.
99
+ - Cross-platform feature code should expose pure helpers so platform branches
100
+ can be tested without launching a real desktop session.
101
+
102
+ ### Native extension rules
103
+
104
+ - `RECIP_SLICE_NATIVE=auto` may fall back to NumPy for source installs.
105
+ - Release/performance validation uses `RECIP_SLICE_NATIVE=require`.
106
+ - Never make the compiled backend scientifically different from the fallback.
107
+ - Do not commit locally generated binaries. Change the `.pyx`, generated C
108
+ source when required by the project workflow, and Python fallback together.
109
+
110
+ ## Implementation workflow
111
+
112
+ 1. Inspect the working tree and preserve unrelated user changes.
113
+ 2. Identify the owning module; avoid adding more responsibility to
114
+ `gui/window.py`, which is the constructor/style facade over focused mixins.
115
+ 3. Put scientific and serialization logic in pure core/reconstruction helpers;
116
+ keep Qt code responsible for interaction and presentation.
117
+ 4. Write or update focused tests with the implementation.
118
+ 5. Update user documentation, the roadmap status, and `CHANGELOG.md` when
119
+ behaviour changes.
120
+ 6. Run the smallest relevant tests, then the repository check before handoff.
121
+
122
+ Do not add a second implementation merely to handle another operating system.
123
+ Prefer one shared path plus a narrow capability adapter when host integration
124
+ really differs.
125
+
126
+ ## Verification
127
+
128
+ Install development dependencies into the configured project environment, not
129
+ the system Python:
130
+
131
+ ```text
132
+ python -m pip install -e ".[dev]"
133
+ ```
134
+
135
+ Run focused tests during development. For GUI work, run the optional GUI module
136
+ headlessly with `QT_QPA_PLATFORM=offscreen`; use shell-appropriate environment
137
+ syntax rather than embedding it in application code.
138
+
139
+ Linux/WSL example:
140
+
141
+ ```bash
142
+ QT_QPA_PLATFORM=offscreen MPLBACKEND=Qt5Agg \
143
+ python -m pytest -q tests/test_gui_optional.py
144
+ ```
145
+
146
+ Windows PowerShell example:
147
+
148
+ ```powershell
149
+ $env:QT_QPA_PLATFORM = "offscreen"
150
+ $env:MPLBACKEND = "Qt5Agg"
151
+ python -m pytest -q tests/test_gui_optional.py
152
+ ```
153
+
154
+ Before handoff, run:
155
+
156
+ ```text
157
+ python tools/project_cycle.py check
158
+ ```
159
+
160
+ Platform-specific behaviour also requires unit tests that simulate each branch
161
+ and a manual smoke check on native Linux, native Windows, and WSL. The smoke
162
+ check should cover clean launch, a path containing spaces/Unicode, dataset
163
+ selection, process start/cancel, result opening, clipboard/export, comparison,
164
+ and any new host integration.
165
+
166
+ ## Roadmap feature checklist
167
+
168
+ Before marking a roadmap item complete, confirm:
169
+
170
+ - the user-facing entry point is discoverable;
171
+ - cancellation and error recovery are defined;
172
+ - source data and existing results cannot be modified accidentally;
173
+ - provenance and versioning are defined for new derived data;
174
+ - tests cover normal, invalid, empty, and backward-compatible cases;
175
+ - Linux, Windows, and WSL behaviour satisfies `docs/roadmap.md`;
176
+ - relevant docs and `CHANGELOG.md` are updated;
177
+ - the full project check passes.
178
+
@@ -0,0 +1,212 @@
1
+ # Changelog
2
+
3
+ ## 0.4.1 - 2026-08-25
4
+
5
+ - Replace the point-only placeholder with the quiet, optional **Tools →
6
+ Analysis…** utility. Drawing now creates an editable draft with draggable
7
+ handles, whole-shape movement, four-corner rectangle resizing, live results,
8
+ saved-grid Arrow-key nudging, explicit Apply/Cancel, and temporary guides only
9
+ while the utility is open.
10
+ - Add **Edit selected** and row double-click editing so applied points, profiles,
11
+ and regions can be corrected and replaced in place without duplicate records.
12
+ - Add saved-grid line profiles, rectangle/circle region integration, optional
13
+ explicit local-median background, coverage-aware raw/net/mean/max summaries,
14
+ a distance-versus-net-signal profile plot, exact-grid A/B results, project
15
+ persistence, and unified CSV/JSON export.
16
+ - Keep 0.4.0 point-record JSON readable and explicitly defer full 3D reflection
17
+ integration, shoebox modelling, and rocking-curve/profile fitting across
18
+ frames.
19
+ - Add a cross-platform ASCII welcome banner to interactive GUI command-window
20
+ launches without adding output to reconstruction, preflight, or JSON reports.
21
+ - Housekeep generated checkout artefacts through recoverable quarantine,
22
+ include `wheelhouse/` in that inventory, and enforce Ruff formatting in the
23
+ project maintenance cycle.
24
+
25
+ ## 0.4.0 - 2026-08-21
26
+
27
+ - Keep the dataset browser responsive by avoiding path resolution and full
28
+ result-manifest validation while building its saved-result hints, removing
29
+ unnecessary WSL-mounted-drive metadata I/O.
30
+ - Fix detector preview's undefined status-text callback; make frame and plane
31
+ selectors and brightness/contrast values directly editable; default the
32
+ black point to Auto; preserve the selected zoom/ROI when Grid or Axes is
33
+ toggled; hide the empty measurement count until a pin exists; and add a
34
+ visible frame-position slider. Compact saved-result entries now show the
35
+ run subfolder and plane count.
36
+ - Fix detector-frame preview startup by importing its popup combo widget. Make
37
+ measurement capture explicit: the Measurements window is modeless, and pins
38
+ and canvas markers are enabled only while that window is open.
39
+ - Simplify the Qt workspace around the frequent dataset, reconstruction,
40
+ run/open, and viewer actions. Move projects, preflight, result management,
41
+ batch/queue commands, comparison utilities, process-log controls, and help
42
+ into synchronized File/Tools/View/Help menus while retaining every existing
43
+ workflow and cancellation path.
44
+ - Shorten visible guidance and tooltips to compact action-oriented text; detailed
45
+ diagnostics remain available in the log, status bar, and Help.
46
+ - Restore the existing-result choice between rewriting and saving a new version;
47
+ rewrites validate the new run before deleting the selected old run, and the
48
+ result browser now shows informative run-folder names and planes.
49
+ - Begin Milestone 4.1 persistent local job queue: add versioned atomic queue
50
+ storage with immutable settings snapshots for single, batch, comparison, and
51
+ export jobs; visible queue/run/retry/cancel/remove actions; and restart
52
+ recovery that requires a validated checkpoint before resuming, otherwise
53
+ allocating a clean timestamped reconstruction run.
54
+ - Begin Milestone 3.4 raw-frame preview and richer preflight: add a visible
55
+ read-only detector-frame preview with deterministic XDS-policy selection,
56
+ display-only scaling, source/frame statistics, and the shared structured
57
+ preflight report used by the CLI.
58
+ - Begin Milestone 3.3 result management: add versioned sidecar metadata for
59
+ display names, tags, notes, favourites, archive state, and version labels;
60
+ add collision-safe result duplication and exact-target moves to recoverable
61
+ hidden trash without renaming scientific manifest members.
62
+ - Begin Milestone 3.2 project/session persistence: add a versioned JSON format
63
+ with portable dataset/result path references, explicit Open project… and
64
+ Save project… actions, restoration of reconstruction/comparison/display/zoom
65
+ state, validated measurement round-tripping, and missing-dataset relinking.
66
+ - Begin Milestone 3.1 explicit comparison alignment: add a pure derived
67
+ comparison workflow with nearest/linear interpolation, A-grid targeting,
68
+ finite-overlap masks, mean/median normalization, optional q translation,
69
+ collision-safe persistence, source manifest identities, and a visible GUI
70
+ Regrid… action for mismatched grids.
71
+ - Add a prioritized development roadmap and an agent starting guide with
72
+ scientific invariants and a native Linux, native Windows, and WSL definition
73
+ of done for future features. Milestone 0 records the GUI control audit and
74
+ makes result identity, drop-down validity, comparison export, process state,
75
+ and cross-platform integration hardening the first development work.
76
+ - Implement Milestone 0 GUI hardening: exact timestamped-run identity, truthful
77
+ product/result/preset selectors, provenance-safe quality details, guarded
78
+ comparison export and modes, dataset reset state, and accurate batch-cancel
79
+ wording. Add headless GUI regressions for legacy/modern/incomplete results,
80
+ WSL detection, and clipboard fallback discovery.
81
+ - Implement the Milestone 1 interaction tier: visible offline Help and a
82
+ clearly labelled in-memory synthetic demo, XDS-aware folder guidance,
83
+ drag-and-drop loading through normal recursive discovery, Qt-native result
84
+ folder/manifest actions with WSL fallback, and viewer-header Export/Image
85
+ actions plus a visible batch-run action. Add headless tests for first-run
86
+ discoverability, Unicode/space-safe drop paths, and result path actions.
87
+ - Begin Milestone 2 analysis tooling: click-to-pin reciprocal-space
88
+ measurements with provenance and optional A/B intensity, labelled marker
89
+ management, CSV/JSON export, two-pin geometry, and pure deterministic
90
+ profile/rectangle/circle ROI summaries with headless GUI and numerical tests.
91
+ - Add the first Milestone 2.3 custom-plane slice: validated Miller-index
92
+ normals, optional hkl offsets and in-plane bases/references, shared CLI and
93
+ workflow arguments, and manifest/result-loader provenance for the resolved
94
+ Cartesian plane definition and sampling units. The guided GUI layer builder
95
+ is still pending.
96
+
97
+ ## 0.3.3 - 2026-08-20
98
+
99
+ ### Cold one-shot GUI workload refinement
100
+
101
+ - Optimise fresh-process reconstruction for the GUI's three recommended plane
102
+ presets: Principal 3, Layers 0–3 (12 planes), and All (20 planes).
103
+ - Add a native four-layer parallel-family accumulator so hk0–hk3, h0l–h3l,
104
+ and 0kl–3kl share reciprocal screening/projection work while retaining
105
+ independent per-plane outputs and frame-order accumulation.
106
+ - Pipeline next-frame screening against GIL-free native plane-family work and
107
+ keep the CMOS cleanup/plane worker split bounded by the effective CPU quota.
108
+ - Read standard uncompressed SMV detector frames directly after validating the
109
+ first header, retaining the existing Fabio path for unsupported formats.
110
+ - Add exact native radius-3 uint16 CMOS halo opening, grouped/row float32
111
+ quantiles, sparse zero-quantile proofs, and an in-place uint16 mixed-mode
112
+ blend. Keep NumPy/SciPy fallbacks for compiler-free and unusual-input paths.
113
+ - Preserve float32 CMOS residuals when the radial background is proved exactly
114
+ zero and perform the regular column correction in place to avoid unnecessary
115
+ detector-sized copies.
116
+ - Reject a cache-unfriendly strided native column-quantile experiment after it
117
+ slowed the real-data benchmark despite exact numerical agreement.
118
+
119
+ ## 0.3.2 - 2026-08-20
120
+
121
+ ### Twelve-plane reconstruction performance
122
+
123
+ - Fuse sparse hard-slab testing, reciprocal projection, bilinear indexing, and
124
+ accumulation into the optional native kernel while retaining the NumPy
125
+ implementation as a source-install fallback.
126
+ - Run independent reciprocal-plane families concurrently only when the fused
127
+ native kernel is available; preserve serial ordering within every plane.
128
+ - Enable the exact temporal reciprocal-distance guard by default for four or
129
+ more hard planes, use an automatic refresh cadence of 20 frames with the
130
+ fused kernel (8 for the NumPy fallback), use up to eight ordered
131
+ prefetch/cleanup workers based on detected CPUs, and default
132
+ BLAS libraries to one thread to avoid oversubscription.
133
+ - Reuse radial sampling-diagnostic geometry across parallel translated planes
134
+ and defer plotting imports when plots are disabled.
135
+ - Route CMOS robust/mixed noise cancellation through sparse plane selection,
136
+ pipeline detector cleanup through ordered frame-prefetch workers, and use
137
+ direct partition-based linear quantiles for finite radial detector shells.
138
+ - Record fused-kernel, family-parallel, temporal-guard, and parallel-CMOS usage
139
+ in reconstruction manifests.
140
+
141
+ ## 0.3.1 - 2026-08-19
142
+
143
+ ### Native sparse accumulator and release alignment
144
+
145
+ - Keep the real-data validated serial sparse plane architecture; do not use the
146
+ rejected asynchronous per-plane accumulation executors.
147
+ - Integrate the exact-order generated-C bilinear accumulator into normal
148
+ setuptools builds while retaining the scientifically equivalent NumPy-serial
149
+ fallback.
150
+ - Add explicit `RECIP_SLICE_NATIVE=auto|require|disable` build policy. Release
151
+ wheel jobs require the native extension so a slow fallback wheel cannot be
152
+ published accidentally.
153
+ - Add cross-platform wheel CI for Linux, Windows, and macOS from one source
154
+ tree; binary wheels are platform-specific but the source distribution is
155
+ shared.
156
+ - Record/report the active sparse accumulator backend in verbose output and
157
+ manifests.
158
+ - Preserve temporal plane candidate caching as opt-in and disabled by default.
159
+ - Reject the later family/phi screening experiment from the release baseline: it
160
+ was numerically exact but measured 14.07 s on the real 12-plane WSL workload
161
+ versus 14.01 s for native serial, with higher peak RSS.
162
+
163
+
164
+ - Raw-pixel reconstruction is now the default: XDS excluded frames, XDS
165
+ region/pixel masks, and detector distortion correction require explicit
166
+ opt-in flags or GUI controls.
167
+ - Added a single version source, an XDS-template/DATA_RANGE dataset plan,
168
+ structured scientific preflight, explicit geometry/signal coverage products,
169
+ shared reconstruction defaults, supported XDS spatial/trusted-pixel
170
+ calibration, and independent `SPOT.XDS` validation infrastructure.
171
+ - Modern physical manifests are schema v2 with input hashes, frame-selection
172
+ provenance, calibration/mask records, and an explicit deprecated alias for
173
+ the historical signal `coverage` product. Added isolated wheel/sdist smoke
174
+ tests and the `preflight` CLI audit command.
175
+ - Preflight now compares XDS QX/QY against the parser's refined pixel-size
176
+ fields, manual globs use template-first frame numbering and reject ambiguous
177
+ filenames, completeness is explicit for raw versus exclusion-enabled modes,
178
+ and manifests include detector-rejection and per-plane sampling diagnostics.
179
+ - The optional SPOT.XDS checker now reports total/indexed/unindexed counts and
180
+ excludes `(0, 0, 0)` unindexed records from residual statistics.
181
+ - Hardened the production cycle so checks always exercise the current checkout
182
+ even when an older globally installed package is present. CI now builds and
183
+ smoke-tests isolated wheel and source-distribution artefacts, including the
184
+ packaged stylesheet and icons.
185
+ - Added recent-project reopening, a searchable indexed-dataset browser, explicit named reconstruction presets, and persistent display/workspace state.
186
+ - Added safe result versioning so existing reconstructions are never replaced silently, plus a saved-run selector, provenance and quality summaries, and Markdown/JSON run-report export.
187
+ - Added an A/B comparison workspace that selects a separate indexed XDS dataset (with optional folder browsing), auto-loads the newest compatible result, offers current-settings slicing when B has no saved slice, and reports cancellable B progress. Added independent plane/product selection, synchronized pan and zoom, blink, exact-grid difference and ratio modes, direct hover intensity comparison, and comparison export.
188
+ - Extended v1 manifests with backward-compatible run provenance and per-plane quality statistics; legacy manifests and arrays remain supported.
189
+ - Redesigned the Qt workspace around numbered Data, Planes, and Settings steps with a direct expert path. Added recursive folder-mode indexing, instant dataset switching (including keyboard navigation), and collapsed optional Appearance controls so the reciprocal-space image receives most of the window.
190
+ - Expanded the two-line image hover readout with raw intensity and unit-cell-aware real `d` spacing, including the selected plane offset; suppressed Matplotlib's duplicate third value line.
191
+ - Added a right-click image context menu with rendered-image clipboard copying, nearest hkl-coordinate copying, direct 600 dpi export, view-range shortcuts, overlay toggles, and display reset. Added unit-cell context-menu copying, explicit PNG clipboard data for broader application compatibility, and a Windows clipboard bridge for WSL launches.
192
+ - Added polished contrast-aware RGB arrows with an independent GUI **Axes** toggle. Arrow heads, shafts, labels, and endpoint markers now scale with the on-screen reciprocal-grid interval; heavier fifth grid lines, fractional hkl cursor coordinates, and a GUI summary of the unit-cell lengths and angles are included.
193
+ - Added a **Custom / Axes RGB** grid-colour mode; Axes RGB colours the two lattice-line families to match their reciprocal-axis arrows.
194
+ - Restored the independent **Axes** a*/b*/c* arrow/marker overlay; it no longer turns on automatically with the lattice grid.
195
+ - Added six per-pane colour-map choices (Black on white, White on black, Viridis, Inferno, Cividis, and Coolwarm). q-axis labels/ticks are hidden by default and are available only from the canvas context menu.
196
+ - Reduced viewer lag by avoiding redundant A-pane redraws for B-only appearance changes, disconnecting stale A/B limit callbacks before figure rebuilds, and throttling high-frequency comparison hover status updates.
197
+ - Made saved-result opening lazy with NumPy memory mapping; non-finite edge padding is trimmed only when a plane is first displayed, and the optional quality scan runs only when **Quality** is opened.
198
+ - Reconstruction outputs now discard zero-coverage outer q-grid margins before saving, including matching q axes and compact per-plane shapes, while retaining the requested full q-range in the manifest.
199
+ - Stabilised combo-box popups so menus remain attached to their controls and stay fully visible near screen edges, and reorganised image adjustment controls into clear level, overlay, and export sections.
200
+ - Changed the GUI q-pixel control to a human-readable reciprocal-pixel ratio, defaulting to `1.0 ×`; reconstruction still receives the converted physical Å⁻¹ spacing.
201
+
202
+ ## 0.1.0
203
+
204
+ - Converted the loose script collection into an installable `src`-layout package.
205
+ - Separated dataset discovery, result validation, workflow configuration, CLI, viewers, and numerical reconstruction.
206
+ - Added stable `recip-slice reconstruct`, `view`, and `gui` entry points.
207
+ - Replaced GUI source-file execution with module-based subprocess execution.
208
+ - Redesigned the Qt workspace around dataset/run and plane-selection tabs with a larger dedicated viewer.
209
+ - Added reconstruction grid and memory estimates, explicit status states, keyboard shortcuts, and improved process error handling.
210
+ - Added strict manifest path, shape, axis, and format validation.
211
+ - Made Qt tests optional rather than failing test discovery when PyQt5 is absent.
212
+ - Added scientific-scope, algorithm, architecture, and reproducibility documentation.
@@ -0,0 +1,65 @@
1
+ # Contributing
2
+
3
+ Start with [AGENTS.md](AGENTS.md) for repository invariants and the
4
+ Linux/Windows/WSL development contract. Planned product work and its acceptance
5
+ criteria are tracked in [docs/roadmap.md](docs/roadmap.md).
6
+
7
+ Use Python 3.10 or newer. Install the development environment with:
8
+
9
+ ```bash
10
+ python -m pip install -e '.[gui,dev]'
11
+ ```
12
+
13
+ Before submitting changes, run:
14
+
15
+ ```bash
16
+ python tools/project_cycle.py check
17
+ ```
18
+
19
+ For a local release-candidate source check, run:
20
+
21
+ ```bash
22
+ python tools/project_cycle.py check
23
+ python tools/project_cycle.py clean --apply
24
+ ```
25
+
26
+ The local check validates the source layout, compiles the project, runs the test
27
+ suite, and checks Ruff and mypy across every Python file. Generated checkout
28
+ artefacts can be removed with `clean --apply`; the move is recoverable from the
29
+ timestamped `.project_housekeeping_trash` directory.
30
+
31
+ GitLab CI is a validation gate only; it runs the full source test cycle and
32
+ does not build or upload release artefacts. Release wheels are built locally
33
+ with `cibuildwheel`. The `cp310` through `cp314` selection in `pyproject.toml`
34
+ produces one tested wheel per supported Python ABI.
35
+
36
+ On Windows, use a native MSVC developer shell and run:
37
+
38
+ ```powershell
39
+ conda create -n recip-wheel-win python=3.12 pip -y
40
+ conda activate recip-wheel-win
41
+ python -m pip install --upgrade pip build twine cibuildwheel==4.2.0
42
+ $env:RECIP_SLICE_NATIVE = "require"
43
+ $env:CIBW_ARCHS_WINDOWS = "AMD64"
44
+ python -m cibuildwheel --platform windows --output-dir wheelhouse/windows .
45
+ ```
46
+
47
+ In WSL, install and start [Docker Desktop with WSL 2 integration](https://docs.docker.com/desktop/features/wsl/)
48
+ or install Podman before running the Linux build. Then run:
49
+
50
+ ```bash
51
+ conda create -n recip-wheel-linux python=3.12 pip -y
52
+ conda activate recip-wheel-linux
53
+ python -m pip install --upgrade pip build twine cibuildwheel==4.2.0
54
+ export RECIP_SLICE_NATIVE=require
55
+ export CIBW_ARCHS_LINUX=x86_64
56
+ python -m cibuildwheel --platform linux --output-dir wheelhouse/linux .
57
+ ```
58
+
59
+ Build the single source distribution once with `python -m build --sdist --outdir wheelhouse`, then
60
+ run `python -m twine check` over the complete `wheelhouse` before uploading.
61
+
62
+ The optional macOS job remains available as a validation job. It is disabled by
63
+ default with `ENABLE_MACOS_CI=false`.
64
+
65
+ Changes to reciprocal-space geometry should include a focused numerical test. Changes to result files must preserve backward loading of legacy three-axis arrays unless the compatibility policy is changed explicitly.
@@ -0,0 +1,7 @@
1
+ include README.md CHANGELOG.md CONTRIBUTING.md AGENTS.md pyproject.toml setup.py run.py
2
+ recursive-include docs *.md *.png
3
+ recursive-include tools *.py
4
+ recursive-include src/recip_slice *.qss *.svg
5
+
6
+ include src/recip_slice/reconstruction/_accum_ext.c
7
+ include src/recip_slice/reconstruction/_accum_ext.pyx