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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes are recorded here. The project follows semantic versioning a

## [Unreleased]

### Added

- Windows launchers: `启动DiffractScout.bat` (GUI) and `quick_export_diffractscout.bat` (drag-and-drop quick-export with Excel next to the first input).
- Packaging stub `scripts/package_windows_portable.py` documenting a future PyInstaller portable layout (`--help` / `--print-recipe`; no freeze yet).
- Optional dependencies `figures` (matplotlib) and `gui-dnd` (tkinterdnd2); `paper` remains as a matplotlib alias.
- Console entry point `diffractscout-quick-export` and GUI entry point `diffractscout-gui` documented alongside `diffractscout`.
- Documentation for CIF2Peaks parity features (lab Excel views, *d*-range filters, bilingual lab sheets, quick-export, figures) in README / README.zh-CN, GUI controls in `docs/GUI.md`, and module mapping in `docs/SOURCE_LINEAGE.md`.

### Notes

- Awaiting the first public GitHub release, archived software DOI, and external validation cases.

## [0.3.0] - 2026-08-12
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include pyproject.toml MANIFEST.in
include README.md README.zh-CN.md LICENSE NOTICE.md AUTHORS.md CITATION.cff CHANGELOG.md
include CONTRIBUTING.md CODE_OF_CONDUCT.md SECURITY.md GOVERNANCE.md SUPPORT.md ROADMAP.md
include 启动DiffractScout.bat quick_export_diffractscout.bat
recursive-include docs *.md *.svg *.png *.json
recursive-include paper *.md *.bib *.svg *.png *.sh *.py
recursive-include examples *.cif *.json *.md
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ diffractscout-gui

The desktop interface exposes the scientific controls used by the Python API: radiation definition, angular window, profile spacing, pseudo-Voigt parameters, elastic-tensor pairing, candidate limits, reciprocal-space resource guards, overwrite authorization, progress, structured diagnostics, and result-folder access. The API key remains in memory and is not written to project files. See [docs/GUI.md](docs/GUI.md).

On Windows, double-click `启动DiffractScout.bat` after an editable install, or drag CIF files onto `quick_export_diffractscout.bat` for a one-shot lab export.

## CIF2Peaks parity features

DiffractScout reimplements the CIF2Peaks desktop workflow inside a provenance-first package (Gemmi engine; not bit-identical intensities). Practical parity includes:

| Capability | Where |
|---|---|
| Laboratory Excel views (Chinese beginner peak table + usage guide sheets) | `export_lab_views` / CLI `--no-lab-views` to disable |
| Optional *d*-spacing window (intersects the 2θ search) | CLI/API `--d-min` / `--d-max` |
| Bilingual lab-facing tables with English canonical CSV/XLSX | Excel `推荐峰表` / `使用说明` plus English `Peaks` |
| One-shot quick export (Cu Kα lab defaults, optional `.xlsx` shortcut) | `diffractscout-quick-export`, `diffractscout quick-export`, Windows drag-drop bat |
| Optional figure generation request | CLI `--figures` / `.[figures]` (matplotlib) |

Column-name mapping and intensity-channel aliases: [docs/SCHEMA_ALIASES.md](docs/SCHEMA_ALIASES.md). Engine semantics vs CIF2Peaks/pymatgen: [docs/ENGINE_PARITY.md](docs/ENGINE_PARITY.md).

## Installation

### Local CIF analysis
Expand All @@ -58,6 +74,14 @@ python -m pip install -e ".[mp]"
export MP_API_KEY="your-key" # PowerShell: $env:MP_API_KEY = "your-key"
```

### Optional extras

```bash
python -m pip install -e ".[figures]" # matplotlib for figure request / paper figures
python -m pip install -e ".[gui-dnd]" # optional Tk drag-and-drop helper (future UX)
python -m pip install -e ".[mp]" # Materials Project
```

### Development environment

```bash
Expand Down
26 changes: 25 additions & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,23 @@ diffractscout-gui
<img src="docs/assets/gui-materials-project.png" width="49%" alt="DiffractScout Materials Project 流程界面">
</p>

