Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dd8d798
Backmerge: master (v0.18.0) into develop [skip ci]
Jun 4, 2026
26ac6cf
Add one-call automatic background estimation for powder patterns (#193)
AndrewSazonov Jun 4, 2026
9a50e51
Audit disabled lint rules and adopt the low-risk subset (#194)
AndrewSazonov Jun 5, 2026
28e4179
Stronger, clearer test suite with cross-engine verification (#195)
AndrewSazonov Jun 7, 2026
2a6c0e1
Extend cross-engine verification suite with FullProf references (#196)
AndrewSazonov Jun 8, 2026
6711fba
Add sample-displacement/transparency corrections and standardize the …
AndrewSazonov Jun 9, 2026
f118217
Calculate and plot a pattern without measured data (#198)
AndrewSazonov Jun 10, 2026
beba720
Support β-tensor displacement parameters and fix dark-mode plots (#199)
AndrewSazonov Jun 11, 2026
be00bc7
Add preferred-orientation (March–Dollase) correction for textured pow…
AndrewSazonov Jun 11, 2026
bfa1f08
Code clean-up and documentation refresh (#201)
AndrewSazonov Jun 12, 2026
6ed1c61
Correct for sample absorption in cylindrical powder diffraction (#202)
AndrewSazonov Jun 15, 2026
c0ae81f
Save projects in the new Edi format with simpler data downloads (#203)
AndrewSazonov Jun 15, 2026
681b195
Resume and extend Bayesian (bumps-DREAM) refinements (#204)
AndrewSazonov Jun 16, 2026
97ef51b
Clear error for invalid joint-fit weights (#205)
AndrewSazonov Jun 16, 2026
62d5b52
Sequential fitting across multi-structure projects, with clearer peak…
AndrewSazonov Jun 17, 2026
db2c9e9
Clearer fit modes that match your loaded data (#207)
AndrewSazonov Jun 17, 2026
813e22d
Verification pages now show live software versions and clearly flag k…
AndrewSazonov Jun 17, 2026
106c84c
Record a second X-ray wavelength (Kα₁/Kα₂) on constant-wavelength ins…
AndrewSazonov Jun 17, 2026
eec8ec8
Add X-ray polarization and monochromator optics for constant-waveleng…
AndrewSazonov Jun 18, 2026
a29d620
X-ray polarization optics and broader CrysFML engine support (#211)
AndrewSazonov Jun 20, 2026
d785903
Add microstructural size/strain broadening and peak-range cutoff (#212)
AndrewSazonov Jun 23, 2026
60684e6
Add time-of-flight verification examples (single crystal & DREAM) and…
AndrewSazonov Jun 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 8 additions & 4 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ coverage:
status:
project:
default:
target: auto
target: 80%
threshold: 1%
# Make project coverage informational (won't block PR)
informational: true
# Project coverage is the real gate (see ADR
# test-suite-and-validation).
informational: false
patch:
default:
target: auto
# Require patch coverage but with threshold
threshold: 1%
# Non-blocking: patch grades diff lines against unit-only
# coverage, so engine/integration-tested code would otherwise
# always fail. See ADR test-suite-and-validation.
informational: true
19 changes: 3 additions & 16 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,8 @@ env:
CI_BRANCH: ${{ github.head_ref || github.ref_name }}

jobs:
# Job 1: Run docstring coverage
docstring-coverage:
runs-on: ubuntu-latest

steps:
- name: Check-out repository
uses: actions/checkout@v6

- name: Set up pixi
uses: ./.github/actions/setup-pixi

- name: Run docstring coverage
run: pixi run docstring-coverage

# Job 2: Run unit tests with coverage and upload to Codecov
# Job 1: Run unit tests with coverage and upload to Codecov.
# Docstring coverage is gated as a static check in lint-format.yml.
unit-tests-coverage:
runs-on: ubuntu-latest

Expand All @@ -65,6 +52,6 @@ jobs:

# Job 4: Build and publish dashboard (reusable workflow)
run-reusable-workflows:
needs: [docstring-coverage, unit-tests-coverage] # depend on the previous jobs
needs: [unit-tests-coverage] # depend on the previous job
uses: ./.github/workflows/dashboard.yml
secrets: inherit
7 changes: 7 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ jobs:
# Note: The gh-pages branch is fetched separately later for mike deployment.
- name: Checkout repository
uses: actions/checkout@v6
with:
# Full history with tags so versioningit derives the real
# version (e.g. 0.18.0+dev40) instead of the v999.0.0 fallback
# (tool.versioningit.vcs default-tag), which would otherwise
# appear as "edi 999" in the executed notebook outputs rendered
# to HTML.
fetch-depth: 0

# Activate dark mode to create documentation with Plotly charts in dark mode
# Need a better solution to automatically switch the chart colour theme based on the mkdocs material switcher
Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/lint-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ jobs:
shell: bash
run: pixi run docstring-lint-check

- name: Check docstring coverage (interrogate)
id: docstring_coverage
continue-on-error: true
shell: bash
run: pixi run docstring-coverage

- name: Check formatting of non-Python files (md, toml, etc.)
id: nonpy_format
continue-on-error: true
Expand All @@ -91,6 +97,30 @@ jobs:
shell: bash
run: pixi run notebook-lint-check

- name: Check unit-test directory mirrors src/ structure
id: test_structure
continue-on-error: true
shell: bash
run: pixi run test-structure-check

- name: Check spelling (codespell)
id: spell
continue-on-error: true
shell: bash
run: pixi run spell-check

- name: Check documentation links (lychee)
id: link
continue-on-error: true
shell: bash
run: pixi run link-check

- name: Build documentation strictly (no tutorial execution)
id: docs_build
continue-on-error: true
shell: bash
run: pixi run docs-build

# Add summary
- name: Add quality checks summary
if: always()
Expand All @@ -106,8 +136,13 @@ jobs:
echo "| py lint | ${{ steps.py_lint.outcome == 'success' && '✅' || '❌' }} |"
echo "| py format | ${{ steps.py_format.outcome == 'success' && '✅' || '❌' }} |"
echo "| docstring lint | ${{ steps.docstring_lint.outcome == 'success' && '✅' || '❌' }} |"
echo "| docstring cover | ${{ steps.docstring_coverage.outcome == 'success' && '✅' || '❌' }} |"
echo "| nonpy format | ${{ steps.nonpy_format.outcome == 'success' && '✅' || '❌' }} |"
echo "| notebooks lint | ${{ steps.notebook_lint.outcome == 'success' && '✅' || '❌' }} |"
echo "| test structure | ${{ steps.test_structure.outcome == 'success' && '✅' || '❌' }} |"
echo "| spelling | ${{ steps.spell.outcome == 'success' && '✅' || '❌' }} |"
echo "| doc links | ${{ steps.link.outcome == 'success' && '✅' || '❌' }} |"
echo "| docs strict build| ${{ steps.docs_build.outcome == 'success' && '✅' || '❌' }} |"
} >> "$GITHUB_STEP_SUMMARY"

# Fail job if any check failed
Expand All @@ -118,7 +153,12 @@ jobs:
|| steps.py_lint.outcome == 'failure'
|| steps.py_format.outcome == 'failure'
|| steps.docstring_lint.outcome == 'failure'
|| steps.docstring_coverage.outcome == 'failure'
|| steps.nonpy_format.outcome == 'failure'
|| steps.notebook_lint.outcome == 'failure'
|| steps.test_structure.outcome == 'failure'
|| steps.spell.outcome == 'failure'
|| steps.link.outcome == 'failure'
|| steps.docs_build.outcome == 'failure'
shell: bash
run: exit 1
71 changes: 71 additions & 0 deletions .github/workflows/nightly-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Nightly run of the FULL test suite across all cost tiers (default, pr,
# and nightly), plus the performance benchmarks. The per-push and per-PR
# runs in test.yml deselect the pr/nightly tiers; the nightly run does
# not. See ADR test-suite-and-validation.

name: Nightly tests

on:
# Run the nightly-tier tests on a daily schedule
schedule:
- cron: '0 3 * * *' # 03:00 UTC daily
# Allow manual runs from the Actions tab
workflow_dispatch:

permissions:
contents: read

# Allow only one concurrent nightly run per ref.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
nightly-tests:
runs-on: ubuntu-latest

steps:
- name: Check-out repository
uses: actions/checkout@v6
with:
# Full history with tags so versioningit derives the real
# version instead of the v999.0.0 fallback in notebook output.
fetch-depth: 0

- name: Set up pixi
uses: ./.github/actions/setup-pixi

# Run each tier as its own step for per-suite visibility. The two
# tutorial steps must stay sequential — they share
# tmp/tutorials/projects/ — so they run as ordered steps rather than
# a single depends-on aggregate. `if: ${{ !cancelled() }}` lets a
# failure in one tier still report the others.
- name: Unit tests
run: pixi run unit-tests

- name: Functional tests
if: ${{ !cancelled() }}
run: pixi run functional-tests

- name: Integration tests
if: ${{ !cancelled() }}
run: pixi run integration-tests

- name: Tutorials as scripts + output check
if: ${{ !cancelled() }}
run: pixi run script-tests-checked

- name: Tutorials + verification notebooks + output check
if: ${{ !cancelled() }}
run: pixi run notebook-tests-checked

- name: Run performance benchmarks
if: ${{ !cancelled() }}
run: pixi run benchmarks

- name: Upload benchmark results
if: ${{ !cancelled() }}
uses: ./.github/actions/upload-artifact
with:
name: benchmark-results
path: benchmark.json
9 changes: 3 additions & 6 deletions .github/workflows/pypi-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,12 @@ on:
# Allow only one concurrent workflow, skipping runs queued between the run
# in-progress and latest queued. And cancel in-progress runs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

# Set the environment variables to be used in all jobs defined in this workflow
env:
CI_BRANCH: ${{ github.head_ref || github.ref_name }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}

jobs:
# Job 1: Test installation from PyPI on multiple OS
pypi-package-tests:
Expand Down Expand Up @@ -77,10 +72,12 @@ jobs:
run: pixi run python -m pytest ../tests/unit/ --color=yes -v

- name: Run functional tests to verify the installation
if: ${{ !cancelled() }}
working-directory: easydiffraction
run: pixi run python -m pytest ../tests/functional/ --color=yes -v

- name: Run integration tests to verify the installation
if: ${{ !cancelled() }}
working-directory: easydiffraction
run: pixi run python -m pytest ../tests/integration/ --color=yes -n auto

Expand Down
41 changes: 30 additions & 11 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,29 @@ jobs:

outputs:
pytest-marks: ${{ steps.set-mark.outputs.pytest_marks }}
run-pr-tier: ${{ steps.set-mark.outputs.run_pr_tier }}

steps:
# Determine if integration tests should be run fully or only the fast ones
# (to save time on branches other than master and develop)
- name: Set mark for integration tests
# Select the test cost tier by branch (see ADR test-suite-and-validation):
# the pr tier runs on develop/master and pull requests; feature-branch
# pushes run only the default (fast) tier. The nightly tier runs
# separately in nightly-test.yml.
- name: Set test tier marker expression
id: set-mark
run: |
if [[ "${{ env.CI_BRANCH }}" == "master" || "${{ env.CI_BRANCH }}" == "develop" ]]; then
echo "pytest_marks=" >> $GITHUB_OUTPUT
# Pull requests and develop/master pushes run the pr tier;
# feature-branch pushes run only the default (fast) tier. On a
# pull_request event CI_BRANCH is the contributor branch, so the
# event type must be checked explicitly. run_pr_tier gates the
# integration steps: the integration layer is entirely pr-marked,
# so on the fast tier its selection is empty and pytest would exit
# 5 ("no tests collected"); skip the step in that case instead.
if [[ "${{ github.event_name }}" == "pull_request" || "${{ env.CI_BRANCH }}" == "master" || "${{ env.CI_BRANCH }}" == "develop" ]]; then
echo 'pytest_marks=-m "not nightly"' >> "$GITHUB_OUTPUT"
echo 'run_pr_tier=true' >> "$GITHUB_OUTPUT"
else
echo "pytest_marks=-m fast" >> $GITHUB_OUTPUT
echo 'pytest_marks=-m "not pr and not nightly"' >> "$GITHUB_OUTPUT"
echo 'run_pr_tier=false' >> "$GITHUB_OUTPUT"
fi

# Job 2: Test code
Expand Down Expand Up @@ -99,7 +111,7 @@ jobs:
env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.XX -> py-3XX-env

echo "Running tests in environment: $env"
pixi run --environment $env unit-tests
pixi run --environment $env unit-tests ${{ needs.env-prepare.outputs.pytest-marks }}
done

- name: Run functional tests
Expand All @@ -114,10 +126,14 @@ jobs:
env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.XX -> py-3XX-env

echo "Running tests in environment: $env"
pixi run --environment $env functional-tests
pixi run --environment $env functional-tests ${{ needs.env-prepare.outputs.pytest-marks }}
done

# Integration tests are entirely pr-marked, so they only run in the pr
# tier (PRs + develop/master). On feature-branch pushes the selection
# would be empty; skip the step rather than fail on pytest exit code 5.
- name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
if: needs.env-prepare.outputs.run-pr-tier == 'true'
shell: bash
run: |
set -euo pipefail
Expand Down Expand Up @@ -173,7 +189,8 @@ jobs:

# Job 3: Test the package
package-test:
needs: source-test # depend on previous job
# env-prepare provides the tier marker expression; source-test the wheel
needs: [env-prepare, source-test]

strategy:
fail-fast: false
Expand Down Expand Up @@ -270,7 +287,7 @@ jobs:
cd easydiffraction_py$py_ver

echo "Running tests"
pixi run python -m pytest ../tests/unit/ --color=yes -v
pixi run python -m pytest ../tests/unit/ --color=yes -v ${{ needs.env-prepare.outputs.pytest-marks }}

echo "Exiting pixi project directory"
cd ..
Expand All @@ -289,13 +306,15 @@ jobs:
cd easydiffraction_py$py_ver

echo "Running tests"
pixi run python -m pytest ../tests/functional/ --color=yes -v
pixi run python -m pytest ../tests/functional/ --color=yes -v ${{ needs.env-prepare.outputs.pytest-marks }}

echo "Exiting pixi project directory"
cd ..
done

# See the source-test job: integration tests run only in the pr tier.
- name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
if: needs.env-prepare.outputs.run-pr-tier == 'true'
shell: bash
run: |
set -euo pipefail
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/tutorial-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
# Full history with tags so versioningit derives the real
# version instead of the v999.0.0 fallback in notebook output.
fetch-depth: 0

- name: Set up pixi
uses: ./.github/actions/setup-pixi
Expand Down
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ build/
# MkDocs
docs/site/

# Generated docs-serving copy of the canonical Three.js (synced from
# src/ by `pixi run docs-sync-vendored-js`; the source of truth is src/)
# Generated docs-serving copies of the canonical JS runtimes and the
# shared figure loader (synced from src/ by `pixi run
# docs-sync-vendored-js`; the source of truth is src/)
docs/docs/assets/javascripts/vendor/threejs/
docs/docs/assets/javascripts/vendor/plotly/
docs/docs/assets/javascripts/ed-figures.js

# Jupyter Notebooks
.ipynb_checkpoints
Expand Down Expand Up @@ -59,3 +62,6 @@ CLAUDE.md
/data/
/projects/
/tmp/

# FullProf/CrysFML Fortran scratch unit files
fort.*
Loading
Loading