界面提供:CIF 文件与文件夹批量选择、递归扫描、光源/能量/波长、`2θ` 范围、步长、FWHM、伪 Voigt 混合参数、弹性配对、候选相数量上限、倒易空间资源限制、覆盖授权、运行状态、结构化日志和结果目录入口。API 密钥只保存在当前进程内存中,不写入项目文件。
界面提供:CIF 文件与文件夹批量选择、递归扫描、光源/能量/波长、`2θ` 范围、步长、FWHM、伪 Voigt 混合参数、弹性配对、候选相数量上限、倒易空间资源限制、覆盖授权、运行状态、结构化日志和结果目录入口。API 密钥只保存在当前进程内存中,不写入项目文件。详见 [docs/GUI.md](docs/GUI.md)。

Windows 下可在可编辑安装后双击 `启动DiffractScout.bat` 启动界面;或将 CIF 拖到 `quick_export_diffractscout.bat` 进行一次实验室默认导出。

## 已吸收 CIF2Peaks 桌面能力

DiffractScout 在可追溯结果包中重实现了 CIF2Peaks 的主要桌面工作流(离线引擎为 Gemmi,强度为语义对齐而非逐字节一致):

| 能力 | 入口 |
|---|---|
| 实验室 Excel 视图(中文推荐峰表 + 使用说明) | `export_lab_views`;CLI `--no-lab-views` 可关闭 |
| *d* 间距过滤窗口(与 2θ 搜索求交) | CLI/API `--d-min` / `--d-max` |
| 中英双语:中文实验室表 + 英文规范列名 CSV/XLSX | 工作簿 `推荐峰表` / `使用说明` 与 `Peaks` |
| 一键快速导出(Cu Kα 实验室默认,可选 `.xlsx` 快捷路径) | `diffractscout-quick-export`、`diffractscout quick-export`、Windows 拖放 bat |
| 可选图件生成请求 | CLI `--figures` / 可选依赖 `.[figures]` |

列名与强度通道别名见 [docs/SCHEMA_ALIASES.md](docs/SCHEMA_ALIASES.md);与 CIF2Peaks/pymatgen 引擎差异见 [docs/ENGINE_PARITY.md](docs/ENGINE_PARITY.md)。

## 安装

Expand All @@ -48,6 +64,14 @@ Materials Project 支持:
python -m pip install -e ".[mp]"
```

可选依赖:

```bash
python -m pip install -e ".[figures]" # matplotlib(图件请求 / 论文图)
python -m pip install -e ".[gui-dnd]" # 可选 Tk 拖放辅助(后续 UX)
python -m pip install -e ".[mp]" # Materials Project
```

开发与测试:

```bash
Expand Down
99 changes: 99 additions & 0 deletions docs/ENGINE_PARITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Diffraction engine parity: Gemmi vs CIF2Peaks (pymatgen)

DiffractScout’s offline powder engine is built on **Gemmi**. CIF2Peaks used
**pymatgen** `XRDCalculator` for theoretical powder lines. The two implementations
are designed for **workflow parity**, not bit-identical intensities.

## What “workflow parity” means

Both tools aim to produce, from a structure-bearing CIF and an X-ray wavelength:

1. indexed reflections with Miller indices, \(d\), \(\theta\), \(2\theta\), \(q\), \(g\);
2. structure-factor-related intensities with and without a laboratory-style
Lorentz–polarization (LP) factor;
3. phase-internal relative intensities (strongest line scaled to 100);
4. volume-normalized intensity channels
\(J = I / V_{\mathrm{cell}}^2\) (legacy names still contain `R_hkl`);
5. optional plane-normal Young’s modulus when a valid \(C_{ij}\) is paired;
6. a continuous pseudo-Voigt display profile for plotting.

Users can move the same scientific questions—candidate peaks, LP vs no-LP
channels, elasticity on `hkl` normals—between the two codebases with the column
aliases in [`SCHEMA_ALIASES.md`](SCHEMA_ALIASES.md).

## What is **not** guaranteed

| Quantity | Expectation |
|---|---|
| Absolute \(I\) or \(J\) values | May differ between Gemmi and pymatgen |
| Peak-by-peak intensity ordering near ties | May swap when values are close |
| Multiplicity of a given representative | Same physical idea; counting of symmetry/Friedel mates can differ in edge cases |
| Representative `hkl` of a family | Both pick a deterministic member; the choice rule may differ |
| Multi-family coincidence at one \(2\theta\) | CIF2Peaks could merge pymatgen families into one peak row; DiffractScout emits one row per unique family |
| Floating-point \(2\theta\), \(d\), \(q\) | Agree to crystallographic precision for clean cells; not bit-identical |

Do **not** use bit-identical intensity regression between CIF2Peaks exports and
DiffractScout as a release gate. Prefer analytic structure-factor checks (e.g.
monoatomic FCC \(\lvert F_{111}\rvert^2\)), space-group absences, and internal
invariants (\(J = I / V^2\), LP ratio consistency).

## Architectural differences

| Topic | CIF2Peaks (pymatgen) | DiffractScout (Gemmi) |
|---|---|---|
| Structure I/O | pymatgen structure from CIF | Gemmi small structure; dedicated occupancy conversion for SF |
| Powder intensities | `XRDCalculator.get_pattern(scaled=False)` | Enumerate Miller candidates, absences, \(\lvert F\rvert^2\), multiplicity, LP |
| Atomic form factors / SF | pymatgen calculator defaults | Gemmi `StructureFactorCalculatorX` |
| Debye–Waller | Assumed 1 when absent | Same practical boundary; missing \(B\) not invented |
| LP factor | Same laboratory-style form \((1+\cos^2 2\theta)/(\sin^2\theta\cos\theta)\) | Same formula in `diffraction.py` |
| Volume-normalized \(J\) | `I_unscaled / V^2` and `(I_unscaled/LP)/V^2` | `I_with_LP / V^2` and `I_no_LP / V^2` |
| Offline base install | Required pymatgen for local XRD | Core analysis uses Gemmi; pymatgen optional via mp-api |
| Provenance | Export notes | SHA-256 inputs, manifest, scientific boundary string |

## Intensity channel correspondence

Conceptually:

```text
I_with_LP ≈ theoretical_intensity_unscaled (CIF2Peaks)
I_no_LP ≈ multiplicity_structure_factor_sq (CIF2Peaks)
J_with_LP = I_with_LP / V_cell^2 ↔ material_scattering_factor_R_hkl
J_no_LP = I_no_LP / V_cell^2 ↔ material_scattering_factor_R_hkl_no_lp
```

The **definitions** of the \(J\) channels match. The **numerators** come from
different structure-factor stacks, so \(J\) values are workflow-comparable, not
byte-equal.

## Systematic absences and indexing

Both engines respect crystallographic absences for the resolved space group.
DiffractScout records space-group resolution order and optional spglib
cross-checks in diagnostics. A mismatch between declared and detected symmetry
is a user-review item in both ecosystems; it can change which lines appear.

## Hexagonal / trigonal labels

CIF2Peaks often retained four-index Miller–Bravais labels when pymatgen supplied
them. DiffractScout stores three-index \(h,k,l\) on `ReflectionRecord` and can
format four-index **display** labels with `label_hkl_for_crystal_system` in
`hkl.py` when the crystal system string indicates hexagonal or trigonal families.
Plane-normal elasticity always uses the three-index plane
`plane_hkl_for_normal` (requiring \(i = -(h+k)\) for four-index input).

## Validation guidance

1. **Contract tests**: \(J = I / V^2\), ranks consistent with channels, LP ratio
\(I_{\mathrm{with\,LP}} / I_{\mathrm{no\,LP}}\).
2. **Analytic fixtures**: known monoatomic cells and expected \(\lvert F\rvert^2\).
3. **Cross-engine comparison**: compare \(d\) and \(2\theta\) to a tight tolerance;
compare intensity **ratios** or top-\(N\) peak sets, not raw floats.
4. **Never** treat legacy `R_hkl` columns as Rietveld residuals (see
`SCHEMA_ALIASES.md` and `SCIENTIFIC_CONTRACTS.md`).

## Summary

DiffractScout preserves the CIF2Peaks **scientific workflow** (indexed peaks, LP
split, volume-normalized channels, optional \(E(n_{hkl})\), plottable profile)
while moving crystallographic computation to Gemmi for an offline-first,
provenance-oriented package. Intensity parity is **semantic**, not bitwise.
33 changes: 33 additions & 0 deletions docs/GUI.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ DiffractScout provides a Tk desktop interface for researchers who prefer to conf
diffractscout-gui
# equivalent
diffractscout gui
# or: python -m diffractscout gui
```

On Windows, after an editable or environment install, double-click `启动DiffractScout.bat` in the repository root (it `cd`s to the script directory and tries `py -3 -m diffractscout gui`, then `diffractscout-gui`).

A normal Python installation with Tk support is required. On Linux, the operating-system package is commonly named `python3-tk` or `tk`.

Optional extra `.[gui-dnd]` installs `tkinterdnd2` for future drag-and-drop enhancements; the current GUI does not require it.

## Local CIF analysis

![Local CIF analysis interface](assets/gui-local.png)
Expand Down Expand Up @@ -63,9 +68,37 @@ Energy and wavelength inputs must be finite and positive. The CLI also makes exp
- `Profile points` rejects a requested grid above the configured count before allocation.
- `Reciprocal candidates` rejects a conservative Miller-candidate estimate, and then the actual candidate list, above the configured limit.
- Elasticity pairing calculates a directional modulus only for a valid 6×6 stiffness tensor with an explicitly compatible coordinate frame.
- **Pair numerical elasticity sidecars** / **Evaluate frame-compatible elasticity** and **Write Excel workbook** appear under Outputs on each tab.

The discrete indexed reflection table remains the primary scientific result. Profile parameters do not represent an inferred instrument function.

## Parity and lab-oriented options (CLI / API)

Several CIF2Peaks-parity settings are available on the shared analysis model. The desktop form currently exposes radiation, angular window, profile spacing, pseudo-Voigt η, resource guards, elasticity pairing, and Excel. The following are configured via CLI or Python `AnalysisSettings` (defaults apply when the GUI omits a control):

| Control | Default in GUI path | CLI / settings |
|---|---|---|
| *d*-spacing filter | off (`d_min_A` / `d_max_A` = `None`) | `--d-min`, `--d-max` |
| Profile lineshape | `pseudo_voigt` | `--profile-model` (`pseudo_voigt`, `gaussian`, `lorentzian`) |
| Pattern axis label | `two_theta` | `--pattern-axis` (`two_theta`, `d_spacing`, `q`, `g`) |
| Laboratory Excel views | on (`export_lab_views=True`) | `--no-lab-views` to disable Chinese `推荐峰表` / `使用说明` sheets |
| Continuous pattern series | on | `--no-patterns` |
| Figure generation request | off | `--figures`, `--figure-preset` (requires optional `.[figures]` when exporters draw plots) |

Laboratory views add bilingual convenience sheets to `results.xlsx` without changing the English canonical CSV columns. See [SCHEMA_ALIASES.md](SCHEMA_ALIASES.md) and [ENGINE_PARITY.md](ENGINE_PARITY.md).

## Quick export (no full form)

For a Cu Kα, 5–120° lab-default one-shot export without opening the notebook UI:

```bash
diffractscout-quick-export path/to/sample.cif -o path/to/sample_out.xlsx
# or
diffractscout quick-export path/to/cifs -o path/to/bundle_dir
```

On Windows, drag CIF files or folders onto `quick_export_diffractscout.bat`. The script writes `<first-stem>_diffractscout.xlsx` next to the first input (bundle: `<stem>_diffractscout_bundle/`).

## Activity log and completion states

The Activity panel reports timestamps and separates informational, warning, and error diagnostics. A completed bundle can contain diagnostic errors for individual phases that failed while other phases succeeded. Completion messages therefore distinguish:
Expand Down
Loading