diff --git a/.badgery.yaml b/.badgery.yaml
index f22752fa..99bcdc1c 100644
--- a/.badgery.yaml
+++ b/.badgery.yaml
@@ -5,19 +5,18 @@ cards:
- group: Tests
type: gh_action
title: Code/package tests (GitHub)
- file: test.yaml
+ file: test.yml
enabled: true
-
- group: Tests
type: gh_action
title: Tutorial tests (GitHub)
- file: tutorial-tests.yaml
+ file: tutorial-tests.yml
enabled: true
- group: Tests
type: gh_action
title: Package tests (PyPI)
- file: pypi-test.yaml
+ file: pypi-test.yml
enabled: true
- group: Code Quality
@@ -60,15 +59,14 @@ cards:
title: Docstring coverage (interrogate)
report: reports/{branch}/coverage-docstring.txt
enabled: true
-
- group: Build & Release
type: gh_action
title: Publishing (PyPI)
- workflow: pypi-publish.yaml
+ workflow: pypi-publish.yml
enabled: true
- group: Build & Release
type: gh_action
title: Docs build/deployment
- workflow: docs.yaml
+ workflow: docs.yml
enabled: true
diff --git a/.copier-answers.yml b/.copier-answers.yml
new file mode 100644
index 00000000..778744fa
--- /dev/null
+++ b/.copier-answers.yml
@@ -0,0 +1,27 @@
+# WARNING: Do not edit this file manually.
+# Any changes will be overwritten by Copier.
+_commit: v0.10.1-25-ga5301e9
+_src_path: gh:easyscience/templates
+app_docs_url: https://easyscience.github.io/diffraction-app
+app_doi: 10.5281/zenodo.18163581
+app_package_name: easydiffraction_app
+app_python: '3.13'
+app_repo_name: diffraction-app
+home_page_url: https://easyscience.github.io/diffraction
+home_repo_name: diffraction
+lib_docs_url: https://easyscience.github.io/diffraction-lib
+lib_doi: 10.5281/zenodo.18163581
+lib_package_name: easydiffraction
+lib_python_max: '3.13'
+lib_python_min: '3.11'
+lib_repo_name: diffraction-lib
+project_contact_email: support@easydiffraction.org
+project_copyright_years: 2021-2026
+project_extended_description: A software for calculating neutron powder diffraction
+ patterns based on a structural model and refining its parameters against experimental
+ data
+project_name: EasyDiffraction
+project_short_description: Diffraction data analysis
+project_shortcut: ED
+project_type: both
+template_type: lib
diff --git a/.github/actions/download-artifact/action.yml b/.github/actions/download-artifact/action.yml
new file mode 100644
index 00000000..e4fd62f5
--- /dev/null
+++ b/.github/actions/download-artifact/action.yml
@@ -0,0 +1,50 @@
+name: 'Download artifact'
+description: 'Generic wrapper for actions/download-artifact'
+inputs:
+ name:
+ description: 'Name of the artifact to download'
+ required: true
+
+ path:
+ description: 'Destination path'
+ required: false
+ default: '.'
+
+ pattern:
+ description: 'Glob pattern to match artifact names (optional)'
+ required: false
+ default: ''
+
+ merge-multiple:
+ description: 'Merge multiple artifacts into the same directory'
+ required: false
+ default: 'false'
+
+ github-token:
+ description: 'GitHub token for cross-repo download (optional)'
+ required: false
+ default: ''
+
+ repository:
+ description: 'owner/repo for cross-repo download (optional)'
+ required: false
+ default: ''
+
+ run-id:
+ description: 'Workflow run ID for cross-run download (optional)'
+ required: false
+ default: ''
+
+runs:
+ using: 'composite'
+ steps:
+ - name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: ${{ inputs.name }}
+ path: ${{ inputs.path }}
+ pattern: ${{ inputs.pattern }}
+ merge-multiple: ${{ inputs.merge-multiple }}
+ github-token: ${{ inputs.github-token }}
+ repository: ${{ inputs.repository }}
+ run-id: ${{ inputs.run-id }}
diff --git a/.github/actions/github-script/action.yml b/.github/actions/github-script/action.yml
new file mode 100644
index 00000000..ab32da56
--- /dev/null
+++ b/.github/actions/github-script/action.yml
@@ -0,0 +1,19 @@
+name: 'GitHub Script'
+description: 'Wrapper for actions/github-script'
+inputs:
+ script:
+ description: 'JavaScript to run'
+ required: true
+
+ github-token:
+ description: 'GitHub token (defaults to github.token)'
+ required: false
+ default: ${{ github.token }}
+
+runs:
+ using: 'composite'
+ steps:
+ - uses: actions/github-script@v8
+ with:
+ script: ${{ inputs.script }}
+ github-token: ${{ inputs.github-token }}
diff --git a/.github/actions/setup-easyscience-bot/action.yml b/.github/actions/setup-easyscience-bot/action.yml
new file mode 100644
index 00000000..4b28eaf8
--- /dev/null
+++ b/.github/actions/setup-easyscience-bot/action.yml
@@ -0,0 +1,40 @@
+name: 'Setup EasyScience bot for pushing'
+description: 'Create GitHub App token and configure git identity + origin remote'
+inputs:
+ app-id:
+ description: 'GitHub App ID'
+ required: true
+ private-key:
+ description: 'GitHub App private key (PEM)'
+ required: true
+ repositories:
+ description: 'Additional repositories to grant access to (newline-separated)'
+ required: false
+ default: ''
+
+outputs:
+ token:
+ description: 'Installation access token'
+ value: ${{ steps.app-token.outputs.token }}
+
+runs:
+ using: 'composite'
+ steps:
+ - name: Create GitHub App installation token
+ id: app-token
+ uses: actions/create-github-app-token@v2
+ with:
+ app-id: ${{ inputs.app-id }}
+ private-key: ${{ inputs.private-key }}
+ repositories: ${{ inputs.repositories }}
+
+ - name: Configure git for pushing
+ shell: bash
+ run: |
+ git config user.name "easyscience[bot]"
+ git config user.email "${{ inputs.app-id }}+easyscience[bot]@users.noreply.github.com"
+
+ - name: Configure origin remote to use the bot token
+ shell: bash
+ run: |
+ git remote set-url origin https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git
diff --git a/.github/actions/setup-pixi/action.yml b/.github/actions/setup-pixi/action.yml
new file mode 100644
index 00000000..167ee623
--- /dev/null
+++ b/.github/actions/setup-pixi/action.yml
@@ -0,0 +1,44 @@
+name: 'Setup Pixi Environment'
+description: 'Sets up pixi with common configuration'
+inputs:
+ environments:
+ description: 'Pixi environments to setup'
+ required: false
+ default: 'default'
+ activate-environment:
+ description: 'Environment to activate'
+ required: false
+ default: 'default'
+ run-install:
+ description: 'Whether to run pixi install'
+ required: false
+ default: 'true'
+ locked:
+ description: 'Whether to run pixi install --locked'
+ required: false
+ default: 'false'
+ frozen:
+ description: 'Whether to run pixi install --frozen'
+ required: false
+ default: 'true'
+ cache:
+ description: 'Whether to use cache'
+ required: false
+ default: 'false'
+ post-cleanup:
+ description: 'Whether to run post cleanup'
+ required: false
+ default: 'false'
+
+runs:
+ using: 'composite'
+ steps:
+ - uses: prefix-dev/setup-pixi@v0.9.4
+ with:
+ environments: ${{ inputs.environments }}
+ activate-environment: ${{ inputs.activate-environment }}
+ run-install: ${{ inputs.run-install }}
+ locked: ${{ inputs.locked }}
+ frozen: ${{ inputs.frozen }}
+ cache: ${{ inputs.cache }}
+ post-cleanup: ${{ inputs.post-cleanup }}
diff --git a/.github/actions/upload-artifact/action.yml b/.github/actions/upload-artifact/action.yml
new file mode 100644
index 00000000..825ac396
--- /dev/null
+++ b/.github/actions/upload-artifact/action.yml
@@ -0,0 +1,49 @@
+name: 'Upload artifact'
+description: 'Generic wrapper for actions/upload-artifact'
+inputs:
+ name:
+ description: 'Artifact name'
+ required: true
+
+ path:
+ description: 'File(s)/dir(s)/glob(s) to upload (newline-separated)'
+ required: true
+
+ include-hidden-files:
+ description: 'Include hidden files'
+ required: false
+ default: 'true'
+
+ if-no-files-found:
+ description: 'warn | error | ignore'
+ required: false
+ default: 'error'
+
+ compression-level:
+ description: '0-9 (0 = no compression)'
+ required: false
+ default: '0'
+
+ retention-days:
+ description: 'Retention in days (optional)'
+ required: false
+ default: ''
+
+ overwrite:
+ description: 'Overwrite an existing artifact with the same name'
+ required: false
+ default: 'false'
+
+runs:
+ using: 'composite'
+ steps:
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ inputs.name }}
+ path: ${{ inputs.path }}
+ include-hidden-files: ${{ inputs.include-hidden-files }}
+ if-no-files-found: ${{ inputs.if-no-files-found }}
+ compression-level: ${{ inputs.compression-level }}
+ retention-days: ${{ inputs.retention-days }}
+ overwrite: ${{ inputs.overwrite }}
diff --git a/.github/actions/upload-codecov/action.yml b/.github/actions/upload-codecov/action.yml
new file mode 100644
index 00000000..37d6298a
--- /dev/null
+++ b/.github/actions/upload-codecov/action.yml
@@ -0,0 +1,42 @@
+name: 'Upload coverage to Codecov'
+description: 'Generic wrapper for codecov/codecov-action@v5'
+
+inputs:
+ name:
+ description: 'Codecov upload name'
+ required: true
+
+ flags:
+ description: 'Codecov flags'
+ required: false
+ default: ''
+
+ files:
+ description: 'Coverage report files'
+ required: true
+
+ fail_ci_if_error:
+ description: 'Fail CI if upload fails'
+ required: false
+ default: 'true'
+
+ verbose:
+ description: 'Enable verbose output'
+ required: false
+ default: 'true'
+
+ token:
+ description: 'Codecov token'
+ required: true
+
+runs:
+ using: composite
+ steps:
+ - uses: codecov/codecov-action@v5
+ with:
+ name: ${{ inputs.name }}
+ flags: ${{ inputs.flags }}
+ files: ${{ inputs.files }}
+ fail_ci_if_error: ${{ inputs.fail_ci_if_error }}
+ verbose: ${{ inputs.verbose }}
+ token: ${{ inputs.token }}
diff --git a/.github/configs/pages-deployment.json b/.github/configs/pages-deployment.json
new file mode 100644
index 00000000..c0d3fbee
--- /dev/null
+++ b/.github/configs/pages-deployment.json
@@ -0,0 +1,6 @@
+{
+ "source": {
+ "branch": "gh-pages",
+ "path": "/"
+ }
+}
diff --git a/.github/configs/rulesets-develop.json b/.github/configs/rulesets-develop.json
new file mode 100644
index 00000000..04489e52
--- /dev/null
+++ b/.github/configs/rulesets-develop.json
@@ -0,0 +1,37 @@
+{
+ "name": "develop branch",
+ "target": "branch",
+ "enforcement": "active",
+ "conditions": {
+ "ref_name": {
+ "include": ["refs/heads/develop"],
+ "exclude": []
+ }
+ },
+ "bypass_actors": [
+ {
+ "actor_id": 2476259,
+ "actor_type": "Integration",
+ "bypass_mode": "always"
+ }
+ ],
+ "rules": [
+ {
+ "type": "non_fast_forward"
+ },
+ {
+ "type": "deletion"
+ },
+ {
+ "type": "pull_request",
+ "parameters": {
+ "allowed_merge_methods": ["squash"],
+ "dismiss_stale_reviews_on_push": false,
+ "require_code_owner_review": false,
+ "require_last_push_approval": false,
+ "required_approving_review_count": 0,
+ "required_review_thread_resolution": false
+ }
+ }
+ ]
+}
diff --git a/.github/configs/rulesets-gh-pages.json b/.github/configs/rulesets-gh-pages.json
new file mode 100644
index 00000000..ebf38928
--- /dev/null
+++ b/.github/configs/rulesets-gh-pages.json
@@ -0,0 +1,19 @@
+{
+ "name": "gh-pages branch",
+ "target": "branch",
+ "enforcement": "active",
+ "conditions": {
+ "ref_name": {
+ "include": ["refs/heads/gh-pages"],
+ "exclude": []
+ }
+ },
+ "rules": [
+ {
+ "type": "non_fast_forward"
+ },
+ {
+ "type": "deletion"
+ }
+ ]
+}
diff --git a/.github/configs/rulesets-master.json b/.github/configs/rulesets-master.json
new file mode 100644
index 00000000..f658a5c6
--- /dev/null
+++ b/.github/configs/rulesets-master.json
@@ -0,0 +1,30 @@
+{
+ "name": "master branch",
+ "target": "branch",
+ "enforcement": "active",
+ "conditions": {
+ "ref_name": {
+ "include": ["~DEFAULT_BRANCH"],
+ "exclude": []
+ }
+ },
+ "rules": [
+ {
+ "type": "non_fast_forward"
+ },
+ {
+ "type": "deletion"
+ },
+ {
+ "type": "pull_request",
+ "parameters": {
+ "allowed_merge_methods": ["merge"],
+ "dismiss_stale_reviews_on_push": false,
+ "require_code_owner_review": false,
+ "require_last_push_approval": false,
+ "required_approving_review_count": 0,
+ "required_review_thread_resolution": false
+ }
+ }
+ ]
+}
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 58e7d29d..d29a15d1 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -2,8 +2,8 @@
## Project Context
-- Python library for crystallographic diffraction analysis, such as refinement
- of the structural model against experimental data.
+- Python library for crystallographic diffraction analysis, such as
+ refinement of the structural model against experimental data.
- Support for
- sample_form: powder and single crystal
- beam_mode: time-of-flight and constant wavelength
@@ -13,124 +13,140 @@
- `cryspy` for Bragg diffraction
- `crysfml` for Bragg diffraction
- `pdffit2` for Total scattering
-- Follow CIF naming conventions where possible. In some places, we deviate for
- better API design, but we try to keep the spirit of the CIF names.
+- Follow CIF naming conventions where possible. In some places, we
+ deviate for better API design, but we try to keep the spirit of the
+ CIF names.
- Reusing the concept of datablocks and categories from CIF. We have
`DatablockItem` (structure or experiment) and `DatablockCollection`
- (collection of structures or experiments), as well as `CategoryItem` (single
- categories in CIF) and `CategoryCollection` (loop categories in CIF).
+ (collection of structures or experiments), as well as `CategoryItem`
+ (single categories in CIF) and `CategoryCollection` (loop categories
+ in CIF).
- Metadata via frozen dataclasses: `TypeInfo`, `Compatibility`,
`CalculatorSupport`.
-- The API is designed for scientists who use EasyDiffraction as a final product
- in a user-friendly, intuitive way. The target users are not software
- developers and may have little or no Python experience. The design is not
- oriented toward developers building their own tooling on top of the library,
- although experienced developers will find their own way. Prioritize
- discoverability, clear error messages, and safe defaults so that
- non-programmers are not stuck by standard API conventions.
-- This project must be developed to be as error-free as possible, with the same
- rigour applied to critical software (e.g. nuclear-plant control systems).
- Every code path must be tested, edge cases must be handled explicitly, and
- silent failures are not acceptable.
+- The API is designed for scientists who use EasyDiffraction as a final
+ product in a user-friendly, intuitive way. The target users are not
+ software developers and may have little or no Python experience. The
+ design is not oriented toward developers building their own tooling on
+ top of the library, although experienced developers will find their
+ own way. Prioritize discoverability, clear error messages, and safe
+ defaults so that non-programmers are not stuck by standard API
+ conventions.
+- This project must be developed to be as error-free as possible, with
+ the same rigour applied to critical software (e.g. nuclear-plant
+ control systems). Every code path must be tested, edge cases must be
+ handled explicitly, and silent failures are not acceptable.
## Code Style
-- Use snake_case for functions and variables, PascalCase for classes, and
- UPPER_SNAKE_CASE for constants.
+- Use snake_case for functions and variables, PascalCase for classes,
+ and UPPER_SNAKE_CASE for constants.
- Use `from __future__ import annotations` in every module.
- Type-annotate all public function signatures.
-- Docstrings on all public classes and methods (Google style).
+- Docstrings on all public classes and methods (numpy style).
- Prefer flat over nested, explicit over clever.
-- Write straightforward code; do not add defensive checks for unlikely edge
- cases.
+- Write straightforward code; do not add defensive checks for unlikely
+ edge cases.
- Prefer composition over deep inheritance.
-- One class per file when the class is substantial; group small related classes.
-- Avoid `**kwargs`; use explicit keyword arguments for clarity, autocomplete,
- and typo detection.
-- Do not use string-based dispatch (e.g. `getattr(self, f'_{name}')`) to route
- to attributes or methods. Instead, write explicit named methods (e.g.
- `_set_sample_form`, `_set_beam_mode`). This keeps the code greppable,
- autocomplete-friendly, and type-safe.
-- Public parameters and descriptors are either **editable** (property with both
- getter and setter) or **read-only** (property with getter only). If internal
- code needs to mutate a read-only property, add a private `_set_` method
- instead of exposing a public setter.
+- One class per file when the class is substantial; group small related
+ classes.
+- Avoid `**kwargs`; use explicit keyword arguments for clarity,
+ autocomplete, and typo detection.
+- Do not use string-based dispatch (e.g. `getattr(self, f'_{name}')`) to
+ route to attributes or methods. Instead, write explicit named methods
+ (e.g. `_set_sample_form`, `_set_beam_mode`). This keeps the code
+ greppable, autocomplete-friendly, and type-safe.
+- Public parameters and descriptors are either **editable** (property
+ with both getter and setter) or **read-only** (property with getter
+ only). If internal code needs to mutate a read-only property, add a
+ private `_set_` method instead of exposing a public setter.
## Architecture
-- Eager imports at the top of the module by default. Use lazy imports (inside a
- method body) only when necessary to break circular dependencies or to keep
- `core/` free of heavy utility imports on rarely-called paths (e.g. `help()`).
+- Eager imports at the top of the module by default. Use lazy imports
+ (inside a method body) only when necessary to break circular
+ dependencies or to keep `core/` free of heavy utility imports on
+ rarely-called paths (e.g. `help()`).
- No `pkgutil` / `importlib` auto-discovery patterns.
- No background/daemon threads.
- No monkey-patching or runtime class mutation.
- Do not use `__all__` in modules; instead, rely on explicit imports in
`__init__.py` to control the public API.
-- Do not use redundant `import X as X` aliases in `__init__.py`. Use plain
- `from module import X`.
-- Concrete classes use `@Factory.register` decorators. To trigger registration,
- each package's `__init__.py` must explicitly import every concrete class (e.g.
- `from .chebyshev import ChebyshevPolynomialBackground`). When adding a new
- concrete class, always add its import to the corresponding `__init__.py`.
-- Switchable categories (those whose implementation can be swapped at runtime
- via a factory) follow a fixed naming convention on the owner (experiment,
- structure, or analysis): `` (read-only property), `_type`
- (getter + setter), `show_supported__types()`,
- `show_current__type()`. The owner class owns the type setter and the
- show methods; the show methods delegate to `Factory.show_supported(...)`
- passing context. Every factory-created category must have this full API, even
- if only one implementation exists today.
-- Categories are flat siblings within their owner (datablock or analysis). A
- category must never be a child of another category of a different type.
- Categories can reference each other via IDs, but not via parent-child nesting.
-- Every finite, closed set of values (factory tags, experiment axes, category
- descriptors with enumerated choices) must use a `(str, Enum)` class. Internal
- code compares against enum members, never raw strings.
+- Do not use redundant `import X as X` aliases in `__init__.py`. Use
+ plain `from module import X`.
+- Concrete classes use `@Factory.register` decorators. To trigger
+ registration, each package's `__init__.py` must explicitly import
+ every concrete class (e.g.
+ `from .chebyshev import ChebyshevPolynomialBackground`). When adding a
+ new concrete class, always add its import to the corresponding
+ `__init__.py`.
+- Switchable categories (those whose implementation can be swapped at
+ runtime via a factory) follow a fixed naming convention on the owner
+ (experiment, structure, or analysis): `` (read-only
+ property), `_type` (getter + setter),
+ `show_supported__types()`, `show_current__type()`.
+ The owner class owns the type setter and the show methods; the show
+ methods delegate to `Factory.show_supported(...)` passing context.
+ Every factory-created category must have this full API, even if only
+ one implementation exists today.
+- Categories are flat siblings within their owner (datablock or
+ analysis). A category must never be a child of another category of a
+ different type. Categories can reference each other via IDs, but not
+ via parent-child nesting.
+- Every finite, closed set of values (factory tags, experiment axes,
+ category descriptors with enumerated choices) must use a `(str, Enum)`
+ class. Internal code compares against enum members, never raw strings.
- Keep `core/` free of domain logic — only base classes and utilities.
-- Don't introduce a new abstraction until there is a concrete second use case.
+- Don't introduce a new abstraction until there is a concrete second use
+ case.
- Don't add dependencies without asking.
## Changes
-- Before implementing any structural or design change (new categories, new
- factories, switchable-category wiring, new datablocks, CIF serialisation
- changes), read `docs/architecture/architecture.md` to understand the current
- design choices and conventions. Follow the documented patterns (factory
- registration, switchable-category naming, metadata classification, etc.) to
- stay consistent with the rest of the codebase. For localised bug fixes or test
- updates, the rules in this file are sufficient.
-- The project is in beta; do not keep legacy code or add deprecation warnings.
- Instead, update tests and tutorials to follow the current API.
+- Before implementing any structural or design change (new categories,
+ new factories, switchable-category wiring, new datablocks, CIF
+ serialisation changes), read `docs/architecture/architecture.md` to
+ understand the current design choices and conventions. Follow the
+ documented patterns (factory registration, switchable-category naming,
+ metadata classification, etc.) to stay consistent with the rest of the
+ codebase. For localised bug fixes or test updates, the rules in this
+ file are sufficient.
+- The project is in beta; do not keep legacy code or add deprecation
+ warnings. Instead, update tests and tutorials to follow the current
+ API.
- Minimal diffs: don't rewrite working code just to reformat it.
-- Never remove or replace existing functionality as part of a new change without
- explicit confirmation. If a refactor would drop features, options, or
- configurations, highlight every removal and wait for approval.
-- Fix only what's asked; flag adjacent issues as comments, don't fix them
- silently.
-- Don't add new features or refactor existing code unless explicitly asked.
+- Never remove or replace existing functionality as part of a new change
+ without explicit confirmation. If a refactor would drop features,
+ options, or configurations, highlight every removal and wait for
+ approval.
+- Fix only what's asked; flag adjacent issues as comments, don't fix
+ them silently.
+- Don't add new features or refactor existing code unless explicitly
+ asked.
- Do not remove TODOs or comments unless the change fully resolves them.
- When renaming, grep the entire project (code, tests, tutorials, docs).
-- Every change should be atomic and self-contained, small enough to be described
- by a single commit message. Make one change, suggest the commit message, then
- stop and wait for confirmation before starting the next change.
+- Every change should be atomic and self-contained, small enough to be
+ described by a single commit message. Make one change, suggest the
+ commit message, then stop and wait for confirmation before starting
+ the next change.
- When in doubt, ask for clarification before making changes.
## Workflow
-- All open issues, design questions, and planned improvements are tracked in
- `docs/architecture/issues_open.md`, ordered by priority. When an issue is
- fully implemented, move it from that file to
+- All open issues, design questions, and planned improvements are
+ tracked in `docs/architecture/issues_open.md`, ordered by priority.
+ When an issue is fully implemented, move it from that file to
`docs/architecture/issues_closed.md`. When the resolution affects the
architecture, update the relevant sections of
`docs/architecture/architecture.md`.
-- After changes, run linting and formatting fixes with `pixi run fix`. Do not
- check what was auto-fixed, just accept the fixes and move on.
+- After changes, run linting and formatting fixes with `pixi run fix`.
+ Do not check what was auto-fixed, just accept the fixes and move on.
- After changes, run unit tests with `pixi run unit-tests`.
-- After changes, run integration tests with `pixi run integration-tests`.
+- After changes, run integration tests with
+ `pixi run integration-tests`.
- After changes, run tutorial tests with `pixi run script-tests`.
-- Suggest a concise commit message (as a code block) after each change (less
- than 72 characters, imperative mood, without prefixing with the type of
- change). E.g.:
+- Suggest a concise commit message (as a code block) after each change
+ (less than 72 characters, imperative mood, without prefixing with the
+ type of change). E.g.:
- Add ChebyshevPolynomialBackground class
- Implement background_type setter on Experiment
- Standardize switchable-category naming convention
diff --git a/.github/scripts/backmerge-conflict-issue.js b/.github/scripts/backmerge-conflict-issue.js
new file mode 100644
index 00000000..f6bd98b5
--- /dev/null
+++ b/.github/scripts/backmerge-conflict-issue.js
@@ -0,0 +1,69 @@
+module.exports = async ({ github, context, core }) => {
+ // Repo context
+ const owner = context.repo.owner
+ const repo = context.repo.repo
+
+ // Link to the exact workflow run that detected the conflict
+ const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`
+
+ // We use a *stable title* so we can find/reuse the same "conflict tracker" issue
+ // instead of creating a new issue on every failed run.
+ const title = 'Backmerge conflict: master → develop'
+
+ // Comment/issue body includes the run URL so maintainers can jump straight to logs.
+ const body = [
+ 'Automatic backmerge failed due to merge conflicts.',
+ '',
+ `Workflow run: ${runUrl}`,
+ '',
+ 'Manual resolution required.',
+ ].join('\n')
+
+ // Label applied to the tracker issue (assumed to already exist in the repo).
+ const label = '[bot] backmerge'
+
+ // Search issues by title across *open and closed* issues.
+ // Why: if the conflict was resolved previously and the issue was closed,
+ // we prefer to reopen it and append a new comment instead of creating duplicates.
+ const q = `repo:${owner}/${repo} is:issue in:title "${title}"`
+ const search = await github.rest.search.issuesAndPullRequests({
+ q,
+ per_page: 10,
+ })
+
+ // Pick the first exact-title match (search can return partial matches).
+ const existing = search.data.items.find((i) => i.title === title)
+
+ if (existing) {
+ // If a tracker issue exists, reuse it:
+ // - reopen it if needed
+ // - add a comment with the new run URL
+ if (existing.state === 'closed') {
+ await github.rest.issues.update({
+ owner,
+ repo,
+ issue_number: existing.number,
+ state: 'open',
+ })
+ }
+
+ await github.rest.issues.createComment({
+ owner,
+ repo,
+ issue_number: existing.number,
+ body,
+ })
+
+ core.notice(`Conflict issue updated: #${existing.number}`)
+ return
+ }
+
+ // No tracker issue exists yet -> create the first one.
+ await github.rest.issues.create({
+ owner,
+ repo,
+ title,
+ body,
+ labels: [label],
+ })
+}
diff --git a/.github/workflows/backmerge.yaml b/.github/workflows/backmerge.yaml
deleted file mode 100644
index f69b5379..00000000
--- a/.github/workflows/backmerge.yaml
+++ /dev/null
@@ -1,66 +0,0 @@
-# This workflow automatically merges `master` into `develop` whenever a new version tag is pushed (v*).
-#
-# Key points:
-# - Directly merges master into develop without creating a PR.
-# - Skips CI on the merge commit using [skip ci] in the commit message.
-# - The code being merged has already been tested as part of the release process.
-# - This ensures develop stays up-to-date with release changes (version bumps, etc.).
-#
-# Required repo config:
-# https://github.com/organizations/easyscience/settings/secrets/actions
-# https://github.com/organizations/easyscience/settings/variables/actions
-# - Actions secret: EASYSCIENCE_APP_KEY (GitHub App private key PEM)
-# - Actions variable: EASYSCIENCE_APP_ID (GitHub App ID)
-# The GitHub App must be added to the develop branch ruleset bypass list.
-
-name: Backmerge (master -> develop)
-
-on:
- push:
- tags: ['v*']
-
-permissions:
- contents: write
-
-jobs:
- backmerge:
- runs-on: ubuntu-latest
-
- steps:
- - name: Create GitHub App installation token
- id: app-token
- uses: actions/create-github-app-token@v2
- with:
- app-id: ${{ vars.EASYSCIENCE_APP_ID }}
- private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
-
- - name: Checkout repository
- uses: actions/checkout@v5
- with:
- fetch-depth: 0
- token: ${{ steps.app-token.outputs.token }}
-
- - name: Configure git for pushing
- run: |
- git config user.name "easyscience[bot]"
- git config user.email "${{ vars.EASYSCIENCE_APP_ID }}+easyscience[bot]@users.noreply.github.com"
-
- - name: Merge master into develop
- run: |
- set -euo pipefail
-
- TAG='${{ github.ref_name }}'
-
- # Ensure local develop branch exists and is up-to-date with origin
- git fetch origin develop:develop
- # Switch to develop branch
- git checkout develop
-
- # Merge master into develop (no fast-forward to preserve history)
- # Use [skip ci] to avoid triggering CI - the code was already tested on master
- git merge origin/master --no-ff -m "Backmerge: ${TAG} from master into develop [skip ci]"
-
- # Push the merge commit to develop
- git push origin develop
-
- echo "✅ Successfully merged master (${TAG}) into develop"
diff --git a/.github/workflows/backmerge.yml b/.github/workflows/backmerge.yml
new file mode 100644
index 00000000..47b3384a
--- /dev/null
+++ b/.github/workflows/backmerge.yml
@@ -0,0 +1,109 @@
+# This workflow automatically merges `master` into `develop` whenever a
+# new version release with a tag is published. It can also be triggered
+# manually via workflow_dispatch for cases where an automatic backmerge
+# is needed outside of the standard release process.
+# If a merge conflict occurs, the workflow creates an issue to notify
+# maintainers for manual resolution.
+
+name: Backmerge (master → develop)
+
+on:
+ release:
+ types: [published, prereleased]
+ workflow_dispatch:
+
+permissions:
+ contents: write
+ issues: write
+
+concurrency:
+ group: backmerge-master-into-develop
+ cancel-in-progress: false
+
+jobs:
+ backmerge:
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+
+ steps:
+ - name: Checkout repository (for local actions)
+ uses: actions/checkout@v5
+
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
+ with:
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
+ repositories: ${{ github.event.repository.name }}
+
+ - name: Checkout repository (with bot token)
+ uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+ token: ${{ steps.bot.outputs.token }}
+
+ - name: Configure git identity
+ run: |
+ git config user.name "easyscience[bot]"
+ git config user.email "${{ vars.EASYSCIENCE_APP_ID }}+easyscience[bot]@users.noreply.github.com"
+
+ - name: Set merge message
+ run: |
+ if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
+ MESSAGE="Backmerge: master into develop (manual) [skip ci]"
+ else
+ TAG="${{ github.event.release.tag_name }}"
+ MESSAGE="Backmerge: master (${TAG}) into develop [skip ci]"
+ fi
+
+ echo "MESSAGE=$MESSAGE" >> "$GITHUB_ENV"
+ echo "message=$MESSAGE" >> "$GITHUB_OUTPUT"
+ echo "📝 Merge message: $MESSAGE" | tee -a "$GITHUB_STEP_SUMMARY"
+
+ - name: Prepare branches
+ run: |
+ git fetch origin master develop
+ git checkout -B develop origin/develop
+
+ - name: Check if develop is already up-to-date
+ id: up_to_date
+ run: |
+ if git merge-base --is-ancestor origin/master develop; then
+ echo "value=true" >> "$GITHUB_OUTPUT"
+ echo "ℹ️ Develop is already up-to-date with master" | tee -a "$GITHUB_STEP_SUMMARY"
+ else
+ echo "value=false" >> "$GITHUB_OUTPUT"
+ fi
+
+ - name: Try merge master into develop
+ id: merge
+ if: steps.up_to_date.outputs.value == 'false'
+ continue-on-error: true
+ run: |
+ if ! git merge origin/master --no-ff -m "${MESSAGE}"; then
+ echo "conflict=true" >> "$GITHUB_OUTPUT"
+ echo "❌ Backmerge conflict detected." | tee -a "$GITHUB_STEP_SUMMARY"
+ git status --porcelain || true
+ exit 0
+ fi
+
+ echo "conflict=false" >> "$GITHUB_OUTPUT"
+ echo "✅ Merge commit created." | tee -a "$GITHUB_STEP_SUMMARY"
+
+ - name: Push to develop (if merge succeeded)
+ if:
+ steps.up_to_date.outputs.value == 'false' && steps.merge.outputs.conflict ==
+ 'false'
+ run: |
+ git push origin develop
+ echo "🚀 Backmerge successful: master → develop" | tee -a "$GITHUB_STEP_SUMMARY"
+
+ - name: Create issue (if merge failed with conflicts)
+ if: steps.merge.outputs.conflict == 'true'
+ uses: ./.github/actions/github-script
+ with:
+ github-token: ${{ steps.bot.outputs.token }}
+ script: |
+ const run = require('./.github/scripts/backmerge-conflict-issue.js')
+ await run({ github, context, core })
diff --git a/.github/workflows/cleanup.yaml b/.github/workflows/cleanup.yml
similarity index 88%
rename from .github/workflows/cleanup.yaml
rename to .github/workflows/cleanup.yml
index eef184db..7305679b 100644
--- a/.github/workflows/cleanup.yaml
+++ b/.github/workflows/cleanup.yml
@@ -22,8 +22,8 @@ on:
default: 6
delete_workflow_pattern:
description:
- 'The name or filename of the workflow. if not set then it will target
- all workflows.'
+ 'The name or filename of the workflow. if not set then it will target all
+ workflows.'
required: false
delete_workflow_by_state_pattern:
description:
@@ -40,8 +40,8 @@ on:
- disabled_manually
delete_run_by_conclusion_pattern:
description:
- 'Remove workflow by conclusion: action_required, cancelled, failure,
- skipped, success'
+ 'Remove workflow by conclusion: action_required, cancelled, failure, skipped,
+ success'
required: true
default: 'All'
type: choice
@@ -53,8 +53,13 @@ on:
- skipped
- success
dry_run:
- description: 'Only log actions, do not perform any delete operations.'
+ description: 'Only log actions, do not perform any delete operations (dry run).'
required: false
+ default: 'false'
+ type: choice
+ options:
+ - 'false'
+ - 'true'
jobs:
del-runs:
@@ -71,8 +76,7 @@ jobs:
repository: ${{ github.repository }}
retain_days: ${{ github.event.inputs.days }}
keep_minimum_runs: ${{ github.event.inputs.minimum_runs }}
- delete_workflow_pattern:
- ${{ github.event.inputs.delete_workflow_pattern }}
+ delete_workflow_pattern: ${{ github.event.inputs.delete_workflow_pattern }}
delete_workflow_by_state_pattern:
${{ github.event.inputs.delete_workflow_by_state_pattern }}
delete_run_by_conclusion_pattern:
diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yml
similarity index 50%
rename from .github/workflows/coverage.yaml
rename to .github/workflows/coverage.yml
index 96ae3386..cd9ff1e0 100644
--- a/.github/workflows/coverage.yaml
+++ b/.github/workflows/coverage.yml
@@ -3,6 +3,8 @@ name: Coverage checks
on:
# Trigger the workflow on push
push:
+ # Do not run on version tags (those are handled by other workflows)
+ tags-ignore: ['v*']
# Trigger the workflow on pull request
pull_request:
# Allows you to run this workflow manually from the Actions tab
@@ -16,8 +18,7 @@ permissions:
# 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.event.pull_request.number || github.ref }}
cancel-in-progress: true
# Set the environment variables to be used in all jobs defined in this workflow
@@ -34,18 +35,7 @@ jobs:
uses: actions/checkout@v5
- name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
+ uses: ./.github/actions/setup-pixi
- name: Run docstring coverage
run: pixi run docstring-coverage
@@ -59,34 +49,21 @@ jobs:
uses: actions/checkout@v5
- name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
+ uses: ./.github/actions/setup-pixi
- name: Run unit tests with coverage
run: pixi run unit-tests-coverage --cov-report=xml:coverage-unit.xml
- name: Upload unit tests coverage to Codecov
if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
+ uses: ./.github/actions/upload-codecov
with:
name: unit-tests-job
flags: unittests
files: ./coverage-unit.xml
- fail_ci_if_error: true
- verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- # Job 3: Run integration tests with coverage and upload to Codecov
+ # Job 2: Run integration tests with coverage and upload to Codecov
integration-tests-coverage:
runs-on: ubuntu-latest
@@ -95,53 +72,23 @@ jobs:
uses: actions/checkout@v5
- name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
+ uses: ./.github/actions/setup-pixi
- name: Run integration tests with coverage
run:
- pixi run integration-tests-coverage
- --cov-report=xml:coverage-integration.xml
+ pixi run integration-tests-coverage --cov-report=xml:coverage-integration.xml
- name: Upload integration tests coverage to Codecov
if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
+ uses: ./.github/actions/upload-codecov
with:
name: integration-tests-job
flags: integration
files: ./coverage-integration.xml
- fail_ci_if_error: true
- verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- # Job 4: Trigger dashboard build
- dashboard-build-trigger:
+ # Job 4: Build and publish dashboard (reusable workflow)
+ run-reusable-workflows:
needs: [docstring-coverage, unit-tests-coverage, integration-tests-coverage] # depend on the previous jobs
-
- runs-on: ubuntu-latest
-
- steps:
- - name: Check-out repository
- uses: actions/checkout@v5
-
- - name: Trigger dashboard build
- uses: actions/github-script@v7
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- await github.rest.actions.createWorkflowDispatch({
- owner: context.repo.owner,
- repo: context.repo.repo,
- workflow_id: "dashboard.yaml",
- ref: "${{ env.CI_BRANCH }}"
- });
+ uses: ./.github/workflows/dashboard.yml
+ secrets: inherit
diff --git a/.github/workflows/dashboard.yaml b/.github/workflows/dashboard.yml
similarity index 66%
rename from .github/workflows/dashboard.yaml
rename to .github/workflows/dashboard.yml
index 71d64401..5159f71b 100644
--- a/.github/workflows/dashboard.yaml
+++ b/.github/workflows/dashboard.yml
@@ -4,12 +4,8 @@ on:
workflow_dispatch:
workflow_call:
-# 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 }}
- cancel-in-progress: true
+permissions:
+ contents: read
# Set the environment variables to be used in all jobs defined in this workflow
env:
@@ -24,78 +20,83 @@ jobs:
runs-on: ubuntu-latest
steps:
- # Create GitHub App token for pushing to external dashboard repo.
- # The 'repositories' parameter is required to grant access to repos
- # other than the one where the workflow is running.
- - name: Create GitHub App installation token
- id: app-token
- uses: actions/create-github-app-token@v2
- with:
- app-id: ${{ vars.EASYSCIENCE_APP_ID }}
- private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
- repositories: |
- ${{ github.event.repository.name }}
- dashboard
-
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
+ uses: ./.github/actions/setup-pixi
+
+ - name: Install badgery
shell: bash
- run: |
- pixi run dev
- pixi add --pypi --git https://github.com/enhantica/badgery badgery
+ run: pixi add --pypi --git https://github.com/enhantica/badgery badgery
- name: Run docstring coverage and code complexity/maintainability checks
run: |
- for BRANCH in ${{ env.DEFAULT_BRANCH }} ${{ env.DEVELOP_BRANCH }} ${{ env.CI_BRANCH }}; do
- echo "=== Processing branch $BRANCH ==="
+ for BRANCH in $DEFAULT_BRANCH $DEVELOP_BRANCH $CI_BRANCH; do
+ echo
+ echo "🔹🔸🔹🔸🔹 Processing branch $BRANCH 🔹🔸🔹🔸🔹"
if [ -d "../$BRANCH" ]; then
echo "Branch $BRANCH already processed, skipping"
continue
fi
+
git worktree add ../$BRANCH origin/$BRANCH
mkdir -p reports/$BRANCH
+
echo "Docstring coverage for branch $BRANCH"
pixi run interrogate -c pyproject.toml --fail-under=0 ../$BRANCH/src > reports/$BRANCH/coverage-docstring.txt
+
echo "Cyclomatic complexity for branch $BRANCH"
pixi run radon cc -s -j ../$BRANCH/src > reports/$BRANCH/cyclomatic-complexity.json
+
echo "Maintainability index for branch $BRANCH"
pixi run radon mi -j ../$BRANCH/src > reports/$BRANCH/maintainability-index.json
+
echo "Raw metrics for branch $BRANCH"
pixi run radon raw -s -j ../$BRANCH/src > reports/$BRANCH/raw-metrics.json
done
- name: Generate dashboard HTML
run: >
- pixi run python -m badgery --config .badgery.yaml --repo ${{
- github.repository }} --branch ${{ env.CI_BRANCH }} --output index.html
+ pixi run python -m badgery --config .badgery.yaml --repo ${{ github.repository
+ }} --branch ${{ env.CI_BRANCH }} --output index.html
- name: Prepare publish directory
run: |
mkdir -p _dashboard_publish/${{ env.REPO_NAME }}/${{ env.CI_BRANCH }}
cp index.html _dashboard_publish/${{ env.REPO_NAME }}/${{ env.CI_BRANCH }}
+ # Create GitHub App token for pushing to external dashboard repo.
+ # The 'repositories' parameter is required to grant access to repos
+ # other than the one where the workflow is running.
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
+ with:
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
+ repositories: |
+ ${{ github.event.repository.name }}
+ dashboard
+
+ # Publish to external dashboard repository with retry logic.
+ # Retry is needed to handle transient GitHub API/authentication issues
+ # that occasionally cause 403 errors when multiple workflows push concurrently.
+ # Uses personal_token (not github_token) as GITHUB_TOKEN cannot access external repos.
- name: Publish to main branch of ${{ github.repository }}
- uses: peaceiris/actions-gh-pages@v3
+ uses: Wandalen/wretry.action@v3.8.0
with:
- external_repository: ${{ env.REPO_OWNER }}/dashboard
- publish_branch: ${{ env.DEFAULT_BRANCH }}
- personal_token: ${{ steps.app-token.outputs.token }}
- publish_dir: ./_dashboard_publish
- keep_files: true
+ attempt_limit: 3
+ attempt_delay: 15000 # 15 seconds between retries
+ action: peaceiris/actions-gh-pages@v4
+ with: |
+ publish_dir: ./_dashboard_publish
+ keep_files: true
+ external_repository: ${{ env.REPO_OWNER }}/dashboard
+ publish_branch: master
+ personal_token: ${{ steps.bot.outputs.token }}
- name: Add dashboard link to summary
run: |
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yml
similarity index 66%
rename from .github/workflows/docs.yaml
rename to .github/workflows/docs.yml
index f9bddf67..66b06e1d 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yml
@@ -14,16 +14,16 @@
name: Docs build and deployment
on:
- # Trigger the workflow on pull request
- pull_request:
- # Selected branches
- branches: [master, main, develop]
# Trigger the workflow on push
push:
# Selected branches
- branches: [master, main, develop]
+ branches: [develop] # master and main are already verified in PR
# Runs on creating a new tag starting with 'v', e.g. 'v1.0.3'
tags: ['v*']
+ # Trigger the workflow on pull request
+ pull_request:
+ # Selected branches
+ branches: [master, main, develop]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
@@ -53,11 +53,7 @@ jobs:
# Single job that builds and deploys documentation.
# Uses macOS runner for consistent Plotly chart rendering.
build-deploy-docs:
- strategy:
- matrix:
- os: [macos-14]
-
- runs-on: ${{ matrix.os }}
+ runs-on: ubuntu-latest # macos-latest
permissions:
contents: write # Required for pushing to the gh-pages branch
@@ -83,22 +79,11 @@ jobs:
fi
echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "$GITHUB_ENV"
echo "DOCS_VERSION=${DOCS_VERSION}" >> "$GITHUB_ENV"
- echo "DEPLOYMENT_URL=https://easyscience.github.io/${{ github.event.repository.name }}/${DOCS_VERSION}" >> "$GITHUB_ENV"
-
- # Create GitHub App token for pushing to gh-pages as easyscience[bot].
- - name: Create GitHub App installation token
- id: app-token
- uses: actions/create-github-app-token@v2
- with:
- app-id: ${{ vars.EASYSCIENCE_APP_ID }}
- private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
# Check out the repository source code.
# Note: The gh-pages branch is fetched separately later for mike deployment.
- - name: Check-out repository
+ - name: Checkout repository
uses: actions/checkout@v5
- with:
- token: ${{ steps.app-token.outputs.token }}
# 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
@@ -114,83 +99,53 @@ jobs:
# Set up the pixi package manager and install dependencies from pixi.toml.
# Uses frozen lockfile to ensure reproducible builds.
- name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- # Install additional development dependencies (e.g., pre-commit hooks, dev tools).
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
-
- # Clone shared documentation assets and branding resources from external repositories.
- # These contain common MkDocs configuration, templates, stylesheets, and images.
- - name: Clone easyscience/assets-docs and easyscience/assets-branding
- run: |
- cd ..
- git clone https://github.com/easyscience/assets-docs.git
- git clone https://github.com/easyscience/assets-branding.git
-
- # Copy assets from the cloned repositories into the docs/ directory.
- # This includes stylesheets, images, templates, and other shared resources.
- - name: Add files from cloned repositories
- run: pixi run docs-assets
-
- # Convert Python scripts in the tutorials/ directory to Jupyter notebooks.
- # This step also strips any existing output from the notebooks and prepares
- # them for documentation.
- - name: Convert tutorial scripts to notebooks
- run: pixi run notebook-prepare
-
- # Pre-import the main package to trigger Matplotlib font cache building.
- # This avoids "Matplotlib is building the font cache" messages during notebook execution.
+ uses: ./.github/actions/setup-pixi
+ # Pre-import the main package to exclude info messages from the docs
+ # E.g., Matplotlib may print messages to stdout/stderr when first
+ # imported. This step allows to avoid "Matplotlib is building the font
+ # cache" messages during notebook execution.
- name: Pre-build site step
run: pixi run python -c "import easydiffraction"
+ # Prepare the Jupyter notebooks for documentation (strip output, etc.).
+ - name: Prepare notebooks
+ run: pixi run notebook-prepare
+
# Execute all Jupyter notebooks to generate output cells (plots, tables, etc.).
# Uses multiple cores for parallel execution to speed up the process.
- name: Run notebooks
- # if: false # Temporarily disabled to speed up the docs build
+ # if: false # Temporarily disabled to speed up the docs build
run: pixi run notebook-exec
- # Move the executed notebooks to docs/tutorials/ directory
- # so they can be included in the documentation site.
- - name: Move notebooks to docs/tutorials
- run: pixi run docs-notebooks
-
- # Create the mkdocs.yml configuration file
- # The file is created by merging two files:
- # - assets-docs/mkdocs.yml - the common configuration (theme, plugins, etc.)
- # - docs/mkdocs.yml - the project-specific configuration (project name, TOC, etc.)
- - name: Create mkdocs.yml file
- run: pixi run docs-config
-
# Build the static files for the documentation site for local inspection
# Input: docs/ directory containing the Markdown files
# Output: site/ directory containing the generated HTML files
- name: Build site for local check
- run: pixi run docs-local
+ run: pixi run docs-build-local
# Upload the static files from the site/ directory to be used for
# local check
- name: Upload built site as artifact
- uses: actions/upload-artifact@v4
+ uses: ./.github/actions/upload-artifact
+ with:
+ name: site-local_easydiffraction-lib-${{ env.RELEASE_VERSION }}
+ path: docs/site/
+
+ # Create GitHub App token for pushing to gh-pages as easyscience[bot].
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
with:
- name: site-local_edl-${{ env.RELEASE_VERSION }}
- path: site/
- if-no-files-found: 'error'
- compression-level: 0
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
- # Configure git user for mike to commit and push to gh-pages branch.
+ # Configure git identity and remote URL so mike pushes as easyscience[bot].
- name: Configure git for pushing
run: |
+ set -euo pipefail
git config user.name "easyscience[bot]"
git config user.email "${{ vars.EASYSCIENCE_APP_ID }}+easyscience[bot]@users.noreply.github.com"
+ git remote set-url origin "https://x-access-token:${{ steps.bot.outputs.token }}@github.com/${{ github.repository }}.git"
# Fetch the gh-pages branch to ensure mike has the latest remote state.
# This is required because the checkout step only fetches the source branch,
@@ -206,10 +161,24 @@ jobs:
# Also sets 'latest' as the default version for the version selector.
- name: Rebuild and deploy docs with mike
run: |
+ # Exit on error (-e), undefined vars (-u), and pipeline failures (pipefail)
+ set -euo pipefail
+
+ REPO_NAME="${{ github.event.repository.name }}"
+ BASE_URL="https://easyscience.github.io/${REPO_NAME}"
+
+ # Deploy the release version and update the "latest" alias
if [[ "${IS_RELEASE_TAG}" == "true" ]]; then
- pixi run docs-deploy "${RELEASE_VERSION#v}" latest
+ pixi run docs-deploy-pre "${RELEASE_VERSION#v}" latest
+ pixi run docs-set-default-pre latest
+ DEPLOYMENT_URL="${BASE_URL}/latest"
+
+ # Deploy/update the "dev" alias (or whatever your convention is)
else
- pixi run docs-deploy dev
+ pixi run docs-deploy-pre dev
+ DEPLOYMENT_URL="${BASE_URL}/dev"
+
fi
- pixi run docs-set-default latest
- echo "🔗 deployment url [${{ env.DEPLOYMENT_URL }}](${{ env.DEPLOYMENT_URL }})" >> $GITHUB_STEP_SUMMARY
+
+ # Add links to the action summary page for easy access
+ echo "🔗 deployment url [${DEPLOYMENT_URL}](${DEPLOYMENT_URL})" >> "${GITHUB_STEP_SUMMARY}"
diff --git a/.github/workflows/issues-labels.yml b/.github/workflows/issues-labels.yml
new file mode 100644
index 00000000..3a60cdd7
--- /dev/null
+++ b/.github/workflows/issues-labels.yml
@@ -0,0 +1,42 @@
+# Verifies if an issue has at least one of the `[scope]` and one of the
+# `[priority]` labels. If not, the bot adds labels with a warning emoji
+# to indicate that those labels need to be added.
+
+name: Issue labels check
+
+on:
+ issues:
+ types: [opened, labeled, unlabeled]
+
+permissions:
+ issues: write
+
+jobs:
+ check-labels:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
+ with:
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
+
+ - name: Check for required [scope] label
+ uses: trstringer/require-label-prefix@v1
+ with:
+ secret: ${{ steps.bot.outputs.token }}
+ prefix: '[scope]'
+ labelSeparator: ' '
+ addLabel: true
+ defaultLabel: '[scope] ⚠️ label needed'
+
+ - name: Check for required [priority] label
+ uses: trstringer/require-label-prefix@v1
+ with:
+ secret: ${{ steps.bot.outputs.token }}
+ prefix: '[priority]'
+ labelSeparator: ' '
+ addLabel: true
+ defaultLabel: '[priority] ⚠️ label needed'
diff --git a/.github/workflows/lint-format.yml b/.github/workflows/lint-format.yml
new file mode 100644
index 00000000..f1135fa5
--- /dev/null
+++ b/.github/workflows/lint-format.yml
@@ -0,0 +1,124 @@
+# The workflow checks
+# - the validity of pyproject.toml,
+# - the presence and correctness of SPDX license headers,
+# - linting and formatting of Python code,
+# - linting and formatting of docstrings in Python code,
+# - formatting of non-Python files (like markdown and toml).
+# - linting of Python code in Jupyter notebooks (for library template).
+#
+# A summary of the checks is added to the GitHub Actions summary.
+
+name: Lint and format checks
+
+on:
+ # Trigger the workflow on push
+ push:
+ branches-ignore: [master, main] # Already verified in PR
+ # Do not run this workflow on creating a new tag starting with
+ # 'v', e.g. 'v1.0.3' (see publish-pypi.yml)
+ tags-ignore: ['v*']
+ # Trigger the workflow on pull request
+ pull_request:
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# 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 }}
+ 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 }}
+
+jobs:
+ lint-format:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+
+ - name: Set up pixi
+ uses: ./.github/actions/setup-pixi
+
+ - name: Run post-install developer steps
+ run: pixi run post-install
+
+ - name: Check validity of pyproject.toml
+ id: pyproject
+ continue-on-error: true
+ shell: bash
+ run: pixi run pyproject-check
+
+ - name: Check SPDX license headers
+ id: license_headers
+ continue-on-error: true
+ shell: bash
+ run: pixi run license-check
+
+ - name: Check linting of Python code
+ id: py_lint
+ continue-on-error: true
+ shell: bash
+ run: pixi run py-lint-check
+
+ - name: Check formatting of Python code
+ id: py_format
+ continue-on-error: true
+ shell: bash
+ run: pixi run py-format-check
+
+ - name: Check linting of docstrings in Python code
+ id: docstring_lint
+ continue-on-error: true
+ shell: bash
+ run: pixi run docstring-lint-check
+
+ - name: Check formatting of non-Python files (md, toml, etc.)
+ id: nonpy_format
+ continue-on-error: true
+ shell: bash
+ run: pixi run nonpy-format-check
+
+ - name: Check linting of Python code in Jupyter notebooks (ipynb)
+ id: notebook_lint
+ continue-on-error: true
+ shell: bash
+ run: pixi run notebook-lint-check
+
+ # Add summary
+ - name: Add quality checks summary
+ if: always()
+ shell: bash
+ run: |
+ {
+ echo "## 🧪 Checks Summary"
+ echo ""
+ echo "| Check | Status |"
+ echo "|-------|--------|"
+ echo "| pyproject.toml | ${{ steps.pyproject.outcome == 'success' && '✅' || '❌' }} |"
+ echo "| license headers | ${{ steps.license_headers.outcome == 'success' && '✅' || '❌' }} |"
+ 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 "| nonpy format | ${{ steps.nonpy_format.outcome == 'success' && '✅' || '❌' }} |"
+ echo "| notebooks lint | ${{ steps.notebook_lint.outcome == 'success' && '✅' || '❌' }} |"
+ } >> "$GITHUB_STEP_SUMMARY"
+
+ # Fail job if any check failed
+ - name: Fail job if any check failed
+ if: |
+ steps.pyproject.outcome == 'failure'
+ || steps.license_headers.outcome == 'failure'
+ || steps.py_lint.outcome == 'failure'
+ || steps.py_format.outcome == 'failure'
+ || steps.docstring_lint.outcome == 'failure'
+ || steps.nonpy_format.outcome == 'failure'
+ || steps.notebook_lint.outcome == 'failure'
+ shell: bash
+ run: exit 1
diff --git a/.github/workflows/labels.yaml b/.github/workflows/pr-labels.yml
similarity index 70%
rename from .github/workflows/labels.yaml
rename to .github/workflows/pr-labels.yml
index 1e8bd846..642cd318 100644
--- a/.github/workflows/labels.yaml
+++ b/.github/workflows/pr-labels.yml
@@ -1,7 +1,16 @@
# Verifies if a pull request has at least one label from a set of valid
# labels before it can be merged.
+#
+# NOTE:
+# This workflow may be triggered twice in quick succession when a PR is
+# created:
+# 1) `opened` — when the pull request is initially created
+# 2) `labeled` — if labels are added immediately after creation
+# (e.g. by manual labeling, another workflow, or GitHub App).
+#
+# These are separate GitHub events, so two workflow runs can be started.
-name: PR label checks
+name: PR labels check
on:
pull_request_target:
@@ -11,15 +20,17 @@ permissions:
pull-requests: read
jobs:
- require-label:
+ check-labels:
runs-on: ubuntu-latest
+
steps:
- - name: Validate required labels
+ - name: Check for valid labels
run: |
PR_LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r '.[]')
+
echo "Current PR labels: $PR_LABELS"
VALID_LABELS=(
- "[maintainer] auto-pull-request"
+ "[bot] release"
"[scope] bug"
"[scope] documentation"
"[scope] enhancement"
diff --git a/.github/workflows/pypi-publish.yaml b/.github/workflows/pypi-publish.yaml
deleted file mode 100644
index 7767f8d2..00000000
--- a/.github/workflows/pypi-publish.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-# Builds a Python package and publish it to PyPI when a new tag is
-# created.
-
-name: PyPI publishing
-
-on:
- # Runs on creating a new tag starting with 'v', e.g. 'v1.0.3'
- push:
- tags: ['v*']
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-jobs:
- pypi-publish:
- runs-on: ubuntu-latest
-
- steps:
- - name: Check-out repository
- uses: actions/checkout@v5
- with:
- fetch-depth: '0' # full history with tags to get the version number by versioningit
-
- - name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
-
- - name: Create Python package
- run: pixi run python -m build
-
- - name: Publish distribution 📦 to PyPI
- uses: pypa/gh-action-pypi-publish@release/v1
- with:
- password: ${{ secrets.PYPI_PASSWORD }}
diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml
new file mode 100644
index 00000000..e9986cac
--- /dev/null
+++ b/.github/workflows/pypi-publish.yml
@@ -0,0 +1,46 @@
+# Builds a Python package and publish it to PyPI when a new tag is
+# created.
+
+name: PyPI publishing
+
+on:
+ # Runs on creating a new tag starting with 'v', e.g. 'v1.0.3'
+ push:
+ tags: ['v*']
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+jobs:
+ pypi-publish:
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
+
+ steps:
+ - name: Check-out repository
+ uses: actions/checkout@v5
+ with:
+ fetch-depth: 0 # full history with tags to get the version number by versioningit
+
+ - name: Set up pixi
+ uses: ./.github/actions/setup-pixi
+
+ # Build the Python package (to dist/ folder)
+ - name: Create Python package
+ run: pixi run default-build
+
+ # Publish the package to PyPI (from dist/ folder)
+ # Instead of publishing with personal access token, we use
+ # GitHub Actions OIDC to get a short-lived token from PyPI.
+ # New publisher must be previously configured in PyPI at
+ # https://pypi.org/manage/project/easydiffraction/settings/publishing/
+ # Use the following data:
+ # Owner: easyscience
+ # Repository name: diffraction-lib
+ # Workflow name: pypi-publish.yml
+ - name: Publish to PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ packages-dir: 'dist'
diff --git a/.github/workflows/pypi-test.yaml b/.github/workflows/pypi-test.yaml
deleted file mode 100644
index e083846e..00000000
--- a/.github/workflows/pypi-test.yaml
+++ /dev/null
@@ -1,97 +0,0 @@
-name: PyPI package tests
-
-on:
- # Run daily, at 00:00.
- schedule:
- - cron: '0 0 * * *'
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-# 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 }}
- cancel-in-progress: true
-
-# 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:
- strategy:
- matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
-
- runs-on: ${{ matrix.os }}
-
- steps:
- - name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- run-install: false
- cache: false
- post-cleanup: false
-
- - name:
- Download the pixi configuration file from the ${{ env.CI_BRANCH}}
- branch
- shell: bash
- run: |
- curl -LO https://raw.githubusercontent.com/easyscience/diffraction-lib/${CI_BRANCH}/pixi.toml
-
- - name: Download the tests from the ${{ env.DEFAULT_BRANCH }} branch
- shell: bash
- run: |
- curl -LO https://github.com/easyscience/diffraction-lib/archive/refs/heads/${DEFAULT_BRANCH}.zip
- unzip ${DEFAULT_BRANCH}.zip -d .
- mkdir -p tests
- cp -r diffraction-lib-${DEFAULT_BRANCH}/tests/* tests/
- cp diffraction-lib-${DEFAULT_BRANCH}/pytest.ini .
- rm -rf ${DEFAULT_BRANCH}.zip diffraction-lib-${DEFAULT_BRANCH}
-
- - name: Create the environment and install dependencies
- run: pixi install
-
- - name: Run unit tests to verify the installation
- run: pixi run unit-tests
-
- - name: Run integration tests to verify the installation
- run: pixi run integration-tests
-
- # Github token to avoid hitting the unauthenticated API rate limit
- - name: List and fetch the EasyDiffraction tutorials
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- pixi run easydiffraction --version
- pixi run easydiffraction list-tutorials
- pixi run easydiffraction download-all-tutorials
-
- - name: Test tutorials as notebooks
- run: pixi run notebook-tests
-
- # Job 2: Trigger dashboard build
- dashboard-build-trigger:
- needs: pypi-package-tests
-
- runs-on: ubuntu-latest
-
- steps:
- - name: Check-out repository
- uses: actions/checkout@v5
-
- - name: Trigger dashboard build
- uses: actions/github-script@v7
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- await github.rest.actions.createWorkflowDispatch({
- owner: context.repo.owner,
- repo: context.repo.repo,
- workflow_id: "dashboard.yaml",
- ref: "${{ env.CI_BRANCH }}"
- });
diff --git a/.github/workflows/pypi-test.yml b/.github/workflows/pypi-test.yml
new file mode 100644
index 00000000..6493e64f
--- /dev/null
+++ b/.github/workflows/pypi-test.yml
@@ -0,0 +1,80 @@
+name: PyPI package tests
+
+on:
+ # Run daily, at 00:00.
+ schedule:
+ - cron: '0 0 * * *'
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# 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 }}
+ 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:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+
+ - name: Set up pixi
+ uses: ./.github/actions/setup-pixi
+ with:
+ environments: ''
+ activate-environment: ''
+ run-install: false
+ frozen: false
+
+ - name: Init pixi project
+ run: pixi init easydiffraction
+
+ - name: Add Python 3.13 from Conda
+ working-directory: easydiffraction
+ run: pixi add "python=3.13"
+
+ - name: Add other Conda dependencies
+ working-directory: easydiffraction
+ run: pixi add gsl
+
+ - name: Add easydiffraction from PyPI
+ working-directory: easydiffraction
+ run: pixi add --pypi "easydiffraction"
+
+ - name: Add dev dependencies from PyPI
+ working-directory: easydiffraction
+ run: pixi add --pypi pytest pytest-xdist
+
+ - name: Add Pixi task as a shortcut
+ working-directory: easydiffraction
+ run: pixi task add easydiffraction "python -m easydiffraction"
+
+ - name: Run unit tests to verify the installation
+ working-directory: easydiffraction
+ run: pixi run python -m pytest ../tests/unit/ --color=yes -v
+
+ - name: Run integration tests to verify the installation
+ working-directory: easydiffraction
+ run: pixi run python -m pytest ../tests/integration/ --color=yes -n auto
+
+ # Job 2: Build and publish dashboard (reusable workflow)
+ run-reusable-workflows:
+ needs: pypi-package-tests # depend on previous job
+ uses: ./.github/workflows/dashboard.yml
+ secrets: inherit
diff --git a/.github/workflows/quality.yaml b/.github/workflows/quality.yaml
deleted file mode 100644
index a3c1b72a..00000000
--- a/.github/workflows/quality.yaml
+++ /dev/null
@@ -1,123 +0,0 @@
-# The workflow is divided into several steps to ensure code quality:
-# - Check the validity of pyproject.toml
-# - Check code linting
-# - Check code formatting
-# - Check formatting of docstrings in the code
-# - Check formatting of Markdown, YAML, TOML, etc. files
-
-name: Code quality checks
-
-on:
- # Trigger the workflow on push
- push:
- # Every branch
- branches: ['**']
- # Do not run this workflow on creating a new tag starting with
- # 'v', e.g. 'v1.0.3' (see publish-pypi.yml)
- tags-ignore: ['v*']
- # Trigger the workflow on pull request
- pull_request:
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-# 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 }}
- cancel-in-progress: true
-
-# Set the environment variables to be used in all jobs defined in this workflow
-env:
- CI_BRANCH: ${{ github.head_ref || github.ref_name }}
-
-jobs:
- code-quality:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v5
-
- - name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
-
- # Check the validity of pyproject.toml
- - name: Check validity of pyproject.toml
- id: check_pyproject
- continue-on-error: true
- shell: bash
- run: pixi run pyproject-check
-
- # Check code linting with Ruff in the project root
- - name: Check code linting
- id: check_code_linting
- continue-on-error: true
- shell: bash
- run: pixi run py-lint-check
-
- # Check code formatting with Ruff in the project root
- - name: Check code formatting
- id: check_code_formatting
- continue-on-error: true
- shell: bash
- run: pixi run py-format-check
-
- # Check formatting of docstrings in the code with docformatter
- - name: Check formatting of docstrings in the code
- id: check_docs_formatting
- continue-on-error: true
- shell: bash
- run: pixi run docs-format-check
-
- # Check formatting of MD, YAML, TOML, etc. files with Prettier in
- # the project root
- - name: Check formatting of MD, YAML, TOML, etc. files
- id: check_others_formatting
- continue-on-error: true
- shell: bash
- run: pixi run nonpy-format-check
-
- # Check formatting of Jupyter Notebooks in the tutorials folder
- - name: Convert tutorial scripts to notebooks and check formatting
- id: check_notebooks_formatting
- continue-on-error: true
- shell: bash
- run: |
- pixi run notebook-prepare
- pixi run notebook-format-check
-
- # Add summary
- - name: Add quality checks summary
- if: always()
- shell: bash
- run: |
- {
- echo "## 🧪 Code Quality Checks Summary"
- echo ""
- echo "| Check | Status |"
- echo "|-------|--------|"
- echo "| pyproject.toml | ${{ steps.check_pyproject.outcome == 'success' && '✅' || '❌' }} |"
- echo "| py lint | ${{ steps.check_code_linting.outcome == 'success' && '✅' || '❌' }} |"
- echo "| py format | ${{ steps.check_code_formatting.outcome == 'success' && '✅' || '❌' }} |"
- echo "| docstring format | ${{ steps.check_docs_formatting.outcome == 'success' && '✅' || '❌' }} |"
- echo "| nonpy format | ${{ steps.check_others_formatting.outcome == 'success' && '✅' || '❌' }} |"
- echo "| notebooks format | ${{ steps.check_notebooks_formatting.outcome == 'success' && '✅' || '❌' }} |"
- } >> "$GITHUB_STEP_SUMMARY"
-
- # Fail job requirement
- - name: Fail job if any check failed
- if: failure()
- shell: bash
- run: exit 1
diff --git a/.github/workflows/release-notes.yaml b/.github/workflows/release-notes.yml
similarity index 81%
rename from .github/workflows/release-notes.yaml
rename to .github/workflows/release-notes.yml
index 73006ff2..cb3e28d6 100644
--- a/.github/workflows/release-notes.yaml
+++ b/.github/workflows/release-notes.yml
@@ -25,18 +25,14 @@ jobs:
fetch-depth: 0 # full history with tags to get the version number
- name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
+ uses: ./.github/actions/setup-pixi
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
+ with:
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
- name: Drafts the next release notes
id: draft
@@ -61,9 +57,8 @@ jobs:
labels: ['[scope] bug']
- title: 'Changed'
labels: ['[scope] maintenance', '[scope] documentation']
-
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_TOKEN: ${{ steps.bot.outputs.token }}
- name: Create GitHub draft release
uses: softprops/action-gh-release@v2
@@ -73,4 +68,4 @@ jobs:
name: ${{ steps.draft.outputs.release_name }}
body: ${{ steps.draft.outputs.release_notes }}
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_TOKEN: ${{ steps.bot.outputs.token }}
diff --git a/.github/workflows/release-pr.yaml b/.github/workflows/release-pr.yaml
deleted file mode 100644
index eda67884..00000000
--- a/.github/workflows/release-pr.yaml
+++ /dev/null
@@ -1,57 +0,0 @@
-# This workflow creates an automated release PR from `develop` into `master`.
-#
-# Usage:
-# - Triggered manually via workflow_dispatch.
-# - Creates a PR titled "Release: merge develop into master".
-# - Adds the label "[maintainer] auto-pull-request" so it is excluded from changelogs.
-# - The PR body makes clear that this is automation only (no review needed).
-#
-# Required repo config:
-# https://github.com/organizations/easyscience/settings/secrets/actions
-# https://github.com/organizations/easyscience/settings/variables/actions
-# - Actions secret: EASYSCIENCE_APP_KEY (GitHub App private key PEM)
-# - Actions variable: EASYSCIENCE_APP_ID (GitHub App ID)
-
-name: Release PR (develop -> master)
-
-on:
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-permissions:
- contents: read
- pull-requests: write
-
-# Set the environment variables to be used in all jobs defined in this workflow
-env:
- DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
-
-jobs:
- create-pull-request:
- runs-on: ubuntu-latest
- steps:
- - name: Create GitHub App installation token
- id: app-token
- uses: actions/create-github-app-token@v2
- with:
- app-id: ${{ vars.EASYSCIENCE_APP_ID }}
- private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
-
- - name: Checkout develop branch
- uses: actions/checkout@v5
- with:
- ref: develop
- token: ${{ steps.app-token.outputs.token }}
-
- - name: Create PR from develop to ${{ env.DEFAULT_BRANCH }}
- run: |
- gh pr create \
- --base ${{ env.DEFAULT_BRANCH }} \
- --head develop \
- --title "Release: merge develop into ${{ env.DEFAULT_BRANCH }}" \
- --label "[maintainer] auto-pull-request" \
- --body "This PR is created automatically to trigger the release pipeline. It merges the accumulated changes from \`develop\` into \`${{ env.DEFAULT_BRANCH }}\`.
-
- It is labeled \`[maintainer] auto-pull-request\` and is excluded from release notes and version bump logic."
- env:
- GH_TOKEN: ${{ steps.app-token.outputs.token }}
diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml
new file mode 100644
index 00000000..7e6fda49
--- /dev/null
+++ b/.github/workflows/release-pr.yml
@@ -0,0 +1,55 @@
+# This workflow creates an automated release PR from a source branch into the default branch.
+#
+# Usage:
+# - Triggered manually via workflow_dispatch.
+# - Creates a PR titled "Release: merge into ".
+# - Adds the label "[bot] release" so it is excluded from changelogs.
+# - The PR body makes clear that this is automation only (no review needed).
+
+name: 'Release PR (develop → master)'
+
+on:
+ workflow_dispatch:
+ inputs:
+ source_branch:
+ description: 'Source branch to create PR from'
+ required: false
+ default: 'develop'
+ type: string
+
+permissions:
+ contents: read
+ pull-requests: write
+
+env:
+ DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
+ SOURCE_BRANCH: ${{ inputs.source_branch || 'develop' }}
+
+jobs:
+ create-pull-request:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout ${{ env.SOURCE_BRANCH }} branch
+ uses: actions/checkout@v5
+ with:
+ ref: ${{ env.SOURCE_BRANCH }}
+
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
+ with:
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
+
+ - name: Create PR from ${{ env.SOURCE_BRANCH }} to ${{ env.DEFAULT_BRANCH }}
+ env:
+ GH_TOKEN: ${{ steps.bot.outputs.token }}
+ run: |
+ gh pr create \
+ --base ${{ env.DEFAULT_BRANCH }} \
+ --head ${{ env.SOURCE_BRANCH }} \
+ --title "Release: merge ${{ env.SOURCE_BRANCH }} into ${{ env.DEFAULT_BRANCH }}" \
+ --label "[bot] release" \
+ --body "This PR is created automatically to trigger the release pipeline. It merges the accumulated changes from \`${{ env.SOURCE_BRANCH }}\` into \`${{ env.DEFAULT_BRANCH }}\`.
+
+ ⚠️ It is labeled \`[bot] release\` and is excluded from release notes and version bump logic."
diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml
deleted file mode 100644
index b837b879..00000000
--- a/.github/workflows/security.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-# Integrates a collection of open source static analysis tools with
-# GitHub code scanning.
-# https://github.com/github/ossar-action
-
-name: Security scans
-
-on:
- # Trigger the workflow on pull request
- pull_request:
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-jobs:
- scan-security-ossar:
- # OSSAR runs on windows-latest.
- # ubuntu-latest and macos-latest support coming soon
- runs-on: windows-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v5
- with:
- # We must fetch at least the immediate parents so that if this is
- # a pull request then we can checkout the head.
- fetch-depth: 2
-
- # If this run was triggered by a pull request event, then checkout
- # the head of the pull request instead of the merge commit.
- - run: git checkout HEAD^2
- if: ${{ github.event_name == 'pull_request' }}
-
- - name: Run open source static analysis tools
- uses: github/ossar-action@main
- id: ossar
-
- - name: Upload results to Security tab
- uses: github/codeql-action/upload-sarif@v3
- with:
- sarif_file: ${{ steps.ossar.outputs.sarifFile }}
diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml
new file mode 100644
index 00000000..9b34cccf
--- /dev/null
+++ b/.github/workflows/security.yml
@@ -0,0 +1,93 @@
+# Code scanning (CodeQL) for vulnerabilities and insecure coding patterns.
+#
+# What this workflow does
+# - Runs GitHub CodeQL analysis and uploads results to your repository's Security tab.
+# - Triggers on PRs (so findings appear as PR checks) and on pushes to `develop`.
+# - Runs on a weekly schedule.
+#
+# Where to find results on GitHub
+# - Repository → Security → Code scanning alerts
+# (You can filter by tool = CodeQL and by branch.)
+#
+# Where to configure on GitHub
+# - Repository → Settings → Advanced Security
+# Enable "GitHub Advanced Security" (if available) and configure CodeQL there.
+# - Repository → Security → Code scanning alerts
+# This page shows findings produced by this workflow.
+#
+# Notes about the scheduled run
+# - Scheduled workflows are triggered from the repository's *default branch*.
+# If your default branch is `master` but you want the scheduled scan to analyze
+# `develop`, this workflow checks out `develop` explicitly for scheduled runs.
+#
+# References
+# - CodeQL Action: https://github.com/github/codeql-action
+# - Advanced setup docs: https://docs.github.com/en/code-security/code-scanning
+
+name: Security scans with CodeQL
+
+on:
+ # Run on pull requests so results show up as PR checks and code
+ # scanning alerts.
+ pull_request:
+ branches: [master, main, develop]
+
+ # Run on pushes (e.g., after merging PRs).
+ push:
+ branches: [master, main, develop]
+
+ # Run weekly. (Cron is in UTC.)
+ schedule:
+ - cron: '0 3 * * 1'
+
+permissions:
+ contents: read
+ security-events: write
+
+jobs:
+ codeql:
+ name: Code scanning
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ # Keep this list tight to avoid noise and speed up runs.
+ language: [python, actions]
+
+ steps:
+ # Scheduled workflows run from the default branch.
+ # We explicitly analyze `develop` on the schedule to keep the scan
+ # focused on the active dev branch.
+ - name: Checkout repository (scheduled → develop)
+ if: ${{ github.event_name == 'schedule' }}
+ uses: actions/checkout@v5
+ with:
+ ref: develop
+
+ - name: Checkout repository
+ if: ${{ github.event_name != 'schedule' }}
+ uses: actions/checkout@v5
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v4
+ with:
+ languages: ${{ matrix.language }}
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v4
+
+ print-link:
+ name: Print results link
+ runs-on: ubuntu-latest
+
+ needs: codeql
+ permissions: {} # no special perms needed just to print links
+
+ steps:
+ - name: Add Code Scanning link to job summary
+ run: |
+ echo "## 🔎 CodeQL Results" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "View Code Scanning alerts here:" >> $GITHUB_STEP_SUMMARY
+ echo "${{ github.server_url }}/${{ github.repository }}/security/code-scanning" >> $GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/test-trigger.yaml b/.github/workflows/test-trigger.yml
similarity index 61%
rename from .github/workflows/test-trigger.yaml
rename to .github/workflows/test-trigger.yml
index dedfbd91..ecf6b40c 100644
--- a/.github/workflows/test-trigger.yaml
+++ b/.github/workflows/test-trigger.yml
@@ -7,6 +7,9 @@ on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
+permissions:
+ contents: read
+
jobs:
code-tests-trigger:
runs-on: ubuntu-latest
@@ -17,14 +20,21 @@ jobs:
with:
ref: develop
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
+ with:
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
+
- name: Dispatch code tests workflow
- uses: actions/github-script@v7
+ uses: ./.github/actions/github-script
with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
+ github-token: ${{ steps.bot.outputs.token }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
- workflow_id: "test.yaml",
+ workflow_id: "test.yml",
ref: "develop"
});
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
deleted file mode 100644
index 11b06f14..00000000
--- a/.github/workflows/test.yaml
+++ /dev/null
@@ -1,259 +0,0 @@
-# This is the main workflow for testing the code before and after
-# packaging it.
-# The workflow is divided into three jobs:
-# 1. env-prepare:
-# - Prepare the environment for testing
-# 2. source-test:
-# - Test the code base against the latest code in the repository
-# - Create the Python package
-# - Upload the Python package for the next job
-# 3. package-test:
-# - Download the Python package (including extra files) from the previous job
-# - Install the downloaded Python package
-# - Test the code base against the installed package
-# 4. dashboard-build-trigger:
-# - Trigger the dashboard build workflow to update the code quality
-# metrics on the dashboard
-
-name: Code and package tests
-
-on:
- # Trigger the workflow on push
- push:
- # Every branch
- branches: ['**']
- # But do not run this workflow on creating a new tag starting with
- # 'v', e.g. 'v1.0.3' (see publish-pypi.yml)
- tags-ignore: ['v*']
- # Trigger the workflow on pull request
- pull_request:
- branches: ['**']
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-# Need permissions to trigger the dashboard build workflow
-permissions:
- actions: write
- contents: read
-
-# 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 }}
- cancel-in-progress: true
-
-# Set the environment variables to be used in all jobs defined in this workflow
-env:
- CI_BRANCH: ${{ github.head_ref || github.ref_name }}
-
-jobs:
- # Job 1: Prepare environment
- env-prepare:
- runs-on: [ubuntu-latest]
-
- outputs:
- pytest-marks: ${{ steps.set-mark.outputs.pytest_marks }}
-
- 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
- id: set-mark
- run: |
- if [[ "${{ env.CI_BRANCH }}" == "master" || "${{ env.CI_BRANCH }}" == "develop" ]]; then
- echo "pytest_marks=" >> $GITHUB_OUTPUT
- else
- echo "pytest_marks=-m fast" >> $GITHUB_OUTPUT
- fi
-
- # Job 2: Test code
- source-test:
- needs: env-prepare # depend on previous job
-
- strategy:
- fail-fast: false
- matrix:
- os: [ubuntu-24.04, macos-14, windows-2022]
-
- runs-on: ${{ matrix.os }}
-
- env:
- PIXI_ENVS: 'py311-dev py313-dev'
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v5
- with:
- fetch-depth: '0' # full history with tags to get the version number by versioningit
-
- - name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: ${{ env.PIXI_ENVS }}
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- pixi run --environment $env dev
- echo "PYTHONPATH:"
- pixi run printenv PYTHONPATH || true
- pixi run --environment $env easydiffraction --version
- done
-
- - name: Run unit tests
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- pixi run --environment $env unit-tests
- done
-
- - name:
- Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- pixi run --environment $env integration-tests ${{ needs.env-prepare.outputs.pytest-marks }}
- done
-
- # Delete all local tags when not on a tagged commit to force versioningit
- # to fall back to the configured default-tag, which is '999.0.0' in our case.
- # This is needed for testing the package in the next job, as its version
- # must be higher than the PyPI version for pip to prefer the local version.
- - name: Force using versioningit default tag (non tagged release)
- if: startsWith(github.ref , 'refs/tags/v') != true
- run: git tag --delete $(git tag)
-
- - name: Create Python package
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- pixi run -e $env dist-build
- env_prefix="${env%%-*}"
- echo "📦 Moving built wheel to dist/$env_prefix/"
- pixi run mkdir -p dist/$env_prefix
- pixi run mv dist/*.whl dist/$env_prefix/
- done
-
- - name: Remove local easydiffraction from pixi.toml
- shell: bash
- run: pixi remove --pypi easydiffraction
-
- - name: Remove Python cache files before uploading
- shell: bash
- run: pixi run clean-pycache
-
- # More than one file/dir need to be specified in 'path', to preserve the
- # structure of the dist/ directory, not only its contents.
- - name: Upload Python package for the next job
- uses: actions/upload-artifact@v4
- with:
- name: edl_${{ matrix.os }}_${{ runner.arch }}
- path: |
- dist/
- tests/
- pytest.ini
- pixi.toml
- pixi.lock
- if-no-files-found: 'error'
- compression-level: 0
-
- # Job 3: Test the package
- package-test:
- needs: [env-prepare, source-test] # depend on previous jobs
-
- strategy:
- fail-fast: false
- matrix:
- os: [ubuntu-24.04, macos-14, windows-2022]
-
- runs-on: ${{ matrix.os }}
-
- env:
- PIXI_ENVS: 'py311-dev py313-dev'
-
- steps:
- - name:
- Download zipped Python package (incl. extra files) from previous job
- uses: actions/download-artifact@v4
- with: # name or path are taken from the upload step of the previous job
- name: edl_${{ matrix.os }}_${{ runner.arch }}
- path: . # directory to extract downloaded zipped artifacts
-
- - name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: ${{ env.PIXI_ENVS }}
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- pixi run --environment $env wheel
- done
-
- - name: Install easydiffraction package from the built wheel
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- env_prefix="${env%%-*}"
- echo "📦 Looking for wheel in dist/$env_prefix/"
- whl_path="$(find dist/${env_prefix} -name '*.whl' | head -1)"
- echo "📦 Installing easydiffraction from: $whl_path"
- pixi run --environment $env python -m uv pip install "${whl_path}[all]" --reinstall-package easydiffraction
- pixi run --environment $env easydiffraction --version
- done
-
- - name: Run unit tests
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- pixi run --environment $env unit-tests
- done
-
- - name:
- Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
- shell: bash
- run: |
- for env in ${{ env.PIXI_ENVS }}; do
- echo "🔹🔸🔹🔸🔹 Current env: $env 🔹🔸🔹🔸🔹"
- pixi run --environment $env integration-tests ${{ needs.env-prepare.outputs.pytest-marks }}
- done
-
- # Job 4: Trigger dashboard build
- dashboard-build-trigger:
- needs: [source-test, package-test] # depend on previous jobs
-
- runs-on: ubuntu-latest
-
- steps:
- - name: Check-out repository
- uses: actions/checkout@v5
-
- - name: Trigger dashboard build
- uses: actions/github-script@v7
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- await github.rest.actions.createWorkflowDispatch({
- owner: context.repo.owner,
- repo: context.repo.repo,
- workflow_id: "dashboard.yaml",
- ref: "${{ env.CI_BRANCH }}"
- });
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 00000000..745c0b03
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,279 @@
+# This is the main workflow for testing the code before and after
+# packaging it.
+# The workflow is divided into three jobs:
+# 1. env-prepare:
+# - Prepare the environment for testing
+# 2. source-test:
+# - Test the code base against the latest code in the repository
+# - Create the Python package
+# - Upload the Python package for the next job
+# 3. package-test:
+# - Download the Python package (including extra files) from the previous job
+# - Install the downloaded Python package
+# - Test the code base against the installed package
+# 4. dashboard-build-trigger:
+# - Trigger the dashboard build workflow to update the code quality
+# metrics on the dashboard
+
+name: Code and package tests
+
+on:
+ # Trigger the workflow on push
+ push:
+ branches-ignore: [master, main] # Already verified in PR
+ # But do not run this workflow on creating a new tag starting with
+ # 'v', e.g. 'v1.0.3' (see publish-pypi.yml)
+ tags-ignore: ['v*']
+ # Trigger the workflow on pull request
+ pull_request:
+ branches: ['**']
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# Need permissions to trigger the dashboard build workflow
+permissions:
+ actions: write
+ contents: read
+
+# 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 }}
+ cancel-in-progress: true
+
+# Set the environment variables to be used in all jobs defined in this workflow
+env:
+ CI_BRANCH: ${{ github.head_ref || github.ref_name }}
+ PY_VERSIONS: '3.11 3.13'
+ PIXI_ENVS: 'py-311-env py-313-env'
+
+jobs:
+ # Job 1: Set up environment variables
+ env-prepare:
+ runs-on: [ubuntu-latest]
+
+ outputs:
+ pytest-marks: ${{ steps.set-mark.outputs.pytest_marks }}
+
+ 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
+ id: set-mark
+ run: |
+ if [[ "${{ env.CI_BRANCH }}" == "master" || "${{ env.CI_BRANCH }}" == "develop" ]]; then
+ echo "pytest_marks=" >> $GITHUB_OUTPUT
+ else
+ echo "pytest_marks=-m fast" >> $GITHUB_OUTPUT
+ fi
+
+ # Job 2: Test code
+ source-test:
+ needs: env-prepare # depend on previous job
+
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-24.04, macos-15, windows-2022]
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+
+ - name: Set up pixi
+ uses: ./.github/actions/setup-pixi
+ with:
+ environments: ${{ env.PIXI_ENVS }}
+
+ - name: Run unit tests
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ for py_ver in $PY_VERSIONS; do
+ echo
+ echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹"
+
+ env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.11 -> py-311-env
+
+ echo "Running tests in environment: $env"
+ pixi run --environment $env unit-tests
+ done
+
+ - name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ for py_ver in $PY_VERSIONS; do
+ echo
+ echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹"
+
+ env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.11 -> py-311-env
+
+ echo "Running tests in environment: $env"
+ pixi run --environment $env integration-tests ${{ needs.env-prepare.outputs.pytest-marks }}
+ done
+
+ # Delete all local tags when not on a tagged commit to force versioningit
+ # to fall back to the configured default-tag, which is '999.0.0' in our case.
+ # This is needed for testing the package in the next job, as its version
+ # must be higher than the PyPI version for pip to prefer the local version.
+ - name: Force using versioningit default tag (non tagged release)
+ if: startsWith(github.ref , 'refs/tags/v') != true
+ run: git tag --delete $(git tag)
+
+ - name: Build package wheels for all Python versions
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ for py_ver in $PY_VERSIONS; do
+ echo
+ echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹"
+
+ env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.11 -> py-311-env
+
+ echo "Building wheel in environment: $env"
+ pixi run --environment $env dist-build
+
+ echo "Moving built wheel to dist/py$py_ver/"
+ pixi run mkdir -p dist/py$py_ver
+ pixi run mv dist/*.whl dist/py$py_ver/
+ done
+
+ - name: Remove Python cache files before uploading
+ shell: bash
+ run: pixi run clean-pycache
+
+ # More than one file/dir need to be specified in 'path', to preserve the
+ # structure of the dist/ directory, not only its contents.
+ - name: Upload package (incl. extras) for next job
+ uses: ./.github/actions/upload-artifact
+ with:
+ name: easydiffraction_${{ matrix.os }}_${{ runner.arch }}
+ path: dist/
+
+ # Job 3: Test the package
+ package-test:
+ needs: source-test # depend on previous job
+
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-24.04, macos-15, windows-2022]
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+
+ - name: Download package (incl. extras) from previous job
+ uses: ./.github/actions/download-artifact
+ with:
+ # name and path should be taken from the upload step of the previous job
+ name: easydiffraction_${{ matrix.os }}_${{ runner.arch }}
+ path: dist/
+
+ - name: Set up pixi
+ uses: ./.github/actions/setup-pixi
+ with:
+ environments: ''
+ activate-environment: ''
+ run-install: false
+ frozen: false
+
+ - name: Install easydiffraction from the built wheel
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ for py_ver in $PY_VERSIONS; do
+ echo
+ echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹"
+
+ echo "Initializing pixi project"
+ pixi init easydiffraction_py$py_ver
+ cd easydiffraction_py$py_ver
+
+ echo "Setting macOS 14.0 as minimum required"
+ pixi project system-requirements add macos 14.0
+
+ echo "Adding Python $py_ver"
+ pixi add "python=$py_ver"
+
+ echo "Adding GNU Scientific Library (required by diffpy.pdffit2)"
+ pixi add gsl
+
+ # diffpy.pdffit2 wheel links @rpath/libc++.1.dylib, which must be
+ # present in the conda env lib/ dir on macOS (Python propagates its
+ # own @loader_path/../lib/ rpath to loaded extensions). Added as
+ # platform-specific deps so this is a no-op on Linux/Windows.
+ echo "Adding libc++ for macOS (required by diffpy.pdffit2)"
+ pixi add --platform osx-arm64 libcxx
+ pixi add --platform osx-64 libcxx
+
+ echo "Looking for wheel in ../dist/py$py_ver/"
+ ls -l "../dist/py$py_ver/"
+
+ whl_path=(../dist/"py$py_ver"/*.whl)
+ if [[ ! -f "${whl_path[0]}" ]]; then
+ echo "❌ No wheel found in ../dist/py$py_ver/"
+ exit 1
+ fi
+
+ whl_url="file://$(python -c 'import os,sys; print(os.path.abspath(sys.argv[1]))' "${whl_path[0]}")"
+
+ echo "Adding easydiffraction from: $whl_url"
+ pixi add --pypi "easydiffraction[dev] @ ${whl_url}"
+
+ echo "Exiting pixi project directory"
+ cd ..
+ done
+
+ - name: Run unit tests
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ for py_ver in $PY_VERSIONS; do
+ echo
+ echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹"
+
+ echo "Entering pixi project directory easydiffraction_py$py_ver"
+ cd easydiffraction_py$py_ver
+
+ echo "Running tests"
+ pixi run python -m pytest ../tests/unit/ --color=yes -v
+
+ echo "Exiting pixi project directory"
+ cd ..
+ done
+
+ - name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ for py_ver in $PY_VERSIONS; do
+ echo
+ echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹"
+
+ echo "Entering pixi project directory easydiffraction_py$py_ver"
+ cd easydiffraction_py$py_ver
+
+ echo "Running tests"
+ pixi run python -m pytest ../tests/integration/ --color=yes -n auto -v ${{ needs.env-prepare.outputs.pytest-marks }}
+
+ echo "Exiting pixi project directory"
+ cd ..
+ done
+
+ # Job 4: Build and publish dashboard (reusable workflow)
+ run-reusable-workflows:
+ needs: package-test # depend on previous job
+ uses: ./.github/workflows/dashboard.yml
+ secrets: inherit
diff --git a/.github/workflows/tutorial-tests-colab.yaml b/.github/workflows/tutorial-tests-colab.yaml
index 08e2e2b6..35c4a753 100644
--- a/.github/workflows/tutorial-tests-colab.yaml
+++ b/.github/workflows/tutorial-tests-colab.yaml
@@ -7,8 +7,7 @@ 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.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
@@ -37,10 +36,10 @@ jobs:
- name: Install Python dependencies
run:
- python -m pip install 'easydiffraction[visualization]' nbconvert
- nbmake pytest pytest-xdist
+ python -m pip install 'easydiffraction[visualization]' nbconvert nbmake pytest
+ pytest-xdist
- name: Check if Jupyter Notebooks run without errors
run: >
- python -m pytest --nbmake docs/tutorials/ --nbmake-timeout=600
- --color=yes -n=auto
+ python -m pytest --nbmake docs/tutorials/ --nbmake-timeout=600 --color=yes
+ -n=auto
diff --git a/.github/workflows/tutorial-tests-trigger.yaml b/.github/workflows/tutorial-tests-trigger.yml
similarity index 61%
rename from .github/workflows/tutorial-tests-trigger.yaml
rename to .github/workflows/tutorial-tests-trigger.yml
index ea32eef2..1bc27f4f 100644
--- a/.github/workflows/tutorial-tests-trigger.yaml
+++ b/.github/workflows/tutorial-tests-trigger.yml
@@ -7,6 +7,9 @@ on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
+permissions:
+ contents: read
+
jobs:
tutorial-tests-trigger:
runs-on: ubuntu-latest
@@ -17,14 +20,21 @@ jobs:
with:
ref: develop
+ - name: Setup easyscience[bot]
+ id: bot
+ uses: ./.github/actions/setup-easyscience-bot
+ with:
+ app-id: ${{ vars.EASYSCIENCE_APP_ID }}
+ private-key: ${{ secrets.EASYSCIENCE_APP_KEY }}
+
- name: Dispatch tutorial tests workflow
- uses: actions/github-script@v7
+ uses: ./.github/actions/github-script
with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
+ github-token: ${{ steps.bot.outputs.token }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
- workflow_id: "tutorial-tests.yaml",
+ workflow_id: "tutorial-tests.yml",
ref: "develop"
});
diff --git a/.github/workflows/tutorial-tests.yaml b/.github/workflows/tutorial-tests.yml
similarity index 55%
rename from .github/workflows/tutorial-tests.yaml
rename to .github/workflows/tutorial-tests.yml
index 301b43d3..4c9244d0 100644
--- a/.github/workflows/tutorial-tests.yaml
+++ b/.github/workflows/tutorial-tests.yml
@@ -4,7 +4,7 @@ on:
# Trigger the workflow on push
push:
# Selected branches
- branches: [master, main, develop]
+ branches: [develop] # master and main are already verified in PR
# Trigger the workflow on pull request
pull_request:
branches: ['**']
@@ -15,11 +15,13 @@ on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
+permissions:
+ contents: read
+
# 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.event.pull_request.number || github.ref }}
cancel-in-progress: true
# Set the environment variables to be used in all jobs defined in this workflow
@@ -41,24 +43,13 @@ jobs:
uses: actions/checkout@v5
- name: Set up pixi
- uses: prefix-dev/setup-pixi@v0.9.3
- with:
- environments: default
- activate-environment: default
- run-install: true
- frozen: true
- cache: false
- post-cleanup: false
-
- - name: Install and setup development dependencies
- shell: bash
- run: pixi run dev
+ uses: ./.github/actions/setup-pixi
- name: Test tutorials as python scripts
shell: bash
run: pixi run script-tests
- - name: Convert tutorial scripts to notebooks
+ - name: Prepare notebooks
shell: bash
run: pixi run notebook-prepare
@@ -66,24 +57,8 @@ jobs:
shell: bash
run: pixi run notebook-tests
- # Job 2: Trigger dashboard build
- dashboard-build-trigger:
- needs: tutorial-tests
-
- runs-on: ubuntu-latest
-
- steps:
- - name: Check-out repository
- uses: actions/checkout@v5
-
- - name: Trigger dashboard build
- uses: actions/github-script@v7
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- await github.rest.actions.createWorkflowDispatch({
- owner: context.repo.owner,
- repo: context.repo.repo,
- workflow_id: "dashboard.yaml",
- ref: "${{ env.CI_BRANCH }}"
- });
+ # Job 2: Build and publish dashboard (reusable workflow)
+ run-reusable-workflows:
+ needs: tutorial-tests # depend on previous job
+ uses: ./.github/workflows/dashboard.yml
+ secrets: inherit
diff --git a/.gitignore b/.gitignore
index 2c43d2b8..6dc595c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,19 @@
# Python
-__pycache__
-.venv
+__pycache__/
+.venv/
.coverage
.pyc
-# PyTest
-.pytest_cache
-
-# MyPy
-.mypy_cache
-
# Pixi
-.pixi
+.pixi/
-# Ruff
-.ruff_cache
+# PyInstaller
+dist/
+build/
+*.spec
+
+# MkDocs
+docs/site/
# Jupyter Notebooks
.ipynb_checkpoints
@@ -24,16 +23,10 @@ node_modules/
# QtCreator
*.autosave
-
-# QtCreator Qml
*.qmlproject.user
*.qmlproject.user.*
-
-# QtCreator Python
*.pyproject.user
*.pyproject.user.*
-
-# QtCreator CMake
CMakeLists.txt.user*
# PyCharm
@@ -46,3 +39,8 @@ CMakeLists.txt.user*
.DS_Store
*.app
*.dmg
+
+# Misc
+.cache/
+*.log
+*.zip
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index c3d471cd..9a3855f4 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,57 +1,61 @@
repos:
- repo: local
hooks:
- # -----------------
- # Pre-commit checks
- # -----------------
+ # -------------
+ # Manual checks
+ # -------------
- id: pixi-pyproject-check
name: pixi run pyproject-check
entry: pixi run pyproject-check
language: system
pass_filenames: false
- stages: [pre-commit]
+ stages: [manual]
- - id: pixi-py-lint-check-staged
- name: pixi run py-lint-check-staged
- entry: pixi run py-lint-check-pre
+ - id: license-headers-check
+ name: pixi run license-check
+ entry: pixi run license-check
language: system
pass_filenames: false
- stages: [pre-commit]
+ stages: [manual]
- - id: pixi-py-format-check-staged
- name: pixi run py-format-check-staged
- entry: pixi run py-format-check-pre
+ - id: pixi-py-lint-check
+ name: pixi run py-lint-check
+ entry: pixi run py-lint-check
language: system
pass_filenames: false
- stages: [pre-commit]
+ stages: [manual]
- - id: pixi-nonpy-format-check-modified
- name: pixi run nonpy-format-check-modified
- entry: pixi run nonpy-format-check-modified
+ - id: pixi-py-format-check
+ name: pixi run py-format-check
+ entry: pixi run py-format-check
language: system
pass_filenames: false
- stages: [pre-commit]
+ stages: [manual]
- - id: pixi-docs-format-check
- name: pixi run docs-format-check
- entry: pixi run docs-format-check
+ - id: pixi-docstring-lint-check
+ name: pixi run docstring-lint-check
+ entry: pixi run docstring-lint-check
language: system
pass_filenames: false
- stages: [pre-commit]
+ stages: [manual]
- # ----------------
- # Pre-push checks
- # ----------------
- id: pixi-nonpy-format-check
name: pixi run nonpy-format-check
entry: pixi run nonpy-format-check
language: system
pass_filenames: false
- stages: [pre-push]
+ stages: [manual]
+
+ - id: pixi-notebook-lint-check
+ name: pixi run notebook-lint-check
+ entry: pixi run notebook-lint-check
+ language: system
+ pass_filenames: false
+ stages: [manual]
- id: pixi-unit-tests
name: pixi run unit-tests
entry: pixi run unit-tests
language: system
pass_filenames: false
- stages: [pre-push]
+ stages: [manual]
diff --git a/.prettierignore b/.prettierignore
index 4bd61611..a08c3c48 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,6 +1,32 @@
+# Git
+.git/
+
+# Copier
+.copier-answers*.yml
+
# Pixi
.pixi
pixi.lock
+# MkDocs
+docs/overrides/
+docs/site/
+docs/docs/assets/
+
+# Python
+.pytest_cache/
+
# MyPy
-.mypy_cache
+.mypy_cache/
+
+# Ruff
+.ruff_cache/
+
+# Node
+node_modules
+
+# Misc
+.benchmarks
+.cache
+deps/
+tmp/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f05c041f..e8dc420f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,94 +1,446 @@
-# Contributing
+# Contributing to EasyDiffraction
-When contributing, please first discuss the change you wish to make via issue,
-email, or any other method with the owners of this repository before making a
-change.
+Thank you for your interest in contributing to **EasyDiffraction**!
-Please note we have a code of conduct, please follow it in all your interactions
-with the project.
+This guide explains how you can:
-## Pull Request Process
+- Report issues
+- Contribute code
+- Improve documentation
+- Suggest enhancements
+- Interact with the EasyScience community
-1. Ensure any install or build dependencies are removed before the end of the
- layer when doing a build.
-2. Update the README.md with details of changes to the interface, this includes
- new environment variables, exposed ports, useful file locations and container
- parameters.
-3. Increase the version numbers in any example files and the README.md to the
- new version that this Pull Request would represent. The versioning scheme we
- use is [SemVer](http://semver.org/).
-4. You may merge the Pull Request in once you have the sign-off of two other
- developers, or if you do not have permission to do that, you may request the
- second reviewer to merge it for you.
+Whether you are an experienced developer or contributing for the first
+time, this document walks you through the entire process step by step.
-## Code of Conduct
+Please make sure you follow the EasyScience organization-wide
+[Code of Conduct](https://github.com/easyscience/.github/blob/master/CODE_OF_CONDUCT.md).
-### Our Pledge
+---
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to make participation in our project and our
-community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, gender identity and expression, level of
-experience, nationality, personal appearance, race, religion, or sexual identity
-and orientation.
+## Table of Contents
-### Our Standards
+- [How to Interact With This Project](#how-to-interact-with-this-project)
+- [1. Understanding the Development Model](#1-understanding-the-development-model)
+- [2. Getting the Code](#2-getting-the-code)
+- [3. Setting Up the Development Environment](#3-setting-up-the-development-environment)
+- [4. Creating a Branch](#4-creating-a-branch)
+- [5. Implementing Your Changes](#5-implementing-your-changes)
+- [6. Code Quality Checks](#6-code-quality-checks)
+- [7. Opening a Pull Request](#7-opening-a-pull-request)
+- [8. Continuous Integration (CI)](#8-continuous-integration-ci)
+- [9. Code Review](#9-code-review)
+- [10. Documentation Contributions](#10-documentation-contributions)
+- [11. Reporting Issues](#11-reporting-issues)
+- [12. Security Issues](#12-security-issues)
+- [13. Releases](#13-releases)
-Examples of behavior that contributes to creating a positive environment
-include:
+---
-- Being respectful of differing viewpoints and experiences
-- Gracefully accepting constructive criticism
-- Focusing on what is best for the community
+## How to Interact With This Project
-Examples of unacceptable behavior by participants include:
+If you are not planning to contribute code, you may want to:
-- Trolling, insulting/derogatory comments, and personal or political attacks
-- Public or private harassment
-- Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-- Other conduct which could reasonably be considered inappropriate in a
- professional setting
+- 🐞 Report a bug — see [Reporting Issues](#11-reporting-issues)
+- 🛡 Report a security issue — see
+ [Security Issues](#12-security-issues)
+- 💬 Ask a question or start a discussion at
+ [Project Discussions](https://github.com/easyscience/diffraction-lib/discussions)
-### Our Responsibilities
+If you plan to contribute code or documentation, continue below.
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
+---
-Project maintainers have the right and responsibility to remove, edit, or reject
-comments, commits, code, wiki edits, issues, and other contributions that are
-not aligned to this Code of Conduct, or to ban temporarily or permanently any
-contributor for other behaviors that they deem inappropriate, threatening,
-offensive, or harmful.
+## 1. Understanding the Development Model
-### Scope
+Before you start coding, it is important to understand how development
+works in this project.
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an appointed
-representative at an online or offline event. Representation of a project may be
-further defined and clarified by project maintainers.
+### Branching Strategy
-### Enforcement
+We use the following branches:
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at suport@easydiffraction.org. All
-complaints will be reviewed and investigated and will result in a response that
-is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an
-incident. Further details of specific enforcement policies may be posted
-separately.
+- `master` — stable releases only
+- `develop` — active development branch
+- Short-lived branches — feature or fix branches created for a single
+ contribution and deleted after merge
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
+> [!IMPORTANT]
+>
+> All normal contributions must target the `develop` branch.
+>
+> - Do **not** open Pull Requests against `master`
+> - Always create your branch from `develop`
+> - Always target `develop` when opening a Pull Request
-### Attribution
+See ADR easyscience/.github#12 for more details on the branching
+strategy.
-This Code of Conduct is adapted from the [Contributor Covenant][homepage],
-version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+---
-[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
+## 2. Getting the Code
+
+### 2.1. If You Are an External Contributor
+
+If you are not a core maintainer of this repository, follow these steps.
+
+1. Open the repository page:
+ `https://github.com/easyscience/diffraction-lib`
+
+2. Click the **Fork** button (top-right corner). This creates your own
+ copy of the repository.
+
+3. Clone your fork locally:
+
+ ```bash
+ git clone https://github.com//diffraction-lib.git
+ cd diffraction-lib
+ ```
+
+4. Add the original repository as `upstream`:
+
+ ```bash
+ git remote add upstream https://github.com/easyscience/diffraction-lib.git
+ ```
+
+5. Switch to the `develop` branch and update it:
+
+ ```bash
+ git fetch upstream
+ git checkout develop
+ git pull upstream develop
+ ```
+
+If you have contributed before, make sure your local `develop` branch is
+up to date before starting new work. You can update it with:
+
+```bash
+git fetch upstream
+git pull upstream develop
+```
+
+This ensures you are working on the latest version of the project.
+
+### 2.2. If You Are a Core Team Member
+
+Core team members can create branches directly in this repository and
+therefore do not need to fork it, but the rest of the workflow remains
+the same.
+
+---
+
+## 3. Setting Up the Development Environment
+
+You need:
+
+- Git
+- Pixi
+
+EasyScience projects use **Pixi** to manage the development environment.
+
+To install Pixi, follow the official instructions:
+https://pixi.prefix.dev/latest/installation/
+
+You do **not** need to manually install Python. Pixi automatically:
+
+- Creates the correct Python environment
+- Installs all required dependencies
+- Installs development tools (linters, formatters, test tools)
+
+Set up the environment:
+
+```bash
+pixi install
+pixi run post-install # Install additional tooling
+```
+
+After this step, your development environment is ready.
+
+See ADR easyscience/.github#63 for more details about using Pixi for
+development.
+
+---
+
+## 4. Creating a Branch
+
+Never work directly on `develop`.
+
+Create a new branch:
+
+```bash
+git checkout -b my-change develop
+```
+
+> [!IMPORTANT]
+>
+> Use a clear and descriptive name, for example:
+>
+> - `improve-solver-speed`
+> - `fix-boundary-condition`
+> - `add-tutorial-example`
+
+Clear branch names make reviews and history easier to understand.
+
+---
+
+## 5. Implementing Your Changes
+
+While developing, make small, logical commits with clear messages.
+
+Example:
+
+```bash
+git add .
+git commit -m "Improve performance of time integrator for large systems"
+```
+
+---
+
+## 6. Code Quality Checks
+
+> [!IMPORTANT]
+>
+> When adding new functionality or making changes, make sure to add or
+> update the following as needed:
+>
+> - 📘 docstrings
+> - 🧪 unit tests
+
+Before opening a Pull Request, always run:
+
+```bash
+pixi run check
+```
+
+This command:
+
+- Validates the pyproject.toml file
+- Checks for licence headers in code files
+- Identifies linting and formatting issues in Python code
+- Checks docstring linting and formatting issues in Python code
+- Detects formatting issues in non-Python files (MD, YAML, TOML etc.)
+- Checks linting issues in Jupyter notebooks (if applicable)
+- Runs unit tests
+
+A successful run should look like this:
+
+```bash
+pixi run pyproject-check.......................Passed
+pixi run license-check.........................Passed
+pixi run py-lint-check.........................Passed
+pixi run py-format-check.......................Passed
+pixi run docstring-lint-check..................Passed
+pixi run nonpy-format-check....................Passed
+pixi run notebook-lint-check...................Passed
+pixi run unit-tests............................Passed
+```
+
+If something fails, read the error message carefully and fix the issue.
+
+You can run individual checks, for example, to run only unit tests:
+
+```bash
+pixi run unit-tests
+```
+
+or to run only Python linting checks:
+
+```bash
+pixi run py-lint-check
+```
+
+Some formatting issues can be fixed automatically:
+
+```bash
+pixi run fix
+```
+
+If everything is correctly formatted, you will see:
+
+```text
+✅ All auto-formatting steps completed successfully!
+```
+
+This indicates that the auto-formatting pipeline completed successfully.
+If you do not see this message and no error messages appear, try running
+the command again.
+
+If errors are reported, resolve them and re-run:
+
+```bash
+pixi run check
+```
+
+> [!IMPORTANT]
+>
+> All checks must pass before your Pull Request can be merged.
+
+If you are unsure how to fix an issue, ask for help in your Pull Request
+discussion.
+
+---
+
+## 7. Opening a Pull Request
+
+Push your branch:
+
+```bash
+git push origin my-change
+```
+
+On GitHub:
+
+- Click **Compare & Pull Request**
+- Ensure the base branch is `develop`
+- Write a clear and concise title
+- Add a description explaining what changed and why
+- Add the required `[scope]` label
+
+### Pull Request Title
+
+> [!IMPORTANT]
+>
+> The PR title appears in release notes and changelogs. It should be
+> concise and informative.
+
+Good examples:
+
+- Improve performance of time integrator for large systems
+- Fix incorrect boundary condition handling in solver
+- Add adaptive step-size control to ODE solver
+- Add tutorial for custom model configuration
+- Refactor solver API for improved readability
+
+### Required `[scope]` Label
+
+> [!IMPORTANT]
+>
+> Each Pull Request must include a `[scope]` label, which is used for
+> automatically suggesting version bumps when preparing a new release.
+
+The available scopes are:
+
+| Label | Description |
+| ----------------------- | ----------------------------------------------------------------------- |
+| `[scope] bug` | Bug report or fix (major.minor.**PATCH**) |
+| `[scope] documentation` | Documentation-only changes (major.minor.patch.**POST**) |
+| `[scope] enhancement` | Adds or improves features (major.**MINOR**.patch) |
+| `[scope] maintenance` | Code/tooling cleanup without feature or bug fix (major.minor.**PATCH**) |
+| `[scope] significant` | Breaking or major changes (**MAJOR**.minor.patch) |
+
+See ADR easyscience/.github#33 for more details on the standardized
+labeling scheme.
+
+---
+
+## 8. Continuous Integration (CI)
+
+After opening a Pull Request:
+
+- Automated checks run automatically
+- You will see green checkmarks or red crosses
+
+If checks fail:
+
+1. Open the failing check
+2. Read the logs
+3. Fix the issue locally
+4. Run `pixi run check`
+5. Push your changes
+
+The Pull Request updates automatically.
+
+---
+
+## 9. Code Review
+
+All Pull Requests are reviewed by at least one core team member.
+
+Code review is collaborative and aims to improve quality.
+
+Do not take comments personally — they are meant to help.
+
+To update your PR:
+
+```bash
+git add .
+git commit -m "Address review comments"
+git push
+```
+
+---
+
+## 10. Documentation Contributions
+
+> [!IMPORTANT]
+>
+> If your change affects user-facing functionality, update the project
+> documentation accordingly — specifically the `nav:` (navigation)
+> structure in `mkdocs.yml` and the relevant documentation Markdown
+> files in `docs/docs/`.
+>
+> ```text
+> 📁 docs
+> ├── 📁 docs - Markdown files for documentation
+> │ └── ...
+> └── 📄 mkdocs.yml - Configuration file (navigation, theme, etc.)
+> ```
+
+This may include:
+
+- API documentation
+- Examples
+- Tutorials
+- Jupyter notebooks
+
+Preview documentation locally:
+
+```bash
+pixi run docs-serve
+```
+
+Open the URL shown in the terminal to review your changes.
+
+---
+
+## 11. Reporting Issues
+
+If you find a bug but cannot work on a fix, please consider opening an
+issue.
+
+When reporting an issue, it helps to:
+
+- Search existing issues first.
+- Provide clear reproduction steps.
+- Include logs, screenshots, and environment details.
+
+Clear and detailed reports help maintainers investigate and resolve
+issues more effectively.
+
+---
+
+## 12. Security Issues
+
+> [!IMPORTANT]
+>
+> Please do **not** report security vulnerabilities publicly.
+
+If you discover a potential vulnerability, please contact the
+maintainers privately so the issue can be investigated and addressed
+responsibly.
+
+---
+
+## 13. Releases
+
+Once your contribution is merged into `develop`, it will eventually be
+included in the next stable release.
+
+When enough changes have accumulated in `develop`, core team members
+merge `develop` into `master` to prepare a new release. The release is
+then tagged and published on GitHub and PyPI.
+
+---
+
+Thank you for contributing to EasyDiffraction and the EasyScience
+ecosystem!
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
deleted file mode 100644
index 2acffeb3..00000000
--- a/DEVELOPMENT.md
+++ /dev/null
@@ -1,150 +0,0 @@
-# Development
-
-This is an example of a workflow that describes the development process.
-
-## Installation and setup with Pixi
-
-- Install Pixi by following the instructions on the
- [official Pixi Installation Guide](https://pixi.sh/latest/installation).
-- Clone repositories with assets for building documentation
- ```bash
- git clone https://github.com/easyscience/assets-docs.git
- git clone https://github.com/easyscience/assets-branding.git
- ```
-- Clone EasyDiffraction library repository
- ```bash
- git clone https://github.com/easyscience/diffraction-lib
- ```
-- Go to the cloned directory
- ```bash
- cd diffraction-lib
- ```
-- Create the environment defined in `pixi.toml` and install all necessary
- dependencies:
- ```bash
- pixi install
- ```
-- Install and setup development dependencies
- ```bash
- pixi run dev
- ```
-
-## Making changes
-
-- Checkout/switch to the `develop` branch
- ```bash
- git checkout develop
- ```
-- Create a new branch from the `develop` one
- ```bash
- git checkout -b new-feature
- ```
-- Make changes in the code
- ```bash
- ...
- ```
-
-## Checking code quality and testing
-
-### Pre-commit checks
-
-- Check code quality (configuration is in `pyproject.toml` and
- `prettierrc.toml`)
- ```bash
- pixi run pre-commit-check
- ```
-- Fix some code quality issues automatically
- ```bash
- pixi run pre-commit-fix
- ```
-
-### Pre-push checks
-
-- Run tests and checks before pushing changes
- ```bash
- pixi run pre-push
- ```
-
-### Individual tests and checks (if needed)
-
-- Check coverage by tests and docstrings
- ```bash
- pixi run cov
- ```
-- Run unit tests
- ```bash
- pixi run unit-tests
- ```
-- Run integration tests
- ```bash
- pixi run integration-tests
- ```
-- Test tutorials as python scripts
- ```bash
- pixi run script-tests
- ```
-- Convert tutorial scripts to notebooks
- ```bash
- pixi run notebook-prepare
- ```
-- Test tutorials as notebooks
- ```bash
- pixi run notebook-tests
- ```
-
-## Building and checking documentation with MkDocs
-
-- Move notebooks to docs/tutorials
- ```bash
- pixi run docs-notebooks
- ```
-- Add extra files to build documentation (from `../assets-docs/` and
- `../assets-branding/` directories)
- ```bash
- pixi run docs-assets
- ```
-- Create mkdocs.yml file
- ```bash
- pixi run docs-config
- ```
-- Build documentation
- ```bash
- pixi run docs-build
- ```
-- Test the documentation locally (built in the `site/` directory). E.g., on
- macOS, open the site in the default browser via the terminal
- ```bash
- open http://127.0.0.1:8000
- ```
-- Clean up after checking documentation
- ```bash
- pixi run docs-clean
- ```
-
-## Committing and pushing changes
-
-- Commit changes
- ```bash
- git add .
- git commit -m "Add new feature"
- ```
-- Push the new branch to a remote repository
- ```bash
- git push -u origin new-feature
- ```
-- Create a pull request on
- [EasyScience GitHub repository](https://github.com/easyscience/diffraction-lib/pulls)
- and request a review from team members
-- Add one of the required labels:
- - `[maintainer] auto-pull-request`
- - `[scope] bug`
- - `[scope] documentation`
- - `[scope] enhancement`
- - `[scope] maintenance`
- - `[scope] significant`
-- After approval, merge the pull request into the `develop` branch using "Squash
- and merge" option
-- Delete the branch remotely
- ```bash
- git push origin --delete new-feature
- ```
diff --git a/LICENSE b/LICENSE
index 4debe9f4..c4e3e48e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
BSD 3-Clause License
-Copyright (c) 2021-2025 EasyDiffraction Python Library contributors
+Copyright (c) 2021-2026 EasyScience contributors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
diff --git a/README.md b/README.md
index 6278d78f..a9fccc67 100644
--- a/README.md
+++ b/README.md
@@ -9,45 +9,45 @@
-**EasyDiffraction** is a Python package for calculating neutron powder
-diffraction patterns based on a structural model and refining its parameters
-against experimental data.
+**EasyDiffraction** is a software for calculating neutron powder
+diffraction patterns based on a structural model and refining its
+parameters against experimental data.
-**EasyDiffraction** is built upon the [EasyScience] framework, which provides
-essential tools for developing scientific libraries and applications.
+
-## Useful Links
-
-- [Main Website] - Learn more about EasyDiffraction.
-- [Documentation] - Access the full documentation.
-- [Discussions] - Ask questions or share ideas.
-- [Issue Tracker] - Report bugs or request new features.
-- [Source Code] - Explore the source code repository.
-
-## Contributing
+**EasyDiffraction** is developed both as a Python library and as a
+cross-platform desktop application.
-We welcome contributions! Our vision is for **EasyDiffraction** to be a
-community-driven, open-source project supported by a diverse group of
-contributors.
+Here, we focus on the Python library. For the graphical user interface
+(GUI), please see the corresponding
+[GUI resources](https://github.com/easyscience/diffraction-app).
-The project is currently maintained by the [European Spallation Source (ESS)].
+License:
+[BSD 3-Clause](https://github.com/easyscience/diffraction-lib/blob/master/LICENSE)
-If you'd like to contribute, please refer to our [Contributing Guidelines] for
-information about our code of conduct and instructions on submitting pull
-requests.
-
-## License
-
-**EasyDiffraction** is licensed under the [BSD 3-Clause License].
+## Useful Links
-
-[BSD 3-Clause License]: https://github.com/easyscience/diffraction-lib/blob/master/LICENSE
-[Contributing Guidelines]: https://github.com/easyscience/diffraction-lib/blob/master/CONTRIBUTING.md
-[EasyScience]: https://easyscience.software
-[European Spallation Source (ESS)]: https://ess.eu
-[Main Website]: https://easydiffraction.org
-[Documentation]: https://docs.easydiffraction.org/lib
-[Discussions]: https://github.com/easyscience/diffraction-lib/discussions
-[Issue Tracker]: https://github.com/easyscience/diffraction-lib/issues
-[Source Code]: https://github.com/easyscience/diffraction-lib
-
+### For Users
+
+- 📖
+ [Documentation](https://easyscience.github.io/diffraction-lib/latest)
+- 🚀
+ [Getting Started](https://easyscience.github.io/diffraction-lib/latest/introduction)
+- 🧪
+ [Tutorials](https://easyscience.github.io/diffraction-lib/latest/tutorials)
+- 💬
+ [Get in Touch](https://easyscience.github.io/diffraction-lib/latest/introduction/#get-in-touch)
+- 🧾
+ [Citation](https://easyscience.github.io/diffraction-lib/latest/introduction/#citation)
+
+### For Contributors
+
+- 🧑💻 [Source Code](https://github.com/easyscience/diffraction-lib)
+- 🐞
+ [Issue Tracker](https://github.com/easyscience/diffraction-lib/issues)
+- 💡
+ [Discussions](https://github.com/easyscience/diffraction-lib/discussions)
+- 🤝
+ [Contributing Guide](https://github.com/easyscience/diffraction-lib/blob/master/CONTRIBUTING.md)
+- 🛡
+ [Code of Conduct](https://github.com/easyscience/.github/blob/master/CODE_OF_CONDUCT.md)
diff --git a/codecov.yml b/codecov.yml
index ffe29da9..f62b13ab 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -11,8 +11,3 @@ coverage:
default:
# Require patch coverage but with threshold
threshold: 1%
-
-ignore:
- # Vendored third-party code - not our code to test
- - 'src/easydiffraction/utils/_vendored/**'
- - 'src/easydiffraction/utils/_vendored/jupyter_dark_detect/**'
diff --git a/docs/architecture/architecture.md b/docs/architecture/architecture.md
index 3770f3ea..884ed4f1 100644
--- a/docs/architecture/architecture.md
+++ b/docs/architecture/architecture.md
@@ -8,11 +8,11 @@
## 1. Overview
-EasyDiffraction is a Python library for crystallographic diffraction analysis
-(Rietveld refinement, pair-distribution-function fitting, etc.). It models the
-domain using **CIF-inspired abstractions** — datablocks, categories, and
-parameters — while providing a high-level, user-friendly API through a single
-`Project` façade.
+EasyDiffraction is a Python library for crystallographic diffraction
+analysis (Rietveld refinement, pair-distribution-function fitting,
+etc.). It models the domain using **CIF-inspired abstractions** —
+datablocks, categories, and parameters — while providing a high-level,
+user-friendly API through a single `Project` façade.
### 1.1 Supported Experiment Dimensions
@@ -25,8 +25,8 @@ Every experiment is fully described by four orthogonal axes:
| Beam mode | constant wavelength, time-of-flight | `BeamModeEnum` |
| Radiation probe | neutron, X-ray | `RadiationProbeEnum` |
-> **Planned extensions:** 1D / 2D data dimensionality, polarised / unpolarised
-> neutron beam.
+> **Planned extensions:** 1D / 2D data dimensionality, polarised /
+> unpolarised neutron beam.
### 1.2 Calculation Engines
@@ -56,50 +56,56 @@ GuardedBase # Controlled attribute access, parent lin
└── DatablockItem # CIF data block (e.g. Structure, Experiment)
```
-`CollectionBase` provides a unified dict-like API over an ordered item list with
-name-based indexing. All key operations — `__getitem__`, `__setitem__`,
-`__delitem__`, `__contains__`, `remove()` — resolve keys through a single
-`_key_for(item)` method that returns `category_entry_name` for category items or
-`datablock_entry_name` for datablock items. Subclasses `CategoryCollection` and
+`CollectionBase` provides a unified dict-like API over an ordered item
+list with name-based indexing. All key operations — `__getitem__`,
+`__setitem__`, `__delitem__`, `__contains__`, `remove()` — resolve keys
+through a single `_key_for(item)` method that returns
+`category_entry_name` for category items or `datablock_entry_name` for
+datablock items. Subclasses `CategoryCollection` and
`DatablockCollection` inherit this consistently.
### 2.2 GuardedBase — Controlled Attribute Access
-`GuardedBase` is the root ABC. It enforces that only **declared `@property`
-attributes** are accessible publicly:
+`GuardedBase` is the root ABC. It enforces that only **declared
+`@property` attributes** are accessible publicly:
-- **`__getattr__`** rejects any attribute not declared as a `@property` on the
- class hierarchy. Shows diagnostics with closest-match suggestions on typos.
+- **`__getattr__`** rejects any attribute not declared as a `@property`
+ on the class hierarchy. Shows diagnostics with closest-match
+ suggestions on typos.
- **`__setattr__`** distinguishes:
- **Private** (`_`-prefixed) — always allowed, no diagnostics.
- - **Read-only public** (property without setter) — blocked with a clear error.
- - **Writable public** (property with setter) — goes through the property
- setter, which is where validation happens.
- - **Unknown** — blocked with diagnostics showing allowed writable attrs.
-- **Parent linkage** — when a `GuardedBase` child is assigned to another, the
- child's `_parent` is set automatically, forming an implicit ownership tree.
-- **Identity** — every instance gets an `_identity: Identity` object for lazy
- CIF-style name resolution (`datablock_entry_name`, `category_code`,
- `category_entry_name`) by walking the `_parent` chain.
-
-**Key design rule:** if a parameter has a public setter, it is writable for the
-user. If only a getter — it is read-only. If internal code needs to set it, a
-private method (underscore prefix) is used. See § 2.2.1 below for the full
-pattern.
+ - **Read-only public** (property without setter) — blocked with a
+ clear error.
+ - **Writable public** (property with setter) — goes through the
+ property setter, which is where validation happens.
+ - **Unknown** — blocked with diagnostics showing allowed writable
+ attrs.
+- **Parent linkage** — when a `GuardedBase` child is assigned to
+ another, the child's `_parent` is set automatically, forming an
+ implicit ownership tree.
+- **Identity** — every instance gets an `_identity: Identity` object for
+ lazy CIF-style name resolution (`datablock_entry_name`,
+ `category_code`, `category_entry_name`) by walking the `_parent`
+ chain.
+
+**Key design rule:** if a parameter has a public setter, it is writable
+for the user. If only a getter — it is read-only. If internal code needs
+to set it, a private method (underscore prefix) is used. See § 2.2.1
+below for the full pattern.
#### 2.2.1 Public Property Convention — Editable vs Read-Only
-Every public parameter or descriptor exposed on a `GuardedBase` subclass follows
-one of two patterns:
+Every public parameter or descriptor exposed on a `GuardedBase` subclass
+follows one of two patterns:
| Kind | Getter | Setter | Internal mutation |
| ------------- | ------ | ------ | ---------------------------------- |
| **Editable** | yes | yes | Via the public setter |
| **Read-only** | yes | no | Via a private `_set_` method |
-**Editable property** — the user can both read and write the value. The setter
-runs through `GuardedBase.__setattr__` and into the property setter, where
-validation happens:
+**Editable property** — the user can both read and write the value. The
+setter runs through `GuardedBase.__setattr__` and into the property
+setter, where validation happens:
```python
@property
@@ -113,11 +119,11 @@ def name(self, new: str) -> None:
self._name = new
```
-**Read-only property** — the user can read but cannot assign. Any attempt to set
-the attribute is blocked by `GuardedBase.__setattr__` with a clear error
-message. If _internal_ code (factory builders, CIF loaders, etc.) needs to set
-the value, it calls a private `_set_` method instead of exposing a public
-setter:
+**Read-only property** — the user can read but cannot assign. Any
+attempt to set the attribute is blocked by `GuardedBase.__setattr__`
+with a clear error message. If _internal_ code (factory builders, CIF
+loaders, etc.) needs to set the value, it calls a private `_set_`
+method instead of exposing a public setter:
```python
@property
@@ -133,12 +139,13 @@ def _set_sample_form(self, value: str) -> None:
**Why this matters:**
-- `GuardedBase.__setattr__` uses the presence of a setter to decide writability.
- Adding a setter "just for internal use" would open the attribute to users.
+- `GuardedBase.__setattr__` uses the presence of a setter to decide
+ writability. Adding a setter "just for internal use" would open the
+ attribute to users.
- Private `_set_` methods keep the public API surface minimal and
intention-clear, while remaining greppable and type-safe.
-- The pattern avoids string-based dispatch — every mutator has an explicit named
- method.
+- The pattern avoids string-based dispatch — every mutator has an
+ explicit named method.
### 2.3 CategoryItem and CategoryCollection
@@ -153,8 +160,8 @@ def _set_sample_form(self, value: str) -> None:
| Display | `show()` on concrete subclasses | `show()` on concrete subclasses |
| Building items | N/A | `add(item)`, `create(**kwargs)` |
-**Update priority:** lower values run first. This ensures correct execution
-order within a datablock (e.g. background before data).
+**Update priority:** lower values run first. This ensures correct
+execution order within a datablock (e.g. background before data).
### 2.4 DatablockItem and DatablockCollection
@@ -170,8 +177,9 @@ order within a datablock (e.g. background before data).
| Dirty flag | `_need_categories_update` | N/A |
When any `Parameter.value` is set, it propagates
-`_need_categories_update = True` up to the owning `DatablockItem`. Serialisation
-(`as_cif`) and plotting trigger `_update_categories()` if the flag is set.
+`_need_categories_update = True` up to the owning `DatablockItem`.
+Serialisation (`as_cif`) and plotting trigger `_update_categories()` if
+the flag is set.
### 2.5 Variable System — Parameters and Descriptors
@@ -191,18 +199,19 @@ CIF-bound concrete classes add a `CifHandler` for serialisation:
| `NumericDescriptor` | `GenericNumericDescriptor` | Read-only or writable number |
| `Parameter` | `GenericParameter` | Fittable numeric value |
-**Initialisation rule:** all Parameters/Descriptors are initialised with their
-default values from `value_spec` (an `AttributeSpec`) **without any validation**
-— we trust internal definitions. Changes go through public property setters,
-which run both type and value validation.
+**Initialisation rule:** all Parameters/Descriptors are initialised with
+their default values from `value_spec` (an `AttributeSpec`) **without
+any validation** — we trust internal definitions. Changes go through
+public property setters, which run both type and value validation.
-**Mixin safety:** Parameter/Descriptor classes must not have init arguments so
-they can be used as mixins safely (e.g. `PdTofDataPointMixin`).
+**Mixin safety:** Parameter/Descriptor classes must not have init
+arguments so they can be used as mixins safely (e.g.
+`PdTofDataPointMixin`).
### 2.6 Validation
-`AttributeSpec` bundles `default`, `data_type`, `validator`, `allow_none`.
-Validators include:
+`AttributeSpec` bundles `default`, `data_type`, `validator`,
+`allow_none`. Validators include:
| Validator | Purpose |
| --------------------- | -------------------------------------- |
@@ -217,13 +226,14 @@ Validators include:
### 3.1 Experiment Type
-An experiment's type is defined by the four enum axes and is **immutable after
-creation**. This avoids the complexity of transforming all internal state when
-the experiment type changes. The type is stored in an `ExperimentType` category
-with four `StringDescriptor`s validated by `MembershipValidator`s. Public
-properties are read-only; factory and CIF-loading code use private setters
-(`_set_sample_form`, `_set_beam_mode`, `_set_radiation_probe`,
-`_set_scattering_type`) during construction only.
+An experiment's type is defined by the four enum axes and is **immutable
+after creation**. This avoids the complexity of transforming all
+internal state when the experiment type changes. The type is stored in
+an `ExperimentType` category with four `StringDescriptor`s validated by
+`MembershipValidator`s. Public properties are read-only; factory and
+CIF-loading code use private setters (`_set_sample_form`,
+`_set_beam_mode`, `_set_radiation_probe`, `_set_scattering_type`) during
+construction only.
### 3.2 Experiment Hierarchy
@@ -245,8 +255,8 @@ Each concrete experiment class carries:
### 3.3 Category Ownership
-Every experiment owns its categories as private attributes with public read-only
-or read-write properties:
+Every experiment owns its categories as private attributes with public
+read-only or read-write properties:
```python
# Read-only — user cannot replace the object, only modify its contents
@@ -265,9 +275,10 @@ experiment.excluded_regions_type = 'default' # triggers ExcludedRegionsFactory.
experiment.linked_phases_type = 'default' # triggers LinkedPhasesFactory.create(...)
```
-**Type switching pattern:** `expt.background_type = 'chebyshev'` rather than
-`expt.background.type = 'chebyshev'`. This keeps the API at the experiment level
-and makes it clear that the entire category object is being replaced.
+**Type switching pattern:** `expt.background_type = 'chebyshev'` rather
+than `expt.background.type = 'chebyshev'`. This keeps the API at the
+experiment level and makes it clear that the entire category object is
+being replaced.
---
@@ -286,8 +297,8 @@ A `Structure` contains three categories:
- `SpaceGroup` — symmetry information (`CategoryItem`)
- `AtomSites` — atomic positions collection (`CategoryCollection`)
-Symmetry constraints (cell metric, atomic coordinates, ADPs) are applied via the
-`crystallography` module during `_update_categories()`.
+Symmetry constraints (cell metric, atomic coordinates, ADPs) are applied
+via the `crystallography` module during `_update_categories()`.
---
@@ -308,13 +319,13 @@ All factories inherit from `FactoryBase`, which provides:
| Display | `show_supported(**filters)` | Pretty-print table of type + description |
| Tag listing | `supported_tags()` | List of all registered tags |
-Each `__init_subclass__` gives every factory its own independent `_registry` and
-`_default_rules`.
+Each `__init_subclass__` gives every factory its own independent
+`_registry` and `_default_rules`.
### 5.2 Default Rules
-`_default_rules` maps frozensets of `(axis_name, enum_value)` tuples to tag
-strings (preferably enum values for type safety):
+`_default_rules` maps frozensets of `(axis_name, enum_value)` tuples to
+tag strings (preferably enum values for type safety):
```python
class PeakFactory(FactoryBase):
@@ -333,13 +344,14 @@ class PeakFactory(FactoryBase):
}
```
-Resolution uses **largest-subset matching**: the rule whose frozenset is the
-biggest subset of the given conditions wins. `frozenset()` acts as a universal
-fallback.
+Resolution uses **largest-subset matching**: the rule whose frozenset is
+the biggest subset of the given conditions wins. `frozenset()` acts as a
+universal fallback.
### 5.3 Metadata on Registered Classes
-Every `@Factory.register`-ed class carries three frozen dataclass attributes:
+Every `@Factory.register`-ed class carries three frozen dataclass
+attributes:
```python
@PeakFactory.register
@@ -365,8 +377,9 @@ class CwlPseudoVoigt(PeakBase, CwlBroadeningMixin):
### 5.4 Registration Trigger
-Concrete classes use `@Factory.register` decorators. To trigger registration,
-each package's `__init__.py` must **explicitly import** every concrete class:
+Concrete classes use `@Factory.register` decorators. To trigger
+registration, each package's `__init__.py` must **explicitly import**
+every concrete class:
```python
# datablocks/experiment/categories/background/__init__.py
@@ -397,12 +410,13 @@ from .line_segment import LineSegmentBackground
| `CalculatorFactory` | Calculation engines | `CryspyCalculator`, `CrysfmlCalculator`, `PdffitCalculator` |
| `MinimizerFactory` | Minimisers | `LmfitMinimizer`, `DfolsMinimizer`, … |
-> **Note:** `ExperimentFactory` and `StructureFactory` are _builder_ factories
-> with `from_cif_path`, `from_cif_str`, `from_data_path`, and `from_scratch`
-> classmethods. `ExperimentFactory` inherits `FactoryBase` and uses `@register`
-> on all four concrete experiment classes; `_resolve_class` looks up the
-> registered class via `default_tag()` + `_supported_map()`. `StructureFactory`
-> is a plain class without `FactoryBase` inheritance (only one structure type
+> **Note:** `ExperimentFactory` and `StructureFactory` are _builder_
+> factories with `from_cif_path`, `from_cif_str`, `from_data_path`, and
+> `from_scratch` classmethods. `ExperimentFactory` inherits
+> `FactoryBase` and uses `@register` on all four concrete experiment
+> classes; `_resolve_class` looks up the registered class via
+> `default_tag()` + `_supported_map()`. `StructureFactory` is a plain
+> class without `FactoryBase` inheritance (only one structure type
> exists today).
### 5.6 Tag Naming Convention
@@ -502,9 +516,9 @@ Tags are the user-facing identifiers for selecting types. They must be:
| `lmfit (least_squares)` | `LmfitMinimizer` (method=`least_squares`) |
| `dfols` | `DfolsMinimizer` |
-> **Note:** minimizer variant tags (`lmfit (leastsq)`, `lmfit (least_squares)`)
-> are planned but not yet re-implemented after the `FactoryBase` migration. See
-> `issues_open.md` for details.
+> **Note:** minimizer variant tags (`lmfit (leastsq)`,
+> `lmfit (least_squares)`) are planned but not yet re-implemented after
+> the `FactoryBase` migration. See `issues_open.md` for details.
### 5.7 Metadata Classification — Which Classes Get What
@@ -514,16 +528,17 @@ Tags are the user-facing identifiers for selecting types. They must be:
> `compatibility`, and `calculator_support`.**
>
> **If a `CategoryItem` only exists as a child row inside a
-> `CategoryCollection`, it does NOT get these attributes — the collection
-> does.**
+> `CategoryCollection`, it does NOT get these attributes — the
+> collection does.**
#### Rationale
-A `LineSegment` item (a single background control point) is never selected,
-created, or queried by a factory. It is always instantiated internally by its
-parent `LineSegmentBackground` collection. The meaningful unit of selection is
-the _collection_, not the item. The user picks "line-segment background" (the
-collection type), not individual line-segment points.
+A `LineSegment` item (a single background control point) is never
+selected, created, or queried by a factory. It is always instantiated
+internally by its parent `LineSegmentBackground` collection. The
+meaningful unit of selection is the _collection_, not the item. The user
+picks "line-segment background" (the collection type), not individual
+line-segment points.
#### Singleton CategoryItems — factory-created (get all three)
@@ -601,28 +616,32 @@ collection type), not individual line-segment points.
### 6.1 Calculator
-The calculator performs the actual diffraction computation. It is attached
-per-experiment on the `ExperimentBase` object. Each experiment auto-resolves its
-calculator on first access based on the data category's `calculator_support`
-metadata and `CalculatorFactory._default_rules`. The `CalculatorFactory` filters
-its registry by `engine_imported` (whether the third-party library is available
-in the environment).
+The calculator performs the actual diffraction computation. It is
+attached per-experiment on the `ExperimentBase` object. Each experiment
+auto-resolves its calculator on first access based on the data
+category's `calculator_support` metadata and
+`CalculatorFactory._default_rules`. The `CalculatorFactory` filters its
+registry by `engine_imported` (whether the third-party library is
+available in the environment).
The experiment exposes the standard switchable-category API:
-- `calculator` — read-only property (lazy, auto-resolved on first access)
+- `calculator` — read-only property (lazy, auto-resolved on first
+ access)
- `calculator_type` — getter + setter
-- `show_supported_calculator_types()` — filtered by data category support
+- `show_supported_calculator_types()` — filtered by data category
+ support
- `show_current_calculator_type()`
### 6.2 Minimiser
-The minimiser drives the optimisation loop. `MinimizerFactory` creates instances
-by tag (e.g. `'lmfit'`, `'dfols'`).
+The minimiser drives the optimisation loop. `MinimizerFactory` creates
+instances by tag (e.g. `'lmfit'`, `'dfols'`).
### 6.3 Fitter
-`Fitter` wraps a minimiser instance and orchestrates the fitting workflow:
+`Fitter` wraps a minimiser instance and orchestrates the fitting
+workflow:
1. Collect `free_parameters` from structures + experiments.
2. Record start values.
@@ -634,10 +653,12 @@ by tag (e.g. `'lmfit'`, `'dfols'`).
`Analysis` is bound to a `Project` and provides the high-level API:
-- Minimiser selection: `current_minimizer`, `show_available_minimizers()`
-- Fit mode: `fit_mode` (`CategoryItem` with a `mode` descriptor validated by
- `FitModeEnum`); `'single'` fits each experiment independently, `'joint'` fits
- all simultaneously with weights from `joint_fit_experiments`.
+- Minimiser selection: `current_minimizer`,
+ `show_available_minimizers()`
+- Fit mode: `fit_mode` (`CategoryItem` with a `mode` descriptor
+ validated by `FitModeEnum`); `'single'` fits each experiment
+ independently, `'joint'` fits all simultaneously with weights from
+ `joint_fit_experiments`.
- Joint-fit weights: `joint_fit_experiments` (`CategoryCollection` of
per-experiment weight entries); sibling of `fit_mode`, not a child.
- Parameter tables: `show_all_params()`, `show_fittable_params()`,
@@ -845,26 +866,26 @@ project.experiments['xray_pdf'].peak_profile_type = 'gaussian-damped-sinc'
### 9.1 Naming and CIF Conventions
-- Follow CIF naming conventions where possible. Deviate for better API design
- when necessary, but keep the spirit of CIF names.
+- Follow CIF naming conventions where possible. Deviate for better API
+ design when necessary, but keep the spirit of CIF names.
- Reuse the concept of datablocks and categories from CIF.
-- `DatablockItem` = one CIF `data_` block, `DatablockCollection` = set of
- blocks.
+- `DatablockItem` = one CIF `data_` block, `DatablockCollection` = set
+ of blocks.
- `CategoryItem` = one CIF category, `CategoryCollection` = CIF loop.
### 9.2 Immutability of Experiment Type
-The experiment type (the four enum axes) can only be set at creation time. It
-cannot be changed afterwards. This avoids the complexity of maintaining
-different state transformations when switching between fundamentally different
-experiment configurations.
+The experiment type (the four enum axes) can only be set at creation
+time. It cannot be changed afterwards. This avoids the complexity of
+maintaining different state transformations when switching between
+fundamentally different experiment configurations.
### 9.3 Category Type Switching
-In contrast to experiment type, categories that have multiple implementations
-(peak profiles, backgrounds, instruments) can be switched at runtime by the
-user. The API pattern uses a type property on the **experiment**, not on the
-category itself:
+In contrast to experiment type, categories that have multiple
+implementations (peak profiles, backgrounds, instruments) can be
+switched at runtime by the user. The API pattern uses a type property on
+the **experiment**, not on the category itself:
```python
# ✅ Correct — type property on the experiment
@@ -874,16 +895,16 @@ expt.background_type = 'chebyshev'
expt.background.type = 'chebyshev'
```
-This makes it clear that the entire category object is being replaced and
-simplifies maintenance.
+This makes it clear that the entire category object is being replaced
+and simplifies maintenance.
### 9.4 Switchable-Category Convention
-Categories whose concrete implementation can be swapped at runtime (background,
-peak profile, etc.) are called **switchable categories**. **Every category must
-be factory-based** — even if only one implementation exists today. This ensures
-a uniform API, consistent discoverability, and makes adding a second
-implementation trivial.
+Categories whose concrete implementation can be swapped at runtime
+(background, peak profile, etc.) are called **switchable categories**.
+**Every category must be factory-based** — even if only one
+implementation exists today. This ensures a uniform API, consistent
+discoverability, and makes adding a second implementation trivial.
| Facet | Naming pattern | Example |
| --------------- | -------------------------------------------- | ------------------------------------------------ |
@@ -894,26 +915,31 @@ implementation trivial.
The convention applies universally:
-- **Experiment:** `calculator_type`, `background_type`, `peak_profile_type`,
- `extinction_type`, `linked_crystal_type`, `excluded_regions_type`,
- `linked_phases_type`, `instrument_type`, `data_type`.
+- **Experiment:** `calculator_type`, `background_type`,
+ `peak_profile_type`, `extinction_type`, `linked_crystal_type`,
+ `excluded_regions_type`, `linked_phases_type`, `instrument_type`,
+ `data_type`.
- **Structure:** `cell_type`, `space_group_type`, `atom_sites_type`.
- **Analysis:** `aliases_type`, `constraints_type`, `fit_mode_type`,
`joint_fit_experiments_type`.
**Design decisions:**
-- The **experiment owns** the `_type` setter because switching replaces the
- entire category object (`self._background = BackgroundFactory.create(...)`).
-- The **experiment owns** the `show_*` methods because they are one-liners that
- delegate to `Factory.show_supported(...)` and can pass experiment-specific
- context (e.g. `scattering_type`, `beam_mode` for peak filtering).
-- Concrete category subclasses provide a public `show()` method for displaying
- the current content (not on the base `CategoryItem`/`CategoryCollection`).
+- The **experiment owns** the `_type` setter because switching replaces
+ the entire category object
+ (`self._background = BackgroundFactory.create(...)`).
+- The **experiment owns** the `show_*` methods because they are
+ one-liners that delegate to `Factory.show_supported(...)` and can pass
+ experiment-specific context (e.g. `scattering_type`, `beam_mode` for
+ peak filtering).
+- Concrete category subclasses provide a public `show()` method for
+ displaying the current content (not on the base
+ `CategoryItem`/`CategoryCollection`).
### 9.5 Discoverable Supported Options
-The user can always discover what is supported for the current experiment:
+The user can always discover what is supported for the current
+experiment:
```python
expt.show_supported_peak_profile_types()
@@ -935,36 +961,38 @@ project.analysis.show_supported_joint_fit_experiments_types()
project.analysis.show_available_minimizers()
```
-Available calculators are filtered by `engine_imported` (whether the library is
-installed) and by the experiment's data category `calculator_support` metadata.
+Available calculators are filtered by `engine_imported` (whether the
+library is installed) and by the experiment's data category
+`calculator_support` metadata.
### 9.6 Enums for Finite Value Sets
-Every attribute, descriptor, or configuration option that accepts a **finite,
-closed set of values** must be represented by a `(str, Enum)` class. This
-applies to:
+Every attribute, descriptor, or configuration option that accepts a
+**finite, closed set of values** must be represented by a `(str, Enum)`
+class. This applies to:
- Factory tags (§5.6) — e.g. `PeakProfileTypeEnum`, `CalculatorEnum`.
- Experiment-axis values — e.g. `SampleFormEnum`, `BeamModeEnum`.
- Category descriptors with enumerated choices — e.g. fit mode
(`FitModeEnum.SINGLE`, `FitModeEnum.JOINT`).
-The enum serves as the **single source of truth** for valid values, their
-user-facing string representations, and their descriptions. Benefits:
+The enum serves as the **single source of truth** for valid values,
+their user-facing string representations, and their descriptions.
+Benefits:
-- **Autocomplete and typo safety** — IDEs list valid members; misspellings are
- caught at assignment time.
-- **Greppable** — searching for `FitModeEnum.JOINT` finds every code path that
- handles joint fitting.
-- **Type-safe dispatch** — `if mode == FitModeEnum.JOINT:` is checked by type
- checkers; `if mode == 'joint':` is not.
-- **Consistent validation** — use `MembershipValidator` with the enum members
- instead of `RegexValidator` with hand-written patterns.
+- **Autocomplete and typo safety** — IDEs list valid members;
+ misspellings are caught at assignment time.
+- **Greppable** — searching for `FitModeEnum.JOINT` finds every code
+ path that handles joint fitting.
+- **Type-safe dispatch** — `if mode == FitModeEnum.JOINT:` is checked by
+ type checkers; `if mode == 'joint':` is not.
+- **Consistent validation** — use `MembershipValidator` with the enum
+ members instead of `RegexValidator` with hand-written patterns.
-**Rule:** internal code must compare against enum members, never raw strings.
-User-facing setters accept either the enum member or its string value (because
-`str(EnumMember) == EnumMember.value` for `(str, Enum)`), but internal dispatch
-always uses the enum:
+**Rule:** internal code must compare against enum members, never raw
+strings. User-facing setters accept either the enum member or its string
+value (because `str(EnumMember) == EnumMember.value` for `(str, Enum)`),
+but internal dispatch always uses the enum:
```python
# ✅ Correct — compare with enum
@@ -976,10 +1004,10 @@ if self._fit_mode.mode.value == 'joint':
### 9.7 Flat Category Structure — No Nested Categories
-Following CIF conventions, categories are **flat siblings** within their owner
-(datablock or analysis object). A category must never be a child of another
-category of a different type. Categories can reference each other via IDs, but
-the ownership hierarchy is always:
+Following CIF conventions, categories are **flat siblings** within their
+owner (datablock or analysis object). A category must never be a child
+of another category of a different type. Categories can reference each
+other via IDs, but the ownership hierarchy is always:
```
Owner (DatablockItem / Analysis)
@@ -999,7 +1027,8 @@ Owner
**Example — `fit_mode` and `joint_fit_experiments`:** `fit_mode` is a
`CategoryItem` holding the active strategy (`'single'` or `'joint'`).
`joint_fit_experiments` is a separate `CategoryCollection` holding
-per-experiment weights. Both are direct children of `Analysis`, not nested:
+per-experiment weights. Both are direct children of `Analysis`, not
+nested:
```python
# ✅ Correct — sibling categories on Analysis
@@ -1022,13 +1051,80 @@ npd 0.7
xrd 0.3
```
+### 9.8 Property Docstring and Type-Hint Template
+
+Every public property backed by a private `Parameter`,
+`NumericDescriptor`, or `StringDescriptor` attribute must follow the
+template below. The `description` field on the descriptor is the
+**single source of truth**; docstrings and type hints are mechanically
+derived from it.
+
+**Definitions:**
+
+| Symbol | Meaning |
+| --------- | -------------------------------------------------------------------------------------- |
+| `{desc}` | `description` string without trailing period |
+| `{units}` | `units` string; omit the `({units})` parenthetical when absent/empty |
+| `{Type}` | Descriptor class name: `Parameter`, `NumericDescriptor`, or `StringDescriptor` |
+| `{ann}` | Setter value annotation: `float` for numeric descriptors, `str` for string descriptors |
+
+**Template — writable property:**
+
+```python
+@property
+def length_a(self) -> Parameter:
+ """Length of the a axis of the unit cell (Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
+ return self._length_a
+
+@length_a.setter
+def length_a(self, value: float) -> None:
+ self._length_a.value = value
+```
+
+**Template — read-only property:**
+
+```python
+@property
+def length_a(self) -> Parameter:
+ """Length of the a axis of the unit cell (Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object.
+ """
+ return self._length_a
+```
+
+**Quick-reference table:**
+
+| Element | Text |
+| ---------------------- | -------------------------------------------------------------------------------------------------------------- |
+| Getter summary line | `"""{desc} ({units}).` (or `"""{desc}.` when unitless) |
+| Getter body (writable) | `Reading this property returns the underlying ``{Type}`` object. Assigning to it updates the parameter value.` |
+| Getter body (readonly) | `Reading this property returns the underlying ``{Type}`` object.` |
+| Setter docstring | _(none — not rendered by griffe / MkDocs)_ |
+| Getter annotation | `-> {Type}` |
+| Setter annotation | `value: {ann}` and `-> None` |
+
+**Notes:**
+
+- Getter docstrings have **no** `Args:` or `Returns:` sections.
+- Setters have **no** docstring.
+- Avoid markdown emphasis (`*a*`) in docstrings; use plain text to stay
+ in sync with the `description` field.
+- The CI tool `pixi run param-consistency-check` validates compliance;
+ `pixi run param-consistency-fix` auto-fixes violations.
+
---
## 10. Issues
- **Open:** [`issues_open.md`](issues_open.md) — prioritised backlog.
-- **Closed:** [`issues_closed.md`](issues_closed.md) — resolved items for
- reference.
+- **Closed:** [`issues_closed.md`](issues_closed.md) — resolved items
+ for reference.
When a resolution affects the architecture described above, the relevant
sections of this document are updated accordingly.
diff --git a/docs/architecture/issues_closed.md b/docs/architecture/issues_closed.md
index bc8ea19b..a67edcbe 100644
--- a/docs/architecture/issues_closed.md
+++ b/docs/architecture/issues_closed.md
@@ -6,26 +6,29 @@ Issues that have been fully resolved. Kept for historical reference.
## Dirty-Flag Guard Was Disabled
-**Resolution:** added `_set_value_from_minimizer()` on `GenericDescriptorBase`
-that writes `_value` directly (no validation) but sets the dirty flag on the
-parent `DatablockItem`. Both `LmfitMinimizer` and `DfolsMinimizer` now use it.
-The guard in `DatablockItem._update_categories()` is enabled and skips redundant
-updates on the user-facing path (CIF export, plotting). During fitting the guard
-is bypassed (`called_by_minimizer=True`) because experiment calculations depend
-on structure parameters owned by a different `DatablockItem`.
+**Resolution:** added `_set_value_from_minimizer()` on
+`GenericDescriptorBase` that writes `_value` directly (no validation)
+but sets the dirty flag on the parent `DatablockItem`. Both
+`LmfitMinimizer` and `DfolsMinimizer` now use it. The guard in
+`DatablockItem._update_categories()` is enabled and skips redundant
+updates on the user-facing path (CIF export, plotting). During fitting
+the guard is bypassed (`called_by_minimizer=True`) because experiment
+calculations depend on structure parameters owned by a different
+`DatablockItem`.
---
## Move Calculator from Global to Per-Experiment
-**Resolution:** removed the global calculator from `Analysis`. Each experiment
-now owns its calculator, auto-resolved on first access from
-`CalculatorFactory._default_rules` (maps `scattering_type` → default tag) and
-filtered by the data category's `calculator_support` metadata (e.g. `PdCwlData`
-→ `{CRYSPY}`, `TotalData` → `{PDFFIT}`). Calculator classes no longer carry
-`compatibility` attributes — limitations are expressed on categories. The
-experiment exposes the standard switchable-category API: `calculator`
-(read-only, lazy), `calculator_type` (getter + setter),
+**Resolution:** removed the global calculator from `Analysis`. Each
+experiment now owns its calculator, auto-resolved on first access from
+`CalculatorFactory._default_rules` (maps `scattering_type` → default
+tag) and filtered by the data category's `calculator_support` metadata
+(e.g. `PdCwlData` → `{CRYSPY}`, `TotalData` → `{PDFFIT}`). Calculator
+classes no longer carry `compatibility` attributes — limitations are
+expressed on categories. The experiment exposes the standard
+switchable-category API: `calculator` (read-only, lazy),
+`calculator_type` (getter + setter),
`show_supported_calculator_types()`, `show_current_calculator_type()`.
Tutorials, tests, and docs updated.
@@ -33,28 +36,32 @@ Tutorials, tests, and docs updated.
## Add Universal Factories for All Categories
-**Resolution:** converted every category to use the `FactoryBase` pattern. Each
-former single-file category is now a package with `factory.py` (trivial
-`FactoryBase` subclass), `default.py` (concrete class with `@register` +
-`type_info`), and `__init__.py` (re-exports preserving import compatibility).
+**Resolution:** converted every category to use the `FactoryBase`
+pattern. Each former single-file category is now a package with
+`factory.py` (trivial `FactoryBase` subclass), `default.py` (concrete
+class with `@register` + `type_info`), and `__init__.py` (re-exports
+preserving import compatibility).
-Experiment categories: `Extinction` → `ShelxExtinction` / `ExtinctionFactory`
-(tag `shelx`), `LinkedCrystal` / `LinkedCrystalFactory` (tag `default`),
-`ExcludedRegions` / `ExcludedRegionsFactory`, `LinkedPhases` /
-`LinkedPhasesFactory`, `ExperimentType` / `ExperimentTypeFactory`.
+Experiment categories: `Extinction` → `ShelxExtinction` /
+`ExtinctionFactory` (tag `shelx`), `LinkedCrystal` /
+`LinkedCrystalFactory` (tag `default`), `ExcludedRegions` /
+`ExcludedRegionsFactory`, `LinkedPhases` / `LinkedPhasesFactory`,
+`ExperimentType` / `ExperimentTypeFactory`.
Structure categories: `Cell` / `CellFactory`, `SpaceGroup` /
`SpaceGroupFactory`, `AtomSites` / `AtomSitesFactory`.
Analysis categories: `Aliases` / `AliasesFactory`, `Constraints` /
-`ConstraintsFactory`, `JointFitExperiments` / `JointFitExperimentsFactory`.
-
-`ShelxExtinction` and `LinkedCrystal` get the full switchable-category API on
-`ScExperimentBase` (`extinction_type`, `linked_crystal_type` getter+setter,
-`show_supported_*_types()`, `show_current_*_type()`). `ExcludedRegions` and
-`LinkedPhases` get the same API on `PdExperimentBase`. `Cell`, `SpaceGroup`, and
-`AtomSites` get it on `Structure`. `Aliases` and `Constraints` get it on
-`Analysis`. Architecture §3.3, §5.5, §5.7, §9.4, §9.5 updated. Copilot
-instructions updated with universal switchable-category scope and
-architecture-first workflow rule. Unit tests extended with factory tests for
-extinction and linked-crystal.
+`ConstraintsFactory`, `JointFitExperiments` /
+`JointFitExperimentsFactory`.
+
+`ShelxExtinction` and `LinkedCrystal` get the full switchable-category
+API on `ScExperimentBase` (`extinction_type`, `linked_crystal_type`
+getter+setter, `show_supported_*_types()`, `show_current_*_type()`).
+`ExcludedRegions` and `LinkedPhases` get the same API on
+`PdExperimentBase`. `Cell`, `SpaceGroup`, and `AtomSites` get it on
+`Structure`. `Aliases` and `Constraints` get it on `Analysis`.
+Architecture §3.3, §5.5, §5.7, §9.4, §9.5 updated. Copilot instructions
+updated with universal switchable-category scope and architecture-first
+workflow rule. Unit tests extended with factory tests for extinction and
+linked-crystal.
diff --git a/docs/architecture/issues_open.md b/docs/architecture/issues_open.md
index d8bd37a2..05ed175f 100644
--- a/docs/architecture/issues_open.md
+++ b/docs/architecture/issues_open.md
@@ -1,9 +1,10 @@
# EasyDiffraction — Open Issues
-Prioritised list of issues, improvements, and design questions to address. Items
-are ordered by a combination of user impact, blocking potential, and
-implementation readiness. When an item is fully implemented, remove it from this
-file and update `architecture.md` if needed.
+Prioritised list of issues, improvements, and design questions to
+address. Items are ordered by a combination of user impact, blocking
+potential, and implementation readiness. When an item is fully
+implemented, remove it from this file and update `architecture.md` if
+needed.
**Legend:** 🔴 High · 🟡 Medium · 🟢 Low
@@ -13,15 +14,16 @@ file and update `architecture.md` if needed.
**Type:** Completeness
-`save()` serialises all components to CIF files but `load()` is a stub that
-raises `NotImplementedError`. Users cannot round-trip a project.
+`save()` serialises all components to CIF files but `load()` is a stub
+that raises `NotImplementedError`. Users cannot round-trip a project.
**Why first:** this is the highest-severity gap. Without it the save
-functionality is only half useful — CIF files are written but cannot be read
-back. Tutorials that demonstrate save/load are blocked.
+functionality is only half useful — CIF files are written but cannot be
+read back. Tutorials that demonstrate save/load are blocked.
-**Fix:** implement `load()` that reads CIF files from the project directory and
-reconstructs structures, experiments, and analysis settings.
+**Fix:** implement `load()` that reads CIF files from the project
+directory and reconstructs structures, experiments, and analysis
+settings.
**Depends on:** nothing (standalone).
@@ -35,11 +37,12 @@ After the `FactoryBase` migration only `'lmfit'` and `'dfols'` remain as
registered tags. The ability to select a specific lmfit algorithm (e.g.
`'lmfit (leastsq)'`, `'lmfit (least_squares)'`) raises a `ValueError`.
-The root cause is that `FactoryBase` assumes one class ↔ one tag; registering
-the same class twice with different constructor arguments is not supported.
+The root cause is that `FactoryBase` assumes one class ↔ one tag;
+registering the same class twice with different constructor arguments is
+not supported.
-**Fix:** decide on an approach (thin subclasses, extended registry, or two-level
-selection) and implement. Thin subclasses is the quickest.
+**Fix:** decide on an approach (thin subclasses, extended registry, or
+two-level selection) and implement. Thin subclasses is the quickest.
**Planned tags:**
@@ -58,8 +61,8 @@ selection) and implement. Thin subclasses is the quickest.
| **B. Extend registry to store `(class, kwargs)` tuples** | No extra classes; factory handles variants natively | `_supported_map` changes shape; `TypeInfo` moves from class attribute to registration-time data |
| **C. Two-level selection** (`engine` + `algorithm`) | Clean separation; engine maps to class, algorithm is a constructor arg | More complex API (`current_minimizer = ('lmfit', 'least_squares')`); needs new `FactoryBase` protocol |
-**Depends on:** nothing (standalone, but should be decided before more factories
-adopt variants).
+**Depends on:** nothing (standalone, but should be decided before more
+factories adopt variants).
---
@@ -67,13 +70,14 @@ adopt variants).
**Type:** Fragility
-`joint_fit_experiments` is created once when `fit_mode` becomes `'joint'`. If
-experiments are added, removed, or renamed afterwards, the weight collection is
-stale. Joint fitting can fail with missing keys or run with incorrect weights.
+`joint_fit_experiments` is created once when `fit_mode` becomes
+`'joint'`. If experiments are added, removed, or renamed afterwards, the
+weight collection is stale. Joint fitting can fail with missing keys or
+run with incorrect weights.
-**Fix:** rebuild or validate `joint_fit_experiments` at the start of every joint
-fit. At minimum, `fit()` should assert that the weight keys exactly match
-`project.experiments.names`.
+**Fix:** rebuild or validate `joint_fit_experiments` at the start of
+every joint fit. At minimum, `fit()` should assert that the weight keys
+exactly match `project.experiments.names`.
**Depends on:** nothing.
@@ -85,18 +89,20 @@ fit. At minimum, `fit()` should assert that the weight keys exactly match
`ConstraintsHandler` is only synchronised from `analysis.aliases` and
`analysis.constraints` when the user explicitly calls
-`project.analysis.apply_constraints()`. The normal fit / serialisation path
-calls `constraints_handler.apply()` directly, so newly added or edited aliases
-and constraints can be ignored until that manual sync step happens.
+`project.analysis.apply_constraints()`. The normal fit / serialisation
+path calls `constraints_handler.apply()` directly, so newly added or
+edited aliases and constraints can be ignored until that manual sync
+step happens.
-**Why high:** this produces silently incorrect results. A user can define
-constraints, run a fit, and believe they were applied when the active singleton
-still contains stale state from a previous run or no state at all.
+**Why high:** this produces silently incorrect results. A user can
+define constraints, run a fit, and believe they were applied when the
+active singleton still contains stale state from a previous run or no
+state at all.
**Fix:** before any automatic constraint application, always refresh the
-singleton from the current `Aliases` and `Constraints` collections. The sync
-should happen inside `Analysis._update_categories()` or inside the constraints
-category itself, not only in a user-facing helper method.
+singleton from the current `Aliases` and `Constraints` collections. The
+sync should happen inside `Analysis._update_categories()` or inside the
+constraints category itself, not only in a user-facing helper method.
**Depends on:** nothing.
@@ -106,10 +112,11 @@ category itself, not only in a user-facing helper method.
**Type:** Consistency
-`Analysis` owns categories (`Aliases`, `Constraints`, `JointFitExperiments`) but
-does not extend `DatablockItem`. Its ad-hoc `_update_categories()` iterates over
-a hard-coded list and does not participate in standard category discovery,
-parameter enumeration, or CIF serialisation.
+`Analysis` owns categories (`Aliases`, `Constraints`,
+`JointFitExperiments`) but does not extend `DatablockItem`. Its ad-hoc
+`_update_categories()` iterates over a hard-coded list and does not
+participate in standard category discovery, parameter enumeration, or
+CIF serialisation.
**Fix:** make `Analysis` extend `DatablockItem`, or extract a shared
`_update_categories()` protocol.
@@ -122,20 +129,22 @@ parameter enumeration, or CIF serialisation.
**Type:** Correctness + Data safety
-`Experiment.data_type` currently validates against all registered data tags
-rather than only those compatible with the experiment's `sample_form` /
-`scattering_type` / `beam_mode`. This allows users to switch an experiment to an
-incompatible data collection class. The setter also replaces the existing data
-object with a fresh empty instance, discarding loaded data without warning.
+`Experiment.data_type` currently validates against all registered data
+tags rather than only those compatible with the experiment's
+`sample_form` / `scattering_type` / `beam_mode`. This allows users to
+switch an experiment to an incompatible data collection class. The
+setter also replaces the existing data object with a fresh empty
+instance, discarding loaded data without warning.
-**Why high:** the current API can create internally inconsistent experiments and
-silently lose measured data, which is especially dangerous for notebook and
-tutorial workflows.
+**Why high:** the current API can create internally inconsistent
+experiments and silently lose measured data, which is especially
+dangerous for notebook and tutorial workflows.
-**Fix:** filter supported data types through `DataFactory.supported_for(...)`
-using the current experiment context, and warn or block when a switch would
-discard existing data. If runtime data-type switching is not a real user need,
-consider making `data` effectively fixed after experiment creation.
+**Fix:** filter supported data types through
+`DataFactory.supported_for(...)` using the current experiment context,
+and warn or block when a switch would discard existing data. If runtime
+data-type switching is not a real user need, consider making `data`
+effectively fixed after experiment creation.
**Depends on:** nothing.
@@ -145,16 +154,17 @@ consider making `data` effectively fixed after experiment creation.
**Type:** Fragility
-Single-fit mode creates a throw-away `Experiments` collection per experiment,
-manually forces `_parent` via `object.__setattr__`, and passes it to `Fitter`.
-This bypasses `GuardedBase` parent tracking and is fragile.
+Single-fit mode creates a throw-away `Experiments` collection per
+experiment, manually forces `_parent` via `object.__setattr__`, and
+passes it to `Fitter`. This bypasses `GuardedBase` parent tracking and
+is fragile.
-**Fix:** make `Fitter.fit()` accept a list of experiment objects (or a single
-experiment) instead of requiring an `Experiments` collection. Or add a
-`fit_single(experiment)` method.
+**Fix:** make `Fitter.fit()` accept a list of experiment objects (or a
+single experiment) instead of requiring an `Experiments` collection. Or
+add a `fit_single(experiment)` method.
-**Depends on:** nothing, but simpler after issue 5 (Analysis refactor) clarifies
-the fitting orchestration.
+**Depends on:** nothing, but simpler after issue 5 (Analysis refactor)
+clarifies the fitting orchestration.
---
@@ -162,14 +172,15 @@ the fitting orchestration.
**Type:** API safety
-`CategoryCollection.create(**kwargs)` accepts arbitrary keyword arguments and
-applies them via `setattr`. Typos are silently dropped (GuardedBase logs a
-warning but does not raise), so items are created with incorrect defaults.
+`CategoryCollection.create(**kwargs)` accepts arbitrary keyword
+arguments and applies them via `setattr`. Typos are silently dropped
+(GuardedBase logs a warning but does not raise), so items are created
+with incorrect defaults.
-**Fix:** concrete collection subclasses (e.g. `AtomSites`, `Background`) should
-override `create()` with explicit parameters for IDE autocomplete and typo
-detection. The base `create(**kwargs)` remains as an internal implementation
-detail.
+**Fix:** concrete collection subclasses (e.g. `AtomSites`, `Background`)
+should override `create()` with explicit parameters for IDE autocomplete
+and typo detection. The base `create(**kwargs)` remains as an internal
+implementation detail.
**Depends on:** nothing.
@@ -179,7 +190,8 @@ detail.
**Type:** Design improvement
-The four current experiment axes will be extended with at least two more:
+The four current experiment axes will be extended with at least two
+more:
| New axis | Options | Enum (proposed) |
| ------------------- | ---------------------- | ------------------------ |
@@ -187,12 +199,12 @@ The four current experiment axes will be extended with at least two more:
| Beam polarisation | unpolarised, polarised | `PolarisationEnum` |
These should follow the same `str, Enum` pattern and integrate into
-`Compatibility` (new `FrozenSet` fields), `_default_rules`, and `ExperimentType`
-(new `StringDescriptor`s with `MembershipValidator`s).
+`Compatibility` (new `FrozenSet` fields), `_default_rules`, and
+`ExperimentType` (new `StringDescriptor`s with `MembershipValidator`s).
-**Migration path:** existing `Compatibility` objects that don't specify the new
-fields use `frozenset()` (empty = "any"), so all existing classes remain
-compatible without changes.
+**Migration path:** existing `Compatibility` objects that don't specify
+the new fields use `frozenset()` (empty = "any"), so all existing
+classes remain compatible without changes.
**Depends on:** nothing.
@@ -202,17 +214,18 @@ compatible without changes.
**Type:** Maintainability
-`Project._update_categories(expt_name)` hard-codes the update order (structures
-→ analysis → one experiment). The `_update_priority` system exists on categories
-but is not used across datablocks. The `expt_name` parameter means only one
-experiment is updated per call, inconsistent with joint-fit workflows.
+`Project._update_categories(expt_name)` hard-codes the update order
+(structures → analysis → one experiment). The `_update_priority` system
+exists on categories but is not used across datablocks. The `expt_name`
+parameter means only one experiment is updated per call, inconsistent
+with joint-fit workflows.
-**Fix:** consider a project-level `_update_priority` on datablocks, or at
-minimum document the required update order. For joint fitting, all experiments
-should be updateable in a single call.
+**Fix:** consider a project-level `_update_priority` on datablocks, or
+at minimum document the required update order. For joint fitting, all
+experiments should be updateable in a single call.
-**Depends on:** benefits from issue 5 (Analysis as DatablockItem) and issue 7
-(fitter refactor).
+**Depends on:** benefits from issue 5 (Analysis as DatablockItem) and
+issue 7 (fitter refactor).
---
@@ -220,17 +233,18 @@ should be updateable in a single call.
**Type:** Maintainability
-`_update()` is an optional override with a no-op default. A clearer contract
-would help contributors:
+`_update()` is an optional override with a no-op default. A clearer
+contract would help contributors:
-- **Active categories** (those that compute something, e.g. `Background`,
- `Data`) should have an explicit `_update()` implementation.
+- **Active categories** (those that compute something, e.g.
+ `Background`, `Data`) should have an explicit `_update()`
+ implementation.
- **Passive categories** (those that only store parameters, e.g. `Cell`,
`SpaceGroup`) keep the no-op default.
The distinction is already implicit in the code; making it explicit in
-documentation (and possibly via a naming convention or flag) would reduce
-confusion for new contributors.
+documentation (and possibly via a naming convention or flag) would
+reduce confusion for new contributors.
**Depends on:** nothing.
@@ -240,10 +254,10 @@ confusion for new contributors.
**Type:** Quality
-Ensuring every parameter survives a `save()` → `load()` cycle is critical for
-reproducibility. A systematic integration test that creates a project, populates
-all categories, saves, reloads, and compares all parameter values would
-strengthen confidence in the serialisation layer.
+Ensuring every parameter survives a `save()` → `load()` cycle is
+critical for reproducibility. A systematic integration test that creates
+a project, populates all categories, saves, reloads, and compares all
+parameter values would strengthen confidence in the serialisation layer.
**Depends on:** issue 1 (`Project.load()` implementation).
@@ -253,17 +267,18 @@ strengthen confidence in the serialisation layer.
**Type:** Performance
-Symmetry constraint application (cell metric, atomic coordinates, ADPs) goes
-through the public `value` setter for each parameter, setting the dirty flag
-repeatedly during what is logically a single batch operation.
+Symmetry constraint application (cell metric, atomic coordinates, ADPs)
+goes through the public `value` setter for each parameter, setting the
+dirty flag repeatedly during what is logically a single batch operation.
No correctness issue — the dirty-flag guard handles this correctly. The
-redundant sets are a minor inefficiency that only matters if profiling shows it
-is a bottleneck.
+redundant sets are a minor inefficiency that only matters if profiling
+shows it is a bottleneck.
**Fix:** introduce a private `_set_value_no_notify()` method on
-`GenericDescriptorBase` for internal batch operations, or a context manager /
-flag on the owning datablock to suppress notifications during a batch.
+`GenericDescriptorBase` for internal batch operations, or a context
+manager / flag on the owning datablock to suppress notifications during
+a batch.
**Depends on:** nothing, but low priority.
@@ -273,11 +288,12 @@ flag on the owning datablock to suppress notifications during a batch.
**Type:** Performance
-The current dirty-flag approach (`_need_categories_update` on `DatablockItem`)
-triggers a full update of all categories when any parameter changes. This is
-simple and correct. If performance becomes a concern with many categories, a
-more granular approach could track which specific categories are dirty. Only
-implement when profiling proves it is needed.
+The current dirty-flag approach (`_need_categories_update` on
+`DatablockItem`) triggers a full update of all categories when any
+parameter changes. This is simple and correct. If performance becomes a
+concern with many categories, a more granular approach could track which
+specific categories are dirty. Only implement when profiling proves it
+is needed.
**Depends on:** nothing, but low priority.
@@ -287,14 +303,16 @@ implement when profiling proves it is needed.
**Type:** Correctness
-Joint-fit weights currently allow invalid numeric values such as negatives or an
-all-zero set. The residual code then normalises by the total weight and applies
-`sqrt(weight)`, which can produce division-by-zero or `nan` residuals.
+Joint-fit weights currently allow invalid numeric values such as
+negatives or an all-zero set. The residual code then normalises by the
+total weight and applies `sqrt(weight)`, which can produce
+division-by-zero or `nan` residuals.
-**Fix:** require weights to be strictly positive, or at minimum validate that
-all weights are non-negative and their total is greater than zero before
-normalisation. This should fail with a clear user-facing error instead of
-letting invalid floating-point values propagate into the minimiser.
+**Fix:** require weights to be strictly positive, or at minimum validate
+that all weights are non-negative and their total is greater than zero
+before normalisation. This should fail with a clear user-facing error
+instead of letting invalid floating-point values propagate into the
+minimiser.
**Depends on:** related to issue 3, but independent.
@@ -304,14 +322,16 @@ letting invalid floating-point values propagate into the minimiser.
**Type:** Completeness
-The current architecture moved calculator selection to the experiment level via
-`calculator_type`, but this selection is not written to CIF during `save()` /
-`show_as_cif()`. Reloading or exporting a project therefore loses explicit
-calculator choices and falls back to auto-resolution.
+The current architecture moved calculator selection to the experiment
+level via `calculator_type`, but this selection is not written to CIF
+during `save()` / `show_as_cif()`. Reloading or exporting a project
+therefore loses explicit calculator choices and falls back to
+auto-resolution.
-**Fix:** serialise `calculator_type` as part of the experiment or analysis
-state, and make sure `load()` restores it. The saved project should represent
-the exact active calculator configuration, not just a re-derivable default.
+**Fix:** serialise `calculator_type` as part of the experiment or
+analysis state, and make sure `load()` restores it. The saved project
+should represent the exact active calculator configuration, not just a
+re-derivable default.
**Depends on:** issue 1 (`Project.load()` implementation).
diff --git a/docs/api-reference/analysis.md b/docs/docs/api-reference/analysis.md
similarity index 100%
rename from docs/api-reference/analysis.md
rename to docs/docs/api-reference/analysis.md
diff --git a/docs/api-reference/core.md b/docs/docs/api-reference/core.md
similarity index 100%
rename from docs/api-reference/core.md
rename to docs/docs/api-reference/core.md
diff --git a/docs/api-reference/crystallography.md b/docs/docs/api-reference/crystallography.md
similarity index 100%
rename from docs/api-reference/crystallography.md
rename to docs/docs/api-reference/crystallography.md
diff --git a/docs/api-reference/datablocks/experiment.md b/docs/docs/api-reference/datablocks/experiment.md
similarity index 100%
rename from docs/api-reference/datablocks/experiment.md
rename to docs/docs/api-reference/datablocks/experiment.md
diff --git a/docs/api-reference/datablocks/structure.md b/docs/docs/api-reference/datablocks/structure.md
similarity index 100%
rename from docs/api-reference/datablocks/structure.md
rename to docs/docs/api-reference/datablocks/structure.md
diff --git a/docs/api-reference/display.md b/docs/docs/api-reference/display.md
similarity index 100%
rename from docs/api-reference/display.md
rename to docs/docs/api-reference/display.md
diff --git a/docs/api-reference/index.md b/docs/docs/api-reference/index.md
similarity index 79%
rename from docs/api-reference/index.md
rename to docs/docs/api-reference/index.md
index 6a6f8be4..351d7f56 100644
--- a/docs/api-reference/index.md
+++ b/docs/docs/api-reference/index.md
@@ -7,19 +7,20 @@ icon: material/code-braces-box
This section contains the reference detailing the functions and modules
available in EasyDiffraction:
-- [core](core.md) – Contains core utilities and foundational objects used across
- the package.
-- [crystallography](crystallography.md) – Handles crystallographic calculations,
- space groups, and symmetry operations.
+- [core](core.md) – Contains core utilities and foundational objects
+ used across the package.
+- [crystallography](crystallography.md) – Handles crystallographic
+ calculations, space groups, and symmetry operations.
- [utils](utils.md) – Miscellaneous utility functions for formatting,
decorators, and general helpers.
- datablocks
- - [experiments](datablocks/experiment.md) – Manages experimental setups and
- instrument parameters, as well as the associated diffraction data.
+ - [experiments](datablocks/experiment.md) – Manages experimental
+ setups and instrument parameters, as well as the associated
+ diffraction data.
- [structures](datablocks/structure.md) – Defines structures, such as
crystallographic structures, and manages their properties.
- [display](display.md) – Tools for plotting data and rendering tables.
- [project](project.md) – Defines the project and manages its state.
-- [analysis](analysis.md) – Provides tools for analyzing diffraction data,
- including fitting and minimization.
+- [analysis](analysis.md) – Provides tools for analyzing diffraction
+ data, including fitting and minimization.
- [summary](summary.md) – Provides a summary of the project.
diff --git a/docs/api-reference/io.md b/docs/docs/api-reference/io.md
similarity index 100%
rename from docs/api-reference/io.md
rename to docs/docs/api-reference/io.md
diff --git a/docs/api-reference/project.md b/docs/docs/api-reference/project.md
similarity index 100%
rename from docs/api-reference/project.md
rename to docs/docs/api-reference/project.md
diff --git a/docs/api-reference/summary.md b/docs/docs/api-reference/summary.md
similarity index 100%
rename from docs/api-reference/summary.md
rename to docs/docs/api-reference/summary.md
diff --git a/docs/api-reference/utils.md b/docs/docs/api-reference/utils.md
similarity index 100%
rename from docs/api-reference/utils.md
rename to docs/docs/api-reference/utils.md
diff --git a/docs/docs/assets/images/favicon.png b/docs/docs/assets/images/favicon.png
new file mode 100644
index 00000000..27628988
Binary files /dev/null and b/docs/docs/assets/images/favicon.png differ
diff --git a/docs/docs/assets/images/logo_dark.svg b/docs/docs/assets/images/logo_dark.svg
new file mode 100644
index 00000000..0be819d0
--- /dev/null
+++ b/docs/docs/assets/images/logo_dark.svg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Logo
+
+ Main circle
+
+
+ Inner circles
+
+
+
+
+
+
+
+
+
+
+ Text
+
+ easy
+
+
+ diffraction
+
+
+
+
\ No newline at end of file
diff --git a/docs/docs/assets/images/logo_light.svg b/docs/docs/assets/images/logo_light.svg
new file mode 100644
index 00000000..84103655
--- /dev/null
+++ b/docs/docs/assets/images/logo_light.svg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Logo
+
+ Main circle
+
+
+ Inner circles
+
+
+
+
+
+
+
+
+
+
+ Text
+
+ easy
+
+
+ diffraction
+
+
+
+
\ No newline at end of file
diff --git a/docs/assets/images/user-guide/data-acquisition_2d-raw-data.jpg b/docs/docs/assets/images/user-guide/data-acquisition_2d-raw-data.jpg
similarity index 100%
rename from docs/assets/images/user-guide/data-acquisition_2d-raw-data.jpg
rename to docs/docs/assets/images/user-guide/data-acquisition_2d-raw-data.jpg
diff --git a/docs/assets/images/user-guide/data-acquisition_instrument.png b/docs/docs/assets/images/user-guide/data-acquisition_instrument.png
similarity index 100%
rename from docs/assets/images/user-guide/data-acquisition_instrument.png
rename to docs/docs/assets/images/user-guide/data-acquisition_instrument.png
diff --git a/docs/assets/images/user-guide/data-analysis_model.png b/docs/docs/assets/images/user-guide/data-analysis_model.png
similarity index 100%
rename from docs/assets/images/user-guide/data-analysis_model.png
rename to docs/docs/assets/images/user-guide/data-analysis_model.png
diff --git a/docs/assets/images/user-guide/data-analysis_refinement.png b/docs/docs/assets/images/user-guide/data-analysis_refinement.png
similarity index 100%
rename from docs/assets/images/user-guide/data-analysis_refinement.png
rename to docs/docs/assets/images/user-guide/data-analysis_refinement.png
diff --git a/docs/assets/images/user-guide/data-reduction_1d-pattern.png b/docs/docs/assets/images/user-guide/data-reduction_1d-pattern.png
similarity index 100%
rename from docs/assets/images/user-guide/data-reduction_1d-pattern.png
rename to docs/docs/assets/images/user-guide/data-reduction_1d-pattern.png
diff --git a/docs/docs/assets/javascripts/extra.js b/docs/docs/assets/javascripts/extra.js
new file mode 100644
index 00000000..9596ee07
--- /dev/null
+++ b/docs/docs/assets/javascripts/extra.js
@@ -0,0 +1,27 @@
+;(function () {
+ 'use strict'
+
+ // Variables
+ const header = document.getElementsByTagName('header')[0]
+
+ console.log(window.pageYOffset)
+
+ // Hide-show header shadow
+ function toggleHeaderShadow() {
+ if (window.pageYOffset <= 0) {
+ header.classList.remove('md-header--shadow')
+ } else {
+ header.classList.add('md-header--shadow')
+ }
+ }
+
+ // Onload
+ window.onload = function () {
+ toggleHeaderShadow()
+ }
+
+ // Onscroll
+ window.onscroll = function () {
+ toggleHeaderShadow()
+ }
+})()
diff --git a/docs/docs/assets/javascripts/mathjax.js b/docs/docs/assets/javascripts/mathjax.js
new file mode 100644
index 00000000..333524ec
--- /dev/null
+++ b/docs/docs/assets/javascripts/mathjax.js
@@ -0,0 +1,33 @@
+window.MathJax = {
+ tex: {
+ //inlineMath: [['\\(', '\\)']],
+ //displayMath: [['\\[', '\\]']],
+ // Add support for $...$ and \(...\) delimiters
+ inlineMath: [
+ ['$', '$'],
+ ['\\(', '\\)'],
+ ],
+ // Add support for $$...$$ and \[...]\ delimiters
+ displayMath: [
+ ['$$', '$$'],
+ ['\\[', '\\]'],
+ ],
+ processEscapes: true,
+ processEnvironments: true,
+ },
+ options: {
+ //ignoreHtmlClass: ".*|",
+ //processHtmlClass: "arithmatex"
+ // Skip code blocks only
+ skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
+ // Only ignore explicit opt-out
+ ignoreHtmlClass: 'no-mathjax|tex2jax_ignore',
+ },
+}
+
+document$.subscribe(() => {
+ MathJax.startup.output.clearCache()
+ MathJax.typesetClear()
+ MathJax.texReset()
+ MathJax.typesetPromise()
+})
diff --git a/docs/docs/assets/stylesheets/extra.css b/docs/docs/assets/stylesheets/extra.css
new file mode 100644
index 00000000..a625be80
--- /dev/null
+++ b/docs/docs/assets/stylesheets/extra.css
@@ -0,0 +1,359 @@
+/*************/
+/* Variables */
+/*************/
+
+:root {
+ --sz-link-color--lightmode: #0184c7;
+ --sz-hovered-link-color--lightmode: #37bdf9;
+ --sz-body-background-color--lightmode: #fafafa;
+ --sz-body-text-color--lightmode: #525252;
+ --sz-body-heading-color--lightmode: #434343;
+ --sz-code-background-color--lightmode: #ececec;
+
+ --sz-link-color--darkmode: #37bdf9;
+ --sz-hovered-link-color--darkmode: #2890c0;
+ --sz-body-background-color--darkmode: #262626;
+ --sz-body-text-color--darkmode: #a3a3a3;
+ --sz-body-heading-color--darkmode: #e5e5e5;
+ --sz-code-background-color--darkmode: #212121;
+}
+
+/****************/
+/* Color styles */
+/****************/
+
+/* Default styles https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/main/_typeset.scss */
+
+/* Light mode */
+
+/* Default light mode https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/main/_colors.scss */
+
+[data-md-color-scheme="default"] {
+
+ /* Primary color shades */
+ --md-primary-fg-color: var(--sz-body-background-color--lightmode); /* Navigation background */
+ --md-primary-bg-color: var(--sz-body-text-color--lightmode); /* E.g., Header title and icons */
+ --md-primary-bg-color--light: var(--sz-body-text-color--lightmode); /* E.g., Header search */
+
+ /* Accent color shades */
+ --md-accent-fg-color: var(--sz-hovered-link-color--lightmode); /* E.g., Hovered `a` elements & copy icon in code */
+
+ /* Default color shades */
+ --md-default-fg-color: var(--sz-body-text-color--lightmode);
+ --md-default-fg-color--light: var(--sz-body-heading-color--lightmode); /* E.g., `h1` color & TOC viewed items & `$` in code */
+ --md-default-fg-color--lighter: var(--sz-body-text-color--lightmode); /* E.g., `¶` sign near `h1-h8` */
+ --md-default-fg-color--lightest: var(--sz-body-text-color--lightmode); /* E.g., Copy icon in code */
+ --md-default-bg-color: var(--sz-body-background-color--lightmode);
+
+ /* Code color shades */
+ --md-code-bg-color: var(--sz-code-background-color--lightmode);
+
+ /* Typeset color shades */
+ --md-typeset-color: var(--sz-body-text-color--lightmode);
+
+ /* Typeset `a` color shades */
+ --md-typeset-a-color: var(--sz-link-color--lightmode);
+
+ /* Footer color shades */
+ --md-footer-fg-color: var(--sz-body-text-color--lightmode); /* E.g., Next -> */
+ --md-footer-fg-color--light: var(--sz-body-text-color--lightmode); /* E.g., © 2022 EasyDiffraction, Material for MkDocs */
+ --md-footer-fg-color--lighter: var(--sz-body-text-color--lightmode); /* E.g. Made with */
+ --md-footer-bg-color: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., Next -> */
+ --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., © 2022 EasyDiffraction */
+
+ /* Custom colors */
+ --sz-red-color: #F44336;
+ --sz-blue-color: #03A9F4;
+ --sz-green-color: #4CAF50;
+ --sz-orange-color: #FF9800;
+
+ /* Logo display */
+ --md-footer-logo-dark-mode: none;
+ --md-footer-logo-light-mode: block;
+}
+
+/* Dark mode */
+
+/* Default dark mode: https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/palette/_scheme.scss */
+
+[data-md-color-scheme="slate"] {
+
+ /* Primary color shades */
+ --md-primary-fg-color: var(--sz-body-background-color--darkmode); /* Navigation background */
+ --md-primary-bg-color: var(--sz-body-text-color--darkmode); /* E.g., Header title and icons */
+ --md-primary-bg-color--light: var(--sz-body-text-color--darkmode); /* E.g., Header search */
+
+ /* Accent color shades */
+ --md-accent-fg-color: var(--sz-hovered-link-color--darkmode); /* E.g., Hovered `a` elements & copy icon in code */
+
+ /* Default color shades */
+ --md-default-fg-color: var(--sz-body-text-color--darkmode);
+ --md-default-fg-color--light: var(--sz-body-heading-color--darkmode); /* E.g., `h1` color & TOC viewed items & `$` in code */
+ --md-default-fg-color--lighter: var(--sz-body-text-color--darkmode); /* E.g., `¶` sign near `h1-h8` */
+ --md-default-fg-color--lightest: var(--sz-body-text-color--darkmode); /* E.g., Copy icon in code */
+ --md-default-bg-color: var(--sz-body-background-color--darkmode);
+
+ /* Code color shades */
+ --md-code-bg-color: var(--sz-code-background-color--darkmode);
+
+ /* Typeset color shades */
+ --md-typeset-color: var(--sz-body-text-color--darkmode);
+
+ /* Typeset `a` color shades */
+ --md-typeset-a-color: var(--sz-link-color--darkmode);
+
+ /* Footer color shades */
+ --md-footer-fg-color: var(--sz-body-text-color--darkmode); /* E.g., Next -> */
+ --md-footer-fg-color--light: var(--sz-body-text-color--darkmode); /* E.g., © 2022 EasyDiffraction, Material for MkDocs */
+ --md-footer-fg-color--lighter: var(--sz-body-text-color--darkmode); /* E.g. Made with */
+ --md-footer-bg-color: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., Next -> */
+ --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., © 2022 EasyDiffraction */
+
+ /* Custom colors */
+ --sz-red-color: #EF9A9A;
+ --sz-blue-color: #81D4FA;
+ --sz-green-color: #A5D6A7;
+ --sz-orange-color: #FFCC80;
+
+ /* Logo display */
+ --md-footer-logo-dark-mode: block;
+ --md-footer-logo-light-mode: none;
+}
+
+/*****************/
+/* Custom styles */
+/*****************/
+
+/* Logo */
+
+#logo_light_mode {
+ display: var(--md-footer-logo-light-mode);
+}
+
+#logo_dark_mode {
+ display: var(--md-footer-logo-dark-mode);
+}
+
+/* Customize default styles of MkDocs Material */
+
+/* Hide navigation title */
+label.md-nav__title[for="__drawer"] {
+ height: 0;
+}
+
+/* Hide site title (first topic) while keeping page title and version selector */
+.md-header__topic:first-child .md-ellipsis {
+ display: none;
+}
+
+/* Increase logo size */
+.md-logo :is(img, svg) {
+ height: 1.8rem !important;
+}
+
+/* Hide GH repo with counts (top right page corner) */
+.md-header__source {
+ display: none;
+}
+
+/* Hide GH repo with counts (navigation bar in mobile view) */
+.md-nav__source {
+ display: none;
+}
+
+/* Ensure all horizontal lines in the navigation list are removed or hidden */
+.md-nav__item {
+ /* Removes any border starting from the second level */
+ border: none !important;
+ /* Modifies the background color to hide the first horizontal line */
+ background-color: var(--md-default-bg-color);
+}
+
+/* Increase TOC (on the right) width */
+.md-nav--secondary {
+ margin-left: -10px;
+ margin-right: -4px;
+}
+
+/* */
+.md-nav__item > .md-nav__link {
+ padding-left: 0.5em; /* Default */
+}
+
+/* Change line height of the tabel cells */
+.md-typeset td,
+.md-typeset th {
+ line-height: 1.25 !important;
+}
+
+/* Change vertical alignment of the icon inside the tabel cells */
+.md-typeset td .twemoji {
+ vertical-align: sub !important;
+}
+
+/* Change the width of the primary sidebar */
+/*
+.md-sidebar--primary {
+ width: 240px;
+}
+*/
+
+/* Change the overall width of the page */
+.md-grid {
+ max-width: 1280px;
+}
+
+/* Needed for mkdocs-jupyter to show download and other buttons on top of the notebook */
+.md-content__button {
+ position: relative !important;
+}
+
+/* Background color of the search input field */
+.md-search__input {
+ background-color: var(--md-code-bg-color) !important;
+}
+
+/* Customize default style of mkdocs-jupyter plugin */
+
+/* Set the width of the notebook to fill 100% and not reduce by the width of .md-content__button's
+Adjust the margins and paddings to fit the defaults in MkDocs Material and do not crop the label in the header
+*/
+.jupyter-wrapper {
+ width: 100% !important;
+ display: flex !important;
+}
+
+.jp-Notebook {
+ padding: 0 !important;
+ margin-top: -3em !important;
+
+ /* Ensure notebook content stretches across the page */
+ width: 100% !important;
+ max-width: 100% !important;
+
+ /* mkdocs-material + some notebook HTML end up as flex */
+ align-items: stretch !important;
+}
+
+.jp-Notebook .jp-Cell {
+ /* Key: flex children often need min-width: 0 to prevent weird shrink */
+ width: 100% !important;
+ max-width: 100% !important;
+ min-width: 0 !important;
+
+ /* Removes jupyter cell paddings */
+ padding-left: 0 !important;
+}
+
+/* Removes jupyter cell prefixes, like In[123]: */
+.prompt,
+.jp-InputPrompt,
+.jp-OutputPrompt {
+ display: none !important;
+}
+
+/* Removes jupyter output cell padding to align with input cell text */
+.jp-RenderedText {
+ padding-left: 0.85em !important;
+}
+
+/* Extra styling the panda dataframes, on top of the style included in the code */
+table.dataframe {
+ float: left;
+ margin-left: 0.75em !important;
+ margin-bottom: 0.5em !important;
+ font-size: var(--jp-code-font-size) !important;
+ color: var(--md-primary-bg-color) !important;
+ /* Allow table cell wrapping in MkDocs-Jupyter outputs */
+ /*
+ table-layout: auto !important;
+ width: auto !important;
+ */
+}
+
+/* Allow wrap for the last column */
+/*
+table.dataframe td:last-child,
+table.dataframe th:last-child {
+ white-space: normal !important;
+ word-break: break-word !important;
+}
+*/
+
+/* Custom styles for the CIF files */
+
+.cif {
+ padding-left: 1em;
+ padding-right: 1em;
+ padding-top: 1px;
+ padding-bottom: 1px;
+ background-color: var(--md-code-bg-color);
+ font-size: small;
+}
+.red {
+ color: var(--sz-red-color);
+}
+.green {
+ color: var(--sz-green-color);
+}
+.blue {
+ color: var(--sz-blue-color);
+}
+.orange {
+ color: var(--sz-orange-color);
+}
+.grey {
+ color: grey;
+}
+
+/**********/
+/* Labels */
+/**********/
+
+.label-cif {
+ padding-top: 0.5ex;
+ padding-bottom: 0.5ex;
+ padding-left: 0.9ex;
+ padding-right: 0.9ex;
+ border-radius: 1ex;
+ color: var(--md-default-fg-color) !important;
+ background-color: var(--md-code-bg-color);
+}
+
+p .label-cif, li .label-cif {
+ vertical-align: 5%;
+ font-size: 12px;
+}
+
+.label-cif:hover {
+ color: white !important;
+}
+
+.label-experiment {
+ padding-top: 0.25ex;
+ padding-bottom: 0.6ex;
+ padding-left: 0.9ex;
+ padding-right: 0.9ex;
+ border-radius: 1ex;
+ color: var(--md-default-fg-color) !important;
+ background-color: rgba(55, 189, 249, 0.1);
+}
+
+p .label-experiment, li .label-experiment {
+ vertical-align: 5%;
+ font-size: 12px;
+}
+
+h1 .label-experiment {
+ padding-top: 0.05ex;
+ padding-bottom: 0.4ex;
+ padding-left: 0.9ex;
+ padding-right: 0.9ex;
+ border-radius: 0.75ex;
+ color: var(--md-default-fg-color) !important;
+ background-color: rgba(55, 189, 249, 0.1);
+}
+
+.label-experiment:hover {
+ color: white !important;
+}
diff --git a/docs/index.md b/docs/docs/index.md
similarity index 53%
rename from docs/index.md
rename to docs/docs/index.md
index a34d3023..73c35423 100644
--- a/docs/index.md
+++ b/docs/docs/index.md
@@ -4,17 +4,18 @@
Here is a brief overview of the main documentation sections:
-- [:material-information-slab-circle: Introduction](introduction/index.md) –
- Provides an overview of EasyDiffraction, including its purpose, licensing,
- latest release details, and contact information.
-- [:material-cog-box: Installation & Setup](installation-and-setup/index.md) –
- Guides users through system requirements, environment configuration, and the
- installation process.
-- [:material-book-open-variant: User Guide](user-guide/index.md) – Covers core
- concepts, key terminology, workflow steps, and essential parameters for
- effective use of EasyDiffraction.
+- [:material-information-slab-circle: Introduction](introduction/index.md)
+ – Provides an overview of EasyDiffraction, including its purpose,
+ licensing, latest release details, and contact information.
+- [:material-cog-box: Installation & Setup](installation-and-setup/index.md)
+ – Guides users through system requirements, environment configuration,
+ and the installation process.
+- [:material-book-open-variant: User Guide](user-guide/index.md) –
+ Covers core concepts, key terminology, workflow steps, and essential
+ parameters for effective use of EasyDiffraction.
- [:material-school: Tutorials](tutorials/index.md) – Offers practical,
- step-by-step examples demonstrating common workflows and data analysis tasks.
-- [:material-code-braces-box: API Reference](api-reference/index.md) – An
- auto-generated reference detailing the available functions and modules in
- EasyDiffraction.
+ step-by-step examples demonstrating common workflows and data analysis
+ tasks.
+- [:material-code-braces-box: API Reference](api-reference/index.md) –
+ An auto-generated reference detailing the available functions and
+ modules in EasyDiffraction.
diff --git a/docs/installation-and-setup/index.md b/docs/docs/installation-and-setup/index.md
similarity index 80%
rename from docs/installation-and-setup/index.md
rename to docs/docs/installation-and-setup/index.md
index 80b64235..0891a55f 100644
--- a/docs/installation-and-setup/index.md
+++ b/docs/docs/installation-and-setup/index.md
@@ -6,16 +6,16 @@ icon: material/cog-box
## Requirements
-EasyDiffraction is a cross-platform Python library compatible with **Python 3.11
-through 3.13**.
+EasyDiffraction is a cross-platform Python library compatible with
+**Python 3.11 through 3.13**.
Make sure Python is installed on your system before proceeding with the
installation.
## Environment Setup optional { #environment-setup data-toc-label="Environment Setup" }
-We recommend using a **virtual environment** to isolate dependencies and avoid
-conflicts with system-wide packages. If any issues arise, you can simply delete
-and recreate the environment.
+We recommend using a **virtual environment** to isolate dependencies and
+avoid conflicts with system-wide packages. If any issues arise, you can
+simply delete and recreate the environment.
#### Creating and Activating a Virtual Environment:
@@ -76,22 +76,23 @@ and recreate the environment.
### Installing from PyPI recommended { #from-pypi data-toc-label="Installing from PyPI" }
-EasyDiffraction is available on **PyPI (Python Package Index)** and can be
-installed using `pip`. We strongly recommend installing it within a virtual
-environment, as described in the [Environment Setup](#environment-setup)
-section.
+EasyDiffraction is available on **PyPI (Python Package Index)** and can
+be installed using `pip`. We strongly recommend installing it within a
+virtual environment, as described in the
+[Environment Setup](#environment-setup) section.
We recommend installing the latest release of EasyDiffraction with the
-`visualization` extras, which include optional dependencies used for simplified
-visualization of charts and tables. This can be especially useful for running
-the Jupyter Notebook examples. To do so, use the following command:
+`visualization` extras, which include optional dependencies used for
+simplified visualization of charts and tables. This can be especially
+useful for running the Jupyter Notebook examples. To do so, use the
+following command:
```bash
pip install 'easydiffraction[visualization]'
```
-If only the core functionality is needed, the library can be installed simply
-with:
+If only the core functionality is needed, the library can be installed
+simply with:
```bash
pip install easydiffraction
@@ -117,8 +118,8 @@ pip show easydiffraction
### Installing from GitHub
-Installing unreleased versions is generally not recommended but may be useful
-for testing.
+Installing unreleased versions is generally not recommended but may be
+useful for testing.
To install EasyDiffraction from, e.g., the `develop` branch of GitHub:
@@ -134,18 +135,20 @@ pip install 'easydiffraction[visualization] @ git+https://github.com/easyscience
## How to Run Tutorials
-EasyDiffraction includes a collection of **Jupyter Notebook examples** that
-demonstrate key functionality. These tutorials serve as **step-by-step guides**
-to help users understand the diffraction data analysis workflow.
+EasyDiffraction includes a collection of **Jupyter Notebook examples**
+that demonstrate key functionality. These tutorials serve as
+**step-by-step guides** to help users understand the diffraction data
+analysis workflow.
They are available as **static HTML pages** in the
-[:material-school: Tutorials](../tutorials/index.md) section. You can also run
-them interactively in two ways:
+[:material-school: Tutorials](../tutorials/index.md) section. You can
+also run them interactively in two ways:
- **Run Locally** – Download the notebook via the :material-download:
**Download** button and run it on your computer.
-- **Run Online** – Use the :google-colab: **Open in Google Colab** button to run
- the tutorial directly in your browser (no setup required).
+- **Run Online** – Use the :google-colab: **Open in Google Colab**
+ button to run the tutorial directly in your browser (no setup
+ required).
!!! note
@@ -154,8 +157,9 @@ them interactively in two ways:
### Run Tutorials Locally
-To run tutorials locally, install **Jupyter Notebook** or **JupyterLab**. Here
-are the steps to follow in the case of **Jupyter Notebook**:
+To run tutorials locally, install **Jupyter Notebook** or
+**JupyterLab**. Here are the steps to follow in the case of **Jupyter
+Notebook**:
- Install Jupyter Notebook and IPython kernel:
```bash
@@ -177,32 +181,34 @@ are the steps to follow in the case of **Jupyter Notebook**:
```bash
http://localhost:8888/
```
-- Open one of the `*.ipynb` files and select the `EasyDiffraction Python kernel`
- to get started.
+- Open one of the `*.ipynb` files and select the
+ `EasyDiffraction Python kernel` to get started.
### Run Tutorials via Google Colab
-**Google Colab** lets you run Jupyter Notebooks in the cloud without any local
-installation.
+**Google Colab** lets you run Jupyter Notebooks in the cloud without any
+local installation.
To use Google Colab:
- Ensure you have a **Google account**.
-- Go to the **[:material-school: Tutorials](../tutorials/index.md)** section.
-- Click the :google-colab: **Open in Google Colab** button on any tutorial.
+- Go to the **[:material-school: Tutorials](../tutorials/index.md)**
+ section.
+- Click the :google-colab: **Open in Google Colab** button on any
+ tutorial.
-This is the fastest way to start experimenting with EasyDiffraction, without
-setting up Python on your system.
+This is the fastest way to start experimenting with EasyDiffraction,
+without setting up Python on your system.
## Installing with Pixi alternative { #installing-with-pixi data-toc-label="Installing with Pixi" }
-[Pixi](https://pixi.sh) is a modern package and environment manager for Python
-and Conda-compatible packages. It simplifies dependency management, environment
-isolation, and reproducibility.
+[Pixi](https://pixi.sh) is a modern package and environment manager for
+Python and Conda-compatible packages. It simplifies dependency
+management, environment isolation, and reproducibility.
The following simple steps provide an alternative setup method for
-EasyDiffraction using Pixi, replacing the traditional virtual environment
-approach.
+EasyDiffraction using Pixi, replacing the traditional virtual
+environment approach.
diff --git a/docs/introduction/index.md b/docs/docs/introduction/index.md
similarity index 90%
rename from docs/introduction/index.md
rename to docs/docs/introduction/index.md
index 2996386b..a2b42b59 100644
--- a/docs/introduction/index.md
+++ b/docs/docs/introduction/index.md
@@ -8,21 +8,22 @@ icon: material/information-slab-circle
**EasyDiffraction** is scientific software for calculating diffraction
patterns
-based on structural models and refining model parameters against experimental
-data.
+based on structural models and refining model parameters against
+experimental data.
-It is available as both a cross-platform desktop application and a Python
-library.
+It is available as both a cross-platform desktop application and a
+Python library.
-This documentation covers the usage of the EasyDiffraction Python library.
+This documentation covers the usage of the EasyDiffraction Python
+library.
For the graphical user interface (GUI) version, refer to the
[GUI documentation](https://docs.easydiffraction.org/app).
## EasyScience
EasyDiffraction is developed using the
-[EasyScience framework](https://easyscience.software), which provides tools
-for
+[EasyScience framework](https://easyscience.software), which provides
+tools for
building modular and flexible scientific libraries and applications.
## License
@@ -35,27 +36,28 @@ EasyDiffraction is released under the
The latest version of the EasyDiffraction Python library is
[{{ vars.release_version }}](https://github.com/easyscience/diffraction-lib/releases/latest).
-For a complete list of new features, bug fixes, and improvements, see the
+For a complete list of new features, bug fixes, and improvements, see
+the
[GitHub Releases page](https://github.com/easyscience/diffraction-lib/releases).
## Citation
-If you use EasyDiffraction in your work, please cite the specific version you
-used.
+If you use EasyDiffraction in your work, please cite the specific
+version you used.
All official releases of the EasyDiffraction library are archived on
Zenodo, each with a version-specific Digital Object Identifier (DOI).
-Citation details in various styles (e.g., APA, MLA) and formats (e.g., BibTeX,
-JSON)
+Citation details in various styles (e.g., APA, MLA) and formats (e.g.,
+BibTeX, JSON)
are available on the
[Zenodo archive page](https://doi.org/10.5281/zenodo.16806521).
## Contributing
-We welcome contributions from the community! EasyDiffraction is intended to be a
-community-driven, open-source project supported by a diverse group of
-contributors.
+We welcome contributions from the community! EasyDiffraction is intended
+to be a community-driven, open-source project supported by a diverse
+group of contributors.
The project is maintained by the
[European Spallation Source (ESS)](https://ess.eu).
diff --git a/docs/docs/tutorials/ed-1.ipynb b/docs/docs/tutorials/ed-1.ipynb
new file mode 100644
index 00000000..9b46deb0
--- /dev/null
+++ b/docs/docs/tutorials/ed-1.ipynb
@@ -0,0 +1,203 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: LBCO, HRPT\n",
+ "\n",
+ "This minimalistic example is designed to show how Rietveld refinement\n",
+ "can be performed when both the crystal structure and experiment\n",
+ "parameters are defined using CIF files.\n",
+ "\n",
+ "For this example, constant-wavelength neutron powder diffraction data\n",
+ "for La0.5Ba0.5CoO3 from HRPT at PSI is used.\n",
+ "\n",
+ "It does not contain any advanced features or options, and includes no\n",
+ "comments or explanations—these can be found in the other tutorials.\n",
+ "Default values are used for all parameters if not specified. Only\n",
+ "essential and self-explanatory code is provided.\n",
+ "\n",
+ "The example is intended for users who are already familiar with the\n",
+ "EasyDiffraction library and want to quickly get started with a simple\n",
+ "refinement. It is also useful for those who want to see what a\n",
+ "refinement might look like in code. For a more detailed explanation of\n",
+ "the code, please refer to the other tutorials."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Step 1: Define Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create minimal project without name and description\n",
+ "project = ed.Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## Step 2: Define Crystal Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Download CIF file from repository\n",
+ "structure_path = ed.download_data(id=1, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add_from_cif_path(structure_path)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "## Step 3: Define Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Download CIF file from repository\n",
+ "expt_path = ed.download_data(id=2, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_cif_path(expt_path)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Step 4: Perform Analysis"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Start refinement. All parameters, which have standard uncertainties\n",
+ "# in the input CIF files, are refined by default.\n",
+ "project.analysis.fit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Show fit results summary\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.show_names()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "16",
+ "metadata": {},
+ "source": [
+ "## Step 5: Show Project Summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.summary.show_report()"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-1.py b/docs/docs/tutorials/ed-1.py
similarity index 100%
rename from tutorials/ed-1.py
rename to docs/docs/tutorials/ed-1.py
diff --git a/docs/docs/tutorials/ed-10.ipynb b/docs/docs/tutorials/ed-10.ipynb
new file mode 100644
index 00000000..d6596816
--- /dev/null
+++ b/docs/docs/tutorials/ed-10.ipynb
@@ -0,0 +1,222 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Pair Distribution Function: Ni, NPD\n",
+ "\n",
+ "This example demonstrates a pair distribution function (PDF) analysis\n",
+ "of Ni, based on data collected from a constant wavelength neutron\n",
+ "powder diffraction experiment.\n",
+ "\n",
+ "The dataset is taken from:\n",
+ "https://github.com/diffpy/cmi_exchange/tree/main/cmi_scripts/fitNiPDF"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = ed.Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.create(name='ni')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['ni'].space_group.name_h_m = 'F m -3 m'\n",
+ "project.structures['ni'].space_group.it_coordinate_system_code = '1'\n",
+ "project.structures['ni'].cell.length_a = 3.52387\n",
+ "project.structures['ni'].atom_sites.create(\n",
+ " label='Ni',\n",
+ " type_symbol='Ni',\n",
+ " fract_x=0.0,\n",
+ " fract_y=0.0,\n",
+ " fract_z=0.0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "## Add Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = ed.download_data(id=6, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_data_path(\n",
+ " name='pdf',\n",
+ " data_path=data_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='constant wavelength',\n",
+ " radiation_probe='neutron',\n",
+ " scattering_type='total',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "11",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['pdf'].linked_phases.create(id='ni', scale=1.0)\n",
+ "project.experiments['pdf'].peak.damp_q = 0\n",
+ "project.experiments['pdf'].peak.broad_q = 0.03\n",
+ "project.experiments['pdf'].peak.cutoff_q = 27.0\n",
+ "project.experiments['pdf'].peak.sharp_delta_1 = 0.0\n",
+ "project.experiments['pdf'].peak.sharp_delta_2 = 2.0\n",
+ "project.experiments['pdf'].peak.damp_particle_diameter = 0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "12",
+ "metadata": {},
+ "source": [
+ "## Select Fitting Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['ni'].cell.length_a.free = True\n",
+ "project.structures['ni'].atom_sites['Ni'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['pdf'].linked_phases['ni'].scale.free = True\n",
+ "project.experiments['pdf'].peak.broad_q.free = True\n",
+ "project.experiments['pdf'].peak.sharp_delta_2.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "## Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "## Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='pdf', show_residual=True)"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-10.py b/docs/docs/tutorials/ed-10.py
similarity index 100%
rename from tutorials/ed-10.py
rename to docs/docs/tutorials/ed-10.py
diff --git a/docs/docs/tutorials/ed-11.ipynb b/docs/docs/tutorials/ed-11.ipynb
new file mode 100644
index 00000000..ddacaac7
--- /dev/null
+++ b/docs/docs/tutorials/ed-11.ipynb
@@ -0,0 +1,254 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Pair Distribution Function: Si, NPD\n",
+ "\n",
+ "This example demonstrates a pair distribution function (PDF) analysis\n",
+ "of Si, based on data collected from a time-of-flight neutron powder\n",
+ "diffraction experiment at NOMAD at SNS."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = ed.Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## Set Plotting Engine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n",
+ "# line below to explicitly set the engine to the required one.\n",
+ "# project.plotter.engine = 'plotly'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Set global plot range for plots\n",
+ "project.plotter.x_max = 40"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "## Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.create(name='si')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = project.structures['si']\n",
+ "structure.space_group.name_h_m.value = 'F d -3 m'\n",
+ "structure.space_group.it_coordinate_system_code = '1'\n",
+ "structure.cell.length_a = 5.43146\n",
+ "structure.atom_sites.create(\n",
+ " label='Si',\n",
+ " type_symbol='Si',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Add Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = ed.download_data(id=5, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_data_path(\n",
+ " name='nomad',\n",
+ " data_path=data_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='time-of-flight',\n",
+ " radiation_probe='neutron',\n",
+ " scattering_type='total',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment = project.experiments['nomad']\n",
+ "experiment.linked_phases.create(id='si', scale=1.0)\n",
+ "experiment.peak.damp_q = 0.02\n",
+ "experiment.peak.broad_q = 0.03\n",
+ "experiment.peak.cutoff_q = 35.0\n",
+ "experiment.peak.sharp_delta_1 = 0.0\n",
+ "experiment.peak.sharp_delta_2 = 4.0\n",
+ "experiment.peak.damp_particle_diameter = 0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "## Select Fitting Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['si'].cell.length_a.free = True\n",
+ "project.structures['si'].atom_sites['Si'].b_iso.free = True\n",
+ "experiment.linked_phases['si'].scale.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.peak.damp_q.free = True\n",
+ "experiment.peak.broad_q.free = True\n",
+ "experiment.peak.sharp_delta_1.free = True\n",
+ "experiment.peak.sharp_delta_2.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "18",
+ "metadata": {},
+ "source": [
+ "## Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "19",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "20",
+ "metadata": {},
+ "source": [
+ "## Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='nomad', show_residual=False)"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-11.py b/docs/docs/tutorials/ed-11.py
similarity index 100%
rename from tutorials/ed-11.py
rename to docs/docs/tutorials/ed-11.py
diff --git a/docs/docs/tutorials/ed-12.ipynb b/docs/docs/tutorials/ed-12.ipynb
new file mode 100644
index 00000000..a6394390
--- /dev/null
+++ b/docs/docs/tutorials/ed-12.ipynb
@@ -0,0 +1,303 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Pair Distribution Function: NaCl, XRD\n",
+ "\n",
+ "This example demonstrates a pair distribution function (PDF) analysis\n",
+ "of NaCl, based on data collected from an X-ray powder diffraction\n",
+ "experiment.\n",
+ "\n",
+ "The dataset is taken from:\n",
+ "https://github.com/diffpy/add2019-diffpy-cmi/tree/master"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = ed.Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## Set Plotting Engine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n",
+ "# line below to explicitly set the engine to the required one.\n",
+ "# project.plotter.engine = 'plotly'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Set global plot range for plots\n",
+ "project.plotter.x_min = 2.0\n",
+ "project.plotter.x_max = 30.0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "## Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.create(name='nacl')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['nacl'].space_group.name_h_m = 'F m -3 m'\n",
+ "project.structures['nacl'].space_group.it_coordinate_system_code = '1'\n",
+ "project.structures['nacl'].cell.length_a = 5.62\n",
+ "project.structures['nacl'].atom_sites.create(\n",
+ " label='Na',\n",
+ " type_symbol='Na',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=1.0,\n",
+ ")\n",
+ "project.structures['nacl'].atom_sites.create(\n",
+ " label='Cl',\n",
+ " type_symbol='Cl',\n",
+ " fract_x=0.5,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='b',\n",
+ " b_iso=1.0,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Add Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = ed.download_data(id=4, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_data_path(\n",
+ " name='xray_pdf',\n",
+ " data_path=data_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='constant wavelength',\n",
+ " radiation_probe='xray',\n",
+ " scattering_type='total',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['xray_pdf'].show_supported_peak_profile_types()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['xray_pdf'].show_current_peak_profile_type()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['xray_pdf'].peak_profile_type = 'gaussian-damped-sinc'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['xray_pdf'].peak.damp_q = 0.03\n",
+ "project.experiments['xray_pdf'].peak.broad_q = 0\n",
+ "project.experiments['xray_pdf'].peak.cutoff_q = 21\n",
+ "project.experiments['xray_pdf'].peak.sharp_delta_1 = 0\n",
+ "project.experiments['xray_pdf'].peak.sharp_delta_2 = 5\n",
+ "project.experiments['xray_pdf'].peak.damp_particle_diameter = 0"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['xray_pdf'].linked_phases.create(id='nacl', scale=0.5)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "## Select Fitting Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['nacl'].cell.length_a.free = True\n",
+ "project.structures['nacl'].atom_sites['Na'].b_iso.free = True\n",
+ "project.structures['nacl'].atom_sites['Cl'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['xray_pdf'].linked_phases['nacl'].scale.free = True\n",
+ "project.experiments['xray_pdf'].peak.damp_q.free = True\n",
+ "project.experiments['xray_pdf'].peak.sharp_delta_2.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22",
+ "metadata": {},
+ "source": [
+ "## Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24",
+ "metadata": {},
+ "source": [
+ "## Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='xray_pdf')"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-12.py b/docs/docs/tutorials/ed-12.py
similarity index 100%
rename from tutorials/ed-12.py
rename to docs/docs/tutorials/ed-12.py
diff --git a/docs/docs/tutorials/ed-13.ipynb b/docs/docs/tutorials/ed-13.ipynb
new file mode 100644
index 00000000..d35f3628
--- /dev/null
+++ b/docs/docs/tutorials/ed-13.ipynb
@@ -0,0 +1,2923 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Fitting Powder Diffraction data\n",
+ "\n",
+ "This notebook guides you through the Rietveld refinement of crystal\n",
+ "structures using simulated powder diffraction data. It consists of two\n",
+ "parts:\n",
+ "- Introduction: A simple reference fit using silicon (Si) crystal\n",
+ " structure.\n",
+ "- Exercise: A more complex fit using La₀.₅Ba₀.₅CoO₃ (LBCO) crystal\n",
+ " structure.\n",
+ "\n",
+ "## 🛠️ Import Library\n",
+ "\n",
+ "We start by importing the necessary library for the analysis. In this\n",
+ "notebook, we use the EasyDiffraction library. As mentioned in the\n",
+ "introduction to EasyScience, EasyDiffraction is built on that\n",
+ "framework and offers a high-level interface focused specifically for\n",
+ "diffraction analysis.\n",
+ "\n",
+ "This notebook is self-contained and designed for hands-on learning.\n",
+ "However, if you're interested in exploring more advanced features or\n",
+ "learning about additional capabilities of the EasyDiffraction library,\n",
+ "please refer to the official documentation:\n",
+ "https://docs.easydiffraction.org/lib\n",
+ "\n",
+ "Depending on your requirements, you may choose to import only specific\n",
+ "classes. However, for the sake of simplicity in this notebook, we will\n",
+ "import the entire library."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/first-steps/#importing-easydiffraction)\n",
+ "for more details about importing the EasyDiffraction library and its\n",
+ "components."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## 📘 Introduction: Simple Reference Fit – Si\n",
+ "\n",
+ "Before diving into the more complex fitting exercise with the\n",
+ "La₀.₅Ba₀.₅CoO₃ (LBCO) crystal structure, let's start with a simpler\n",
+ "example using the silicon (Si) crystal structure. This will help us\n",
+ "understand the basic concepts and steps involved in fitting a crystal\n",
+ "structure using powder diffraction data.\n",
+ "\n",
+ "For this part of the notebook, we will use the powder diffraction data\n",
+ "previously simulated using the Si crystal structure.\n",
+ "\n",
+ "### 📦 Create a Project – 'reference'\n",
+ "\n",
+ "In EasyDiffraction, a project serves as a container for all\n",
+ "information related to the analysis of a specific experiment or set of\n",
+ "experiments. It enables you to organize your data, experiments,\n",
+ "crystal structures, and fitting parameters in an organized manner. You\n",
+ "can think of it as a folder containing all the essential details about\n",
+ "your analysis. The project also allows us to visualize both the\n",
+ "measured and calculated diffraction patterns, among other things."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/project/)\n",
+ "for more details about creating a project and its purpose in the\n",
+ "analysis workflow."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1 = ed.Project(name='reference')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6",
+ "metadata": {},
+ "source": [
+ "You can set the title and description of the project to provide\n",
+ "context and information about the analysis being performed. This is\n",
+ "useful for documentation purposes and helps others (or yourself in the\n",
+ "future) understand the purpose of the project at a glance."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.info.title = 'Reference Silicon Fit'\n",
+ "project_1.info.description = 'Fitting simulated powder diffraction pattern of Si.'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "### 🔬 Create an Experiment\n",
+ "\n",
+ "An experiment represents a specific diffraction measurement performed\n",
+ "on a specific sample using a particular instrument. It contains\n",
+ "details about the measured data, instrument parameters, and other\n",
+ "relevant information."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/)\n",
+ "for more details about experiments and their purpose in the analysis\n",
+ "workflow."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_dir = 'data'\n",
+ "file_name = 'reduced_Si.xye'\n",
+ "si_xye_path = f'{data_dir}/{file_name}'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "Uncomment the following cell if your data reduction failed and the\n",
+ "reduced data file is missing. In this case, you can download our\n",
+ "pre-generated reduced data file from the EasyDiffraction repository.\n",
+ "The `download_data` function will not overwrite an existing file\n",
+ "unless you set `overwrite=True`, so it's safe to run even if the\n",
+ "file is already present."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "si_xye_path = ed.download_data(id=17, destination=data_dir)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "Now we can create the experiment and load the measured data. In this\n",
+ "case, the experiment is defined as a powder diffraction measurement\n",
+ "using time-of-flight neutrons. The measured data is loaded from a file\n",
+ "containing the reduced diffraction pattern of Si from the data\n",
+ "reduction notebook."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#defining-an-experiment-manually)\n",
+ "for more details about different types of experiments."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.experiments.add_from_data_path(\n",
+ " name='sim_si',\n",
+ " data_path=si_xye_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='time-of-flight',\n",
+ " radiation_probe='neutron',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "16",
+ "metadata": {},
+ "source": [
+ "#### Inspect Measured Data\n",
+ "\n",
+ "After creating the experiment, we can examine the measured data. The\n",
+ "measured data consists of a diffraction pattern having time-of-flight\n",
+ "(TOF) values and corresponding intensities. The TOF values are given\n",
+ "in microseconds (μs), and the intensities are in arbitrary units.\n",
+ "\n",
+ "The data is stored in XYE format, a simple text format containing\n",
+ "three columns: TOF, intensity, and intensity error (if available)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#measured-data-category)\n",
+ "for more details about the measured data and its format.\n",
+ "\n",
+ "To visualize the measured data, we can use the `plot_meas` method of\n",
+ "the project. Before plotting, we need to set the plotting engine to\n",
+ "'plotly', which provides interactive visualizations."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "18",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://easyscience.github.io/diffraction-lib/user-guide/first-steps/#supported-plotters)\n",
+ "for more details about setting the plotting engine."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "19",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n",
+ "# line below to explicitly set the engine to the required one.\n",
+ "# project.plotter.engine = 'plotly'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.plot_meas(expt_name='sim_si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21",
+ "metadata": {},
+ "source": [
+ "If you zoom in on the highest TOF peak (around 120,000 μs), you will\n",
+ "notice that it has a broad and unusual shape. This distortion, along\n",
+ "with additional effects on the low TOF peaks, is most likely an\n",
+ "artifact related to the simplifications made during the simulation\n",
+ "and/or reduction process and is currently under investigation.\n",
+ "However, this is outside the scope of this school. Therefore, we will\n",
+ "simply exclude both the low and high TOF regions from the analysis by\n",
+ "adding an excluded regions to the experiment.\n",
+ "\n",
+ "In real experiments, it is often necessary to exclude certain regions\n",
+ "from the measured data. For example, the direct beam can significantly\n",
+ "increase the background at very low angles, making those parts of the\n",
+ "diffractogram unreliable. Additionally, sample environment components\n",
+ "may introduce unwanted peaks. In such cases, excluding specific\n",
+ "regions is often simpler and more effective than modeling them with an\n",
+ "additional sample phase."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#excluded-regions-category)\n",
+ "for more details about excluding regions from the measured data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.experiments['sim_si'].excluded_regions.create(id='1', start=0, end=55000)\n",
+ "project_1.experiments['sim_si'].excluded_regions.create(id='2', start=105500, end=200000)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24",
+ "metadata": {},
+ "source": [
+ "To visualize the effect of excluding the high TOF region, we can plot\n",
+ "the measured data again. The excluded region will be omitted from the\n",
+ "plot and is not used in the fitting process."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.plot_meas(expt_name='sim_si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument Parameters\n",
+ "\n",
+ "After the experiment is created and measured data is loaded, we need\n",
+ "to set the instrument parameters.\n",
+ "\n",
+ "In this type of experiment, the instrument parameters define how the\n",
+ "measured data is converted between d-spacing and time-of-flight (TOF)\n",
+ "during the data reduction process as well as the angular position of\n",
+ "the detector. So, we put values based on those from the reduction.\n",
+ "These values can be found in the header of the corresponding .XYE\n",
+ "file. Their names are `two_theta` and `DIFC`, which stand for the\n",
+ "two-theta angle and the linear conversion factor from d-spacing to\n",
+ "TOF, respectively.\n",
+ "\n",
+ "You can set them manually, but it is more convenient to use the\n",
+ "`get_value_from_xye_header` function from the EasyDiffraction library."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#instrument-category)\n",
+ "for more details about the instrument parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "28",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.experiments['sim_si'].instrument.setup_twotheta_bank = ed.get_value_from_xye_header(\n",
+ " si_xye_path, 'two_theta'\n",
+ ")\n",
+ "project_1.experiments['sim_si'].instrument.calib_d_to_tof_linear = ed.get_value_from_xye_header(\n",
+ " si_xye_path, 'DIFC'\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29",
+ "metadata": {},
+ "source": [
+ "Before proceeding, let's take a quick look at the concept of\n",
+ "parameters in EasyDiffraction, which is similar to the parameter\n",
+ "concept in EasyScience. The current version of EasyDiffraction is\n",
+ "transitioning to reuse the parameter system from EasyScience.\n",
+ "\n",
+ "That is, every parameter is an object, which has different attributes,\n",
+ "such as `value`, `units`, etc. To display the parameter of interest,\n",
+ "you can simply print the parameter object.\n",
+ "\n",
+ "For example, to display the linear conversion factor from d-spacing to\n",
+ "TOF, which is the `calib_d_to_tof_linear` parameter, you can do the\n",
+ "following:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(project_1.experiments['sim_si'].instrument.calib_d_to_tof_linear)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "31",
+ "metadata": {},
+ "source": [
+ "The `value` attribute represents the current value of the parameter as\n",
+ "a float. You can access it directly by using the `value` attribute of\n",
+ "the parameter. This is useful when you want to use the parameter value\n",
+ "in calculations or when you want to assign it to another parameter.\n",
+ "For example, to get only the value of the same parameter as floating\n",
+ "point number, but not the whole object, you can do the following:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "32",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(project_1.experiments['sim_si'].instrument.calib_d_to_tof_linear.value)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "33",
+ "metadata": {},
+ "source": [
+ "Note that to set the value of the parameter, you can simply assign a\n",
+ "new value to the parameter object without using the `value` attribute,\n",
+ "as we did above."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "34",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/parameters/)\n",
+ "for more details about parameters in EasyDiffraction and their\n",
+ "attributes."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile Parameters\n",
+ "\n",
+ "The next set of parameters is needed to define the peak profile used\n",
+ "in the fitting process. The peak profile describes the shape of the\n",
+ "diffraction peaks. They include parameters for the broadening and\n",
+ "asymmetry of the peaks.\n",
+ "\n",
+ "There are several commonly used peak profile functions:\n",
+ "- **Gaussian**: Describes peaks with a symmetric bell-shaped curve,\n",
+ " often used when instrumental broadening dominates. [Click for more\n",
+ " details.](https://mantidproject.github.io/docs-versioned/v6.1.0/fitting/fitfunctions/Gaussian.html)\n",
+ "- **Lorentzian**: Produces narrower central peaks with longer tails,\n",
+ " frequently used to model size broadening effects. [Click for more\n",
+ " details.](https://mantidproject.github.io/docs-versioned/v6.1.0/fitting/fitfunctions/Lorentzian.html)\n",
+ "- **Pseudo-Voigt**: A linear combination of Gaussian and Lorentzian\n",
+ " components, providing flexibility to represent real diffraction\n",
+ " peaks. [Click for more\n",
+ " details.](https://mantidproject.github.io/docs-versioned/v6.1.0/fitting/fitfunctions/PseudoVoigt.html)\n",
+ "- **Pseudo-Voigt convoluted with Ikeda-Carpenter**: Incorporates the\n",
+ " asymmetry introduced by the neutron pulse shape in time-of-flight\n",
+ " instruments. This is a common choice for TOF neutron powder\n",
+ " diffraction data. [Click for more\n",
+ " details.](https://docs.mantidproject.org/v6.1.0/fitting/fitfunctions/IkedaCarpenterPV.html)\n",
+ "\n",
+ "Here, we use a pseudo-Voigt peak profile function with Ikeda-Carpenter\n",
+ "asymmetry.\n",
+ "\n",
+ "The parameter values are typically determined experimentally on the\n",
+ "same instrument and under the same configuration as the data being\n",
+ "analyzed, using measurements of a standard sample. In our case, the Si\n",
+ "sample serves as this standard reference. We will refine the peak\n",
+ "profile parameters here, and these refined values will be used as\n",
+ "starting points for the more complex fit in the next part of the\n",
+ "notebook. For this initial fit, we will provide reasonable physical\n",
+ "guesses as starting values."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#peak-category)\n",
+ "for more details about the peak profile types."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.experiments['sim_si'].peak_profile_type = 'pseudo-voigt * ikeda-carpenter'\n",
+ "project_1.experiments['sim_si'].peak.broad_gauss_sigma_0 = 69498\n",
+ "project_1.experiments['sim_si'].peak.broad_gauss_sigma_1 = -55578\n",
+ "project_1.experiments['sim_si'].peak.broad_gauss_sigma_2 = 14560\n",
+ "project_1.experiments['sim_si'].peak.broad_mix_beta_0 = 0.0019\n",
+ "project_1.experiments['sim_si'].peak.broad_mix_beta_1 = 0.0137\n",
+ "project_1.experiments['sim_si'].peak.asym_alpha_0 = -0.0055\n",
+ "project_1.experiments['sim_si'].peak.asym_alpha_1 = 0.0147"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "38",
+ "metadata": {},
+ "source": [
+ "#### Set Background\n",
+ "\n",
+ "The background of the diffraction pattern represents the portion of\n",
+ "the pattern that is not related to the crystal structure of the\n",
+ "sample. It's rather represents noise and other sources of scattering\n",
+ "that can affect the measured intensities. This includes contributions\n",
+ "from the instrument, the sample holder, the sample environment, and\n",
+ "other sources of incoherent scattering.\n",
+ "\n",
+ "The background can be modeled in various ways. In this example, we\n",
+ "will use a simple line segment background, which is a common approach\n",
+ "for powder diffraction data. The background intensity at any point is\n",
+ "defined by linear interpolation between neighboring points. The\n",
+ "background points are selected to span the range of the diffraction\n",
+ "pattern while avoiding the peaks.\n",
+ "\n",
+ "We will add several background points at specific TOF values (in μs)\n",
+ "and corresponding intensity values. These points are chosen to\n",
+ "represent the background level in the diffraction pattern free from\n",
+ "any peaks.\n",
+ "\n",
+ "The background points are added using the `add` method of the\n",
+ "`background` object. The `x` parameter represents the TOF value, and\n",
+ "the `y` parameter represents the intensity value at that TOF.\n",
+ "\n",
+ "Let's set all the background points at a constant value of 0.01, which\n",
+ "can be roughly estimated by the eye, and we will refine them later\n",
+ "during the fitting process."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#background-category)\n",
+ "for more details about the background and its types."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.experiments['sim_si'].background_type = 'line-segment'\n",
+ "project_1.experiments['sim_si'].background.create(id='1', x=50000, y=0.01)\n",
+ "project_1.experiments['sim_si'].background.create(id='2', x=60000, y=0.01)\n",
+ "project_1.experiments['sim_si'].background.create(id='3', x=70000, y=0.01)\n",
+ "project_1.experiments['sim_si'].background.create(id='4', x=80000, y=0.01)\n",
+ "project_1.experiments['sim_si'].background.create(id='5', x=90000, y=0.01)\n",
+ "project_1.experiments['sim_si'].background.create(id='6', x=100000, y=0.01)\n",
+ "project_1.experiments['sim_si'].background.create(id='7', x=110000, y=0.01)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41",
+ "metadata": {},
+ "source": [
+ "### 🧩 Create a Structure – Si\n",
+ "\n",
+ "After setting up the experiment, we need to create a structure that\n",
+ "describes the crystal structure of the sample being analyzed.\n",
+ "\n",
+ "In this case, we will create a structure for silicon (Si) with a\n",
+ "cubic crystal structure. The structure contains information about\n",
+ "the space group, lattice parameters, atomic positions of the atoms in\n",
+ "the unit cell, atom types, occupancies and atomic displacement\n",
+ "parameters. The structure is essential for the fitting process, as\n",
+ "it is used to calculate the expected diffraction pattern.\n",
+ "\n",
+ "EasyDiffraction refines the crystal structure of the sample, but does\n",
+ "not solve it. Therefore, we need a good starting point with reasonable\n",
+ "structural parameters.\n",
+ "\n",
+ "Here, we define the Si structure as a cubic structure. As this is a\n",
+ "cubic structure, we only need to define the single lattice parameter,\n",
+ "which is the length of the unit cell edge. The Si crystal structure\n",
+ "has a single atom in the unit cell, which is located at the origin (0,\n",
+ "0, 0) of the unit cell. The symmetry of this site is defined by the\n",
+ "Wyckoff letter 'a'. The atomic displacement parameter defines the\n",
+ "thermal vibrations of the atoms in the unit cell and is presented as\n",
+ "an isotropic parameter (B_iso).\n",
+ "\n",
+ "Sometimes, the initial crystal structure parameters can be obtained\n",
+ "from one of the crystallographic databases, like for example the\n",
+ "Crystallography Open Database (COD). In this case, we use the COD\n",
+ "entry for silicon as a reference for the initial crystal structure\n",
+ "model: https://www.crystallography.net/cod/4507226.html\n",
+ "\n",
+ "Usually, the crystal structure parameters are provided in a CIF file\n",
+ "format, which is a standard format for crystallographic data. An\n",
+ "example of a CIF file for silicon is shown below. The CIF file\n",
+ "contains the space group information, unit cell parameters, and atomic\n",
+ "positions."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "42",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/data-format/)\n",
+ "for more details about the CIF format and its use in EasyDiffraction."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43",
+ "metadata": {},
+ "source": [
+ "```\n",
+ "data_si\n",
+ "\n",
+ "_space_group.name_H-M_alt \"F d -3 m\"\n",
+ "_space_group.IT_coordinate_system_code 2\n",
+ "\n",
+ "_cell.length_a 5.43\n",
+ "_cell.length_b 5.43\n",
+ "_cell.length_c 5.43\n",
+ "_cell.angle_alpha 90.0\n",
+ "_cell.angle_beta 90.0\n",
+ "_cell.angle_gamma 90.0\n",
+ "\n",
+ "loop_\n",
+ "_atom_site.label\n",
+ "_atom_site.type_symbol\n",
+ "_atom_site.fract_x\n",
+ "_atom_site.fract_y\n",
+ "_atom_site.fract_z\n",
+ "_atom_site.wyckoff_letter\n",
+ "_atom_site.occupancy\n",
+ "_atom_site.ADP_type\n",
+ "_atom_site.B_iso_or_equiv\n",
+ "Si Si 0 0 0 a 1.0 Biso 0.89\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "44",
+ "metadata": {},
+ "source": [
+ "As with adding the experiment in the previous step, we will create a\n",
+ "default structure and then modify its parameters to match the Si\n",
+ "structure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "45",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/structure/)\n",
+ "for more details about structures and their purpose in the data\n",
+ "analysis workflow."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "46",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.structures.create(name='si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "49",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/structure/#space-group-category)\n",
+ "for more details about the space group."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "50",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.structures['si'].space_group.name_h_m = 'F d -3 m'\n",
+ "project_1.structures['si'].space_group.it_coordinate_system_code = '2'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "51",
+ "metadata": {},
+ "source": [
+ "#### Set Lattice Parameters"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/structure/#cell-category)\n",
+ "for more details about the unit cell parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "53",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.structures['si'].cell.length_a = 5.43"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "54",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "55",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/structure/#atom-sites-category)\n",
+ "for more details about the atom sites category."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "56",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.structures['si'].atom_sites.create(\n",
+ " label='Si',\n",
+ " type_symbol='Si',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.89,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57",
+ "metadata": {},
+ "source": [
+ "### 🔗 Assign Structure to Experiment\n",
+ "\n",
+ "Now we need to assign, or link, this structure to the experiment\n",
+ "created above. This linked crystallographic phase will be used to\n",
+ "calculate the expected diffraction pattern based on the crystal\n",
+ "structure defined in the structure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#linked-phases-category)\n",
+ "for more details about linking a structure to an experiment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "59",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.experiments['sim_si'].linked_phases.create(id='si', scale=1.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "60",
+ "metadata": {},
+ "source": [
+ "### 🚀 Analyze and Fit the Data\n",
+ "\n",
+ "After setting up the experiment and structure, we can now analyze\n",
+ "the measured diffraction pattern and perform the fit. Building on the\n",
+ "analogies from the EasyScience library and the previous notebooks, we\n",
+ "can say that all the parameters we introduced earlier — those defining\n",
+ "the structure (crystal structure parameters) and the experiment\n",
+ "(instrument, background, and peak profile parameters) — together form\n",
+ "the complete set of parameters that can be refined during the fitting\n",
+ "process.\n",
+ "\n",
+ "Unlike in the previous analysis notebooks, we will not create a\n",
+ "**math_model** object here. The mathematical model used to calculate\n",
+ "the expected diffraction pattern is already defined in the library and\n",
+ "will be applied automatically during the fitting process."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "61",
+ "metadata": {
+ "title": "**Reminder:**"
+ },
+ "source": [
+ "\n",
+ "The fitting process involves comparing the measured diffraction\n",
+ "pattern with the calculated diffraction pattern based on the crystal\n",
+ "structure and instrument parameters. The goal is to adjust the\n",
+ "parameters of the structure and the experiment to minimize the\n",
+ "difference between the measured and calculated diffraction patterns.\n",
+ "This is done by refining the parameters of the structure and the\n",
+ "instrument settings to achieve a better fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "62",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/analysis/#minimization-optimization)\n",
+ "for more details about the fitting process in EasyDiffraction."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "63",
+ "metadata": {},
+ "source": [
+ "#### Set Fit Parameters\n",
+ "\n",
+ "To perform the fit, we need to specify the refinement parameters.\n",
+ "These are the parameters that will be adjusted during the fitting\n",
+ "process to minimize the difference between the measured and calculated\n",
+ "diffraction patterns. This is done by setting the `free` attribute of\n",
+ "the corresponding parameters to `True`.\n",
+ "\n",
+ "Note: setting `param.free = True` is equivalent to using `param.fixed\n",
+ "= False` in the EasyScience library.\n",
+ "\n",
+ "We will refine the scale factor of the Si phase, the intensities of\n",
+ "the background points as well as the peak profile parameters. The\n",
+ "structure parameters of the Si phase will not be refined, as this\n",
+ "sample is considered a reference sample with known parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "64",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.experiments['sim_si'].linked_phases['si'].scale.free = True\n",
+ "\n",
+ "for line_segment in project_1.experiments['sim_si'].background:\n",
+ " line_segment.y.free = True\n",
+ "\n",
+ "project_1.experiments['sim_si'].peak.broad_gauss_sigma_0.free = True\n",
+ "project_1.experiments['sim_si'].peak.broad_gauss_sigma_1.free = True\n",
+ "project_1.experiments['sim_si'].peak.broad_gauss_sigma_2.free = True\n",
+ "project_1.experiments['sim_si'].peak.broad_mix_beta_0.free = True\n",
+ "project_1.experiments['sim_si'].peak.broad_mix_beta_1.free = True\n",
+ "project_1.experiments['sim_si'].peak.asym_alpha_0.free = True\n",
+ "project_1.experiments['sim_si'].peak.asym_alpha_1.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "65",
+ "metadata": {},
+ "source": [
+ "#### Show Free Parameters\n",
+ "\n",
+ "We can check which parameters are free to be refined by calling the\n",
+ "`show_free_params` method of the `analysis` object of the project."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "66",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://easyscience.github.io/diffraction-lib/user-guide/first-steps/#available-parameters)\n",
+ "for more details on how to\n",
+ "- show all parameters of the project,\n",
+ "- show all fittable parameters, and\n",
+ "- show only free parameters of the project."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "67",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "68",
+ "metadata": {},
+ "source": [
+ "#### Visualize Diffraction Patterns\n",
+ "\n",
+ "Before performing the fit, we can visually compare the measured\n",
+ "diffraction pattern with the calculated diffraction pattern based on\n",
+ "the initial parameters of the structure and the instrument. This\n",
+ "provides an indication of how well the initial parameters match the\n",
+ "measured data. The `plot_meas_vs_calc` method of the project allows\n",
+ "this comparison."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "69",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.plot_meas_vs_calc(expt_name='sim_si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "70",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting\n",
+ "\n",
+ "We can now perform the fit using the `fit` method of the `analysis`\n",
+ "object of the project."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "71",
+ "metadata": {
+ "tags": [
+ "doc-link"
+ ]
+ },
+ "source": [
+ "📖 See\n",
+ "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/analysis/#perform-fit)\n",
+ "for more details about the fitting process."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "72",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.analysis.fit()\n",
+ "project_1.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "73",
+ "metadata": {},
+ "source": [
+ "#### Check Fit Results\n",
+ "\n",
+ "You can see that the agreement between the measured and calculated\n",
+ "diffraction patterns is now much improved and that the intensities of\n",
+ "the calculated peaks align much better with the measured peaks. To\n",
+ "check the quality of the fit numerically, we can look at the\n",
+ "goodness-of-fit χ² value and the reliability R-factors. The χ² value\n",
+ "is a measure of how well the calculated diffraction pattern matches\n",
+ "the measured pattern, and it is calculated as the sum of the squared\n",
+ "differences between the measured and calculated intensities, divided\n",
+ "by the number of data points. Ideally, the χ² value should be close to\n",
+ "1, indicating a good fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "74",
+ "metadata": {},
+ "source": [
+ "#### Visualize Fit Results\n",
+ "\n",
+ "After the fit is completed, we can plot the comparison between the\n",
+ "measured and calculated diffraction patterns again to see how well the\n",
+ "fit improved the agreement between the two. The calculated diffraction\n",
+ "pattern is now based on the refined parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "75",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.plot_meas_vs_calc(expt_name='sim_si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "76",
+ "metadata": {},
+ "source": [
+ "#### TOF vs d-spacing\n",
+ "\n",
+ "The diffraction pattern is typically analyzed and plotted in the\n",
+ "time-of-flight (TOF) axis, which represents the time it takes for\n",
+ "neutrons to travel from the sample to the detector. However, it is\n",
+ "sometimes more convenient to visualize the diffraction pattern in the\n",
+ "d-spacing axis, which represents the distance between planes in the\n",
+ "crystal lattice.\n",
+ "\n",
+ "The conversion from d-spacing to TOF was already introduced in the\n",
+ "data reduction notebook. As a reminder, the two are related through\n",
+ "the instrument calibration parameters according to the equation:\n",
+ "\n",
+ "$$ \\text{TOF} = \\text{offset} + \\text{linear} \\cdot d + \\text{quad}\n",
+ "\\cdot d^{2}, $$\n",
+ "\n",
+ "where `offset`, `linear`, and `quad` are calibration parameters.\n",
+ "\n",
+ "In our case, only the `linear` term is used (the\n",
+ "`calib_d_to_tof_linear` parameter we set earlier). The `offset` and\n",
+ "`quad` terms were not part of the data reduction and are therefore set\n",
+ "to 0 by default.\n",
+ "\n",
+ "The `plot_meas_vs_calc` method of the project allows us to plot the\n",
+ "measured and calculated diffraction patterns in the d-spacing axis by\n",
+ "setting the `d_spacing` parameter to `True`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "77",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.plot_meas_vs_calc(expt_name='sim_si', x='d_spacing')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "78",
+ "metadata": {},
+ "source": [
+ "As you can see, the calculated diffraction pattern now matches the\n",
+ "measured pattern much more closely. Typically, additional experimental\n",
+ "parameters are included in the refinement process to further improve\n",
+ "the fit. In this example, the structural parameters are not refined\n",
+ "because the Si crystal structure is a well-known standard reference\n",
+ "used to calibrate both the instrument and the experimental setup. The\n",
+ "refined experimental parameters obtained here will then be applied\n",
+ "when fitting the crystal structures of other materials.\n",
+ "\n",
+ "In the next part of the notebook, we will move to a more advanced case\n",
+ "and fit a more complex crystal structure: La₀.₅Ba₀.₅CoO₃ (LBCO).\n",
+ "\n",
+ "#### Save Project\n",
+ "\n",
+ "Before moving on, we can save the project to disk for later use. This\n",
+ "will preserve the entire project structure, including experiments,\n",
+ "structures, and fitting results. The project is saved into a\n",
+ "directory specified by the `dir_path` attribute of the project object."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "79",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_1.save_as(dir_path='powder_diffraction_Si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "80",
+ "metadata": {},
+ "source": [
+ "## 💪 Exercise: Complex Fit – LBCO\n",
+ "\n",
+ "Now that you have a basic understanding of the fitting process, we\n",
+ "will undertake a more complex fit of the La₀.₅Ba₀.₅CoO₃ (LBCO) crystal\n",
+ "structure using simulated powder diffraction data from the data\n",
+ "reduction notebook.\n",
+ "\n",
+ "You can use the same approach as in the previous part of the notebook,\n",
+ "but this time we will refine a more complex crystal structure LBCO\n",
+ "with multiple atoms in the unit cell.\n",
+ "\n",
+ "### 📦 Exercise 1: Create a Project\n",
+ "\n",
+ "Create a new project for the LBCO fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "81",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "82",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can use the same approach as in the previous part of the notebook,\n",
+ "but this time we will create a new project for the LBCO fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "83",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "84",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2 = ed.Project(name='main')\n",
+ "project_2.info.title = 'La0.5Ba0.5CoO3 Fit'\n",
+ "project_2.info.description = 'Fitting simulated powder diffraction pattern of La0.5Ba0.5CoO3.'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "85",
+ "metadata": {},
+ "source": [
+ "### 🔬 Exercise 2: Define an Experiment\n",
+ "\n",
+ "#### Exercise 2.1: Create an Experiment\n",
+ "\n",
+ "Create an experiment within the new project and load the reduced\n",
+ "diffraction pattern for LBCO."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "86",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "87",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can use the same approach as in the previous part of the notebook,\n",
+ "but this time you need to use the data file for LBCO."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "88",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "89",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "data_dir = 'data'\n",
+ "file_name = 'reduced_LBCO.xye'\n",
+ "lbco_xye_path = f'{data_dir}/{file_name}'\n",
+ "\n",
+ "# Uncomment the following line if your data reduction failed and the\n",
+ "# reduced data file is missing.\n",
+ "lbco_xye_path = ed.download_data(id=18, destination=data_dir)\n",
+ "\n",
+ "project_2.experiments.add_from_data_path(\n",
+ " name='sim_lbco',\n",
+ " data_path=lbco_xye_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='time-of-flight',\n",
+ " radiation_probe='neutron',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "90",
+ "metadata": {},
+ "source": [
+ "#### Exercise 2.1: Inspect Measured Data\n",
+ "\n",
+ "Check the measured data of the LBCO experiment. Are there any peaks\n",
+ "with the shape similar to those excluded in the Si fit? If so, exclude\n",
+ "them from this analysis as well."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "91",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "92",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can use the `plot_meas` method of the project to visualize the\n",
+ "measured diffraction pattern. You can also use the `excluded_regions`\n",
+ "attribute of the experiment to exclude specific regions from the\n",
+ "analysis as we did in the previous part of the notebook."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "93",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "94",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.plot_meas(expt_name='sim_lbco')\n",
+ "\n",
+ "project_2.experiments['sim_lbco'].excluded_regions.create(id='1', start=0, end=55000)\n",
+ "project_2.experiments['sim_lbco'].excluded_regions.create(id='2', start=105500, end=200000)\n",
+ "\n",
+ "project_2.plot_meas(expt_name='sim_lbco')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "95",
+ "metadata": {},
+ "source": [
+ "#### Exercise 2.2: Set Instrument Parameters\n",
+ "\n",
+ "Set the instrument parameters for the LBCO experiment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "96",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "97",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the values from the data reduction process for the LBCO and\n",
+ "follow the same approach as in the previous part of the notebook."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "98",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "99",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.experiments['sim_lbco'].instrument.setup_twotheta_bank = ed.get_value_from_xye_header(\n",
+ " lbco_xye_path, 'two_theta'\n",
+ ")\n",
+ "project_2.experiments['sim_lbco'].instrument.calib_d_to_tof_linear = ed.get_value_from_xye_header(\n",
+ " lbco_xye_path, 'DIFC'\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "100",
+ "metadata": {},
+ "source": [
+ "#### Exercise 2.3: Set Peak Profile Parameters\n",
+ "\n",
+ "Set the peak profile parameters for the LBCO experiment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "101",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "102",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the values from the\n",
+ "previous part of the notebook. You can either manually copy the values\n",
+ "from the Si fit or use the `value` attribute of the parameters from\n",
+ "the Si experiment to set the initial values for the LBCO experiment.\n",
+ "This will help us to have a good starting point for the fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "103",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "104",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "# # Create a reference to the peak profile parameters from the Si\n",
+ "sim_si_peak = project_1.experiments['sim_si'].peak\n",
+ "project_2.experiments['sim_lbco'].peak_profile_type = 'pseudo-voigt * ikeda-carpenter'\n",
+ "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_0 = sim_si_peak.broad_gauss_sigma_0.value\n",
+ "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_1 = sim_si_peak.broad_gauss_sigma_1.value\n",
+ "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_2 = sim_si_peak.broad_gauss_sigma_2.value\n",
+ "project_2.experiments['sim_lbco'].peak.broad_mix_beta_0 = sim_si_peak.broad_mix_beta_0.value\n",
+ "project_2.experiments['sim_lbco'].peak.broad_mix_beta_1 = sim_si_peak.broad_mix_beta_1.value\n",
+ "project_2.experiments['sim_lbco'].peak.asym_alpha_0 = sim_si_peak.asym_alpha_0.value\n",
+ "project_2.experiments['sim_lbco'].peak.asym_alpha_1 = sim_si_peak.asym_alpha_1.value"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "105",
+ "metadata": {},
+ "source": [
+ "#### Exercise 2.4: Set Background\n",
+ "\n",
+ "Set the background points for the LBCO experiment. What would you\n",
+ "suggest as the initial intensity value for the background points?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "106",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "107",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the same approach as in the previous part of the notebook, but\n",
+ "this time you need to set the background points for the LBCO\n",
+ "experiment. You can zoom in on the measured diffraction pattern to\n",
+ "determine the approximate background level."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "108",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "109",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.experiments['sim_lbco'].background_type = 'line-segment'\n",
+ "project_2.experiments['sim_lbco'].background.create(id='1', x=50000, y=0.2)\n",
+ "project_2.experiments['sim_lbco'].background.create(id='2', x=60000, y=0.2)\n",
+ "project_2.experiments['sim_lbco'].background.create(id='3', x=70000, y=0.2)\n",
+ "project_2.experiments['sim_lbco'].background.create(id='4', x=80000, y=0.2)\n",
+ "project_2.experiments['sim_lbco'].background.create(id='5', x=90000, y=0.2)\n",
+ "project_2.experiments['sim_lbco'].background.create(id='6', x=100000, y=0.2)\n",
+ "project_2.experiments['sim_lbco'].background.create(id='7', x=110000, y=0.2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "110",
+ "metadata": {},
+ "source": [
+ "### 🧩 Exercise 3: Define a Structure – LBCO\n",
+ "\n",
+ "The LBSO structure is not as simple as the Si one, as it contains\n",
+ "multiple atoms in the unit cell. It is not in COD, so we give you the\n",
+ "structural parameters in CIF format to create the structure.\n",
+ "\n",
+ "Note that those parameters are not necessarily the most accurate ones,\n",
+ "but they are a good starting point for the fit. The aim of the study\n",
+ "is to refine the LBCO lattice parameters."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "111",
+ "metadata": {},
+ "source": [
+ "```\n",
+ "data_lbco\n",
+ "\n",
+ "_space_group.name_H-M_alt \"P m -3 m\"\n",
+ "_space_group.IT_coordinate_system_code 1\n",
+ "\n",
+ "_cell.length_a 3.89\n",
+ "_cell.length_b 3.89\n",
+ "_cell.length_c 3.89\n",
+ "_cell.angle_alpha 90.0\n",
+ "_cell.angle_beta 90.0\n",
+ "_cell.angle_gamma 90.0\n",
+ "\n",
+ "loop_\n",
+ "_atom_site.label\n",
+ "_atom_site.type_symbol\n",
+ "_atom_site.fract_x\n",
+ "_atom_site.fract_y\n",
+ "_atom_site.fract_z\n",
+ "_atom_site.wyckoff_letter\n",
+ "_atom_site.occupancy\n",
+ "_atom_site.ADP_type\n",
+ "_atom_site.B_iso_or_equiv\n",
+ "La La 0.0 0.0 0.0 a 0.5 Biso 0.95\n",
+ "Ba Ba 0.0 0.0 0.0 a 0.5 Biso 0.95\n",
+ "Co Co 0.5 0.5 0.5 b 1.0 Biso 0.80\n",
+ "O O 0.0 0.5 0.5 c 1.0 Biso 1.66\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "112",
+ "metadata": {},
+ "source": [
+ "Note that the `occupancy` of the La and Ba atoms is 0.5\n",
+ "and those atoms are located in the same position (0, 0, 0) in the unit\n",
+ "cell. This means that an extra attribute `occupancy` needs to be set\n",
+ "for those atoms later in the structure.\n",
+ "\n",
+ "We model the La/Ba site using the virtual crystal approximation. In\n",
+ "this approach, the scattering is taken as a weighted average of La and\n",
+ "Ba. This reproduces the average diffraction pattern well but does not\n",
+ "capture certain real-world effects.\n",
+ "\n",
+ "The edge cases are:\n",
+ "- **Random distribution**. La and Ba atoms are placed randomly. The\n",
+ " Bragg peaks still match the average structure, but the pattern also\n",
+ " shows extra background (diffuse scattering) between the peaks, but\n",
+ " this is usually neglected in the analysis.\n",
+ "- **Perfect ordering**. La and Ba arrange themselves in a regular\n",
+ " pattern, creating a larger repeating unit. This gives rise to extra\n",
+ " peaks (\"superlattice reflections\") and changes the intensity of\n",
+ " some existing peaks.\n",
+ "- **Virtual crystal approximation (our model)**. We replace the site\n",
+ " with a single \"virtual atom\" that averages La and Ba. This gives\n",
+ " the correct average Bragg peaks but leaves out the extra background\n",
+ " of the random case and the extra peaks of the ordered case."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "113",
+ "metadata": {},
+ "source": [
+ "#### Exercise 3.1: Create Structure\n",
+ "\n",
+ "Add a structure for LBCO to the project. The structure\n",
+ "parameters will be set in the next exercises."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "114",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "115",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can use the same approach as in the previous part of the notebook,\n",
+ "but this time you need to use the name corresponding to the LBCO\n",
+ "structure, e.g. 'lbco'."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "116",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "117",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.structures.create(name='lbco')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "118",
+ "metadata": {},
+ "source": [
+ "#### Exercise 3.2: Set Space Group\n",
+ "\n",
+ "Set the space group for the LBCO structure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "119",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "120",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the space group name and IT coordinate system code from the CIF\n",
+ "data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "121",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "122",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.structures['lbco'].space_group.name_h_m = 'P m -3 m'\n",
+ "project_2.structures['lbco'].space_group.it_coordinate_system_code = '1'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "123",
+ "metadata": {},
+ "source": [
+ "#### Exercise 3.3: Set Lattice Parameters\n",
+ "\n",
+ "Set the lattice parameters for the LBCO structure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "124",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "125",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the lattice parameters from the CIF data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "126",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "127",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.structures['lbco'].cell.length_a = 3.88"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "128",
+ "metadata": {},
+ "source": [
+ "#### Exercise 3.4: Set Atom Sites\n",
+ "\n",
+ "Set the atom sites for the LBCO structure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "129",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "130",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the atom sites from the CIF data. You can use the `add` method of\n",
+ "the `atom_sites` attribute of the structure to add the atom sites."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "131",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "132",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.structures['lbco'].atom_sites.create(\n",
+ " label='La',\n",
+ " type_symbol='La',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.95,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "project_2.structures['lbco'].atom_sites.create(\n",
+ " label='Ba',\n",
+ " type_symbol='Ba',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.95,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "project_2.structures['lbco'].atom_sites.create(\n",
+ " label='Co',\n",
+ " type_symbol='Co',\n",
+ " fract_x=0.5,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='b',\n",
+ " b_iso=0.80,\n",
+ ")\n",
+ "project_2.structures['lbco'].atom_sites.create(\n",
+ " label='O',\n",
+ " type_symbol='O',\n",
+ " fract_x=0,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=1.66,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "133",
+ "metadata": {},
+ "source": [
+ "### 🔗 Exercise 4: Assign Structure to Experiment\n",
+ "\n",
+ "Now assign the LBCO structure to the experiment created above."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "134",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "135",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the `linked_phases` attribute of the experiment to link the\n",
+ "crystal structure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "136",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "137",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.experiments['sim_lbco'].linked_phases.create(id='lbco', scale=1.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "138",
+ "metadata": {},
+ "source": [
+ "### 🚀 Exercise 5: Analyze and Fit the Data\n",
+ "\n",
+ "#### Exercise 5.1: Set Fit Parameters\n",
+ "\n",
+ "Select the initial set of parameters to be refined during the fitting\n",
+ "process."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "139",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "140",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can start with the scale factor and the background points, as in\n",
+ "the Si fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "141",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "142",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.experiments['sim_lbco'].linked_phases['lbco'].scale.free = True\n",
+ "\n",
+ "for line_segment in project_2.experiments['sim_lbco'].background:\n",
+ " line_segment.y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "143",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.2: Run Fitting\n",
+ "\n",
+ "Visualize the measured and calculated diffraction patterns before\n",
+ "fitting and then run the fitting process."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "144",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "145",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the `plot_meas_vs_calc` method of the project to visualize the\n",
+ "measured and calculated diffraction patterns before fitting. Then, use\n",
+ "the `fit` method of the `analysis` object of the project to perform\n",
+ "the fitting process."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "146",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "147",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco')\n",
+ "\n",
+ "project_2.analysis.fit()\n",
+ "project_2.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "148",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.3: Find the Misfit in the Fit\n",
+ "\n",
+ "Visualize the measured and calculated diffraction patterns after the\n",
+ "fit. As you can see, the fit shows noticeable discrepancies. If you\n",
+ "zoom in on different regions of the pattern, you will observe that all\n",
+ "the calculated peaks are shifted to the left.\n",
+ "\n",
+ "What could be the reason for the misfit?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "149",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "150",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Consider the following options:\n",
+ "1. The conversion parameters from TOF to d-spacing are not correct.\n",
+ "2. The lattice parameters of the LBCO phase are not correct.\n",
+ "3. The peak profile parameters are not correct.\n",
+ "4. The background points are not correct."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "151",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "152",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "\n",
+ "1. ❌ The conversion parameters from TOF to d-spacing were set based\n",
+ "on the data reduction step. While they are specific to each dataset\n",
+ "and thus differ from those used for the Si data, the full reduction\n",
+ "workflow has already been validated with the Si fit. Therefore, they\n",
+ "are not the cause of the misfit in this case.\n",
+ "2. ✅ The lattice parameters of the LBCO phase were set based on the\n",
+ "CIF data, which is a good starting point, but they are not necessarily\n",
+ "as accurate as needed for the fit. The lattice parameters may need to\n",
+ "be refined.\n",
+ "3. ❌ The peak profile parameters do not change the position of the\n",
+ "peaks, but rather their shape.\n",
+ "4. ❌ The background points affect the background level, but not the\n",
+ "peak positions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "153",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "154",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.4: Refine the LBCO Lattice Parameter\n",
+ "\n",
+ "To improve the fit, refine the lattice parameters of the LBCO phase."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "155",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "156",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "To achieve this, we will set the `free` attribute of the `length_a`\n",
+ "parameter of the LBCO cell to `True`.\n",
+ "\n",
+ "LBCO has a cubic crystal structure (space group `P m -3 m`), which\n",
+ "means that `length_b` and `length_c` are constrained to be equal to\n",
+ "`length_a`. Therefore, only `length_a` needs to be refined; the other\n",
+ "two will be updated automatically. All cell angles are fixed at 90°,\n",
+ "so they do not require refinement."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "157",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "158",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.structures['lbco'].cell.length_a.free = True\n",
+ "\n",
+ "project_2.analysis.fit()\n",
+ "project_2.analysis.show_fit_results()\n",
+ "\n",
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "159",
+ "metadata": {},
+ "source": [
+ "One of the main goals of this study was to refine the lattice\n",
+ "parameter of the LBCO phase. As shown in the updated fit results, the\n",
+ "overall fit has improved significantly, even though the change in cell\n",
+ "length is less than 1% of the initial value. This demonstrates how\n",
+ "even a small adjustment to the lattice parameter can have a\n",
+ "substantial impact on the quality of the fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "160",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.5: Visualize the Fit Results in d-spacing\n",
+ "\n",
+ "Plot measured vs calculated diffraction patterns in d-spacing instead\n",
+ "of TOF."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "161",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "162",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Use the `plot_meas_vs_calc` method of the project and set the\n",
+ "`d_spacing` parameter to `True`."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "163",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "164",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x='d_spacing')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "165",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.6: Refine the Peak Profile Parameters\n",
+ "\n",
+ "As you can see, the fit is now relatively good and the peak positions\n",
+ "are much closer to the measured data.\n",
+ "\n",
+ "The peak profile parameters were not refined, and their starting\n",
+ "values were set based on the previous fit of the Si standard sample.\n",
+ "Although these starting values are reasonable and provide a good\n",
+ "starting point for the fit, they are not necessarily optimal for the\n",
+ "LBCO phase. This can be seen while inspecting the individual peaks in\n",
+ "the diffraction pattern. For example, the calculated curve does not\n",
+ "perfectly describe the peak at about 1.38 Å, as can be seen below:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "166",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x='d_spacing', x_min=1.35, x_max=1.40)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "167",
+ "metadata": {},
+ "source": [
+ "The peak profile parameters are determined based on both the\n",
+ "instrument and the sample characteristics, so they can vary when\n",
+ "analyzing different samples on the same instrument. Therefore, it is\n",
+ "better to refine them as well.\n",
+ "\n",
+ "Select the peak profile parameters to be refined during the fitting\n",
+ "process."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "168",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "169",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can set the `free` attribute of the peak profile parameters to\n",
+ "`True` to allow the fitting process to adjust them. You can use the\n",
+ "same approach as in the previous part of the notebook, but this time\n",
+ "you will refine the peak profile parameters of the LBCO phase."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "170",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "171",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_0.free = True\n",
+ "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_1.free = True\n",
+ "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_2.free = True\n",
+ "project_2.experiments['sim_lbco'].peak.broad_mix_beta_0.free = True\n",
+ "project_2.experiments['sim_lbco'].peak.broad_mix_beta_1.free = True\n",
+ "project_2.experiments['sim_lbco'].peak.asym_alpha_0.free = True\n",
+ "project_2.experiments['sim_lbco'].peak.asym_alpha_1.free = True\n",
+ "\n",
+ "project_2.analysis.fit()\n",
+ "project_2.analysis.show_fit_results()\n",
+ "\n",
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x='d_spacing', x_min=1.35, x_max=1.40)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "172",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.7: Find Undefined Features\n",
+ "\n",
+ "After refining the lattice parameter and the peak profile parameters,\n",
+ "the fit is significantly improved, but inspect the diffraction pattern\n",
+ "again. Are you noticing anything undefined?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "173",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "174",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "While the fit is now significantly better, there are still some\n",
+ "unexplained peaks in the diffraction pattern. These peaks are not\n",
+ "accounted for by the LBCO phase. For example, if you zoom in on the\n",
+ "region around 1.6 Å (or 95,000 μs), you will notice that the rightmost\n",
+ "peak is not explained by the LBCO phase at all."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "175",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "176",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x='d_spacing', x_min=1.53, x_max=1.7)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "177",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.8: Identify the Cause of the Unexplained Peaks\n",
+ "\n",
+ "Analyze the residual peaks that remain after refining the LBCO phase\n",
+ "and the peak-profile parameters. Based on their positions and\n",
+ "characteristics, decide which potential cause best explains the\n",
+ "misfit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "178",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "179",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Consider the following options:\n",
+ "1. The LBCO phase is not correctly modeled.\n",
+ "2. The LBCO phase is not the only phase present in the sample.\n",
+ "3. The data reduction process introduced artifacts.\n",
+ "4. The studied sample is not LBCO, but rather a different phase."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "180",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "181",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "1. ❌ In principle, this could be the case, as sometimes the presence\n",
+ "of extra peaks in the diffraction pattern can indicate lower symmetry\n",
+ "than the one used in the model, or that the model is not complete.\n",
+ "However, in this case, the LBCO phase is correctly modeled based on\n",
+ "the CIF data.\n",
+ "2. ✅ The unexplained peaks are due to the presence of an impurity\n",
+ "phase in the sample, which is not included in the current model.\n",
+ "3. ❌ The data reduction process is not likely to introduce such\n",
+ "specific peaks, as it is tested and verified in the previous part of\n",
+ "the notebook.\n",
+ "4. ❌ This could also be the case in real experiments, but in this\n",
+ "case, we know that the sample is LBCO, as it was simulated based on\n",
+ "the CIF data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "182",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.9: Identify the impurity phase\n",
+ "\n",
+ "Use the positions of the unexplained peaks to identify the most likely\n",
+ "secondary phase present in the sample."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "183",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "184",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "Check the positions of the unexplained peaks in the diffraction\n",
+ "pattern. Compare them with the known diffraction patterns in the\n",
+ "previous part of the notebook."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "185",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "186",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "The unexplained peaks are likely due to the presence of a small amount\n",
+ "of Si in the LBCO sample. In real experiments, it might happen, e.g.,\n",
+ "because the sample holder was not cleaned properly after the Si\n",
+ "experiment.\n",
+ "\n",
+ "You can visalize both the patterns of the Si and LBCO phases to\n",
+ "confirm this hypothesis."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "187",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "project_1.plot_meas_vs_calc(expt_name='sim_si', x='d_spacing', x_min=1, x_max=1.7)\n",
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x='d_spacing', x_min=1, x_max=1.7)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "188",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.10: Create a Second Structure – Si as Impurity\n",
+ "\n",
+ "Create a second structure for the Si phase, which is the impurity\n",
+ "phase identified in the previous step. Link this structure to the\n",
+ "LBCO experiment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "189",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "190",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can use the same approach as in the previous part of the notebook,\n",
+ "but this time you need to create a structure for Si and link it to\n",
+ "the LBCO experiment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "191",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "192",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "# Set Space Group\n",
+ "project_2.structures.create(name='si')\n",
+ "project_2.structures['si'].space_group.name_h_m = 'F d -3 m'\n",
+ "project_2.structures['si'].space_group.it_coordinate_system_code = '2'\n",
+ "\n",
+ "# Set Lattice Parameters\n",
+ "project_2.structures['si'].cell.length_a = 5.43\n",
+ "\n",
+ "# Set Atom Sites\n",
+ "project_2.structures['si'].atom_sites.create(\n",
+ " label='Si',\n",
+ " type_symbol='Si',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.89,\n",
+ ")\n",
+ "\n",
+ "# Assign Structure to Experiment\n",
+ "project_2.experiments['sim_lbco'].linked_phases.create(id='si', scale=1.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "193",
+ "metadata": {},
+ "source": [
+ "#### Exercise 5.11: Refine the Scale of the Si Phase\n",
+ "\n",
+ "Visualize the measured diffraction pattern and the calculated\n",
+ "diffraction pattern. Check if the Si phase is contributing to the\n",
+ "calculated diffraction pattern. Refine the scale factor of the Si\n",
+ "phase to improve the fit."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "194",
+ "metadata": {},
+ "source": [
+ "**Hint:**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "195",
+ "metadata": {
+ "tags": [
+ "dmsc-school-hint"
+ ]
+ },
+ "source": [
+ "You can use the `plot_meas_vs_calc` method of the project to visualize\n",
+ "the patterns. Then, set the `free` attribute of the `scale` parameter\n",
+ "of the Si phase to `True` to allow the fitting process to adjust the\n",
+ "scale factor."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "196",
+ "metadata": {},
+ "source": [
+ "**Solution:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "197",
+ "metadata": {
+ "tags": [
+ "solution",
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "# Before optimizing the parameters, we can visualize the measured\n",
+ "# diffraction pattern and the calculated diffraction pattern based on\n",
+ "# the two phases: LBCO and Si.\n",
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco')\n",
+ "\n",
+ "# As you can see, the calculated pattern is now the sum of both phases,\n",
+ "# and Si peaks are visible in the calculated pattern. However, their\n",
+ "# intensities are much too high. Therefore, we need to refine the scale\n",
+ "# factor of the Si phase.\n",
+ "project_2.experiments['sim_lbco'].linked_phases['si'].scale.free = True\n",
+ "\n",
+ "# Now we can perform the fit with both phases included.\n",
+ "project_2.analysis.fit()\n",
+ "project_2.analysis.show_fit_results()\n",
+ "\n",
+ "# Let's plot the measured diffraction pattern and the calculated\n",
+ "# diffraction pattern both for the full range and for a zoomed-in region\n",
+ "# around the previously unexplained peak near 95,000 μs. The calculated\n",
+ "# pattern will be the sum of the two phases.\n",
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco')\n",
+ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x_min=88000, x_max=101000)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "198",
+ "metadata": {},
+ "source": [
+ "All previously unexplained peaks are now accounted for in the pattern,\n",
+ "and the fit is improved. Some discrepancies in the peak intensities\n",
+ "remain, but further improvements would require more advanced data\n",
+ "reduction and analysis, which are beyond the scope of this school.\n",
+ "\n",
+ "To review the analysis results, you can generate and print a summary\n",
+ "report using the `show_report()` method, as demonstrated in the cell\n",
+ "below. The report includes parameters related to the structure and\n",
+ "the experiment, such as the refined unit cell parameter `a` of LBCO.\n",
+ "\n",
+ "Information about the crystal or magnetic structure, along with\n",
+ "experimental details, fitting quality, and other relevant data, is\n",
+ "often submitted to crystallographic journals as part of a scientific\n",
+ "publication. It can also be deposited in crystallographic databases\n",
+ "when relevant."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "199",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_2.summary.show_report()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "200",
+ "metadata": {},
+ "source": [
+ "Finally, we save the project to disk to preserve the current state of\n",
+ "the analysis."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "201",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project_2.save_as(dir_path='powder_diffraction_LBCO_Si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "202",
+ "metadata": {},
+ "source": [
+ "#### Final Remarks\n",
+ "\n",
+ "In this part of the notebook, you learned how to use EasyDiffraction\n",
+ "to refine lattice parameters of a more complex crystal structure,\n",
+ "La₀.₅Ba₀.₅CoO₃ (LBCO).\n",
+ "\n",
+ "In real experiments, you might also refine\n",
+ "additional parameters, such as atomic positions, occupancies, and\n",
+ "atomic displacement factors, to achieve an even better fit. For our\n",
+ "purposes, we'll stop here, as the goal was to give you a starting\n",
+ "point for analyzing more complex crystal structures with\n",
+ "EasyDiffraction."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "203",
+ "metadata": {},
+ "source": [
+ "## 🎁 Bonus\n",
+ "\n",
+ "Congratulations — you've now completed the diffraction data analysis\n",
+ "part of the DMSC Summer School!\n",
+ "\n",
+ "If you'd like to keep exploring, the EasyDiffraction library offers\n",
+ "many additional tutorials and examples on the official documentation\n",
+ "site: 👉 https://docs.easydiffraction.org/lib/tutorials/\n",
+ "\n",
+ "Besides the Python package, EasyDiffraction also comes with a\n",
+ "graphical user interface (GUI) that lets you perform similar analyses\n",
+ "without writing code. To be fair, it's not *quite* feature-complete\n",
+ "compared to the Python library yet — but we're working on it! 🚧\n",
+ "\n",
+ "If you prefer a point-and-click interface over coding, the GUI\n",
+ "provides a user-friendly way to analyze diffraction data. You can\n",
+ "download it as a standalone application here: 👉\n",
+ "https://easydiffraction.org\n",
+ "\n",
+ "We'd love to hear your feedback on EasyDiffraction — both the library\n",
+ "and the GUI! 💬"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "tags,title,-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-13.py b/docs/docs/tutorials/ed-13.py
similarity index 100%
rename from tutorials/ed-13.py
rename to docs/docs/tutorials/ed-13.py
diff --git a/docs/docs/tutorials/ed-14.ipynb b/docs/docs/tutorials/ed-14.ipynb
new file mode 100644
index 00000000..25927d6a
--- /dev/null
+++ b/docs/docs/tutorials/ed-14.ipynb
@@ -0,0 +1,319 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: Tb2TiO7, HEiDi\n",
+ "\n",
+ "Crystal structure refinement of Tb2TiO7 using single crystal neutron\n",
+ "diffraction data from HEiDi at FRM II."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Step 1: Define Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create minimal project without name and description\n",
+ "project = ed.Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## Step 2: Define Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Download CIF file from repository\n",
+ "structure_path = ed.download_data(id=20, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add_from_cif_path(structure_path)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.show_names()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = project.structures['tbti']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites['Tb'].b_iso = 0.0\n",
+ "structure.atom_sites['Ti'].b_iso = 0.0\n",
+ "structure.atom_sites['O1'].b_iso = 0.0\n",
+ "structure.atom_sites['O2'].b_iso = 0.0"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "11",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "12",
+ "metadata": {},
+ "source": [
+ "## Step 3: Define Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = ed.download_data(id=19, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_data_path(\n",
+ " name='heidi',\n",
+ " data_path=data_path,\n",
+ " sample_form='single crystal',\n",
+ " beam_mode='constant wavelength',\n",
+ " radiation_probe='neutron',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment = project.experiments['heidi'] # TODO: "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.linked_crystal.id = 'tbti'\n",
+ "experiment.linked_crystal.scale = 1.0"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.instrument.setup_wavelength = 0.793"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.extinction.mosaicity = 29820\n",
+ "experiment.extinction.radius = 30"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "## Step 4: Perform Analysis"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='heidi')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.linked_crystal.scale.free = True\n",
+ "experiment.extinction.radius.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Start refinement. All parameters, which have standard uncertainties\n",
+ "# in the input CIF files, are refined by default.\n",
+ "project.analysis.fit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Show fit results summary\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "26",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.show_names()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='heidi')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28",
+ "metadata": {},
+ "source": [
+ "## Step 5: Show Project Summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "29",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.summary.show_report()"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-14.py b/docs/docs/tutorials/ed-14.py
similarity index 100%
rename from tutorials/ed-14.py
rename to docs/docs/tutorials/ed-14.py
diff --git a/docs/docs/tutorials/ed-15.ipynb b/docs/docs/tutorials/ed-15.ipynb
new file mode 100644
index 00000000..a426f2ee
--- /dev/null
+++ b/docs/docs/tutorials/ed-15.ipynb
@@ -0,0 +1,296 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: Taurine, SENJU\n",
+ "\n",
+ "Crystal structure refinement of Taurine using time-of-flight single\n",
+ "crystal neutron diffraction data from SENJU at J-PARC."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Step 1: Define Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create minimal project without name and description\n",
+ "project = ed.Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## Step 2: Define Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Download CIF file from repository\n",
+ "structure_path = ed.download_data(id=21, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add_from_cif_path(structure_path)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.show_names()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = project.structures['taurine']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# structure.show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Step 3: Define Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = ed.download_data(id=22, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_data_path(\n",
+ " name='senju',\n",
+ " data_path=data_path,\n",
+ " sample_form='single crystal',\n",
+ " beam_mode='time-of-flight',\n",
+ " radiation_probe='neutron',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment = project.experiments['senju']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.linked_crystal.id = 'taurine'\n",
+ "experiment.linked_crystal.scale = 1.0"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.extinction.mosaicity = 1000.0\n",
+ "experiment.extinction.radius = 100.0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "## Step 4: Perform Analysis"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='senju')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "19",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.linked_crystal.scale.free = True\n",
+ "experiment.extinction.radius.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# experiment.show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Start refinement. All parameters, which have standard uncertainties\n",
+ "# in the input CIF files, are refined by default.\n",
+ "project.analysis.fit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Show fit results summary\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# experiment.show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.show_names()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='senju')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "## Step 5: Show Project Summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.summary.show_report()"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-15.py b/docs/docs/tutorials/ed-15.py
similarity index 100%
rename from tutorials/ed-15.py
rename to docs/docs/tutorials/ed-15.py
diff --git a/docs/docs/tutorials/ed-16.ipynb b/docs/docs/tutorials/ed-16.ipynb
new file mode 100644
index 00000000..688297e6
--- /dev/null
+++ b/docs/docs/tutorials/ed-16.ipynb
@@ -0,0 +1,623 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Joint Refinement: Si, Bragg + PDF\n",
+ "\n",
+ "This example demonstrates a joint refinement of the Si crystal\n",
+ "structure combining Bragg diffraction and pair distribution function\n",
+ "(PDF) analysis. The Bragg experiment uses time-of-flight neutron\n",
+ "powder diffraction data from SEPD at Argonne, while the PDF\n",
+ "experiment uses data from NOMAD at SNS. A single shared Si structure\n",
+ "is refined simultaneously against both datasets."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from easydiffraction import ExperimentFactory\n",
+ "from easydiffraction import Project\n",
+ "from easydiffraction import StructureFactory\n",
+ "from easydiffraction import download_data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Define Structure\n",
+ "\n",
+ "A single Si structure is shared between the Bragg and PDF\n",
+ "experiments. Structural parameters refined against both datasets\n",
+ "simultaneously.\n",
+ "\n",
+ "#### Create Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = StructureFactory.from_scratch(name='si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.space_group.name_h_m = 'F d -3 m'\n",
+ "structure.space_group.it_coordinate_system_code = '1'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a = 5.42"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites.create(\n",
+ " label='Si',\n",
+ " type_symbol='Si',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.2,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Define Experiments\n",
+ "\n",
+ "Two experiments are defined: one for Bragg diffraction and one for\n",
+ "PDF analysis. Both are linked to the same Si structure.\n",
+ "\n",
+ "### Experiment 1: Bragg (SEPD, TOF)\n",
+ "\n",
+ "#### Download Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bragg_data_path = download_data(id=7, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bragg_expt = ExperimentFactory.from_data_path(\n",
+ " name='sepd', data_path=bragg_data_path, beam_mode='time-of-flight'\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bragg_expt.instrument.setup_twotheta_bank = 144.845\n",
+ "bragg_expt.instrument.calib_d_to_tof_offset = -9.2\n",
+ "bragg_expt.instrument.calib_d_to_tof_linear = 7476.91\n",
+ "bragg_expt.instrument.calib_d_to_tof_quad = -1.54"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bragg_expt.peak_profile_type = 'pseudo-voigt * ikeda-carpenter'\n",
+ "bragg_expt.peak.broad_gauss_sigma_0 = 5.0\n",
+ "bragg_expt.peak.broad_gauss_sigma_1 = 45.0\n",
+ "bragg_expt.peak.broad_gauss_sigma_2 = 1.0\n",
+ "bragg_expt.peak.broad_mix_beta_0 = 0.04221\n",
+ "bragg_expt.peak.broad_mix_beta_1 = 0.00946\n",
+ "bragg_expt.peak.asym_alpha_0 = 0.0\n",
+ "bragg_expt.peak.asym_alpha_1 = 0.5971"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bragg_expt.background_type = 'line-segment'\n",
+ "for x in range(0, 35000, 5000):\n",
+ " bragg_expt.background.create(id=str(x), x=x, y=200)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bragg_expt.linked_phases.create(id='si', scale=13.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "23",
+ "metadata": {},
+ "source": [
+ "### Experiment 2: PDF (NOMAD, TOF)\n",
+ "\n",
+ "#### Download Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pdf_data_path = download_data(id=5, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "25",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "26",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pdf_expt = ExperimentFactory.from_data_path(\n",
+ " name='nomad',\n",
+ " data_path=pdf_data_path,\n",
+ " beam_mode='time-of-flight',\n",
+ " scattering_type='total',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile (PDF Parameters)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "28",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pdf_expt.peak.damp_q = 0.02\n",
+ "pdf_expt.peak.broad_q = 0.02\n",
+ "pdf_expt.peak.cutoff_q = 35.0\n",
+ "pdf_expt.peak.sharp_delta_1 = 0.001\n",
+ "pdf_expt.peak.sharp_delta_2 = 4.0\n",
+ "pdf_expt.peak.damp_particle_diameter = 0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pdf_expt.linked_phases.create(id='si', scale=1.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "31",
+ "metadata": {},
+ "source": [
+ "## Define Project\n",
+ "\n",
+ "The project object manages the shared structure, both experiments,\n",
+ "and the analysis.\n",
+ "\n",
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "32",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "33",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "34",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add(structure)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35",
+ "metadata": {},
+ "source": [
+ "#### Add Experiments"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "36",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add(bragg_expt)\n",
+ "project.experiments.add(pdf_expt)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37",
+ "metadata": {},
+ "source": [
+ "## Perform Analysis\n",
+ "\n",
+ "This section shows the joint analysis process. The calculator is\n",
+ "auto-resolved per experiment: CrysPy for Bragg, PDFfit for PDF.\n",
+ "\n",
+ "#### Set Fit Mode and Weights"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit_mode.mode = 'joint'\n",
+ "project.analysis.joint_fit_experiments.create(id='sepd', weight=0.7)\n",
+ "project.analysis.joint_fit_experiments.create(id='nomad', weight=0.3)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39",
+ "metadata": {},
+ "source": [
+ "#### Set Minimizer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated (Before Fit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', show_residual=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "43",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='nomad', show_residual=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "44",
+ "metadata": {},
+ "source": [
+ "#### Set Fitting Parameters\n",
+ "\n",
+ "Shared structural parameters are refined against both datasets\n",
+ "simultaneously."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a.free = True\n",
+ "structure.atom_sites['Si'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "46",
+ "metadata": {},
+ "source": [
+ "Bragg experiment parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bragg_expt.linked_phases['si'].scale.free = True\n",
+ "bragg_expt.instrument.calib_d_to_tof_offset.free = True\n",
+ "bragg_expt.peak.broad_gauss_sigma_0.free = True\n",
+ "bragg_expt.peak.broad_gauss_sigma_1.free = True\n",
+ "bragg_expt.peak.broad_gauss_sigma_2.free = True\n",
+ "for point in bragg_expt.background:\n",
+ " point.y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48",
+ "metadata": {},
+ "source": [
+ "PDF experiment parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pdf_expt.linked_phases['si'].scale.free = True\n",
+ "pdf_expt.peak.damp_q.free = True\n",
+ "pdf_expt.peak.broad_q.free = True\n",
+ "pdf_expt.peak.sharp_delta_1.free = True\n",
+ "pdf_expt.peak.sharp_delta_2.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "50",
+ "metadata": {},
+ "source": [
+ "#### Show Free Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "51",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "53",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "54",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated (After Fit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "55",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', show_residual=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "56",
+ "metadata": {
+ "lines_to_next_cell": 2
+ },
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='nomad', show_residual=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "57",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-16.py b/docs/docs/tutorials/ed-16.py
similarity index 100%
rename from tutorials/ed-16.py
rename to docs/docs/tutorials/ed-16.py
diff --git a/docs/docs/tutorials/ed-2.ipynb b/docs/docs/tutorials/ed-2.ipynb
new file mode 100644
index 00000000..0a4af0f3
--- /dev/null
+++ b/docs/docs/tutorials/ed-2.ipynb
@@ -0,0 +1,344 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: LBCO, HRPT\n",
+ "\n",
+ "This minimalistic example is designed to show how Rietveld refinement\n",
+ "can be performed when both the crystal structure and experiment are\n",
+ "defined directly in code. Only the experimentally measured data is\n",
+ "loaded from an external file.\n",
+ "\n",
+ "For this example, constant-wavelength neutron powder diffraction data\n",
+ "for La0.5Ba0.5CoO3 from HRPT at PSI is used.\n",
+ "\n",
+ "It does not contain any advanced features or options, and includes no\n",
+ "comments or explanations—these can be found in the other tutorials.\n",
+ "Default values are used for all parameters if not specified. Only\n",
+ "essential and self-explanatory code is provided.\n",
+ "\n",
+ "The example is intended for users who are already familiar with the\n",
+ "EasyDiffraction library and want to quickly get started with a simple\n",
+ "refinement. It is also useful for those who want to see what a\n",
+ "refinement might look like in code. For a more detailed explanation of\n",
+ "the code, please refer to the other tutorials."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Step 1: Define Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = ed.Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## Step 2: Define Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.create(name='lbco')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = project.structures['lbco']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.space_group.name_h_m = 'P m -3 m'\n",
+ "structure.space_group.it_coordinate_system_code = '1'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a = 3.88"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites.create(\n",
+ " label='La',\n",
+ " type_symbol='La',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.5,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Ba',\n",
+ " type_symbol='Ba',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.5,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Co',\n",
+ " type_symbol='Co',\n",
+ " fract_x=0.5,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='b',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O',\n",
+ " type_symbol='O',\n",
+ " fract_x=0,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Step 3: Define Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = ed.download_data(id=3, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_data_path(\n",
+ " name='hrpt',\n",
+ " data_path=data_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='constant wavelength',\n",
+ " radiation_probe='neutron',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment = project.experiments['hrpt']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.instrument.setup_wavelength = 1.494\n",
+ "experiment.instrument.calib_twotheta_offset = 0.6"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.peak.broad_gauss_u = 0.1\n",
+ "experiment.peak.broad_gauss_v = -0.1\n",
+ "experiment.peak.broad_gauss_w = 0.1\n",
+ "experiment.peak.broad_lorentz_y = 0.1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.background.create(id='1', x=10, y=170)\n",
+ "experiment.background.create(id='2', x=30, y=170)\n",
+ "experiment.background.create(id='3', x=50, y=170)\n",
+ "experiment.background.create(id='4', x=110, y=170)\n",
+ "experiment.background.create(id='5', x=165, y=170)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.excluded_regions.create(id='1', start=0, end=5)\n",
+ "experiment.excluded_regions.create(id='2', start=165, end=180)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "19",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.linked_phases.create(id='lbco', scale=10.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "20",
+ "metadata": {},
+ "source": [
+ "## Step 4: Perform Analysis"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a.free = True\n",
+ "\n",
+ "structure.atom_sites['La'].b_iso.free = True\n",
+ "structure.atom_sites['Ba'].b_iso.free = True\n",
+ "structure.atom_sites['Co'].b_iso.free = True\n",
+ "structure.atom_sites['O'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {
+ "lines_to_next_cell": 2
+ },
+ "outputs": [],
+ "source": [
+ "experiment.instrument.calib_twotheta_offset.free = True\n",
+ "\n",
+ "experiment.peak.broad_gauss_u.free = True\n",
+ "experiment.peak.broad_gauss_v.free = True\n",
+ "experiment.peak.broad_gauss_w.free = True\n",
+ "experiment.peak.broad_lorentz_y.free = True\n",
+ "\n",
+ "experiment.background['1'].y.free = True\n",
+ "experiment.background['2'].y.free = True\n",
+ "experiment.background['3'].y.free = True\n",
+ "experiment.background['4'].y.free = True\n",
+ "experiment.background['5'].y.free = True\n",
+ "\n",
+ "experiment.linked_phases['lbco'].scale.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-2.py b/docs/docs/tutorials/ed-2.py
similarity index 100%
rename from tutorials/ed-2.py
rename to docs/docs/tutorials/ed-2.py
diff --git a/docs/docs/tutorials/ed-3.ipynb b/docs/docs/tutorials/ed-3.ipynb
new file mode 100644
index 00000000..0fadb404
--- /dev/null
+++ b/docs/docs/tutorials/ed-3.ipynb
@@ -0,0 +1,1805 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: LBCO, HRPT\n",
+ "\n",
+ "This example demonstrates how to use the EasyDiffraction API in a\n",
+ "simplified, user-friendly manner that closely follows the GUI workflow\n",
+ "for a Rietveld refinement of La0.5Ba0.5CoO3 crystal structure using\n",
+ "constant wavelength neutron powder diffraction data from HRPT at PSI.\n",
+ "\n",
+ "It is intended for users with minimal programming experience who want\n",
+ "to learn how to perform standard crystal structure fitting using\n",
+ "diffraction data. This script covers creating a project, adding\n",
+ "crystal structures and experiments, performing analysis, and refining\n",
+ "parameters.\n",
+ "\n",
+ "Only a single import of `easydiffraction` is required, and all\n",
+ "operations are performed through high-level components of the\n",
+ "`project` object, such as `project.structures`,\n",
+ "`project.experiments`, and `project.analysis`. The `project` object is\n",
+ "the main container for all information."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import easydiffraction as ed"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Step 1: Create a Project\n",
+ "\n",
+ "This section explains how to create a project and define its metadata."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4",
+ "metadata": {},
+ "source": [
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = ed.Project(name='lbco_hrpt')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6",
+ "metadata": {},
+ "source": [
+ "#### Set Project Metadata"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.info.title = 'La0.5Ba0.5CoO3 at HRPT@PSI'\n",
+ "project.info.description = \"\"\"This project demonstrates a standard\n",
+ "refinement of La0.5Ba0.5CoO3, which crystallizes in a perovskite-type\n",
+ "structure, using neutron powder diffraction data collected in constant\n",
+ "wavelength mode at the HRPT diffractometer (PSI).\"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "#### Show Project Metadata as CIF"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.info.show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "10",
+ "metadata": {},
+ "source": [
+ "#### Save Project\n",
+ "\n",
+ "When saving the project for the first time, you need to specify the\n",
+ "directory path. In the example below, the project is saved to a\n",
+ "temporary location defined by the system."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "11",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save_as(dir_path='lbco_hrpt', temporary=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "12",
+ "metadata": {},
+ "source": [
+ "#### Set Up Data Plotter"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "Show supported plotting engines."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plotter.show_supported_engines()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "Show current plotting configuration."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plotter.show_config()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "Set plotting engine."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n",
+ "# line below to explicitly set the engine to the required one.\n",
+ "# project.plotter.engine = 'plotly'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "## Step 2: Define Structure\n",
+ "\n",
+ "This section shows how to add structures and modify their\n",
+ "parameters."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "20",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.create(name='lbco')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22",
+ "metadata": {},
+ "source": [
+ "#### Show Defined Structures\n",
+ "\n",
+ "Show the names of the crystal structures added. These names are used\n",
+ "to access the structure using the syntax:\n",
+ "`project.structures[name]`. All structure parameters can be accessed\n",
+ "via the `project` object."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.show_names()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group\n",
+ "\n",
+ "Modify the default space group parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].space_group.name_h_m = 'P m -3 m'\n",
+ "project.structures['lbco'].space_group.it_coordinate_system_code = '1'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell\n",
+ "\n",
+ "Modify the default unit cell parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].cell.length_a = 3.88"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites\n",
+ "\n",
+ "Add atom sites to the structure."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "29",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].atom_sites.create(\n",
+ " label='La',\n",
+ " type_symbol='La',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.5,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "project.structures['lbco'].atom_sites.create(\n",
+ " label='Ba',\n",
+ " type_symbol='Ba',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.5,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "project.structures['lbco'].atom_sites.create(\n",
+ " label='Co',\n",
+ " type_symbol='Co',\n",
+ " fract_x=0.5,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='b',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "project.structures['lbco'].atom_sites.create(\n",
+ " label='O',\n",
+ " type_symbol='O',\n",
+ " fract_x=0,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "30",
+ "metadata": {},
+ "source": [
+ "#### Show Structure as CIF"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "32",
+ "metadata": {},
+ "source": [
+ "#### Show Structure Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "33",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "34",
+ "metadata": {},
+ "source": [
+ "#### Save Project State\n",
+ "\n",
+ "Save the project state after adding the structure. This ensures\n",
+ "that all changes are stored and can be accessed later. The project\n",
+ "state is saved in the directory specified during project creation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36",
+ "metadata": {},
+ "source": [
+ "## Step 3: Define Experiment\n",
+ "\n",
+ "This section shows how to add experiments, configure their parameters,\n",
+ "and link the structures defined in the previous step."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37",
+ "metadata": {},
+ "source": [
+ "#### Download Measured Data\n",
+ "\n",
+ "Download the data file from the EasyDiffraction repository on GitHub."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = ed.download_data(id=3, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39",
+ "metadata": {},
+ "source": [
+ "#### Add Diffraction Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add_from_data_path(\n",
+ " name='hrpt',\n",
+ " data_path=data_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='constant wavelength',\n",
+ " radiation_probe='neutron',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41",
+ "metadata": {},
+ "source": [
+ "#### Show Defined Experiments"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.show_names()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43",
+ "metadata": {},
+ "source": [
+ "#### Show Measured Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas(expt_name='hrpt')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "45",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument\n",
+ "\n",
+ "Modify the default instrument parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].instrument.setup_wavelength = 1.494\n",
+ "project.experiments['hrpt'].instrument.calib_twotheta_offset = 0.6"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "47",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile\n",
+ "\n",
+ "Show supported peak profile types."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "48",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].show_supported_peak_profile_types()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "49",
+ "metadata": {},
+ "source": [
+ "Show the current peak profile type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "50",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].show_current_peak_profile_type()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "51",
+ "metadata": {},
+ "source": [
+ "Select the desired peak profile type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "52",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].peak_profile_type = 'pseudo-voigt'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "53",
+ "metadata": {},
+ "source": [
+ "Modify default peak profile parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "54",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].peak.broad_gauss_u = 0.1\n",
+ "project.experiments['hrpt'].peak.broad_gauss_v = -0.1\n",
+ "project.experiments['hrpt'].peak.broad_gauss_w = 0.1\n",
+ "project.experiments['hrpt'].peak.broad_lorentz_x = 0\n",
+ "project.experiments['hrpt'].peak.broad_lorentz_y = 0.1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "55",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56",
+ "metadata": {},
+ "source": [
+ "Show supported background types."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "57",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].show_supported_background_types()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58",
+ "metadata": {},
+ "source": [
+ "Show current background type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "59",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].show_current_background_type()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "60",
+ "metadata": {},
+ "source": [
+ "Select the desired background type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "61",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].background_type = 'line-segment'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "62",
+ "metadata": {},
+ "source": [
+ "Add background points."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "63",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].background.create(id='10', x=10, y=170)\n",
+ "project.experiments['hrpt'].background.create(id='30', x=30, y=170)\n",
+ "project.experiments['hrpt'].background.create(id='50', x=50, y=170)\n",
+ "project.experiments['hrpt'].background.create(id='110', x=110, y=170)\n",
+ "project.experiments['hrpt'].background.create(id='165', x=165, y=170)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "64",
+ "metadata": {},
+ "source": [
+ "Show current background points."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "65",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].background.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "66",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases\n",
+ "\n",
+ "Link the structure defined in the previous step to the experiment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "67",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].linked_phases.create(id='lbco', scale=10.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "68",
+ "metadata": {},
+ "source": [
+ "#### Show Experiment as CIF"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "69",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "70",
+ "metadata": {},
+ "source": [
+ "#### Save Project State"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "71",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "72",
+ "metadata": {},
+ "source": [
+ "## Step 4: Perform Analysis\n",
+ "\n",
+ "This section explains the analysis process, including how to set up\n",
+ "calculation and fitting engines.\n",
+ "\n",
+ "#### Set Calculator\n",
+ "\n",
+ "Show supported calculation engines for this experiment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "73",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].show_supported_calculator_types()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "74",
+ "metadata": {},
+ "source": [
+ "Show current calculation engine for this experiment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "75",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].show_current_calculator_type()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "76",
+ "metadata": {},
+ "source": [
+ "Select the desired calculation engine."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "77",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].calculator_type = 'cryspy'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "78",
+ "metadata": {},
+ "source": [
+ "#### Show Calculated Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "79",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_calc(expt_name='hrpt')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "80",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "81",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "82",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=38, x_max=41, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "83",
+ "metadata": {},
+ "source": [
+ "#### Show Parameters\n",
+ "\n",
+ "Show all parameters of the project."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "84",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# project.analysis.show_all_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "85",
+ "metadata": {},
+ "source": [
+ "Show all fittable parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "86",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_fittable_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "87",
+ "metadata": {},
+ "source": [
+ "Show only free parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "88",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "89",
+ "metadata": {},
+ "source": [
+ "Show how to access parameters in the code."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "90",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# project.analysis.how_to_access_parameters()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "91",
+ "metadata": {},
+ "source": [
+ "#### Set Fit Mode\n",
+ "\n",
+ "Show supported fit modes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "92",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_supported_fit_mode_types()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "93",
+ "metadata": {},
+ "source": [
+ "Show current fit mode."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "94",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_current_fit_mode_type()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "95",
+ "metadata": {},
+ "source": [
+ "Select desired fit mode."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "96",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit_mode.mode = 'single'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "97",
+ "metadata": {},
+ "source": [
+ "#### Set Minimizer\n",
+ "\n",
+ "Show supported fitting engines."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "98",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_available_minimizers()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "99",
+ "metadata": {},
+ "source": [
+ "Show current fitting engine."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "100",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_current_minimizer()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "101",
+ "metadata": {},
+ "source": [
+ "Select desired fitting engine."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "102",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "103",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 1/5\n",
+ "\n",
+ "Set structure parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "104",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].cell.length_a.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "105",
+ "metadata": {},
+ "source": [
+ "Set experiment parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "106",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].linked_phases['lbco'].scale.free = True\n",
+ "project.experiments['hrpt'].instrument.calib_twotheta_offset.free = True\n",
+ "project.experiments['hrpt'].background['10'].y.free = True\n",
+ "project.experiments['hrpt'].background['30'].y.free = True\n",
+ "project.experiments['hrpt'].background['50'].y.free = True\n",
+ "project.experiments['hrpt'].background['110'].y.free = True\n",
+ "project.experiments['hrpt'].background['165'].y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "107",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "108",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "109",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "110",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "111",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "112",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "113",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=38, x_max=41, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "114",
+ "metadata": {},
+ "source": [
+ "#### Save Project State"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "115",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save_as(dir_path='lbco_hrpt', temporary=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "116",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 2/5\n",
+ "\n",
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "117",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['hrpt'].peak.broad_gauss_u.free = True\n",
+ "project.experiments['hrpt'].peak.broad_gauss_v.free = True\n",
+ "project.experiments['hrpt'].peak.broad_gauss_w.free = True\n",
+ "project.experiments['hrpt'].peak.broad_lorentz_y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "118",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "119",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "120",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "121",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "122",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "123",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "124",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=38, x_max=41, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "125",
+ "metadata": {},
+ "source": [
+ "#### Save Project State"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "126",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save_as(dir_path='lbco_hrpt', temporary=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "127",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 3/5\n",
+ "\n",
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "128",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].atom_sites['La'].b_iso.free = True\n",
+ "project.structures['lbco'].atom_sites['Ba'].b_iso.free = True\n",
+ "project.structures['lbco'].atom_sites['Co'].b_iso.free = True\n",
+ "project.structures['lbco'].atom_sites['O'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "129",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "130",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "131",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "132",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "133",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "134",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "135",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=38, x_max=41, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "136",
+ "metadata": {},
+ "source": [
+ "#### Save Project State"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "137",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save_as(dir_path='lbco_hrpt', temporary=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "138",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 4/5\n",
+ "\n",
+ "#### Set Constraints\n",
+ "\n",
+ "Set aliases for parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "139",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.aliases.create(\n",
+ " label='biso_La',\n",
+ " param_uid=project.structures['lbco'].atom_sites['La'].b_iso.uid,\n",
+ ")\n",
+ "project.analysis.aliases.create(\n",
+ " label='biso_Ba',\n",
+ " param_uid=project.structures['lbco'].atom_sites['Ba'].b_iso.uid,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "140",
+ "metadata": {},
+ "source": [
+ "Set constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "141",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.constraints.create(lhs_alias='biso_Ba', rhs_expr='biso_La')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "142",
+ "metadata": {},
+ "source": [
+ "Show defined constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "143",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_constraints()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "144",
+ "metadata": {},
+ "source": [
+ "Show free parameters before applying constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "145",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "146",
+ "metadata": {},
+ "source": [
+ "Apply constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "147",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.apply_constraints()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "148",
+ "metadata": {},
+ "source": [
+ "Show free parameters after applying constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "149",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "150",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "151",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "152",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "153",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "154",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=38, x_max=41, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "155",
+ "metadata": {},
+ "source": [
+ "#### Save Project State"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "156",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save_as(dir_path='lbco_hrpt', temporary=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "157",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 5/5\n",
+ "\n",
+ "#### Set Constraints\n",
+ "\n",
+ "Set more aliases for parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "158",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.aliases.create(\n",
+ " label='occ_La',\n",
+ " param_uid=project.structures['lbco'].atom_sites['La'].occupancy.uid,\n",
+ ")\n",
+ "project.analysis.aliases.create(\n",
+ " label='occ_Ba',\n",
+ " param_uid=project.structures['lbco'].atom_sites['Ba'].occupancy.uid,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "159",
+ "metadata": {},
+ "source": [
+ "Set more constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "160",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.constraints.create(\n",
+ " lhs_alias='occ_Ba',\n",
+ " rhs_expr='1 - occ_La',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "161",
+ "metadata": {},
+ "source": [
+ "Show defined constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "162",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_constraints()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "163",
+ "metadata": {},
+ "source": [
+ "Apply constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "164",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.apply_constraints()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "165",
+ "metadata": {},
+ "source": [
+ "Set structure parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "166",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures['lbco'].atom_sites['La'].occupancy.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "167",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "168",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "169",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "170",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "171",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "172",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "173",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=38, x_max=41, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "174",
+ "metadata": {},
+ "source": [
+ "#### Save Project State"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "175",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.save_as(dir_path='lbco_hrpt', temporary=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "176",
+ "metadata": {},
+ "source": [
+ "## Step 5: Summary\n",
+ "\n",
+ "This final section shows how to review the results of the analysis."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "177",
+ "metadata": {},
+ "source": [
+ "#### Show Project Summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "178",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.summary.show_report()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "179",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-3.py b/docs/docs/tutorials/ed-3.py
similarity index 100%
rename from tutorials/ed-3.py
rename to docs/docs/tutorials/ed-3.py
diff --git a/docs/docs/tutorials/ed-4.ipynb b/docs/docs/tutorials/ed-4.ipynb
new file mode 100644
index 00000000..0b784054
--- /dev/null
+++ b/docs/docs/tutorials/ed-4.ipynb
@@ -0,0 +1,705 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: PbSO4, NPD + XRD\n",
+ "\n",
+ "This example demonstrates a more advanced use of the EasyDiffraction\n",
+ "library by explicitly creating and configuring structures and\n",
+ "experiments before adding them to a project. It could be more suitable\n",
+ "for users who are interested in creating custom workflows. This\n",
+ "tutorial provides minimal explanation and is intended for users\n",
+ "already familiar with EasyDiffraction.\n",
+ "\n",
+ "The tutorial covers a Rietveld refinement of PbSO4 crystal structure\n",
+ "based on the joint fit of both X-ray and neutron diffraction data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from easydiffraction import ExperimentFactory\n",
+ "from easydiffraction import Project\n",
+ "from easydiffraction import StructureFactory\n",
+ "from easydiffraction import download_data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Define Structure\n",
+ "\n",
+ "This section shows how to add structures and modify their\n",
+ "parameters.\n",
+ "\n",
+ "#### Create Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = StructureFactory.from_scratch(name='pbso4')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.space_group.name_h_m = 'P n m a'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a = 8.47\n",
+ "structure.cell.length_b = 5.39\n",
+ "structure.cell.length_c = 6.95"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {
+ "lines_to_next_cell": 2
+ },
+ "outputs": [],
+ "source": [
+ "structure.atom_sites.create(\n",
+ " label='Pb',\n",
+ " type_symbol='Pb',\n",
+ " fract_x=0.1876,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.167,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=1.37,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='S',\n",
+ " type_symbol='S',\n",
+ " fract_x=0.0654,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.684,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.3777,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O1',\n",
+ " type_symbol='O',\n",
+ " fract_x=0.9082,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.5954,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=1.9764,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O2',\n",
+ " type_symbol='O',\n",
+ " fract_x=0.1935,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.5432,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=1.4456,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O3',\n",
+ " type_symbol='O',\n",
+ " fract_x=0.0811,\n",
+ " fract_y=0.0272,\n",
+ " fract_z=0.8086,\n",
+ " wyckoff_letter='d',\n",
+ " b_iso=1.2822,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Define Experiments\n",
+ "\n",
+ "This section shows how to add experiments, configure their parameters,\n",
+ "and link the structures defined in the previous step.\n",
+ "\n",
+ "### Experiment 1: npd\n",
+ "\n",
+ "#### Download Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path1 = download_data(id=13, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt1 = ExperimentFactory.from_data_path(\n",
+ " name='npd',\n",
+ " data_path=data_path1,\n",
+ " radiation_probe='neutron',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt1.instrument.setup_wavelength = 1.91\n",
+ "expt1.instrument.calib_twotheta_offset = -0.1406"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt1.peak.broad_gauss_u = 0.139\n",
+ "expt1.peak.broad_gauss_v = -0.412\n",
+ "expt1.peak.broad_gauss_w = 0.386\n",
+ "expt1.peak.broad_lorentz_x = 0\n",
+ "expt1.peak.broad_lorentz_y = 0.088"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "20",
+ "metadata": {},
+ "source": [
+ "Select the background type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt1.background_type = 'line-segment'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22",
+ "metadata": {},
+ "source": [
+ "Add background points."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for id, x, y in [\n",
+ " ('1', 11.0, 206.1624),\n",
+ " ('2', 15.0, 194.75),\n",
+ " ('3', 20.0, 194.505),\n",
+ " ('4', 30.0, 188.4375),\n",
+ " ('5', 50.0, 207.7633),\n",
+ " ('6', 70.0, 201.7002),\n",
+ " ('7', 120.0, 244.4525),\n",
+ " ('8', 153.0, 226.0595),\n",
+ "]:\n",
+ " expt1.background.create(id=id, x=x, y=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt1.linked_phases.create(id='pbso4', scale=1.5)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "### Experiment 2: xrd\n",
+ "\n",
+ "#### Download Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path2 = download_data(id=16, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "29",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt2 = ExperimentFactory.from_data_path(\n",
+ " name='xrd',\n",
+ " data_path=data_path2,\n",
+ " radiation_probe='xray',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "30",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt2.instrument.setup_wavelength = 1.540567\n",
+ "expt2.instrument.calib_twotheta_offset = -0.05181"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "32",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "33",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt2.peak.broad_gauss_u = 0.304138\n",
+ "expt2.peak.broad_gauss_v = -0.112622\n",
+ "expt2.peak.broad_gauss_w = 0.021272\n",
+ "expt2.peak.broad_lorentz_x = 0\n",
+ "expt2.peak.broad_lorentz_y = 0.057691"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "34",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35",
+ "metadata": {},
+ "source": [
+ "Select background type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "36",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt2.background_type = 'chebyshev'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37",
+ "metadata": {},
+ "source": [
+ "Add background points."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for id, x, y in [\n",
+ " ('1', 0, 119.195),\n",
+ " ('2', 1, 6.221),\n",
+ " ('3', 2, -45.725),\n",
+ " ('4', 3, 8.119),\n",
+ " ('5', 4, 54.552),\n",
+ " ('6', 5, -20.661),\n",
+ "]:\n",
+ " expt2.background.create(id=id, order=x, coef=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt2.linked_phases.create(id='pbso4', scale=0.001)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41",
+ "metadata": {},
+ "source": [
+ "## Define Project\n",
+ "\n",
+ "The project object is used to manage structures, experiments, and\n",
+ "analysis.\n",
+ "\n",
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add(structure)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "45",
+ "metadata": {},
+ "source": [
+ "#### Add Experiments"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add(expt1)\n",
+ "project.experiments.add(expt2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "47",
+ "metadata": {},
+ "source": [
+ "## Perform Analysis\n",
+ "\n",
+ "This section outlines the analysis process, including how to configure\n",
+ "calculation and fitting engines.\n",
+ "\n",
+ "#### Set Fit Mode"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "48",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit_mode.mode = 'joint'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "49",
+ "metadata": {},
+ "source": [
+ "#### Set Minimizer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "50",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "51",
+ "metadata": {},
+ "source": [
+ "#### Set Fitting Parameters\n",
+ "\n",
+ "Set structure parameters to be optimized."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "52",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a.free = True\n",
+ "structure.cell.length_b.free = True\n",
+ "structure.cell.length_c.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "53",
+ "metadata": {},
+ "source": [
+ "Set experiment parameters to be optimized."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "54",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt1.linked_phases['pbso4'].scale.free = True\n",
+ "\n",
+ "expt1.instrument.calib_twotheta_offset.free = True\n",
+ "\n",
+ "expt1.peak.broad_gauss_u.free = True\n",
+ "expt1.peak.broad_gauss_v.free = True\n",
+ "expt1.peak.broad_gauss_w.free = True\n",
+ "expt1.peak.broad_lorentz_y.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "55",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt2.linked_phases['pbso4'].scale.free = True\n",
+ "\n",
+ "expt2.instrument.calib_twotheta_offset.free = True\n",
+ "\n",
+ "expt2.peak.broad_gauss_u.free = True\n",
+ "expt2.peak.broad_gauss_v.free = True\n",
+ "expt2.peak.broad_gauss_w.free = True\n",
+ "expt2.peak.broad_lorentz_y.free = True\n",
+ "\n",
+ "for term in expt2.background:\n",
+ " term.coef.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56",
+ "metadata": {},
+ "source": [
+ "#### Perform Fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "57",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "59",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='npd', x_min=35.5, x_max=38.3, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "60",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='xrd', x_min=29.0, x_max=30.4, show_residual=True)"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-4.py b/docs/docs/tutorials/ed-4.py
similarity index 100%
rename from tutorials/ed-4.py
rename to docs/docs/tutorials/ed-4.py
diff --git a/docs/docs/tutorials/ed-5.ipynb b/docs/docs/tutorials/ed-5.ipynb
new file mode 100644
index 00000000..2ee5ec1a
--- /dev/null
+++ b/docs/docs/tutorials/ed-5.ipynb
@@ -0,0 +1,638 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: Co2SiO4, D20\n",
+ "\n",
+ "This example demonstrates a Rietveld refinement of Co2SiO4 crystal\n",
+ "structure using constant wavelength neutron powder diffraction data\n",
+ "from D20 at ILL."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from easydiffraction import ExperimentFactory\n",
+ "from easydiffraction import Project\n",
+ "from easydiffraction import StructureFactory\n",
+ "from easydiffraction import download_data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Define Structure\n",
+ "\n",
+ "This section shows how to add structures and modify their\n",
+ "parameters.\n",
+ "\n",
+ "#### Create Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = StructureFactory.from_scratch(name='cosio')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.space_group.name_h_m = 'P n m a'\n",
+ "structure.space_group.it_coordinate_system_code = 'abc'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a = 10.3\n",
+ "structure.cell.length_b = 6.0\n",
+ "structure.cell.length_c = 4.8"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites.create(\n",
+ " label='Co1',\n",
+ " type_symbol='Co',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Co2',\n",
+ " type_symbol='Co',\n",
+ " fract_x=0.279,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.985,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Si',\n",
+ " type_symbol='Si',\n",
+ " fract_x=0.094,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.429,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O1',\n",
+ " type_symbol='O',\n",
+ " fract_x=0.091,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.771,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O2',\n",
+ " type_symbol='O',\n",
+ " fract_x=0.448,\n",
+ " fract_y=0.25,\n",
+ " fract_z=0.217,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O3',\n",
+ " type_symbol='O',\n",
+ " fract_x=0.164,\n",
+ " fract_y=0.032,\n",
+ " fract_z=0.28,\n",
+ " wyckoff_letter='d',\n",
+ " b_iso=0.5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Define Experiment\n",
+ "\n",
+ "This section shows how to add experiments, configure their parameters,\n",
+ "and link the structures defined in the previous step.\n",
+ "\n",
+ "#### Download Measured Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = download_data(id=12, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt = ExperimentFactory.from_data_path(name='d20', data_path=data_path)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.instrument.setup_wavelength = 1.87\n",
+ "expt.instrument.calib_twotheta_offset = 0.1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.peak.broad_gauss_u = 0.3\n",
+ "expt.peak.broad_gauss_v = -0.5\n",
+ "expt.peak.broad_gauss_w = 0.4"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.background.create(id='1', x=8, y=500)\n",
+ "expt.background.create(id='2', x=9, y=500)\n",
+ "expt.background.create(id='3', x=10, y=500)\n",
+ "expt.background.create(id='4', x=11, y=500)\n",
+ "expt.background.create(id='5', x=12, y=500)\n",
+ "expt.background.create(id='6', x=15, y=500)\n",
+ "expt.background.create(id='7', x=25, y=500)\n",
+ "expt.background.create(id='8', x=30, y=500)\n",
+ "expt.background.create(id='9', x=50, y=500)\n",
+ "expt.background.create(id='10', x=70, y=500)\n",
+ "expt.background.create(id='11', x=90, y=500)\n",
+ "expt.background.create(id='12', x=110, y=500)\n",
+ "expt.background.create(id='13', x=130, y=500)\n",
+ "expt.background.create(id='14', x=150, y=500)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.linked_phases.create(id='cosio', scale=1.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "23",
+ "metadata": {},
+ "source": [
+ "## Define Project\n",
+ "\n",
+ "The project object is used to manage the structure, experiment, and\n",
+ "analysis.\n",
+ "\n",
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "25",
+ "metadata": {},
+ "source": [
+ "#### Set Plotting Engine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "26",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n",
+ "# line below to explicitly set the engine to the required one.\n",
+ "# project.plotter.engine = 'plotly'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "28",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add(structure)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29",
+ "metadata": {},
+ "source": [
+ "#### Add Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add(expt)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "31",
+ "metadata": {},
+ "source": [
+ "## Perform Analysis\n",
+ "\n",
+ "This section shows the analysis process, including how to set up\n",
+ "calculation and fitting engines.\n",
+ "\n",
+ "#### Set Minimizer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "32",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "33",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "34",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='d20', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='d20', x_min=41, x_max=54, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36",
+ "metadata": {},
+ "source": [
+ "#### Set Free Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a.free = True\n",
+ "structure.cell.length_b.free = True\n",
+ "structure.cell.length_c.free = True\n",
+ "\n",
+ "structure.atom_sites['Co2'].fract_x.free = True\n",
+ "structure.atom_sites['Co2'].fract_z.free = True\n",
+ "structure.atom_sites['Si'].fract_x.free = True\n",
+ "structure.atom_sites['Si'].fract_z.free = True\n",
+ "structure.atom_sites['O1'].fract_x.free = True\n",
+ "structure.atom_sites['O1'].fract_z.free = True\n",
+ "structure.atom_sites['O2'].fract_x.free = True\n",
+ "structure.atom_sites['O2'].fract_z.free = True\n",
+ "structure.atom_sites['O3'].fract_x.free = True\n",
+ "structure.atom_sites['O3'].fract_y.free = True\n",
+ "structure.atom_sites['O3'].fract_z.free = True\n",
+ "\n",
+ "structure.atom_sites['Co1'].b_iso.free = True\n",
+ "structure.atom_sites['Co2'].b_iso.free = True\n",
+ "structure.atom_sites['Si'].b_iso.free = True\n",
+ "structure.atom_sites['O1'].b_iso.free = True\n",
+ "structure.atom_sites['O2'].b_iso.free = True\n",
+ "structure.atom_sites['O3'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.linked_phases['cosio'].scale.free = True\n",
+ "\n",
+ "expt.instrument.calib_twotheta_offset.free = True\n",
+ "\n",
+ "expt.peak.broad_gauss_u.free = True\n",
+ "expt.peak.broad_gauss_v.free = True\n",
+ "expt.peak.broad_gauss_w.free = True\n",
+ "expt.peak.broad_lorentz_y.free = True\n",
+ "\n",
+ "for point in expt.background:\n",
+ " point.y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39",
+ "metadata": {},
+ "source": [
+ "#### Set Constraints\n",
+ "\n",
+ "Set aliases for parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.aliases.create(\n",
+ " label='biso_Co1',\n",
+ " param_uid=project.structures['cosio'].atom_sites['Co1'].b_iso.uid,\n",
+ ")\n",
+ "project.analysis.aliases.create(\n",
+ " label='biso_Co2',\n",
+ " param_uid=project.structures['cosio'].atom_sites['Co2'].b_iso.uid,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41",
+ "metadata": {},
+ "source": [
+ "Set constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.constraints.create(\n",
+ " lhs_alias='biso_Co2',\n",
+ " rhs_expr='biso_Co1',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43",
+ "metadata": {},
+ "source": [
+ "Apply constraints."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.apply_constraints()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "45",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "47",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "48",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='d20', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='d20', x_min=41, x_max=54, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "50",
+ "metadata": {},
+ "source": [
+ "## Summary\n",
+ "\n",
+ "This final section shows how to review the results of the analysis."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "51",
+ "metadata": {},
+ "source": [
+ "#### Show Project Summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "52",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.summary.show_report()"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-5.py b/docs/docs/tutorials/ed-5.py
similarity index 100%
rename from tutorials/ed-5.py
rename to docs/docs/tutorials/ed-5.py
diff --git a/docs/docs/tutorials/ed-6.ipynb b/docs/docs/tutorials/ed-6.ipynb
new file mode 100644
index 00000000..599c09eb
--- /dev/null
+++ b/docs/docs/tutorials/ed-6.ipynb
@@ -0,0 +1,849 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: HS, HRPT\n",
+ "\n",
+ "This example demonstrates a Rietveld refinement of HS crystal\n",
+ "structure using constant wavelength neutron powder diffraction data\n",
+ "from HRPT at PSI."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from easydiffraction import ExperimentFactory\n",
+ "from easydiffraction import Project\n",
+ "from easydiffraction import StructureFactory\n",
+ "from easydiffraction import download_data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Define Structure\n",
+ "\n",
+ "This section shows how to add structures and modify their\n",
+ "parameters.\n",
+ "\n",
+ "#### Create Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = StructureFactory.from_scratch(name='hs')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.space_group.name_h_m = 'R -3 m'\n",
+ "structure.space_group.it_coordinate_system_code = 'h'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {
+ "lines_to_next_cell": 2
+ },
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a = 6.9\n",
+ "structure.cell.length_c = 14.1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites.create(\n",
+ " label='Zn',\n",
+ " type_symbol='Zn',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='b',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Cu',\n",
+ " type_symbol='Cu',\n",
+ " fract_x=0.5,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='e',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='O',\n",
+ " type_symbol='O',\n",
+ " fract_x=0.21,\n",
+ " fract_y=-0.21,\n",
+ " fract_z=0.06,\n",
+ " wyckoff_letter='h',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Cl',\n",
+ " type_symbol='Cl',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0.197,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.5,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='H',\n",
+ " type_symbol='2H',\n",
+ " fract_x=0.13,\n",
+ " fract_y=-0.13,\n",
+ " fract_z=0.08,\n",
+ " wyckoff_letter='h',\n",
+ " b_iso=0.5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Define Experiment\n",
+ "\n",
+ "This section shows how to add experiments, configure their parameters,\n",
+ "and link the structures defined in the previous step.\n",
+ "\n",
+ "#### Download Measured Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = download_data(id=11, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt = ExperimentFactory.from_data_path(name='hrpt', data_path=data_path)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.instrument.setup_wavelength = 1.89\n",
+ "expt.instrument.calib_twotheta_offset = 0.0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.peak.broad_gauss_u = 0.1\n",
+ "expt.peak.broad_gauss_v = -0.2\n",
+ "expt.peak.broad_gauss_w = 0.2\n",
+ "expt.peak.broad_lorentz_x = 0.0\n",
+ "expt.peak.broad_lorentz_y = 0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.background.create(id='1', x=4.4196, y=500)\n",
+ "expt.background.create(id='2', x=6.6207, y=500)\n",
+ "expt.background.create(id='3', x=10.4918, y=500)\n",
+ "expt.background.create(id='4', x=15.4634, y=500)\n",
+ "expt.background.create(id='5', x=45.6041, y=500)\n",
+ "expt.background.create(id='6', x=74.6844, y=500)\n",
+ "expt.background.create(id='7', x=103.4187, y=500)\n",
+ "expt.background.create(id='8', x=121.6311, y=500)\n",
+ "expt.background.create(id='9', x=159.4116, y=500)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.linked_phases.create(id='hs', scale=0.5)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "23",
+ "metadata": {},
+ "source": [
+ "## Define Project\n",
+ "\n",
+ "The project object is used to manage the structure, experiment, and\n",
+ "analysis.\n",
+ "\n",
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "25",
+ "metadata": {},
+ "source": [
+ "#### Set Plotting Engine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "26",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n",
+ "# line below to explicitly set the engine to the required one.\n",
+ "# project.plotter.engine = 'plotly'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "28",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add(structure)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29",
+ "metadata": {},
+ "source": [
+ "#### Add Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add(expt)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "31",
+ "metadata": {},
+ "source": [
+ "## Perform Analysis\n",
+ "\n",
+ "This section shows the analysis process, including how to set up\n",
+ "calculation and fitting engines.\n",
+ "\n",
+ "#### Set Minimizer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "32",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "33",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "34",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=48, x_max=51, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 1/5\n",
+ "\n",
+ "Set parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a.free = True\n",
+ "structure.cell.length_c.free = True\n",
+ "\n",
+ "expt.linked_phases['hs'].scale.free = True\n",
+ "expt.instrument.calib_twotheta_offset.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "38",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "39",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "40",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "41",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "43",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=48, x_max=51, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "46",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 2/5\n",
+ "\n",
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.peak.broad_gauss_u.free = True\n",
+ "expt.peak.broad_gauss_v.free = True\n",
+ "expt.peak.broad_gauss_w.free = True\n",
+ "expt.peak.broad_lorentz_x.free = True\n",
+ "\n",
+ "for point in expt.background:\n",
+ " point.y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "50",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "51",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "52",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "53",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "54",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "55",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=48, x_max=51, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 3/5\n",
+ "\n",
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "57",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites['O'].fract_x.free = True\n",
+ "structure.atom_sites['O'].fract_z.free = True\n",
+ "structure.atom_sites['Cl'].fract_z.free = True\n",
+ "structure.atom_sites['H'].fract_x.free = True\n",
+ "structure.atom_sites['H'].fract_z.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "59",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "60",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "61",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "62",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "63",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "64",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "65",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=48, x_max=51, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "66",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 4/5\n",
+ "\n",
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "67",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites['Zn'].b_iso.free = True\n",
+ "structure.atom_sites['Cu'].b_iso.free = True\n",
+ "structure.atom_sites['O'].b_iso.free = True\n",
+ "structure.atom_sites['Cl'].b_iso.free = True\n",
+ "structure.atom_sites['H'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "68",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "69",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "70",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "71",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "72",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "73",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "74",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "75",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='hrpt', x_min=48, x_max=51, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "76",
+ "metadata": {},
+ "source": [
+ "## Summary\n",
+ "\n",
+ "This final section shows how to review the results of the analysis."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "77",
+ "metadata": {},
+ "source": [
+ "#### Show Project Summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "78",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.summary.show_report()"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-6.py b/docs/docs/tutorials/ed-6.py
similarity index 100%
rename from tutorials/ed-6.py
rename to docs/docs/tutorials/ed-6.py
diff --git a/docs/docs/tutorials/ed-7.ipynb b/docs/docs/tutorials/ed-7.ipynb
new file mode 100644
index 00000000..869dc723
--- /dev/null
+++ b/docs/docs/tutorials/ed-7.ipynb
@@ -0,0 +1,741 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: Si, SEPD\n",
+ "\n",
+ "This example demonstrates a Rietveld refinement of Si crystal\n",
+ "structure using time-of-flight neutron powder diffraction data from\n",
+ "SEPD at Argonne."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from easydiffraction import ExperimentFactory\n",
+ "from easydiffraction import Project\n",
+ "from easydiffraction import StructureFactory\n",
+ "from easydiffraction import download_data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Define Structure\n",
+ "\n",
+ "This section shows how to add structures and modify their\n",
+ "parameters.\n",
+ "\n",
+ "#### Create Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = StructureFactory.from_scratch(name='si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.space_group.name_h_m = 'F d -3 m'\n",
+ "structure.space_group.it_coordinate_system_code = '2'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a = 5.431"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites.create(\n",
+ " label='Si',\n",
+ " type_symbol='Si',\n",
+ " fract_x=0.125,\n",
+ " fract_y=0.125,\n",
+ " fract_z=0.125,\n",
+ " b_iso=0.5,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Define Experiment\n",
+ "\n",
+ "This section shows how to add experiments, configure their\n",
+ "parameters, and link the structures defined in the previous step.\n",
+ "\n",
+ "#### Download Measured Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = download_data(id=7, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt = ExperimentFactory.from_data_path(\n",
+ " name='sepd', data_path=data_path, beam_mode='time-of-flight'\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.instrument.setup_twotheta_bank = 144.845\n",
+ "expt.instrument.calib_d_to_tof_offset = 0.0\n",
+ "expt.instrument.calib_d_to_tof_linear = 7476.91\n",
+ "expt.instrument.calib_d_to_tof_quad = -1.54"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.peak_profile_type = 'pseudo-voigt * ikeda-carpenter'\n",
+ "expt.peak.broad_gauss_sigma_0 = 3.0\n",
+ "expt.peak.broad_gauss_sigma_1 = 40.0\n",
+ "expt.peak.broad_gauss_sigma_2 = 2.0\n",
+ "expt.peak.broad_mix_beta_0 = 0.04221\n",
+ "expt.peak.broad_mix_beta_1 = 0.00946"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Asymmetry"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.peak.asym_alpha_0 = 0.0\n",
+ "expt.peak.asym_alpha_1 = 0.5971"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.background_type = 'line-segment'\n",
+ "for x in range(0, 35000, 5000):\n",
+ " expt.background.create(id=str(x), x=x, y=200)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "23",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.linked_phases.create(id='si', scale=10.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "25",
+ "metadata": {},
+ "source": [
+ "## Define Project\n",
+ "\n",
+ "The project object is used to manage the structure, experiment, and\n",
+ "analysis.\n",
+ "\n",
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "26",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "28",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add(structure)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29",
+ "metadata": {},
+ "source": [
+ "#### Add Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add(expt)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "31",
+ "metadata": {},
+ "source": [
+ "## Perform Analysis\n",
+ "\n",
+ "This section shows the analysis process, including how to set up\n",
+ "calculation and fitting engines.\n",
+ "\n",
+ "#### Set Minimizer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "32",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "33",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "34",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', show_residual=True)\n",
+ "project.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 1/5\n",
+ "\n",
+ "Set parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "36",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a.free = True\n",
+ "\n",
+ "expt.linked_phases['si'].scale.free = True\n",
+ "expt.instrument.calib_d_to_tof_offset.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "43",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "44",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 2/5\n",
+ "\n",
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for point in expt.background:\n",
+ " point.y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "46",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "50",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "51",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "52",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "53",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 3/5\n",
+ "\n",
+ "Fix background points."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "54",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for point in expt.background:\n",
+ " point.y.free = False"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "55",
+ "metadata": {},
+ "source": [
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "56",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt.peak.broad_gauss_sigma_0.free = True\n",
+ "expt.peak.broad_gauss_sigma_1.free = True\n",
+ "expt.peak.broad_gauss_sigma_2.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "58",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "59",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "60",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "61",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "62",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "63",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "64",
+ "metadata": {},
+ "source": [
+ "### Perform Fit 4/5\n",
+ "\n",
+ "Set more parameters to be refined."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "65",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites['Si'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "66",
+ "metadata": {},
+ "source": [
+ "Show free parameters after selection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "67",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.show_free_params()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "68",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "69",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "70",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "71",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "72",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-7.py b/docs/docs/tutorials/ed-7.py
similarity index 100%
rename from tutorials/ed-7.py
rename to docs/docs/tutorials/ed-7.py
diff --git a/docs/docs/tutorials/ed-8.ipynb b/docs/docs/tutorials/ed-8.ipynb
new file mode 100644
index 00000000..4bc42ad1
--- /dev/null
+++ b/docs/docs/tutorials/ed-8.ipynb
@@ -0,0 +1,747 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: NCAF, WISH\n",
+ "\n",
+ "This example demonstrates a Rietveld refinement of Na2Ca3Al2F14\n",
+ "crystal structure using time-of-flight neutron powder diffraction data\n",
+ "from WISH at ISIS.\n",
+ "\n",
+ "Two datasets from detector banks 5+6 and 4+7 are used for joint\n",
+ "fitting."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from easydiffraction import ExperimentFactory\n",
+ "from easydiffraction import Project\n",
+ "from easydiffraction import StructureFactory\n",
+ "from easydiffraction import download_data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Define Structure\n",
+ "\n",
+ "This section covers how to add structures and modify their\n",
+ "parameters.\n",
+ "\n",
+ "#### Create Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure = StructureFactory.from_scratch(name='ncaf')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.space_group.name_h_m = 'I 21 3'\n",
+ "structure.space_group.it_coordinate_system_code = '1'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.cell.length_a = 10.250256"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites.create(\n",
+ " label='Ca',\n",
+ " type_symbol='Ca',\n",
+ " fract_x=0.4663,\n",
+ " fract_y=0.0,\n",
+ " fract_z=0.25,\n",
+ " wyckoff_letter='b',\n",
+ " b_iso=0.92,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Al',\n",
+ " type_symbol='Al',\n",
+ " fract_x=0.2521,\n",
+ " fract_y=0.2521,\n",
+ " fract_z=0.2521,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.73,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='Na',\n",
+ " type_symbol='Na',\n",
+ " fract_x=0.0851,\n",
+ " fract_y=0.0851,\n",
+ " fract_z=0.0851,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=2.08,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='F1',\n",
+ " type_symbol='F',\n",
+ " fract_x=0.1377,\n",
+ " fract_y=0.3054,\n",
+ " fract_z=0.1195,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=0.90,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='F2',\n",
+ " type_symbol='F',\n",
+ " fract_x=0.3625,\n",
+ " fract_y=0.3633,\n",
+ " fract_z=0.1867,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=1.37,\n",
+ ")\n",
+ "structure.atom_sites.create(\n",
+ " label='F3',\n",
+ " type_symbol='F',\n",
+ " fract_x=0.4612,\n",
+ " fract_y=0.4612,\n",
+ " fract_z=0.4612,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.88,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "## Define Experiment\n",
+ "\n",
+ "This section shows how to add experiments, configure their parameters,\n",
+ "and link the structures defined in the previous step.\n",
+ "\n",
+ "#### Download Measured Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path56 = download_data(id=9, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path47 = download_data(id=10, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt56 = ExperimentFactory.from_data_path(\n",
+ " name='wish_5_6',\n",
+ " data_path=data_path56,\n",
+ " beam_mode='time-of-flight',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt47 = ExperimentFactory.from_data_path(\n",
+ " name='wish_4_7',\n",
+ " data_path=data_path47,\n",
+ " beam_mode='time-of-flight',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt56.instrument.setup_twotheta_bank = 152.827\n",
+ "expt56.instrument.calib_d_to_tof_offset = -13.5\n",
+ "expt56.instrument.calib_d_to_tof_linear = 20773.0\n",
+ "expt56.instrument.calib_d_to_tof_quad = -1.08308"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "19",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt47.instrument.setup_twotheta_bank = 121.660\n",
+ "expt47.instrument.calib_d_to_tof_offset = -15.0\n",
+ "expt47.instrument.calib_d_to_tof_linear = 18660.0\n",
+ "expt47.instrument.calib_d_to_tof_quad = -0.47488"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "20",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt56.peak.broad_gauss_sigma_0 = 0.0\n",
+ "expt56.peak.broad_gauss_sigma_1 = 0.0\n",
+ "expt56.peak.broad_gauss_sigma_2 = 15.5\n",
+ "expt56.peak.broad_mix_beta_0 = 0.007\n",
+ "expt56.peak.broad_mix_beta_1 = 0.01\n",
+ "expt56.peak.asym_alpha_0 = -0.0094\n",
+ "expt56.peak.asym_alpha_1 = 0.1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt47.peak.broad_gauss_sigma_0 = 0.0\n",
+ "expt47.peak.broad_gauss_sigma_1 = 29.8\n",
+ "expt47.peak.broad_gauss_sigma_2 = 18.0\n",
+ "expt47.peak.broad_mix_beta_0 = 0.006\n",
+ "expt47.peak.broad_mix_beta_1 = 0.015\n",
+ "expt47.peak.asym_alpha_0 = -0.0115\n",
+ "expt47.peak.asym_alpha_1 = 0.1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "23",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt56.background_type = 'line-segment'\n",
+ "for idx, (x, y) in enumerate(\n",
+ " [\n",
+ " (9162, 465),\n",
+ " (11136, 593),\n",
+ " (13313, 497),\n",
+ " (14906, 546),\n",
+ " (16454, 533),\n",
+ " (17352, 496),\n",
+ " (18743, 428),\n",
+ " (20179, 452),\n",
+ " (21368, 397),\n",
+ " (22176, 468),\n",
+ " (22827, 477),\n",
+ " (24644, 380),\n",
+ " (26439, 381),\n",
+ " (28257, 378),\n",
+ " (31196, 343),\n",
+ " (34034, 328),\n",
+ " (37265, 310),\n",
+ " (41214, 323),\n",
+ " (44827, 283),\n",
+ " (49830, 273),\n",
+ " (52905, 257),\n",
+ " (58204, 260),\n",
+ " (62916, 261),\n",
+ " (70186, 262),\n",
+ " (74204, 262),\n",
+ " (82103, 268),\n",
+ " (91958, 268),\n",
+ " (102712, 262),\n",
+ " ],\n",
+ " start=1,\n",
+ "):\n",
+ " expt56.background.create(id=str(idx), x=x, y=y)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt47.background_type = 'line-segment'\n",
+ "for idx, (x, y) in enumerate(\n",
+ " [\n",
+ " (9090, 488),\n",
+ " (10672, 566),\n",
+ " (12287, 494),\n",
+ " (14037, 559),\n",
+ " (15451, 529),\n",
+ " (16764, 445),\n",
+ " (18076, 460),\n",
+ " (19456, 413),\n",
+ " (20466, 511),\n",
+ " (21880, 396),\n",
+ " (23798, 391),\n",
+ " (25447, 385),\n",
+ " (28073, 349),\n",
+ " (30058, 332),\n",
+ " (32583, 309),\n",
+ " (34804, 355),\n",
+ " (37160, 318),\n",
+ " (40324, 290),\n",
+ " (46895, 260),\n",
+ " (50631, 256),\n",
+ " (54602, 246),\n",
+ " (58439, 264),\n",
+ " (66520, 250),\n",
+ " (75002, 258),\n",
+ " (83649, 257),\n",
+ " (92770, 255),\n",
+ " (101524, 260),\n",
+ " ],\n",
+ " start=1,\n",
+ "):\n",
+ " expt47.background.create(id=str(idx), x=x, y=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt56.linked_phases.create(id='ncaf', scale=1.0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "28",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt47.linked_phases.create(id='ncaf', scale=2.0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29",
+ "metadata": {},
+ "source": [
+ "#### Set Excluded Regions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt56.excluded_regions.create(id='1', start=0, end=10010)\n",
+ "expt56.excluded_regions.create(id='2', start=100010, end=200000)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt47.excluded_regions.create(id='1', start=0, end=10006)\n",
+ "expt47.excluded_regions.create(id='2', start=100004, end=200000)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "32",
+ "metadata": {},
+ "source": [
+ "## Define Project\n",
+ "\n",
+ "The project object is used to manage the structure, experiments,\n",
+ "and analysis\n",
+ "\n",
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "33",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "34",
+ "metadata": {},
+ "source": [
+ "#### Set Plotting Engine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n",
+ "# line below to explicitly set the engine to the required one.\n",
+ "# project.plotter.engine = 'plotly'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36",
+ "metadata": {},
+ "source": [
+ "#### Add Structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add(structure)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "38",
+ "metadata": {},
+ "source": [
+ "#### Add Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "39",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add(expt56)\n",
+ "project.experiments.add(expt47)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "40",
+ "metadata": {},
+ "source": [
+ "## Perform Analysis\n",
+ "\n",
+ "This section shows the analysis process, including how to set up\n",
+ "calculation and fitting engines.\n",
+ "\n",
+ "#### Set Minimizer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "41",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "42",
+ "metadata": {},
+ "source": [
+ "#### Set Fit Mode"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "43",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit_mode.mode = 'joint'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "44",
+ "metadata": {},
+ "source": [
+ "#### Set Free Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure.atom_sites['Ca'].b_iso.free = True\n",
+ "structure.atom_sites['Al'].b_iso.free = True\n",
+ "structure.atom_sites['Na'].b_iso.free = True\n",
+ "structure.atom_sites['F1'].b_iso.free = True\n",
+ "structure.atom_sites['F2'].b_iso.free = True\n",
+ "structure.atom_sites['F3'].b_iso.free = True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "expt56.linked_phases['ncaf'].scale.free = True\n",
+ "expt56.instrument.calib_d_to_tof_offset.free = True\n",
+ "expt56.instrument.calib_d_to_tof_linear.free = True\n",
+ "expt56.peak.broad_gauss_sigma_2.free = True\n",
+ "expt56.peak.broad_mix_beta_0.free = True\n",
+ "expt56.peak.broad_mix_beta_1.free = True\n",
+ "expt56.peak.asym_alpha_1.free = True\n",
+ "\n",
+ "expt47.linked_phases['ncaf'].scale.free = True\n",
+ "expt47.instrument.calib_d_to_tof_linear.free = True\n",
+ "expt47.instrument.calib_d_to_tof_offset.free = True\n",
+ "expt47.peak.broad_gauss_sigma_2.free = True\n",
+ "expt47.peak.broad_mix_beta_0.free = True\n",
+ "expt47.peak.broad_mix_beta_1.free = True\n",
+ "expt47.peak.asym_alpha_1.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "47",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "48",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='wish_5_6', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='wish_4_7', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "50",
+ "metadata": {},
+ "source": [
+ "#### Run Fitting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "51",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "53",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='wish_5_6', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "54",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='wish_4_7', show_residual=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "55",
+ "metadata": {},
+ "source": [
+ "## Summary\n",
+ "\n",
+ "This final section shows how to review the results of the analysis."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56",
+ "metadata": {},
+ "source": [
+ "#### Show Project Summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "57",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.summary.show_report()"
+ ]
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-8.py b/docs/docs/tutorials/ed-8.py
similarity index 100%
rename from tutorials/ed-8.py
rename to docs/docs/tutorials/ed-8.py
diff --git a/docs/docs/tutorials/ed-9.ipynb b/docs/docs/tutorials/ed-9.ipynb
new file mode 100644
index 00000000..735964ae
--- /dev/null
+++ b/docs/docs/tutorials/ed-9.ipynb
@@ -0,0 +1,704 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Structure Refinement: LBCO+Si, McStas\n",
+ "\n",
+ "This example demonstrates a Rietveld refinement of La0.5Ba0.5CoO3\n",
+ "crystal structure with a small amount of Si phase using time-of-flight\n",
+ "neutron powder diffraction data simulated with McStas."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Import Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from easydiffraction import ExperimentFactory\n",
+ "from easydiffraction import Project\n",
+ "from easydiffraction import StructureFactory\n",
+ "from easydiffraction import download_data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Define Structures\n",
+ "\n",
+ "This section shows how to add structures and modify their\n",
+ "parameters.\n",
+ "\n",
+ "### Create Structure 1: LBCO"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_1 = StructureFactory.from_scratch(name='lbco')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_1.space_group.name_h_m = 'P m -3 m'\n",
+ "structure_1.space_group.it_coordinate_system_code = '1'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_1.cell.length_a = 3.8909"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_1.atom_sites.create(\n",
+ " label='La',\n",
+ " type_symbol='La',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.2,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "structure_1.atom_sites.create(\n",
+ " label='Ba',\n",
+ " type_symbol='Ba',\n",
+ " fract_x=0,\n",
+ " fract_y=0,\n",
+ " fract_z=0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.2,\n",
+ " occupancy=0.5,\n",
+ ")\n",
+ "structure_1.atom_sites.create(\n",
+ " label='Co',\n",
+ " type_symbol='Co',\n",
+ " fract_x=0.5,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='b',\n",
+ " b_iso=0.2567,\n",
+ ")\n",
+ "structure_1.atom_sites.create(\n",
+ " label='O',\n",
+ " type_symbol='O',\n",
+ " fract_x=0,\n",
+ " fract_y=0.5,\n",
+ " fract_z=0.5,\n",
+ " wyckoff_letter='c',\n",
+ " b_iso=1.4041,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "### Create Structure 2: Si"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_2 = StructureFactory.from_scratch(name='si')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "#### Set Space Group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "14",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_2.space_group.name_h_m = 'F d -3 m'\n",
+ "structure_2.space_group.it_coordinate_system_code = '2'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "#### Set Unit Cell"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_2.cell.length_a = 5.43146"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "#### Set Atom Sites"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_2.atom_sites.create(\n",
+ " label='Si',\n",
+ " type_symbol='Si',\n",
+ " fract_x=0.0,\n",
+ " fract_y=0.0,\n",
+ " fract_z=0.0,\n",
+ " wyckoff_letter='a',\n",
+ " b_iso=0.0,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "## Define Experiment\n",
+ "\n",
+ "This section shows how to add experiments, configure their parameters,\n",
+ "and link the structures defined in the previous step.\n",
+ "\n",
+ "#### Download Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = download_data(id=8, destination='data')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21",
+ "metadata": {},
+ "source": [
+ "#### Create Experiment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment = ExperimentFactory.from_data_path(\n",
+ " name='mcstas',\n",
+ " data_path=data_path,\n",
+ " sample_form='powder',\n",
+ " beam_mode='time-of-flight',\n",
+ " radiation_probe='neutron',\n",
+ " scattering_type='bragg',\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "23",
+ "metadata": {},
+ "source": [
+ "#### Set Instrument"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "24",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.instrument.setup_twotheta_bank = 94.90931761529106\n",
+ "experiment.instrument.calib_d_to_tof_offset = 0.0\n",
+ "experiment.instrument.calib_d_to_tof_linear = 58724.76869981215\n",
+ "experiment.instrument.calib_d_to_tof_quad = -0.00001"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "25",
+ "metadata": {},
+ "source": [
+ "#### Set Peak Profile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "26",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# experiment.peak_profile_type = 'pseudo-voigt * ikeda-carpenter'\n",
+ "experiment.peak.broad_gauss_sigma_0 = 45137\n",
+ "experiment.peak.broad_gauss_sigma_1 = -52394\n",
+ "experiment.peak.broad_gauss_sigma_2 = 22998\n",
+ "experiment.peak.broad_mix_beta_0 = 0.0055\n",
+ "experiment.peak.broad_mix_beta_1 = 0.0041\n",
+ "experiment.peak.asym_alpha_0 = 0\n",
+ "experiment.peak.asym_alpha_1 = 0.0097"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27",
+ "metadata": {},
+ "source": [
+ "#### Set Background"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28",
+ "metadata": {},
+ "source": [
+ "Select the background type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "29",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.background_type = 'line-segment'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "30",
+ "metadata": {},
+ "source": [
+ "Add background points."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.background.create(id='1', x=45000, y=0.2)\n",
+ "experiment.background.create(id='2', x=50000, y=0.2)\n",
+ "experiment.background.create(id='3', x=55000, y=0.2)\n",
+ "experiment.background.create(id='4', x=65000, y=0.2)\n",
+ "experiment.background.create(id='5', x=70000, y=0.2)\n",
+ "experiment.background.create(id='6', x=75000, y=0.2)\n",
+ "experiment.background.create(id='7', x=80000, y=0.2)\n",
+ "experiment.background.create(id='8', x=85000, y=0.2)\n",
+ "experiment.background.create(id='9', x=90000, y=0.2)\n",
+ "experiment.background.create(id='10', x=95000, y=0.2)\n",
+ "experiment.background.create(id='11', x=100000, y=0.2)\n",
+ "experiment.background.create(id='12', x=105000, y=0.2)\n",
+ "experiment.background.create(id='13', x=110000, y=0.2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "32",
+ "metadata": {},
+ "source": [
+ "#### Set Linked Phases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "33",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.linked_phases.create(id='lbco', scale=4.0)\n",
+ "experiment.linked_phases.create(id='si', scale=0.2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "34",
+ "metadata": {},
+ "source": [
+ "## Define Project\n",
+ "\n",
+ "The project object is used to manage structures, experiments, and\n",
+ "analysis.\n",
+ "\n",
+ "#### Create Project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project = Project()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36",
+ "metadata": {},
+ "source": [
+ "#### Add Structures"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.add(structure_1)\n",
+ "project.structures.add(structure_2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "38",
+ "metadata": {},
+ "source": [
+ "#### Show Structures"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "39",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.structures.show_names()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "40",
+ "metadata": {},
+ "source": [
+ "#### Add Experiments"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "41",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments.add(experiment)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "42",
+ "metadata": {},
+ "source": [
+ "#### Set Excluded Regions\n",
+ "\n",
+ "Show measured data as loaded from the file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "43",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas(expt_name='mcstas')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "44",
+ "metadata": {},
+ "source": [
+ "Add excluded regions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.excluded_regions.create(id='1', start=0, end=40000)\n",
+ "experiment.excluded_regions.create(id='2', start=108000, end=200000)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "46",
+ "metadata": {},
+ "source": [
+ "Show excluded regions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.excluded_regions.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48",
+ "metadata": {},
+ "source": [
+ "Show measured data after adding excluded regions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas(expt_name='mcstas')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "50",
+ "metadata": {},
+ "source": [
+ "Show experiment as CIF."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "51",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.experiments['mcstas'].show_as_cif()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52",
+ "metadata": {},
+ "source": [
+ "## Perform Analysis\n",
+ "\n",
+ "This section outlines the analysis process, including how to configure\n",
+ "calculation and fitting engines.\n",
+ "\n",
+ "#### Set Minimizer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "53",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.current_minimizer = 'lmfit'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "54",
+ "metadata": {},
+ "source": [
+ "#### Set Fitting Parameters\n",
+ "\n",
+ "Set structure parameters to be optimized."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "55",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "structure_1.cell.length_a.free = True\n",
+ "structure_1.atom_sites['Co'].b_iso.free = True\n",
+ "structure_1.atom_sites['O'].b_iso.free = True\n",
+ "\n",
+ "structure_2.cell.length_a.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56",
+ "metadata": {},
+ "source": [
+ "Set experiment parameters to be optimized."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "57",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "experiment.linked_phases['lbco'].scale.free = True\n",
+ "experiment.linked_phases['si'].scale.free = True\n",
+ "\n",
+ "experiment.peak.broad_gauss_sigma_0.free = True\n",
+ "experiment.peak.broad_gauss_sigma_1.free = True\n",
+ "experiment.peak.broad_gauss_sigma_2.free = True\n",
+ "\n",
+ "experiment.peak.asym_alpha_1.free = True\n",
+ "experiment.peak.broad_mix_beta_0.free = True\n",
+ "experiment.peak.broad_mix_beta_1.free = True\n",
+ "\n",
+ "for point in experiment.background:\n",
+ " point.y.free = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58",
+ "metadata": {},
+ "source": [
+ "#### Perform Fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "59",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.analysis.fit()\n",
+ "project.analysis.show_fit_results()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "60",
+ "metadata": {},
+ "source": [
+ "#### Plot Measured vs Calculated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "61",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "project.plot_meas_vs_calc(expt_name='mcstas')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "62",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tutorials/ed-9.py b/docs/docs/tutorials/ed-9.py
similarity index 100%
rename from tutorials/ed-9.py
rename to docs/docs/tutorials/ed-9.py
diff --git a/tutorials/index.json b/docs/docs/tutorials/index.json
similarity index 98%
rename from tutorials/index.json
rename to docs/docs/tutorials/index.json
index 138b0e51..d40d1896 100644
--- a/tutorials/index.json
+++ b/docs/docs/tutorials/index.json
@@ -86,7 +86,7 @@
"13": {
"url": "https://easyscience.github.io/diffraction-lib/{version}/tutorials/ed-13/ed-13.ipynb",
"original_name": "dmsc-summer-school-2025_analysis-powder-diffraction",
- "title": "DMSC Summer School 2025: Powder Diffraction Analysis",
+ "title": "DMSC Summer School: Powder Diffraction Analysis",
"description": "Comprehensive workshop tutorial covering Rietveld refinement of Si and La0.5Ba0.5CoO3 using simulated powder diffraction data",
"level": "workshop"
},
diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md
new file mode 100644
index 00000000..5e406e59
--- /dev/null
+++ b/docs/docs/tutorials/index.md
@@ -0,0 +1,95 @@
+---
+icon: material/school
+---
+
+# :material-school: Tutorials
+
+This section presents a collection of **Jupyter Notebook** tutorials
+that demonstrate how to use EasyDiffraction for various tasks. These
+tutorials serve as self-contained, step-by-step **guides** to help users
+grasp the workflow of diffraction data analysis using EasyDiffraction.
+
+Instructions on how to run the tutorials are provided in the
+[:material-cog-box: Installation & Setup](../installation-and-setup/index.md#how-to-run-tutorials)
+section of the documentation.
+
+The tutorials are organized into the following categories.
+
+## Getting Started
+
+- [LBCO `quick` CIF](ed-1.ipynb) – A minimal example intended as a quick
+ reference for users already familiar with the EasyDiffraction API or
+ who want to see how Rietveld refinement of the La0.5Ba0.5CoO3 crystal
+ structure can be performed when both the structure and experiment are
+ loaded from CIF files. Data collected from constant wavelength neutron
+ powder diffraction at HRPT at PSI.
+- [LBCO `quick` `code`](ed-2.ipynb) – A minimal example intended as a
+ quick reference for users already familiar with the EasyDiffraction
+ API or who want to see an example refinement when both the structure
+ and experiment are defined directly in code. This tutorial covers a
+ Rietveld refinement of the La0.5Ba0.5CoO3 crystal structure using
+ constant wavelength neutron powder diffraction data from HRPT at PSI.
+- [LBCO `complete`](ed-3.ipynb) – Demonstrates the use of the
+ EasyDiffraction API in a simplified, user-friendly manner that closely
+ follows the GUI workflow for a Rietveld refinement of the
+ La0.5Ba0.5CoO3 crystal structure using constant wavelength neutron
+ powder diffraction data from HRPT at PSI. This tutorial provides a
+ full explanation of the workflow with detailed comments and
+ descriptions of every step, making it suitable for users who are new
+ to EasyDiffraction or those who prefer a more guided approach.
+
+## Powder Diffraction
+
+- [Co2SiO4 `pd-neut-cwl`](ed-5.ipynb) – Demonstrates a Rietveld
+ refinement of the Co2SiO4 crystal structure using constant wavelength
+ neutron powder diffraction data from D20 at ILL.
+- [HS `pd-neut-cwl`](ed-6.ipynb) – Demonstrates a Rietveld refinement of
+ the HS crystal structure using constant wavelength neutron powder
+ diffraction data from HRPT at PSI.
+- [Si `pd-neut-tof`](ed-7.ipynb) – Demonstrates a Rietveld refinement of
+ the Si crystal structure using time-of-flight neutron powder
+ diffraction data from SEPD at Argonne.
+- [NCAF `pd-neut-tof`](ed-8.ipynb) – Demonstrates a Rietveld refinement
+ of the Na2Ca3Al2F14 crystal structure using two time-of-flight neutron
+ powder diffraction datasets (from two detector banks) of the WISH
+ instrument at ISIS.
+
+## Single Crystal Diffraction
+
+- [Tb2TiO7 `sg-neut-cwl`](ed-14.ipynb) – Demonstrates structure
+ refinement of Tb2TiO7 using constant wavelength neutron single crystal
+ diffraction data from HEiDi at FRM II.
+- [Taurine `sg-neut-tof`](ed-15.ipynb) – Demonstrates structure
+ refinement of Taurine using time-of-flight neutron single crystal
+ diffraction data from SENJU at J-PARC.
+
+## Pair Distribution Function (PDF)
+
+- [Ni `pd-neut-cwl`](ed-10.ipynb) – Demonstrates a PDF analysis of Ni
+ using data collected from a constant wavelength neutron powder
+ diffraction experiment.
+- [Si `pd-neut-tof`](ed-11.ipynb) – Demonstrates a PDF analysis of Si
+ using data collected from a time-of-flight neutron powder diffraction
+ experiment at NOMAD at SNS.
+- [NaCl `pd-xray`](ed-12.ipynb) – Demonstrates a PDF analysis of NaCl
+ using data collected from an X-ray powder diffraction experiment.
+
+## Multi-Structure & Multi-Experiment Refinement
+
+- [PbSO4 NPD+XRD](ed-4.ipynb) – Joint fit of PbSO4 using X-ray and
+ neutron constant wavelength powder diffraction data.
+- [LBCO+Si McStas](ed-9.ipynb) – Multi-phase Rietveld refinement of
+ La0.5Ba0.5CoO3 with Si impurity using time-of-flight neutron data
+ simulated with McStas.
+- [Si Bragg+PDF](ed-16.ipynb) – Joint refinement of Si combining Bragg
+ diffraction (SEPD) and pair distribution function (NOMAD) analysis. A
+ single shared structure is refined simultaneously against both
+ datasets.
+
+## Workshops & Schools
+
+- [DMSC Summer School](ed-13.ipynb) – A workshop tutorial that
+ demonstrates a Rietveld refinement of the La0.5Ba0.5CoO3 crystal
+ structure using time-of-flight neutron powder diffraction data
+ simulated with McStas. This tutorial is designed for the ESS DMSC
+ Summer School.
diff --git a/docs/user-guide/analysis-workflow/analysis.md b/docs/docs/user-guide/analysis-workflow/analysis.md
similarity index 68%
rename from docs/user-guide/analysis-workflow/analysis.md
rename to docs/docs/user-guide/analysis-workflow/analysis.md
index 73086b3b..f0341519 100644
--- a/docs/user-guide/analysis-workflow/analysis.md
+++ b/docs/docs/user-guide/analysis-workflow/analysis.md
@@ -5,57 +5,62 @@ icon: material/calculator
# :material-calculator: Analysis
This section provides an overview of **diffraction data analysis** in
-EasyDiffraction, focusing on model-dependent analysis, calculation engines, and
-minimization techniques.
+EasyDiffraction, focusing on model-dependent analysis, calculation
+engines, and minimization techniques.
-In EasyDiffraction, we focus on **model-dependent analysis**, where a model is
-constructed based on prior knowledge of the studied system, and its parameters
-are optimized to achieve the best agreement between experimental and calculated
-diffraction data. Model-dependent analysis is widely used in neutron and X-ray
-scattering data.
+In EasyDiffraction, we focus on **model-dependent analysis**, where a
+model is constructed based on prior knowledge of the studied system, and
+its parameters are optimized to achieve the best agreement between
+experimental and calculated diffraction data. Model-dependent analysis
+is widely used in neutron and X-ray scattering data.
## Calculation
-EasyDiffraction relies on third-party crystallographic libraries, referred to as
-**calculation engines** or just **calculators**, to perform the calculations.
+EasyDiffraction relies on third-party crystallographic libraries,
+referred to as **calculation engines** or just **calculators**, to
+perform the calculations.
-The calculation engines are used to calculate the diffraction pattern for the
-defined model of the studied structure using the instrumental and other required
-experiment-related parameters, such as the wavelength, resolution, etc.
+The calculation engines are used to calculate the diffraction pattern
+for the defined model of the studied structure using the instrumental
+and other required experiment-related parameters, such as the
+wavelength, resolution, etc.
-You do not necessarily need the measured data to perform the calculations, but
-you need a structural model and some details about the type of experiment you
-want to simulate.
+You do not necessarily need the measured data to perform the
+calculations, but you need a structural model and some details about the
+type of experiment you want to simulate.
-EasyDiffraction is designed as a flexible and extensible tool that supports
-different **calculation engines** for diffraction pattern calculations.
-Currently, we integrate CrysPy, CrysFML, and PDFfit2 libraries as calculation
-engines.
+EasyDiffraction is designed as a flexible and extensible tool that
+supports different **calculation engines** for diffraction pattern
+calculations. Currently, we integrate CrysPy, CrysFML, and PDFfit2
+libraries as calculation engines.
### CrysPy Calculator
-[CrysPy](https://www.cryspy.fr) is a Python library originally developed for
-analysing polarised neutron diffraction data. It is now evolving into a more
-general purpose library and covers powders and single crystals, nuclear and
-(commensurate) magnetic structures, unpolarised neutron and X-ray diffraction.
+[CrysPy](https://www.cryspy.fr) is a Python library originally developed
+for analysing polarised neutron diffraction data. It is now evolving
+into a more general purpose library and covers powders and single
+crystals, nuclear and (commensurate) magnetic structures, unpolarised
+neutron and X-ray diffraction.
### CrysFML Calculator
-[CrysFML](https://code.ill.fr/scientific-software/CrysFML2008) library is a
-collection of Fortran modules for crystallographic computations. It is used in
-the software package [FullProf](https://www.ill.eu/sites/fullprof/), and we are
-currently working on its integration into EasyDiffraction.
+[CrysFML](https://code.ill.fr/scientific-software/CrysFML2008) library
+is a collection of Fortran modules for crystallographic computations. It
+is used in the software package
+[FullProf](https://www.ill.eu/sites/fullprof/), and we are currently
+working on its integration into EasyDiffraction.
### PDFfit2 Calculator
-[PDFfit2](https://github.com/diffpy/diffpy.pdffit2/) is a Python library for
-calculating the pair distribution function (PDF) from crystallographic models.
+[PDFfit2](https://github.com/diffpy/diffpy.pdffit2/) is a Python library
+for calculating the pair distribution function (PDF) from
+crystallographic models.
### Set Calculator
-The calculator is automatically selected based on the experiment type (e.g.,
-`cryspy` for Bragg diffraction, `pdffit` for total scattering). To show the
-supported calculation engines for a specific experiment:
+The calculator is automatically selected based on the experiment type
+(e.g., `cryspy` for Bragg diffraction, `pdffit` for total scattering).
+To show the supported calculation engines for a specific experiment:
```python
project.experiments['hrpt'].show_supported_calculator_types()
@@ -77,9 +82,9 @@ project.experiments['hrpt'].calculator_type = 'cryspy'
## Minimization / Optimization
-The process of refining model parameters involves iterating through multiple
-steps until the calculated data sufficiently matches the experimental data. This
-process is illustrated in the following diagram:
+The process of refining model parameters involves iterating through
+multiple steps until the calculated data sufficiently matches the
+experimental data. This process is illustrated in the following diagram:
```mermaid
flowchart LR
@@ -95,31 +100,34 @@ flowchart LR
d-- Threshold reached -->e
```
-Like the calculation engines, EasyDiffraction is designed to utilize various
-third-party libraries for model refinement and parameter optimization. These
-libraries provide robust curve fitting and uncertainty estimation tools.
+Like the calculation engines, EasyDiffraction is designed to utilize
+various third-party libraries for model refinement and parameter
+optimization. These libraries provide robust curve fitting and
+uncertainty estimation tools.
### Lmfit Minimizer
Most of the examples in this section will use the
-[lmfit](https://lmfit.github.io/lmfit-py/) package, which provides a high-level
-interface to non-linear optimisation and curve fitting problems for Python. It
-is one of the tools that can be used to fit models to the experimental data.
+[lmfit](https://lmfit.github.io/lmfit-py/) package, which provides a
+high-level interface to non-linear optimisation and curve fitting
+problems for Python. It is one of the tools that can be used to fit
+models to the experimental data.
### Bumps Minimizer
Another package that can be used for the same purpose is
-[bumps](https://bumps.readthedocs.io/en/latest/). In addition to traditional
-optimizers which search for the best minimum they can find in the search space,
-bumps provides Bayesian uncertainty analysis which explores all viable minima
-and finds confidence intervals on the parameters based on uncertainty in the
-measured values.
+[bumps](https://bumps.readthedocs.io/en/latest/). In addition to
+traditional optimizers which search for the best minimum they can find
+in the search space, bumps provides Bayesian uncertainty analysis which
+explores all viable minima and finds confidence intervals on the
+parameters based on uncertainty in the measured values.
### DFO-LS Minimizer
-[DFO-LS](https://github.com/numericalalgorithmsgroup/dfols) (Derivative-Free
-Optimizer for Least-Squares) is a Python library for solving nonlinear
-least-squares minimization, without requiring derivatives of the objective.
+[DFO-LS](https://github.com/numericalalgorithmsgroup/dfols)
+(Derivative-Free Optimizer for Least-Squares) is a Python library for
+solving nonlinear least-squares minimization, without requiring
+derivatives of the objective.
### Set Minimizer
@@ -148,9 +156,10 @@ project.analysis.current_minimizer = 'lmfit'
### Fit Mode
-In EasyDiffraction, you can set the **fit mode** to control how the refinement
-process is performed. The fit mode determines whether the refinement is
-performed independently for each experiment or jointly across all experiments.
+In EasyDiffraction, you can set the **fit mode** to control how the
+refinement process is performed. The fit mode determines whether the
+refinement is performed independently for each experiment or jointly
+across all experiments.
The supported fit modes are:
@@ -173,14 +182,14 @@ print(project.analysis.fit_mode.mode.value)
### Perform Fit
-Refining the structure and experiment parameters against measured data is
-usually divided into several steps, where each step involves adding or removing
-parameters to be refined, calculating the model data, and comparing it to the
-experimental data as shown in the diagram above.
+Refining the structure and experiment parameters against measured data
+is usually divided into several steps, where each step involves adding
+or removing parameters to be refined, calculating the model data, and
+comparing it to the experimental data as shown in the diagram above.
-To select the parameters to be refined, you can set the attribute `free` of the
-parameters to `True`. This indicates that the parameter is free to be optimized
-during the refinement process.
+To select the parameters to be refined, you can set the attribute `free`
+of the parameters to `True`. This indicates that the parameter is free
+to be optimized during the refinement process.
Here is an example of how to set parameters to be refined:
@@ -195,15 +204,16 @@ project.experiments['hrpt'].background['10'].y.free = True
project.experiments['hrpt'].background['165'].y.free = True
```
-After setting the parameters to be refined, you can perform the fit using the
-`fit` method of the `analysis` object:
+After setting the parameters to be refined, you can perform the fit
+using the `fit` method of the `analysis` object:
```python
project.analysis.fit()
```
-This method will iterate through the defined steps, adjusting the parameters
-until the calculated data sufficiently matches the experimental data.
+This method will iterate through the defined steps, adjusting the
+parameters until the calculated data sufficiently matches the
+experimental data.
An example of the output after performing the fit is:
@@ -233,9 +243,9 @@ Fit results
📈 Fitted parameters:
```
-Now, you can inspect the fitted parameters to see how they have changed during
-the refinement process, select more parameters to be refined, and perform
-additional fits as needed.
+Now, you can inspect the fitted parameters to see how they have changed
+during the refinement process, select more parameters to be refined, and
+perform additional fits as needed.
To plot the measured vs calculated data after the fit, you can use the
`plot_meas_vs_calc` method of the `analysis` object:
@@ -246,16 +256,16 @@ project.plot_meas_vs_calc(expt_name='hrpt', show_residual=True)
## Constraints
-In EasyDiffraction, you can define **constraints** on the model parameters to
-ensure that they remain within a specific range or follow a certain relationship
-during the refinement process.
+In EasyDiffraction, you can define **constraints** on the model
+parameters to ensure that they remain within a specific range or follow
+a certain relationship during the refinement process.
### Setting Aliases
-Before setting constraints, you need to set aliases for the parameters you want
-to constrain. This can be done using the `add` method of the `aliases` object.
-Aliases are used to reference parameters in a more readable way, making it
-easier to manage constraints.
+Before setting constraints, you need to set aliases for the parameters
+you want to constrain. This can be done using the `add` method of the
+`aliases` object. Aliases are used to reference parameters in a more
+readable way, making it easier to manage constraints.
An example of setting aliases for parameters in a structure:
@@ -283,11 +293,11 @@ project.analysis.aliases.create(
### Setting Constraints
-Now that you have set the aliases, you can define constraints using the `add`
-method of the `constraints` object. Constraints are defined by specifying the
-**left-hand side (lhs) alias** and the **right-hand side (rhs) expression**. The
-rhs expression can be a simple alias or a more complex expression involving
-other aliases.
+Now that you have set the aliases, you can define constraints using the
+`add` method of the `constraints` object. Constraints are defined by
+specifying the **left-hand side (lhs) alias** and the **right-hand side
+(rhs) expression**. The rhs expression can be a simple alias or a more
+complex expression involving other aliases.
An example of setting constraints for the aliases defined above:
@@ -303,15 +313,16 @@ project.analysis.constraints.create(
)
```
-These constraints ensure that the `biso_Ba` parameter is equal to `biso_La`, and
-the `occ_Ba` parameter is equal to `1 - occ_La`. This means that the occupancy
-of the Ba atom will always be adjusted based on the occupancy of the La atom,
-and the isotropic displacement parameter for Ba will be equal to that of La
-during the refinement process.
+These constraints ensure that the `biso_Ba` parameter is equal to
+`biso_La`, and the `occ_Ba` parameter is equal to `1 - occ_La`. This
+means that the occupancy of the Ba atom will always be adjusted based on
+the occupancy of the La atom, and the isotropic displacement parameter
+for Ba will be equal to that of La during the refinement process.
### Viewing Constraints
-To view the defined constraints, you can use the `show_constraints` method:
+To view the defined constraints, you can use the `show_constraints`
+method:
```python
project.analysis.show_constraints()
@@ -361,8 +372,9 @@ Example output:
## Saving an Analysis
-Saving the project, as described in the [Project](project.md) section, will also
-save the analysis settings to the `analysis.cif` inside the project directory.
+Saving the project, as described in the [Project](project.md) section,
+will also save the analysis settings to the `analysis.cif` inside the
+project directory.
diff --git a/docs/user-guide/analysis-workflow/experiment.md b/docs/docs/user-guide/analysis-workflow/experiment.md
similarity index 84%
rename from docs/user-guide/analysis-workflow/experiment.md
rename to docs/docs/user-guide/analysis-workflow/experiment.md
index a62d9822..c121d6a9 100644
--- a/docs/user-guide/analysis-workflow/experiment.md
+++ b/docs/docs/user-guide/analysis-workflow/experiment.md
@@ -4,10 +4,10 @@ icon: material/microscope
# :material-microscope: Experiment
-An **Experiment** in EasyDiffraction includes the measured diffraction data
-along with all relevant parameters that describe the experimental setup and
-associated conditions. This can include information about the instrumental
-resolution, peak shape, background, etc.
+An **Experiment** in EasyDiffraction includes the measured diffraction
+data along with all relevant parameters that describe the experimental
+setup and associated conditions. This can include information about the
+instrumental resolution, peak shape, background, etc.
## Defining an Experiment
@@ -15,23 +15,26 @@ EasyDiffraction allows you to:
- **Load an existing experiment** from a file (**CIF** format). Both the
metadata and measured data are expected to be in CIF format.
-- **Manually define** a new experiment by specifying its type, other necessary
- experimental parameters, as well as load measured data. This is useful when
- you want to create an experiment from scratch or when you have a measured data
- file in a non-CIF format (e.g., `.xye`, `.xy`).
-
-Below, you will find instructions on how to define and manage experiments in
-EasyDiffraction. It is assumed that you have already created a `project` object,
-as described in the [Project](project.md) section as well as defined its
-`structures`, as described in the [Structure](model.md) section.
+- **Manually define** a new experiment by specifying its type, other
+ necessary experimental parameters, as well as load measured data. This
+ is useful when you want to create an experiment from scratch or when
+ you have a measured data file in a non-CIF format (e.g., `.xye`,
+ `.xy`).
+
+Below, you will find instructions on how to define and manage
+experiments in EasyDiffraction. It is assumed that you have already
+created a `project` object, as described in the [Project](project.md)
+section as well as defined its `structures`, as described in the
+[Structure](model.md) section.
### Adding from CIF
-This is the most straightforward way to define an experiment in EasyDiffraction.
-If you have a crystallographic information file (CIF) for your experiment, that
-contains both the necessary information (metadata) about the experiment as well
-as the measured data, you can add it to your `project.experiments` collection
-using the `add_from_cif_path` method. In this case, the name of the experiment
+This is the most straightforward way to define an experiment in
+EasyDiffraction. If you have a crystallographic information file (CIF)
+for your experiment, that contains both the necessary information
+(metadata) about the experiment as well as the measured data, you can
+add it to your `project.experiments` collection using the
+`add_from_cif_path` method. In this case, the name of the experiment
will be taken from CIF.
```python
@@ -51,9 +54,9 @@ project.experiments.add_from_cif_str(cif_string)
```
Accessing the experiment after adding it will also be done through the
-`experiments` object of the `project` instance. The name of the experiment will
-be the same as the data block id in the CIF file. For example, if the CIF file
-contains a data block with the id `hrpt`,
+`experiments` object of the `project` instance. The name of the
+experiment will be the same as the data block id in the CIF file. For
+example, if the CIF file contains a data block with the id `hrpt`,
@@ -77,20 +80,22 @@ project.experiments['hrpt']
### Defining Manually
-If you do not have a CIF file or prefer to define the experiment manually, you
-can use the `add_from_data_path` method of the `experiments` object of the
-`project` instance. In this case, you will need to specify the **name** of the
-experiment, which will be used to reference it later, as well as **data_path**
-to the measured data file (e.g., `.xye`, `.xy`). Supported formats are described
-in the [Measured Data Category](#5-measured-data-category) section.
+If you do not have a CIF file or prefer to define the experiment
+manually, you can use the `add_from_data_path` method of the
+`experiments` object of the `project` instance. In this case, you will
+need to specify the **name** of the experiment, which will be used to
+reference it later, as well as **data_path** to the measured data file
+(e.g., `.xye`, `.xy`). Supported formats are described in the
+[Measured Data Category](#measured-data-category) section.
-Optionally, you can also specify the additional parameters that define the
-**type of experiment** you want to create. If you do not specify any of these
-parameters, the default values will be used, which are the first in the list of
-supported options for each parameter:
+Optionally, you can also specify the additional parameters that define
+the **type of experiment** you want to create. If you do not specify any
+of these parameters, the default values will be used, which are the
+first in the list of supported options for each parameter:
- **sample_form**: The form of the sample (powder, single crystal).
-- **beam_mode**: The mode of the beam (constant wavelength, time-of-flight).
+- **beam_mode**: The mode of the beam (constant wavelength,
+ time-of-flight).
- **radiation_probe**: The type of radiation used (neutron, X-ray).
- **scattering_type**: The type of scattering (bragg, total).
@@ -100,8 +105,8 @@ supported options for each parameter:
these parameters. If you need to change them, you must create a new experiment
or redefine the existing one.
-Here is an example of how to add an experiment with all relevant components
-explicitly defined:
+Here is an example of how to add an experiment with all relevant
+components explicitly defined:
```python
# Add an experiment with default parameters, based on the specified type.
@@ -125,9 +130,9 @@ project.experiments.add_from_data_path(
)
```
-If you do not have measured data for fitting and only want to view the simulated
-pattern, you can define an experiment without measured data using the `create`
-method:
+If you do not have measured data for fitting and only want to view the
+simulated pattern, you can define an experiment without measured data
+using the `create` method:
```python
# Add an experiment without measured data
@@ -159,23 +164,24 @@ project.experiments.add(experiment)
## Modifying Parameters
-When an experiment is added, it is created with a set of default parameters that
-you can modify to match your specific experimental setup. All parameters are
-grouped into categories based on their function, making it easier to manage and
-understand the different aspects of the experiment:
-
-1. **Instrument Category**: Defines the instrument configuration, including
- wavelength, two-theta offset, and resolution parameters.
-2. **Peak Category**: Specifies the peak profile type and its parameters, such
- as broadening and asymmetry.
-3. **Background Category**: Defines the background type and allows you to add
- background points.
-4. **Linked Phases Category**: Links the structure defined in the previous step
- to the experiment, allowing you to specify the scale factor for the linked
- phase.
-5. **Measured Data Category**: Contains the measured data. The expected format
- depends on the experiment type, but generally includes columns for 2θ angle
- or TOF and intensity.
+When an experiment is added, it is created with a set of default
+parameters that you can modify to match your specific experimental
+setup. All parameters are grouped into categories based on their
+function, making it easier to manage and understand the different
+aspects of the experiment:
+
+1. **Instrument Category**: Defines the instrument configuration,
+ including wavelength, two-theta offset, and resolution parameters.
+2. **Peak Category**: Specifies the peak profile type and its
+ parameters, such as broadening and asymmetry.
+3. **Background Category**: Defines the background type and allows you
+ to add background points.
+4. **Linked Phases Category**: Links the structure defined in the
+ previous step to the experiment, allowing you to specify the scale
+ factor for the linked phase.
+5. **Measured Data Category**: Contains the measured data. The expected
+ format depends on the experiment type, but generally includes columns
+ for 2θ angle or TOF and intensity.
### 1. Instrument Category { #instrument-category }
@@ -230,10 +236,10 @@ project.experiments['hrpt'].linked_phases.create(id='lbco', scale=10.0)
### 6. Measured Data Category { #measured-data-category }
-If you do not have a CIF file for your experiment, you can load measured data
-from a file in a supported format. The measured data will be automatically
-converted into CIF format and added to the experiment. The expected format
-depends on the experiment type.
+If you do not have a CIF file for your experiment, you can load measured
+data from a file in a supported format. The measured data will be
+automatically converted into CIF format and added to the experiment. The
+expected format depends on the experiment type.
#### Supported data file formats:
@@ -245,8 +251,8 @@ depends on the experiment type.
- [\_pd_meas.2theta_scan](../parameters/pd_meas.md)
- [\_pd_meas.intensity_total](../parameters/pd_meas.md)
-If no **standard deviations** are provided, they are automatically calculated as
-the **square root** of measured intensities.
+If no **standard deviations** are provided, they are automatically
+calculated as the **square root** of measured intensities.
Optional comments with `#` are possible in data file headers.
@@ -602,5 +608,5 @@ loop_
---
-Now that the experiment has been defined, you can proceed to the next step:
-[Analysis](analysis.md).
+Now that the experiment has been defined, you can proceed to the next
+step: [Analysis](analysis.md).
diff --git a/docs/docs/user-guide/analysis-workflow/index.md b/docs/docs/user-guide/analysis-workflow/index.md
new file mode 100644
index 00000000..84598210
--- /dev/null
+++ b/docs/docs/user-guide/analysis-workflow/index.md
@@ -0,0 +1,37 @@
+# Analysis Workflow
+
+To streamline the **data analysis process**, EasyDiffraction follows a
+structured workflow divided into **five key steps**:
+
+```mermaid
+flowchart LR
+ a(Project)
+ b(Model)
+ c(Experiment)
+ d(Analysis)
+ e(Summary)
+ a --> b
+ b --> c
+ c --> d
+ d --> e
+```
+
+- [:material-archive: Project](project.md) – Establish a **project** as
+ a container for structure and experiment parameters, measured and
+ calculated data, analysis settings and results.
+- [:material-puzzle: Structure](model.md) – Load an existing
+ **crystallographic model** in CIF format or define a new one from
+ scratch.
+- [:material-microscope: Experiment](experiment.md) – Import
+ **experimental diffraction data** and configure **instrumental** and
+ other relevant parameters.
+- [:material-calculator: Analysis](analysis.md) – **Calculate the
+ diffraction pattern** and **optimize the structural model** by
+ refining its parameters to match experimental measurements.
+- [:material-clipboard-text: Summary](summary.md) – Generate a
+ **report** summarizing the results of the analysis, including refined
+ parameters.
+
+Each step is described in detail in its respective section, guiding
+users through the **entire diffraction data analysis workflow** in
+EasyDiffraction.
diff --git a/docs/user-guide/analysis-workflow/model.md b/docs/docs/user-guide/analysis-workflow/model.md
similarity index 77%
rename from docs/user-guide/analysis-workflow/model.md
rename to docs/docs/user-guide/analysis-workflow/model.md
index c437ea62..95e309cd 100644
--- a/docs/user-guide/analysis-workflow/model.md
+++ b/docs/docs/user-guide/analysis-workflow/model.md
@@ -5,35 +5,38 @@ icon: material/puzzle
# :material-puzzle: Structure
The **Structure** in EasyDiffraction represents the **crystallographic
-structure** used to calculate the diffraction pattern, which is then fitted to
-the **experimentally measured data** to refine the structural parameters.
+structure** used to calculate the diffraction pattern, which is then
+fitted to the **experimentally measured data** to refine the structural
+parameters.
EasyDiffraction allows you to:
- **Load an existing model** from a file (**CIF** format).
-- **Manually define** a new structure by specifying crystallographic parameters.
+- **Manually define** a new structure by specifying crystallographic
+ parameters.
-Below, you will find instructions on how to define and manage crystallographic
-models in EasyDiffraction. It is assumed that you have already created a
-`project` object, as described in the [Project](project.md) section.
+Below, you will find instructions on how to define and manage
+crystallographic models in EasyDiffraction. It is assumed that you have
+already created a `project` object, as described in the
+[Project](project.md) section.
## Adding a Model from CIF
-This is the most straightforward way to define a structure in EasyDiffraction.
-If you have a crystallographic information file (CIF) for your structure, you
-can add it to your project using the `add_from_cif_path` method of the
-`project.structures` collection. In this case, the name of the model will be
-taken from CIF.
+This is the most straightforward way to define a structure in
+EasyDiffraction. If you have a crystallographic information file (CIF)
+for your structure, you can add it to your project using the
+`add_from_cif_path` method of the `project.structures` collection. In
+this case, the name of the model will be taken from CIF.
```python
# Load a phase from a CIF file
project.structures.add_from_cif_path('data/lbco.cif')
```
-Accessing the model after loading it will be done through the `structures`
-collection of the `project` instance. The name of the model will be the same as
-the data block id in the CIF file. For example, if the CIF file contains a data
-block with the id `lbco`,
+Accessing the model after loading it will be done through the
+`structures` collection of the `project` instance. The name of the model
+will be the same as the data block id in the CIF file. For example, if
+the CIF file contains a data block with the id `lbco`,
@@ -57,10 +60,10 @@ project.structures['lbco']
## Defining a Model Manually
-If you do not have a CIF file or prefer to define the model manually, you can
-use the `create` method of the `structures` object of the `project` instance. In
-this case, you will need to specify the name of the model, which will be used to
-reference it later.
+If you do not have a CIF file or prefer to define the model manually,
+you can use the `create` method of the `structures` object of the
+`project` instance. In this case, you will need to specify the name of
+the model, which will be used to reference it later.
```python
# Add a structure with default parameters
@@ -68,15 +71,17 @@ reference it later.
project.structures.create(name='nacl')
```
-The `add` method creates a new structure with default parameters. You can then
-modify its parameters to match your specific crystallographic structure. All
-parameters are grouped into the following categories, which makes it easier to
-manage the model:
+The `add` method creates a new structure with default parameters. You
+can then modify its parameters to match your specific crystallographic
+structure. All parameters are grouped into the following categories,
+which makes it easier to manage the model:
-1. **Space Group Category**: Defines the symmetry of the crystal structure.
-2. **Cell Category**: Specifies the dimensions and angles of the unit cell.
-3. **Atom Sites Category**: Describes the positions and properties of atoms
- within the unit cell.
+1. **Space Group Category**: Defines the symmetry of the crystal
+ structure.
+2. **Cell Category**: Specifies the dimensions and angles of the unit
+ cell.
+3. **Atom Sites Category**: Describes the positions and properties of
+ atoms within the unit cell.
### 1. Space Group Category { #space-group-category }
@@ -177,10 +182,10 @@ Structure 🧩 'lbco' as cif
## Saving a Model
-Saving the project, as described in the [Project](project.md) section, will also
-save the model. Each model is saved as a separate CIF file in the `structures`
-subdirectory of the project directory. The project file contains references to
-these files.
+Saving the project, as described in the [Project](project.md) section,
+will also save the model. Each model is saved as a separate CIF file in
+the `structures` subdirectory of the project directory. The project file
+contains references to these files.
Below is an example of the saved CIF file for the `lbco` model:
@@ -223,5 +228,5 @@ O O 0 0.5 0.5 c 1 Biso 1.4041
---
-Now that the crystallographic model has been defined and added to the project,
-you can proceed to the next step: [Experiment](experiment.md).
+Now that the crystallographic model has been defined and added to the
+project, you can proceed to the next step: [Experiment](experiment.md).
diff --git a/docs/user-guide/analysis-workflow/project.md b/docs/docs/user-guide/analysis-workflow/project.md
similarity index 85%
rename from docs/user-guide/analysis-workflow/project.md
rename to docs/docs/user-guide/analysis-workflow/project.md
index 45e1d9c5..ad41f852 100644
--- a/docs/user-guide/analysis-workflow/project.md
+++ b/docs/docs/user-guide/analysis-workflow/project.md
@@ -4,25 +4,26 @@ icon: material/archive
# :material-archive: Project
-The **Project** serves as a container for all data and metadata associated with
-a particular data analysis task. It acts as the top-level entity in
-EasyDiffraction, ensuring structured organization and easy access to relevant
-information. Each project can contain multiple **experimental datasets**, with
-each dataset containing contribution from multiple **structures**.
+The **Project** serves as a container for all data and metadata
+associated with a particular data analysis task. It acts as the
+top-level entity in EasyDiffraction, ensuring structured organization
+and easy access to relevant information. Each project can contain
+multiple **experimental datasets**, with each dataset containing
+contribution from multiple **structures**.
EasyDiffraction allows you to:
- **Manually create** a new project by specifying its metadata.
- **Load an existing project** from a file (**CIF** format).
-Below are instructions on how to set up a project in EasyDiffraction. It is
-assumed that you have already imported the `easydiffraction` package, as
-described in the [First Steps](../first-steps.md) section.
+Below are instructions on how to set up a project in EasyDiffraction. It
+is assumed that you have already imported the `easydiffraction` package,
+as described in the [First Steps](../first-steps.md) section.
## Creating a Project Manually
-You can manually create a new project and specify its short **name**, **title**
-and **description**. All these parameters are optional.
+You can manually create a new project and specify its short **name**,
+**title** and **description**. All these parameters are optional.
```py
# Create a new project
@@ -44,10 +45,11 @@ Saving the initial project requires specifying the directory path:
project.save_as(dir_path='lbco_hrpt')
```
-If working in the interactive mode in a Jupyter notebook or similar environment,
-you can also save the project after every significant change. This is useful for
-keeping track of changes and ensuring that your work is not lost. If you already
-saved the project with `save_as`, you can just call the `save`:
+If working in the interactive mode in a Jupyter notebook or similar
+environment, you can also save the project after every significant
+change. This is useful for keeping track of changes and ensuring that
+your work is not lost. If you already saved the project with `save_as`,
+you can just call the `save`:
```python
project.save()
@@ -55,8 +57,9 @@ project.save()
## Loading a Project from CIF
-If you have an existing project, you can load it directly from a CIF file. This
-is useful for reusing previously defined projects or sharing them with others.
+If you have an existing project, you can load it directly from a CIF
+file. This is useful for reusing previously defined projects or sharing
+them with others.
```python
project.load('data/lbco_hrpt.cif')
@@ -89,8 +92,8 @@ The example below illustrates a typical **project structure** for a
## Project Files
-Below is a complete project example stored in the `La0.5Ba0.5CoO3` directory,
-showing the contents of all files in the project.
+Below is a complete project example stored in the `La0.5Ba0.5CoO3`
+directory, showing the contents of all files in the project.
!!! warning "Important"
@@ -101,8 +104,8 @@ showing the contents of all files in the project.
### 1. project.cif
-This file provides an overview of the project, including file names of the
-**structures** and **experiments** associated with the project.
+This file provides an overview of the project, including file names of
+the **structures** and **experiments** associated with the project.
@@ -127,9 +130,9 @@ hrpt.cif
### 2. structures / lbco.cif
-This file contains crystallographic information associated with the structure
-model, including **space group**, **unit cell parameters**, and **atomic
-positions**.
+This file contains crystallographic information associated with the
+structure model, including **space group**, **unit cell parameters**,
+and **atomic positions**.
@@ -168,9 +171,9 @@ O O 0 0.5 0.5 c 1 Biso 1.4041
### 3. experiments / hrpt.cif
-This file contains the **experiment type**, **instrumental parameters**, **peak
-parameters**, **associated phases**, **background parameters** and **measured
-diffraction data**.
+This file contains the **experiment type**, **instrumental parameters**,
+**peak parameters**, **associated phases**, **background parameters**
+and **measured diffraction data**.
@@ -236,8 +239,8 @@ loop_
### 4. analysis.cif
-This file contains settings used for data analysis, including the choice of
-**calculation** and **fitting** engines, as well as user defined
+This file contains settings used for data analysis, including the choice
+of **calculation** and **fitting** engines, as well as user defined
**constraints**.
diff --git a/docs/user-guide/analysis-workflow/summary.md b/docs/docs/user-guide/analysis-workflow/summary.md
similarity index 72%
rename from docs/user-guide/analysis-workflow/summary.md
rename to docs/docs/user-guide/analysis-workflow/summary.md
index 4790f857..34a89b61 100644
--- a/docs/user-guide/analysis-workflow/summary.md
+++ b/docs/docs/user-guide/analysis-workflow/summary.md
@@ -5,20 +5,20 @@ icon: material/clipboard-text
# :material-clipboard-text: Summary
The **Summary** section represents the final step in the data processing
-workflow. It involves generating a **summary report** that consolidates the
-results of the diffraction data analysis, providing a comprehensive overview of
-the model refinement process and its outcomes.
+workflow. It involves generating a **summary report** that consolidates
+the results of the diffraction data analysis, providing a comprehensive
+overview of the model refinement process and its outcomes.
## Contents of the Summary Report
The summary report includes key details such as:
-- Final refined model parameters – Optimized crystallographic and instrumental
- parameters.
-- Goodness-of-fit indicators – Metrics such as R-factors, chi-square (χ²), and
- residuals.
-- Graphical representation – Visualization of experimental vs. calculated
- diffraction patterns.
+- Final refined model parameters – Optimized crystallographic and
+ instrumental parameters.
+- Goodness-of-fit indicators – Metrics such as R-factors, chi-square
+ (χ²), and residuals.
+- Graphical representation – Visualization of experimental vs.
+ calculated diffraction patterns.
## Viewing the Summary Report
@@ -36,8 +36,9 @@ including model parameters, fit statistics, and data visualizations.
## Saving a Summary
-Saving the project, as described in the [Project](project.md) section, will also
-save the summary report to the `summary.cif` inside the project directory.
+Saving the project, as described in the [Project](project.md) section,
+will also save the summary report to the `summary.cif` inside the
+project directory.
{ width="450", loading=lazy }
@@ -42,10 +43,10 @@ Credits: DOI 10.1126/science.1238932
## Data Reduction
-Data reduction involves processing the raw data to remove background noise,
-correct for instrumental effects, and convert the data into a more usable
-format. The goal is to produce a clean and reliable dataset suitable for
-analysis.
+Data reduction involves processing the raw data to remove background
+noise, correct for instrumental effects, and convert the data into a
+more usable format. The goal is to produce a clean and reliable dataset
+suitable for analysis.
{ width="450", loading=lazy }
@@ -57,28 +58,32 @@ Credits: DOI 10.1126/science.1238932
## Data Analysis
-Data analysis uses the reduced data to extract meaningful information about the
-crystallographic structure. This may include determining the crystal or magnetic
-structure, identifying phases, performing quantitative analysis, etc.
-
-Analysis often involves comparing experimental data with data calculated from a
-crystallographic model to validate and interpret the results. For powder
-diffraction, techniques such as Rietveld or Le Bail refinement may be used.
-
-In EasyDiffraction, we focus on this **model-dependent analysis**. A model is
-built using prior knowledge of the system, and its parameters are optimized to
-achieve the best agreement between experimental and calculated diffraction data.
-
-By "model", we usually refer to a **crystallographic model** of the sample. This
-includes unit cell parameters, space group, atomic positions, thermal
-parameters, and more. However, the term "model" also encompasses experimental
-aspects such as instrumental resolution, background, peak shape, etc. Therefore,
-EasyDiffraction separates the model into two parts: the **structure** and the
-**experiment**.
-
-The aim of data analysis is to refine the structural parameters of the sample by
-minimizing the difference (or **residual**) between the experimental and
-calculated data — and this is exactly where EasyDiffraction comes into play.
+Data analysis uses the reduced data to extract meaningful information
+about the crystallographic structure. This may include determining the
+crystal or magnetic structure, identifying phases, performing
+quantitative analysis, etc.
+
+Analysis often involves comparing experimental data with data calculated
+from a crystallographic model to validate and interpret the results. For
+powder diffraction, techniques such as Rietveld or Le Bail refinement
+may be used.
+
+In EasyDiffraction, we focus on this **model-dependent analysis**. A
+model is built using prior knowledge of the system, and its parameters
+are optimized to achieve the best agreement between experimental and
+calculated diffraction data.
+
+By "model", we usually refer to a **crystallographic model** of the
+sample. This includes unit cell parameters, space group, atomic
+positions, thermal parameters, and more. However, the term "model" also
+encompasses experimental aspects such as instrumental resolution,
+background, peak shape, etc. Therefore, EasyDiffraction separates the
+model into two parts: the **structure** and the **experiment**.
+
+The aim of data analysis is to refine the structural parameters of the
+sample by minimizing the difference (or **residual**) between the
+experimental and calculated data — and this is exactly where
+EasyDiffraction comes into play.
{ width="450", loading=lazy }
diff --git a/docs/user-guide/data-format.md b/docs/docs/user-guide/data-format.md
similarity index 76%
rename from docs/user-guide/data-format.md
rename to docs/docs/user-guide/data-format.md
index 63e2e52e..da7c92b1 100644
--- a/docs/user-guide/data-format.md
+++ b/docs/docs/user-guide/data-format.md
@@ -1,46 +1,48 @@
# Data Format
-Before starting the data analysis workflow, it is important to define the **data
-formats** used in EasyDiffraction.
+Before starting the data analysis workflow, it is important to define
+the **data formats** used in EasyDiffraction.
## Crystallographic Information File
-Each software package typically uses its own **data format** and **parameter
-names** for storing and sharing data. In EasyDiffraction, we use the
-**Crystallographic Information File (CIF)** format, which is widely used in
-crystallography and materials science. It provides both a human-readable syntax
-and a set of dictionaries that define the meaning of each parameter.
+Each software package typically uses its own **data format** and
+**parameter names** for storing and sharing data. In EasyDiffraction, we
+use the **Crystallographic Information File (CIF)** format, which is
+widely used in crystallography and materials science. It provides both a
+human-readable syntax and a set of dictionaries that define the meaning
+of each parameter.
These dictionaries are maintained by the
[International Union of Crystallography (IUCr)](https://www.iucr.org).
The base dictionary, **coreCIF**, contains the most common parameters in
-crystallography. The **pdCIF** dictionary covers parameters specific to powder
-diffraction, **magCIF** is used for magnetic structure analysis.
+crystallography. The **pdCIF** dictionary covers parameters specific to
+powder diffraction, **magCIF** is used for magnetic structure analysis.
-As most parameters needed for diffraction data analysis are already covered by
-IUCr dictionaries, EasyDiffraction uses the strict **CIF format** and follows
-these dictionaries as closely as possible — for both input and output —
-throughout the workflow described in the
+As most parameters needed for diffraction data analysis are already
+covered by IUCr dictionaries, EasyDiffraction uses the strict **CIF
+format** and follows these dictionaries as closely as possible — for
+both input and output — throughout the workflow described in the
[Analysis Workflow](analysis-workflow/index.md) section.
The key advantage of CIF is the standardized naming of parameters and
-categories, which promotes interoperability and familiarity among researchers.
+categories, which promotes interoperability and familiarity among
+researchers.
If a required parameter is not defined in the standard dictionaries,
EasyDiffraction introduces **custom CIF keywords**, documented in the
-[Parameters](parameters.md) section under the **CIF name for serialization**
-columns.
+[Parameters](parameters.md) section under the **CIF name for
+serialization** columns.
## Format Comparison
-Below, we compare **CIF** with another common data format in programming:
-**JSON**.
+Below, we compare **CIF** with another common data format in
+programming: **JSON**.
### Scientific Journals
Let's assume the following structural data for La₀.₅Ba₀.₅CoO₃ (LBCO), as
-reported in a scientific publication. These parameters are to be refined during
-diffraction data analysis:
+reported in a scientific publication. These parameters are to be refined
+during diffraction data analysis:
Table 1. Crystallographic data. Space group: _Pm3̅m_.
@@ -53,8 +55,8 @@ Table 1. Crystallographic data. Space group: _Pm3̅m_.
| beta | 90.0 |
| gamma | 90.0 |
-Table 2. Atomic coordinates (_x_, _y_, _z_), occupancies (occ) and isotropic
-displacement parameters (_Biso_)
+Table 2. Atomic coordinates (_x_, _y_, _z_), occupancies (occ) and
+isotropic displacement parameters (_Biso_)
| Label | Type | x | y | z | occ | Biso |
| ----- | ---- | --- | --- | --- | --- | ------ |
@@ -102,17 +104,17 @@ O O 0 0.5 0.5 c 1 Biso 1.4041
-Here, unit cell parameters are grouped under the `_cell` category, and atomic
-positions under the `_atom_site` category. The `loop_` keyword indicates that
-multiple rows follow for the listed parameters. Each atom is identified using
-`_atom_site.label`.
+Here, unit cell parameters are grouped under the `_cell` category, and
+atomic positions under the `_atom_site` category. The `loop_` keyword
+indicates that multiple rows follow for the listed parameters. Each atom
+is identified using `_atom_site.label`.
### JSON
-Representing the same data in **JSON** results in a format that is more verbose
-and less human-readable, especially for large datasets. JSON is ideal for
-structured data in programming environments, whereas CIF is better suited for
-human-readable crystallographic data.
+Representing the same data in **JSON** results in a format that is more
+verbose and less human-readable, especially for large datasets. JSON is
+ideal for structured data in programming environments, whereas CIF is
+better suited for human-readable crystallographic data.
```json
{
@@ -173,11 +175,11 @@ human-readable crystallographic data.
## Experiment Definition
-The previous example described the **structure** (crystallographic model), but
-how is the **experiment** itself represented?
+The previous example described the **structure** (crystallographic
+model), but how is the **experiment** itself represented?
-The experiment is also saved as a CIF file. For example, background intensity in
-a powder diffraction experiment might be represented as:
+The experiment is also saved as a CIF file. For example, background
+intensity in a powder diffraction experiment might be represented as:
@@ -197,13 +199,13 @@ loop_
-More details on how to define the experiment in CIF format are provided in the
-[Experiment](analysis-workflow/experiment.md) section.
+More details on how to define the experiment in CIF format are provided
+in the [Experiment](analysis-workflow/experiment.md) section.
## Other Input/Output Blocks
-EasyDiffraction uses CIF consistently throughout its workflow, including in the
-following blocks:
+EasyDiffraction uses CIF consistently throughout its workflow, including
+in the following blocks:
- **project**: contains the project information
- **structure**: defines the structure
@@ -217,11 +219,13 @@ Example CIF files for each block are provided in the
## Other Data Formats
-While CIF is the primary format in EasyDiffraction, we also support other
-formats for importing measured data. These include plain text files with
-multiple columns. The meaning of the columns depends on the experiment type.
+While CIF is the primary format in EasyDiffraction, we also support
+other formats for importing measured data. These include plain text
+files with multiple columns. The meaning of the columns depends on the
+experiment type.
-For example, in a standard constant-wavelength powder diffraction experiment:
+For example, in a standard constant-wavelength powder diffraction
+experiment:
- Column 1: 2θ angle
- Column 2: intensity
diff --git a/docs/user-guide/first-steps.md b/docs/docs/user-guide/first-steps.md
similarity index 56%
rename from docs/user-guide/first-steps.md
rename to docs/docs/user-guide/first-steps.md
index acb50bec..b4366684 100644
--- a/docs/user-guide/first-steps.md
+++ b/docs/docs/user-guide/first-steps.md
@@ -1,44 +1,44 @@
# First Steps
-This section introduces the basic usage of the EasyDiffraction Python API.
-You'll learn how to import the package, use core classes and utility functions,
-and access built-in helper methods to streamline diffraction data analysis
-workflows.
+This section introduces the basic usage of the EasyDiffraction Python
+API. You'll learn how to import the package, use core classes and
+utility functions, and access built-in helper methods to streamline
+diffraction data analysis workflows.
## Importing EasyDiffraction
### Importing the entire package
-To start using EasyDiffraction, first import the package in your Python script
-or Jupyter Notebook. This can be done with the following command:
+To start using EasyDiffraction, first import the package in your Python
+script or Jupyter Notebook. This can be done with the following command:
```python
import easydiffraction
```
-Alternatively, you can import it with an alias to avoid naming conflicts and for
-convenience:
+Alternatively, you can import it with an alias to avoid naming conflicts
+and for convenience:
```python
import easydiffraction as ed
```
-The latter syntax allows you to access all the modules and classes within the
-package using the `ed` prefix. For example, you can create a project instance
-like this:
+The latter syntax allows you to access all the modules and classes
+within the package using the `ed` prefix. For example, you can create a
+project instance like this:
```python
project = ed.Project()
```
A complete tutorial using the `import` syntax can be found
-[here](../../tutorials/ed-3/).
+[here](../tutorials/ed-3.ipynb).
### Importing specific parts
-Alternatively, you can import specific classes or methods from the package. For
-example, you can import the `Project`, `Structure`, `Experiment` classes and
-`download_from_repository` method like this:
+Alternatively, you can import specific classes or methods from the
+package. For example, you can import the `Project`, `Structure`,
+`Experiment` classes and `download_from_repository` method like this:
```python
from easydiffraction import Project
@@ -47,24 +47,25 @@ from easydiffraction import Experiment
from easydiffraction import download_from_repository
```
-This enables you to use these classes and methods directly without the package
-prefix. This is especially useful when you're using only a few components and
-want to keep your code clean and concise. In this case, you can create a project
-instance like this:
+This enables you to use these classes and methods directly without the
+package prefix. This is especially useful when you're using only a few
+components and want to keep your code clean and concise. In this case,
+you can create a project instance like this:
```python
project = Project()
```
A complete tutorial using the `from` syntax can be found
-[here](../../tutorials/ed-4/).
+[here](../tutorials/ed-4.ipynb).
## Utility functions
-EasyDiffraction also provides several utility functions that can simplify your
-workflow. One of them is the `download_from_repository` function, which allows
-you to download data files from our remote repository, making it easy to access
-and use them while experimenting with EasyDiffraction.
+EasyDiffraction also provides several utility functions that can
+simplify your workflow. One of them is the `download_from_repository`
+function, which allows you to download data files from our remote
+repository, making it easy to access and use them while experimenting
+with EasyDiffraction.
For example, you can download a data file like this:
@@ -78,29 +79,31 @@ ed.download_from_repository(
)
```
-This command will download the `hrpt_lbco.xye` file from the `docs` branch of
-the EasyDiffraction repository and save it in the `data` directory of your
-current working directory. This is particularly useful for quickly accessing
-example datasets without having to manually download them.
+This command will download the `hrpt_lbco.xye` file from the `docs`
+branch of the EasyDiffraction repository and save it in the `data`
+directory of your current working directory. This is particularly useful
+for quickly accessing example datasets without having to manually
+download them.
## Help methods
-EasyDiffraction provides several helper methods to display supported engines for
-calculation, minimization, and plotting. These methods can be called on the
-`Project` instance to display the available options for different categories.
+EasyDiffraction provides several helper methods to display supported
+engines for calculation, minimization, and plotting. These methods can
+be called on the `Project` instance to display the available options for
+different categories.
### Supported calculators
-The calculator is automatically selected based on the experiment type. You can
-use the `show_supported_calculator_types()` method on an experiment to see which
-calculation engines are compatible:
+The calculator is automatically selected based on the experiment type.
+You can use the `show_supported_calculator_types()` method on an
+experiment to see which calculation engines are compatible:
```python
project.experiments['hrpt'].show_supported_calculator_types()
```
-This will display a list of supported calculators along with their descriptions,
-allowing you to choose the one that best fits your needs.
+This will display a list of supported calculators along with their
+descriptions, allowing you to choose the one that best fits your needs.
An example of the output for a Bragg diffraction experiment:
@@ -119,24 +122,25 @@ project.show_available_minimizers()
### Available parameters
-EasyDiffraction provides several methods for showing the available parameters
-grouped in different categories. For example, you can use:
+EasyDiffraction provides several methods for showing the available
+parameters grouped in different categories. For example, you can use:
-- `project.analysis.show_all_params()` – to display all available parameters for
- the analysis step.
-- `project.analysis.show_fittable_params()` – to display only the parameters
- that can be fitted during the analysis.
-- `project.analysis.show_free_params()` – to display the parameters that are
- currently free to be adjusted during the fitting process.
+- `project.analysis.show_all_params()` – to display all available
+ parameters for the analysis step.
+- `project.analysis.show_fittable_params()` – to display only the
+ parameters that can be fitted during the analysis.
+- `project.analysis.show_free_params()` – to display the parameters that
+ are currently free to be adjusted during the fitting process.
-Finally, you can use the `project.analysis.how_to_access_parameters()` method to
-get a brief overview of how to access and modify parameters in the analysis
-step, along with their unique identifiers in the CIF format. This can be
-particularly useful for users who are new to the EasyDiffraction API or those
-who want to quickly understand how to work with parameters in their projects.
+Finally, you can use the `project.analysis.how_to_access_parameters()`
+method to get a brief overview of how to access and modify parameters in
+the analysis step, along with their unique identifiers in the CIF
+format. This can be particularly useful for users who are new to the
+EasyDiffraction API or those who want to quickly understand how to work
+with parameters in their projects.
-An example of the output for the `project.analysis.how_to_access_parameters()`
-method is:
+An example of the output for the
+`project.analysis.how_to_access_parameters()` method is:
| | Code variable | Unique ID for CIF |
| --- | --------------------------------------------------- | -------------------------------- |
@@ -151,8 +155,9 @@ method is:
### Supported plotters
-To see the available plotters, you can use the `show_available_plotters()`
-method on the `plotter` attribute of the `Project` instance:
+To see the available plotters, you can use the
+`show_available_plotters()` method on the `plotter` attribute of the
+`Project` instance:
```python
project.plotter.show_supported_engines()
@@ -167,16 +172,19 @@ An example of the output is:
## Data analysis workflow
-Once the EasyDiffraction package is imported, you can proceed with the **data
-analysis**. This step can be split into several sub-steps, such as creating a
-project, defining structures, adding experimental data, etc.
-
-EasyDiffraction provides a **Python API** that allows you to perform these steps
-programmatically in a certain linear order. This is especially useful for users
-who prefer to work in a script or Jupyter Notebook environment. The API is
-designed to be intuitive and easy to use, allowing you to focus on the analysis
-rather than low-level implementation details.
-
-Because this workflow is an important part of the EasyDiffraction package, it is
-described in detail in the separate
-[Analysis Workflow](analysis-workflow/index.md) section of the documentation.
+Once the EasyDiffraction package is imported, you can proceed with the
+**data analysis**. This step can be split into several sub-steps, such
+as creating a project, defining structures, adding experimental data,
+etc.
+
+EasyDiffraction provides a **Python API** that allows you to perform
+these steps programmatically in a certain linear order. This is
+especially useful for users who prefer to work in a script or Jupyter
+Notebook environment. The API is designed to be intuitive and easy to
+use, allowing you to focus on the analysis rather than low-level
+implementation details.
+
+Because this workflow is an important part of the EasyDiffraction
+package, it is described in detail in the separate
+[Analysis Workflow](analysis-workflow/index.md) section of the
+documentation.
diff --git a/docs/user-guide/glossary.md b/docs/docs/user-guide/glossary.md
similarity index 80%
rename from docs/user-guide/glossary.md
rename to docs/docs/user-guide/glossary.md
index 827cfdf5..75f0300c 100644
--- a/docs/user-guide/glossary.md
+++ b/docs/docs/user-guide/glossary.md
@@ -1,25 +1,29 @@
# Glossary
-Before guiding you through the use of EasyDiffraction, we define some common
-terms and abbreviations used throughout the documentation and tutorials.
+Before guiding you through the use of EasyDiffraction, we define some
+common terms and abbreviations used throughout the documentation and
+tutorials.
## Dictionary Type Labels
-The following labels are used to identify different types of CIF dictionaries:
+The following labels are used to identify different types of CIF
+dictionaries:
- [coreCIF][1]{:.label-cif} – Core CIF dictionary by the
[IUCr](https://www.iucr.org).
- [pdCIF][2]{:.label-cif} – Powder CIF dictionary by the
[IUCr](https://www.iucr.org).
-- [easydiffractionCIF][0]{:.label-cif} – Custom CIF dictionary developed for
- EasyDiffraction.
+- [easydiffractionCIF][0]{:.label-cif} – Custom CIF dictionary developed
+ for EasyDiffraction.
-For more information about CIF, see the [Data Format](data-format.md) section.
+For more information about CIF, see the [Data Format](data-format.md)
+section.
## Experiment Type Labels
-EasyDiffraction supports a variety of experiment types, each with its own set of
-parameters. The following labels identify the supported experiment types:
+EasyDiffraction supports a variety of experiment types, each with its
+own set of parameters. The following labels identify the supported
+experiment types:
### Neutron Diffraction
@@ -27,8 +31,8 @@ parameters. The following labels identify the supported experiment types:
constant wavelength.
- [pd-neut-tof][0]{:.label-experiment} – Powder neutron diffraction with
time-of-flight.
-- [sc-neut-cwl][0]{:.label-experiment} – Single-crystal neutron diffraction with
- constant wavelength.
+- [sc-neut-cwl][0]{:.label-experiment} – Single-crystal neutron
+ diffraction with constant wavelength.
### X-ray Diffraction
diff --git a/docs/user-guide/index.md b/docs/docs/user-guide/index.md
similarity index 57%
rename from docs/user-guide/index.md
rename to docs/docs/user-guide/index.md
index a6671f3d..2ddc28b9 100644
--- a/docs/user-guide/index.md
+++ b/docs/docs/user-guide/index.md
@@ -4,20 +4,21 @@ icon: material/book-open-variant
# :material-book-open-variant: User Guide
-This section provides an overview of the **core concepts**, **key parameters**
-and **workflow steps** required for using EasyDiffraction effectively.
+This section provides an overview of the **core concepts**, **key
+parameters** and **workflow steps** required for using EasyDiffraction
+effectively.
Here is a brief overview of the User Guide sections:
-- [Glossary](glossary.md) – Defines common terms and labels used throughout the
- documentation.
-- [Concept](concept.md) – Introduces the overall idea behind diffraction data
- processing and where EasyDiffraction fits.
-- [Data Format](data-format.md) – Explains the Crystallographic Information File
- (CIF) and how it's used in EasyDiffraction.
-- [Parameters](parameters.md) – Describes how parameters are structured, named,
- and accessed within the EasyDiffraction library.
-- [First Steps](first-steps.md) – Shows how to begin using EasyDiffraction in
- Python or Jupyter notebooks.
+- [Glossary](glossary.md) – Defines common terms and labels used
+ throughout the documentation.
+- [Concept](concept.md) – Introduces the overall idea behind diffraction
+ data processing and where EasyDiffraction fits.
+- [Data Format](data-format.md) – Explains the Crystallographic
+ Information File (CIF) and how it's used in EasyDiffraction.
+- [Parameters](parameters.md) – Describes how parameters are structured,
+ named, and accessed within the EasyDiffraction library.
+- [First Steps](first-steps.md) – Shows how to begin using
+ EasyDiffraction in Python or Jupyter notebooks.
- [Analysis Workflow](analysis-workflow/index.md) – Breaks down the data
analysis pipeline into practical, sequential steps.
diff --git a/docs/user-guide/parameters.md b/docs/docs/user-guide/parameters.md
similarity index 90%
rename from docs/user-guide/parameters.md
rename to docs/docs/user-guide/parameters.md
index 794f65aa..622bf6f1 100644
--- a/docs/user-guide/parameters.md
+++ b/docs/docs/user-guide/parameters.md
@@ -1,52 +1,58 @@
# Parameters
-The data analysis process, introduced in the [Concept](concept.md) section,
-assumes that you mainly work with different parameters. The parameters are used
-to describe the structure and the experiment and are required to set up the
-analysis.
+The data analysis process, introduced in the [Concept](concept.md)
+section, assumes that you mainly work with different parameters. The
+parameters are used to describe the structure and the experiment and are
+required to set up the analysis.
-Each parameter in EasyDiffraction has a specific name used for code reference,
-and it belongs to a specific category.
+Each parameter in EasyDiffraction has a specific name used for code
+reference, and it belongs to a specific category.
- In many cases, the EasyDiffraction name is the same as the CIF name.
-- In some cases, the EasyDiffraction name is a slightly modified version of the
- CIF name to comply with Python naming conventions. For example, `name_H-M_alt`
- becomes `name_h_m`, replacing hyphens with underscores and using lowercase
- letters.
-- In rare cases, the EasyDiffraction name is a bit shorter, like `b_iso` instead
- of CIF `B_iso_or_equiv`, to make the code a bit more user-friendly.
-- When there is no defined CIF name for a parameter, EasyDiffraction introduces
- its own name, which is used in the code as well as an equivalent CIF name to
- be placed in the custom CIF dictionary `easydiffractionCIF`.
-
-EasyDiffraction names are used in code, while CIF names are used to store and
-retrieve the full state of a data analysis project in CIF format. You can find
-more about the project in the [Project](analysis-workflow/project.md) section.
+- In some cases, the EasyDiffraction name is a slightly modified version
+ of the CIF name to comply with Python naming conventions. For example,
+ `name_H-M_alt` becomes `name_h_m`, replacing hyphens with underscores
+ and using lowercase letters.
+- In rare cases, the EasyDiffraction name is a bit shorter, like `b_iso`
+ instead of CIF `B_iso_or_equiv`, to make the code a bit more
+ user-friendly.
+- When there is no defined CIF name for a parameter, EasyDiffraction
+ introduces its own name, which is used in the code as well as an
+ equivalent CIF name to be placed in the custom CIF dictionary
+ `easydiffractionCIF`.
+
+EasyDiffraction names are used in code, while CIF names are used to
+store and retrieve the full state of a data analysis project in CIF
+format. You can find more about the project in the
+[Project](analysis-workflow/project.md) section.
## Parameter Attributes
-Parameters in EasyDiffraction are more than just variables. They are objects
-that, in addition to the name and value, also include attributes such as the
-description, unit, uncertainty, minimum and maximum values, etc. All these
-attributes are described in the [API Reference](../api-reference/index.md)
-section. Examples of how to use these parameters in code are provided in the
+Parameters in EasyDiffraction are more than just variables. They are
+objects that, in addition to the name and value, also include attributes
+such as the description, unit, uncertainty, minimum and maximum values,
+etc. All these attributes are described in the
+[API Reference](../api-reference/index.md) section. Examples of how to
+use these parameters in code are provided in the
[Analysis Workflow](analysis-workflow/index.md) and
[Tutorials](../tutorials/index.md) sections.
-The most important attribute, besides `name` and `value`, is `free`, which is
-used to define whether the parameter is free or fixed for optimization during
-the fitting process. The `free` attribute is set to `False` by default, which
-means the parameter is fixed. To optimize a parameter, set `free` to `True`.
+The most important attribute, besides `name` and `value`, is `free`,
+which is used to define whether the parameter is free or fixed for
+optimization during the fitting process. The `free` attribute is set to
+`False` by default, which means the parameter is fixed. To optimize a
+parameter, set `free` to `True`.
-Although parameters are central, EasyDiffraction hides their creation and
-attribute handling from the user. The user only accesses the required parameters
-through the top-level objects, such as `project`, `structures`, `experiments`,
-etc. The parameters are created and initialized automatically when a new project
-is created or an existing one is loaded.
+Although parameters are central, EasyDiffraction hides their creation
+and attribute handling from the user. The user only accesses the
+required parameters through the top-level objects, such as `project`,
+`structures`, `experiments`, etc. The parameters are created and
+initialized automatically when a new project is created or an existing
+one is loaded.
In the following sections, you can see a list of the parameters used in
-EasyDiffraction. Use the tabs to switch between how to access a parameter in
-code and its CIF name for serialization.
+EasyDiffraction. Use the tabs to switch between how to access a
+parameter in code and its CIF name for serialization.
!!! warning "Important"
@@ -59,23 +65,27 @@ code and its CIF name for serialization.
project.structures['nacl'].space_group.name_h_m
```
-In the example above, `space_group` is a structure category, and `name_h_m` is
-the parameter. For simplicity, only the last part (`category.parameter`) of the
-full access name will be shown in the tables below.
+In the example above, `space_group` is a structure category, and
+`name_h_m` is the parameter. For simplicity, only the last part
+(`category.parameter`) of the full access name will be shown in the
+tables below.
-In addition, the CIF names are also provided for each parameter, which are used
-to serialize the parameters in the CIF format.
+In addition, the CIF names are also provided for each parameter, which
+are used to serialize the parameters in the CIF format.
-Tags defining the corresponding experiment type are also given before the table.
+Tags defining the corresponding experiment type are also given before
+the table.
## Structure parameters
-Below is a list of parameters used to describe the structure in EasyDiffraction.
+Below is a list of parameters used to describe the structure in
+EasyDiffraction.
### Crystall structure parameters
-[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment}
-[pd-xray][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment}
+[pd-neut-cwl][3]{:.label-experiment}
+[pd-neut-tof][3]{:.label-experiment} [pd-xray][3]{:.label-experiment}
+[sc-neut-cwl][3]{:.label-experiment}
=== "How to access in the code"
@@ -130,8 +140,9 @@ EasyDiffraction.
### Common parameters
-[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment}
-[pd-xray][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment}
+[pd-neut-cwl][3]{:.label-experiment}
+[pd-neut-tof][3]{:.label-experiment} [pd-xray][3]{:.label-experiment}
+[sc-neut-cwl][3]{:.label-experiment}
=== "How to access in the code"
@@ -153,8 +164,8 @@ EasyDiffraction.
### Standard powder diffraction
-[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment}
-[pd-xray][3]{:.label-experiment}
+[pd-neut-cwl][3]{:.label-experiment}
+[pd-neut-tof][3]{:.label-experiment} [pd-xray][3]{:.label-experiment}
=== "How to access in the code"
@@ -240,7 +251,8 @@ EasyDiffraction.
### Total scattering
-[pd-neut-total][3]{:.label-experiment} [pd-xray-total][3]{:.label-experiment}
+[pd-neut-total][3]{:.label-experiment}
+[pd-xray-total][3]{:.label-experiment}
=== "How to access in the code"
diff --git a/docs/user-guide/parameters/_diffrn_radiation.md b/docs/docs/user-guide/parameters/_diffrn_radiation.md
similarity index 87%
rename from docs/user-guide/parameters/_diffrn_radiation.md
rename to docs/docs/user-guide/parameters/_diffrn_radiation.md
index e3c0a7e9..6e2f0a06 100644
--- a/docs/user-guide/parameters/_diffrn_radiation.md
+++ b/docs/docs/user-guide/parameters/_diffrn_radiation.md
@@ -4,13 +4,13 @@
Data items in this category describe the radiation used in measuring the
diffraction intensities. Please see the
-[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for
-further details.
+[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
+for further details.
## [\_diffrn_radiation.probe](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
-The nature of the radiation used (i.e. the name of the subatomic particle or the
-region of the electromagnetic spectrum).
+The nature of the radiation used (i.e. the name of the subatomic
+particle or the region of the electromagnetic spectrum).
Supported values: `neutron` and `x-ray`
diff --git a/docs/user-guide/parameters/_diffrn_radiation_wavelength.md b/docs/docs/user-guide/parameters/_diffrn_radiation_wavelength.md
similarity index 95%
rename from docs/user-guide/parameters/_diffrn_radiation_wavelength.md
rename to docs/docs/user-guide/parameters/_diffrn_radiation_wavelength.md
index 4d205788..3b750b22 100644
--- a/docs/user-guide/parameters/_diffrn_radiation_wavelength.md
+++ b/docs/docs/user-guide/parameters/_diffrn_radiation_wavelength.md
@@ -4,8 +4,8 @@
Data items in this category describe the wavelength of radiation used in
diffraction measurements. Please see the
-[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for
-further details.
+[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
+for further details.
## [\_diffrn_radiation_wavelength.wavelength](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
diff --git a/docs/user-guide/parameters/_exptl_crystal.md b/docs/docs/user-guide/parameters/_exptl_crystal.md
similarity index 100%
rename from docs/user-guide/parameters/_exptl_crystal.md
rename to docs/docs/user-guide/parameters/_exptl_crystal.md
diff --git a/docs/user-guide/parameters/_extinction.md b/docs/docs/user-guide/parameters/_extinction.md
similarity index 100%
rename from docs/user-guide/parameters/_extinction.md
rename to docs/docs/user-guide/parameters/_extinction.md
diff --git a/docs/user-guide/parameters/_pd_calib.md b/docs/docs/user-guide/parameters/_pd_calib.md
similarity index 94%
rename from docs/user-guide/parameters/_pd_calib.md
rename to docs/docs/user-guide/parameters/_pd_calib.md
index 2b96a4c8..407c5f73 100644
--- a/docs/user-guide/parameters/_pd_calib.md
+++ b/docs/docs/user-guide/parameters/_pd_calib.md
@@ -2,8 +2,8 @@
# \_pd_calib
-This section defines the parameters used for the calibration of the instrument,
-similar to this
+This section defines the parameters used for the calibration of the
+instrument, similar to this
[IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd).
## [\_pd_calib.2theta_offset](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
diff --git a/docs/user-guide/parameters/atom_site.md b/docs/docs/user-guide/parameters/atom_site.md
similarity index 82%
rename from docs/user-guide/parameters/atom_site.md
rename to docs/docs/user-guide/parameters/atom_site.md
index 44325b8a..7acdb650 100644
--- a/docs/user-guide/parameters/atom_site.md
+++ b/docs/docs/user-guide/parameters/atom_site.md
@@ -2,16 +2,16 @@
# \_atom_site
-Data items in this category record details about the atom sites in a crystal
-structure, such as the positional coordinates and atomic displacement
-parameters. Please see the
+Data items in this category record details about the atom sites in a
+crystal structure, such as the positional coordinates and atomic
+displacement parameters. Please see the
[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CATOM_SITE.html)
for further details.
## [\_atom_site.label](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.label.html)
-This is a unique identifier for a particular site in the asymmetric unit of the
-crystal unit cell.
+This is a unique identifier for a particular site in the asymmetric unit
+of the crystal unit cell.
## [\_atom_site.type_symbol](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.type_symbol.html)
@@ -19,7 +19,8 @@ A code to identify the atom specie(s) occupying this site.
## \_atom_site.fract
-Atom-site coordinates as fractions of the [\_cell_length](cell.md) values.
+Atom-site coordinates as fractions of the [\_cell_length](cell.md)
+values.
- [\_atom_site.fract_x](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_x.html)
- [\_atom_site.fract_y](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_y.html)
@@ -31,8 +32,8 @@ The fraction of the atom type present at this site.
## [\_atom_site.ADP_type](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.adp_type.html)
-Code for type of atomic displacement parameters used for the site. Currently
-only `Biso` (isotropic B) is supported.
+Code for type of atomic displacement parameters used for the site.
+Currently only `Biso` (isotropic B) is supported.
## [\_atom_site.B_iso_or_equiv](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.B_iso_or_equiv.html)
@@ -43,17 +44,17 @@ displacement parameter, in angstroms squared.
`optional parameter`
-The number of different sites that are generated by the application of the
-space-group symmetry to the coordinates given for this site. It is equal to the
-multiplicity given for this Wyckoff site in International Tables for
-Crystallography Vol. A (2002).
+The number of different sites that are generated by the application of
+the space-group symmetry to the coordinates given for this site. It is
+equal to the multiplicity given for this Wyckoff site in International
+Tables for Crystallography Vol. A (2002).
## [\_atom_site.Wyckoff_symbol](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.Wyckoff_symbol.html)
`optional parameter`
-The Wyckoff symbol (letter) as listed in the space-group tables of International
-Tables for Crystallography Vol. A.
+The Wyckoff symbol (letter) as listed in the space-group tables of
+International Tables for Crystallography Vol. A.
[0]: #
diff --git a/docs/user-guide/parameters/background.md b/docs/docs/user-guide/parameters/background.md
similarity index 75%
rename from docs/user-guide/parameters/background.md
rename to docs/docs/user-guide/parameters/background.md
index 89985470..e307c981 100644
--- a/docs/user-guide/parameters/background.md
+++ b/docs/docs/user-guide/parameters/background.md
@@ -2,26 +2,27 @@
# \_pd_background
-This category defines various background functions that could be used when
-calculating diffractograms. Please see the
-[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for
-further details.
+This category defines various background functions that could be used
+when calculating diffractograms. Please see the
+[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
+for further details.
## [\_pd_background.line_segment_X](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
-List of X-coordinates used to create many straight-line segments representing
-the background in a calculated diffractogram.
+List of X-coordinates used to create many straight-line segments
+representing the background in a calculated diffractogram.
Supported values: `2theta` and `time-of-flight`
## [\_pd_background.line_segment_intensity](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
-List of intensities used to create many straight-line segments representing the
-background in a calculated diffractogram.
+List of intensities used to create many straight-line segments
+representing the background in a calculated diffractogram.
## [\_pd_background.X_coordinate](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
-The type of X-coordinate against which the pd_background values were calculated.
+The type of X-coordinate against which the pd_background values were
+calculated.
[0]: #
diff --git a/docs/user-guide/parameters/cell.md b/docs/docs/user-guide/parameters/cell.md
similarity index 95%
rename from docs/user-guide/parameters/cell.md
rename to docs/docs/user-guide/parameters/cell.md
index 5aeb12ae..806df516 100644
--- a/docs/user-guide/parameters/cell.md
+++ b/docs/docs/user-guide/parameters/cell.md
@@ -2,8 +2,8 @@
# \_cell
-Data items in this category record details about the crystallographic cell
-parameters and their measurement. Please see the
+Data items in this category record details about the crystallographic
+cell parameters and their measurement. Please see the
[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CCELL.html)
for further details.
diff --git a/docs/user-guide/parameters/expt_type.md b/docs/docs/user-guide/parameters/expt_type.md
similarity index 95%
rename from docs/user-guide/parameters/expt_type.md
rename to docs/docs/user-guide/parameters/expt_type.md
index 5aeb12ae..806df516 100644
--- a/docs/user-guide/parameters/expt_type.md
+++ b/docs/docs/user-guide/parameters/expt_type.md
@@ -2,8 +2,8 @@
# \_cell
-Data items in this category record details about the crystallographic cell
-parameters and their measurement. Please see the
+Data items in this category record details about the crystallographic
+cell parameters and their measurement. Please see the
[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CCELL.html)
for further details.
diff --git a/docs/user-guide/parameters/instrument.md b/docs/docs/user-guide/parameters/instrument.md
similarity index 73%
rename from docs/user-guide/parameters/instrument.md
rename to docs/docs/user-guide/parameters/instrument.md
index 3975161c..fbeca6c9 100644
--- a/docs/user-guide/parameters/instrument.md
+++ b/docs/docs/user-guide/parameters/instrument.md
@@ -2,21 +2,22 @@
# \_pd_instr
-This section contains information relevant to the instrument used for the
-diffraction measurement, similar to this
+This section contains information relevant to the instrument used for
+the diffraction measurement, similar to this
[IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd).
## [\_pd_instr.resolution](#)
-In general, the profile of a Bragg reflection centred at the peak position can
-be approximated by mathematical convolution of contributions from the
-instrument, called the instrumental resolution function, and from the
-microstructure of the sample. Because many contributions to powder diffraction
-peaks have a nearly Gaussian or Lorentzian shape, the pseudo-Voigt function, is
-widely used to describe peak profiles in powder diffraction.
+In general, the profile of a Bragg reflection centred at the peak
+position can be approximated by mathematical convolution of
+contributions from the instrument, called the instrumental resolution
+function, and from the microstructure of the sample. Because many
+contributions to powder diffraction peaks have a nearly Gaussian or
+Lorentzian shape, the pseudo-Voigt function, is widely used to describe
+peak profiles in powder diffraction.
-Half-width parameters (normally characterising the instrumental resolution
-function) as implemented in [CrysPy](https://cryspy.fr):
+Half-width parameters (normally characterising the instrumental
+resolution function) as implemented in [CrysPy](https://cryspy.fr):
- \_pd_instr.resolution_u
- \_pd_instr.resolution_v
@@ -34,7 +35,8 @@ Lorentzian isotropic particle size parameteras implemented in
## [\_pd_instr.reflex_asymmetry](#)
-Peak profile asymmetry parameters as implemented in [CrysPy](https://cryspy.fr).
+Peak profile asymmetry parameters as implemented in
+[CrysPy](https://cryspy.fr).
- \_pd_instr.reflex_asymmetry_p1
- \_pd_instr.reflex_asymmetry_p2
diff --git a/docs/user-guide/parameters/linked_phases.md b/docs/docs/user-guide/parameters/linked_phases.md
similarity index 86%
rename from docs/user-guide/parameters/linked_phases.md
rename to docs/docs/user-guide/parameters/linked_phases.md
index df3f6d29..1d00f1d2 100644
--- a/docs/user-guide/parameters/linked_phases.md
+++ b/docs/docs/user-guide/parameters/linked_phases.md
@@ -2,10 +2,10 @@
# \_pd_phase_block
-A table of phases relevant to the current data block. Each phase is identified
-by its data block identifier. Please see the
-[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for
-further details.
+A table of phases relevant to the current data block. Each phase is
+identified by its data block identifier. Please see the
+[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
+for further details.
## [\_pd_phase_block.id](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd)
diff --git a/docs/user-guide/parameters/pd_meas.md b/docs/docs/user-guide/parameters/pd_meas.md
similarity index 97%
rename from docs/user-guide/parameters/pd_meas.md
rename to docs/docs/user-guide/parameters/pd_meas.md
index b294a96a..fcb4db17 100644
--- a/docs/user-guide/parameters/pd_meas.md
+++ b/docs/docs/user-guide/parameters/pd_meas.md
@@ -7,8 +7,8 @@ This section contains the measured diffractogram, similar to this
## [\_pd_meas.2theta_scan](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic)
-2θ diffraction angle (in degrees) for intensity points measured in a scanning
-method.
+2θ diffraction angle (in degrees) for intensity points measured in a
+scanning method.
## [\_pd_meas.time-of-flight](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic)
diff --git a/docs/user-guide/parameters/peak.md b/docs/docs/user-guide/parameters/peak.md
similarity index 95%
rename from docs/user-guide/parameters/peak.md
rename to docs/docs/user-guide/parameters/peak.md
index 5aeb12ae..806df516 100644
--- a/docs/user-guide/parameters/peak.md
+++ b/docs/docs/user-guide/parameters/peak.md
@@ -2,8 +2,8 @@
# \_cell
-Data items in this category record details about the crystallographic cell
-parameters and their measurement. Please see the
+Data items in this category record details about the crystallographic
+cell parameters and their measurement. Please see the
[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CCELL.html)
for further details.
diff --git a/docs/user-guide/parameters/space_group.md b/docs/docs/user-guide/parameters/space_group.md
similarity index 87%
rename from docs/user-guide/parameters/space_group.md
rename to docs/docs/user-guide/parameters/space_group.md
index 883be103..ae5bce6b 100644
--- a/docs/user-guide/parameters/space_group.md
+++ b/docs/docs/user-guide/parameters/space_group.md
@@ -2,16 +2,16 @@
# \_space_group
-Contains all the data items that refer to the space group as a whole. Please see
-the
+Contains all the data items that refer to the space group as a whole.
+Please see the
[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CSPACE_GROUP.html)
for further details.
## [\_space_group.name_H-M_alt](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Ispace_group.name_H-M_alt.html)
-The international Hermann-Mauguin space-group symbol as defined in International
-Tables for Crystallography Volume A. It allows any Hermann-Mauguin symbol to be
-given.
+The international Hermann-Mauguin space-group symbol as defined in
+International Tables for Crystallography Volume A. It allows any
+Hermann-Mauguin symbol to be given.
## [\_space_group.IT_coordinate_system_code](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Ispace_group.IT_coordinate_system_code.html)
diff --git a/docs/includes/abbreviations.md b/docs/includes/abbreviations.md
new file mode 100644
index 00000000..682f16ff
--- /dev/null
+++ b/docs/includes/abbreviations.md
@@ -0,0 +1,15 @@
+
+
+*[CIF]: Crystallographic Information File.
+*[curl]: Command-line tool for transferring data with URLs.
+*[GitHub]: A web-based platform for version control and collaboration.
+*[Google Colab]: Cloud service that allows you to run Jupyter Notebooks in the cloud.
+*[IUCr]: International Union of Crystallography.
+*[Jupyter Notebook]: An open-source web application that allows you to create and share documents that contain live code, equations, visualizations, and narrative text.
+*[JupyterLab]: Web-based interactive development environment for notebooks, code, and data.
+*[pip]: Package installer for Python.
+*[PyPI]: The Python Package Index is a repository of software for the Python programming language.
+*[Conda]: Conda is a cross-platform, language-agnostic binary package manager.
+*[Pixi]: A modern package manager for Windows, macOS, and Linux.
+
+
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 467bfec8..55ca5f22 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -1,45 +1,167 @@
-###########################
-# Override default settings
-###########################
-
# Project information
-site_name: '' #EasyDiffraction Library
-site_url: https://easyscience.github.io/diffraction-lib/ #https://docs.easydiffraction.org/lib/
+site_name: EasyDiffraction Library
+site_url: https://easyscience.github.io/diffraction-lib
# Repository
-repo_url: https://github.com/easyscience/diffraction-lib/
+repo_url: https://github.com/easyscience/diffraction-lib
edit_uri: edit/develop/docs/
# Copyright
-copyright: © 2026 EasyDiffraction
+copyright: © 2021-2026 EasyDiffraction
+
+# Sets the theme and theme-specific configuration
+theme:
+ name: material
+ custom_dir: overrides
+ features:
+ #- content.action.edit # Temporary disable edit button (until decided on which branch to use and where to host the notebooks)
+ #- content.action.view
+ - content.code.annotate
+ - content.code.copy # Auto generated button to copy a code block's content
+ - content.tooltips
+ - navigation.footer
+ - navigation.indexes
+ #- navigation.instant # Instant loading, but it causes issues with rendering equations
+ #- navigation.sections
+ - navigation.top # Back-to-top button
+ - navigation.tracking # Anchor tracking
+ - search.highlight
+ - search.share
+ - search.suggest
+ - toc.follow
+ palette:
+ # Palette toggle for light mode
+ - media: '(prefers-color-scheme: light)'
+ scheme: default
+ primary: custom
+ toggle:
+ icon: fontawesome/solid/sun
+ name: Switch to dark mode
+ # Palette toggle for dark mode
+ - media: '(prefers-color-scheme: dark)'
+ scheme: slate
+ primary: custom
+ toggle:
+ icon: fontawesome/solid/moon
+ name: Switch to light mode
+ font:
+ text: Mulish
+ code: Roboto Mono
+ icon:
+ edit: material/file-edit-outline
+ favicon: assets/images/favicon.png
+ logo_dark_mode: assets/images/logo_dark.svg
+ logo_light_mode: assets/images/logo_light.svg
-# Extra icons in the bottom right corner
+# A set of key-value pairs, where the values can be any valid YAML
+# construct, that will be passed to the template
extra:
- social:
+ generator: false # Disable `Made with Material for MkDocs` (bottom left)
+ social: # Extra icons in the bottom right corner
+ - icon: easyscience # File: overrides/.icons/easyscience.svg
+ link: https://easyscience.org
+ name: EasyScience Framework Webpage
- icon: easydiffraction # File: overrides/.icons/easydiffraction.svg
- link: https://easydiffraction.org
+ link: https://easyscience.github.io/diffraction
name: EasyDiffraction Main Webpage
- icon: app # File: overrides/.icons/app.svg
- link: https://docs.easydiffraction.org/app/
+ link: https://easyscience.github.io/diffraction-app
name: EasyDiffraction Application Docs
- icon: fontawesome/brands/github # Name as in Font Awesome
link: https://github.com/easyscience/diffraction-lib
name: EasyDiffraction Library Source Code on GitHub
+ # Set custom variables to be used in Markdown and HTML files
+ vars:
+ ci_branch: !ENV CI_BRANCH
+ github_repository: !ENV GITHUB_REPOSITORY
+ release_version: !ENV RELEASE_VERSION
+ docs_version: !ENV DOCS_VERSION
+ notebooks_dir: !ENV NOTEBOOKS_DIR
+ # Renders a version selector in the header
+ version:
+ provider: mike
+
+# Customization to be included by the theme
+extra_css:
+ - assets/stylesheets/extra.css
+
+extra_javascript:
+ - assets/javascripts/extra.js
+ # MathJax for rendering mathematical expressions
+ - assets/javascripts/mathjax.js # Custom MathJax config to ensure compatibility with mkdocs-jupyter
+ - https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js # Official MathJax CDN
+
+# A list of extensions beyond the ones that MkDocs uses by default (meta, toc, tables, and fenced_code)
+markdown_extensions:
+ - abbr
+ - admonition
+ - attr_list
+ - def_list
+ - footnotes
+ - pymdownx.arithmatex: # rendering of equations and integrates with MathJax or KaTeX
+ generic: true
+ - pymdownx.blocks.caption
+ - pymdownx.details
+ - pymdownx.emoji:
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
+ options:
+ custom_icons:
+ - docs/overrides/.icons
+ - pymdownx.highlight: # whether highlighting should be carried out during build time by Pygments
+ use_pygments: true
+ pygments_lang_class: true
+ - pymdownx.snippets:
+ auto_append:
+ - docs/includes/abbreviations.md
+ - pymdownx.superfences: # whether highlighting should be carried out during build time by Pygments
+ custom_fences:
+ - name: mermaid
+ class: mermaid
+ format: !!python/name:pymdownx.superfences.fence_code_format
+ - pymdownx.tabbed: # enables content tabs
+ alternate_style: true
+ - pymdownx.tasklist:
+ custom_checkbox: true
+ - toc:
+ toc_depth: 3
-# Jupyter notebooks
+# A list of plugins (with optional configuration settings) to use when building the site
plugins:
+ - autorefs
+ - inline-svg
+ - markdownextradata # Plugin that injects the mkdocs.yml extra variables into the Markdown template
+ - mike # Plugin that makes it easy to deploy multiple versions of the docs
- mkdocs-jupyter:
- execute_ignore:
- - '*.ipynb' # Do not execute any notebooks
-# - 'quick*.ipynb'
-# - 'basic*.ipynb'
-# - 'advanced*.ipynb'
-# - 'cryst*.ipynb'
-# - 'pdf*.ipynb'
+ include: ['*.ipynb'] # Default: ['*.py', '*.ipynb']
+ execute: false # Do not execute notebooks during build. They are expected to be pre-executed.
+ allow_errors: false
+ include_source: true
+ include_requirejs: true # Required for Plotly
+ #custom_mathjax_url: 'https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js' # See 'extra_javascript' above
+ ignore_h1_titles: true # Use titles defined in the nav section below
+ remove_tag_config:
+ remove_input_tags:
+ - hide-in-docs
+ - mkdocstrings:
+ handlers:
+ python:
+ paths: ['src'] # Change 'src' to your actual sources directory
+ options:
+ docstring_style: numpy
+ group_by_category: false
+ heading_level: 1
+ show_root_heading: true
+ show_root_full_path: false
+ show_submodules: true
+ show_source: true
+ - search
-##################
-# Add new settings
-##################
+# Determines additional directories to watch when running mkdocs serve
+watch:
+ - includes
+ - overrides
+ - ../src
# Exclude files and folders from the global navigation
not_in_nav: |
@@ -100,7 +222,6 @@ nav:
- experiment: api-reference/datablocks/experiment.md
- structure: api-reference/datablocks/structure.md
- display: api-reference/display.md
- - experiments: api-reference/experiment.md
- io: api-reference/io.md
- project: api-reference/project.md
- summary: api-reference/summary.md
diff --git a/docs/overrides/.icons/app.svg b/docs/overrides/.icons/app.svg
new file mode 100644
index 00000000..b4fdd4f3
--- /dev/null
+++ b/docs/overrides/.icons/app.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/docs/overrides/.icons/easydiffraction.svg b/docs/overrides/.icons/easydiffraction.svg
new file mode 100644
index 00000000..5813e570
--- /dev/null
+++ b/docs/overrides/.icons/easydiffraction.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docs/overrides/.icons/easyscience.svg b/docs/overrides/.icons/easyscience.svg
new file mode 100644
index 00000000..fb514912
--- /dev/null
+++ b/docs/overrides/.icons/easyscience.svg
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/overrides/.icons/google-colab.svg b/docs/overrides/.icons/google-colab.svg
new file mode 100644
index 00000000..9cd9d1b0
--- /dev/null
+++ b/docs/overrides/.icons/google-colab.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/docs/overrides/main.html b/docs/overrides/main.html
new file mode 100644
index 00000000..2e146827
--- /dev/null
+++ b/docs/overrides/main.html
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+{% if page.nb_url %}
+ {# Parse notebook path/URL #}
+ {% set parts = page.nb_url.split('/') %}
+ {% set tutorial_name = parts[-2] %}
+ {% set filename = parts[-1] %}
+
+ {# Colab url #}
+ {% set base_colab_url = "https://colab.research.google.com/github/" %}
+ {% set colab_url =
+ base_colab_url ~ config.extra.vars.github_repository ~
+ "/blob/gh-pages/" ~ config.extra.vars.docs_version ~
+ "/tutorials/" ~ tutorial_name ~ "/" ~ filename
+ %}
+
+ {# Download link: relative to the current page #}
+ {% set file_url = filename %}
+
+ {# Open in Colab (absolute GitHub URL; works anywhere) #}
+
+ {% include ".icons/google-colab.svg" %}
+
+
+ {# Download: use a RELATIVE link to the file next to this page #}
+
+ {% include ".icons/material/download.svg" %}
+
+{% endif %}
+
+{{ super() }}
+{% endblock content %}
diff --git a/docs/overrides/partials/logo.html b/docs/overrides/partials/logo.html
new file mode 100644
index 00000000..78fa69ca
--- /dev/null
+++ b/docs/overrides/partials/logo.html
@@ -0,0 +1,15 @@
+{% if ( config.theme.logo_light_mode and config.theme.logo_dark_mode ) %}
+
+
+{% elif config.theme.logo %}
+
+{% else %} {% set icon = config.theme.icon.logo or "material/library" %} {%
+include ".icons/" ~ icon ~ ".svg" %} {% endif %}
diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md
deleted file mode 100644
index a7c2cc37..00000000
--- a/docs/tutorials/index.md
+++ /dev/null
@@ -1,90 +0,0 @@
----
-icon: material/school
----
-
-# :material-school: Tutorials
-
-This section presents a collection of **Jupyter Notebook** tutorials that
-demonstrate how to use EasyDiffraction for various tasks. These tutorials serve
-as self-contained, step-by-step **guides** to help users grasp the workflow of
-diffraction data analysis using EasyDiffraction.
-
-Instructions on how to run the tutorials are provided in the
-[:material-cog-box: Installation & Setup](../installation-and-setup/index.md#how-to-run-tutorials)
-section of the documentation.
-
-The tutorials are organized into the following categories.
-
-## Getting Started
-
-- [LBCO `quick` CIF](ed-1.ipynb) – A minimal example intended as a quick
- reference for users already familiar with the EasyDiffraction API or who want
- to see how Rietveld refinement of the La0.5Ba0.5CoO3 crystal structure can be
- performed when both the structure and experiment are loaded from CIF files.
- Data collected from constant wavelength neutron powder diffraction at HRPT at
- PSI.
-- [LBCO `quick` `code`](ed-2.ipynb) – A minimal example intended as a quick
- reference for users already familiar with the EasyDiffraction API or who want
- to see an example refinement when both the structure and experiment are
- defined directly in code. This tutorial covers a Rietveld refinement of the
- La0.5Ba0.5CoO3 crystal structure using constant wavelength neutron powder
- diffraction data from HRPT at PSI.
-- [LBCO `complete`](ed-3.ipynb) – Demonstrates the use of the EasyDiffraction
- API in a simplified, user-friendly manner that closely follows the GUI
- workflow for a Rietveld refinement of the La0.5Ba0.5CoO3 crystal structure
- using constant wavelength neutron powder diffraction data from HRPT at PSI.
- This tutorial provides a full explanation of the workflow with detailed
- comments and descriptions of every step, making it suitable for users who are
- new to EasyDiffraction or those who prefer a more guided approach.
-
-## Powder Diffraction
-
-- [Co2SiO4 `pd-neut-cwl`](ed-5.ipynb) – Demonstrates a Rietveld refinement of
- the Co2SiO4 crystal structure using constant wavelength neutron powder
- diffraction data from D20 at ILL.
-- [HS `pd-neut-cwl`](ed-6.ipynb) – Demonstrates a Rietveld refinement of the HS
- crystal structure using constant wavelength neutron powder diffraction data
- from HRPT at PSI.
-- [Si `pd-neut-tof`](ed-7.ipynb) – Demonstrates a Rietveld refinement of the Si
- crystal structure using time-of-flight neutron powder diffraction data from
- SEPD at Argonne.
-- [NCAF `pd-neut-tof`](ed-8.ipynb) – Demonstrates a Rietveld refinement of the
- Na2Ca3Al2F14 crystal structure using two time-of-flight neutron powder
- diffraction datasets (from two detector banks) of the WISH instrument at ISIS.
-
-## Single Crystal Diffraction
-
-- [Tb2TiO7 `sg-neut-cwl`](ed-14.ipynb) – Demonstrates structure refinement of
- Tb2TiO7 using constant wavelength neutron single crystal diffraction data from
- HEiDi at FRM II.
-- [Taurine `sg-neut-tof`](ed-15.ipynb) – Demonstrates structure refinement of
- Taurine using time-of-flight neutron single crystal diffraction data from
- SENJU at J-PARC.
-
-## Pair Distribution Function (PDF)
-
-- [Ni `pd-neut-cwl`](ed-10.ipynb) – Demonstrates a PDF analysis of Ni using data
- collected from a constant wavelength neutron powder diffraction experiment.
-- [Si `pd-neut-tof`](ed-11.ipynb) – Demonstrates a PDF analysis of Si using data
- collected from a time-of-flight neutron powder diffraction experiment at NOMAD
- at SNS.
-- [NaCl `pd-xray`](ed-12.ipynb) – Demonstrates a PDF analysis of NaCl using data
- collected from an X-ray powder diffraction experiment.
-
-## Multi-Structure & Multi-Experiment Refinement
-
-- [PbSO4 NPD+XRD](ed-4.ipynb) – Joint fit of PbSO4 using X-ray and neutron
- constant wavelength powder diffraction data.
-- [LBCO+Si McStas](ed-9.ipynb) – Multi-phase Rietveld refinement of
- La0.5Ba0.5CoO3 with Si impurity using time-of-flight neutron data simulated
- with McStas.
-- [Si Bragg+PDF](ed-16.ipynb) – Joint refinement of Si combining Bragg
- diffraction (SEPD) and pair distribution function (NOMAD) analysis. A single
- shared structure is refined simultaneously against both datasets.
-
-## Workshops & Schools
-
-- [DMSC Summer School](ed-13.ipynb) – A workshop tutorial that demonstrates a
- Rietveld refinement of the La0.5Ba0.5CoO3 crystal structure using
- time-of-flight neutron powder diffraction data simulated with McStas. This
- tutorial is designed for the ESS DMSC Summer School.
diff --git a/docs/user-guide/analysis-workflow/index.md b/docs/user-guide/analysis-workflow/index.md
deleted file mode 100644
index 51c1f623..00000000
--- a/docs/user-guide/analysis-workflow/index.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Analysis Workflow
-
-To streamline the **data analysis process**, EasyDiffraction follows a
-structured workflow divided into **five key steps**:
-
-```mermaid
-flowchart LR
- a(Project)
- b(Model)
- c(Experiment)
- d(Analysis)
- e(Summary)
- a --> b
- b --> c
- c --> d
- d --> e
-```
-
-- [:material-archive: Project](project.md) – Establish a **project** as a
- container for structure and experiment parameters, measured and calculated
- data, analysis settings and results.
-- [:material-puzzle: Structure](model.md) – Load an existing **crystallographic
- model** in CIF format or define a new one from scratch.
-- [:material-microscope: Experiment](experiment.md) – Import **experimental
- diffraction data** and configure **instrumental** and other relevant
- parameters.
-- [:material-calculator: Analysis](analysis.md) – **Calculate the diffraction
- pattern** and **optimize the structural model** by refining its parameters to
- match experimental measurements.
-- [:material-clipboard-text: Summary](summary.md) – Generate a **report**
- summarizing the results of the analysis, including refined parameters.
-
-Each step is described in detail in its respective section, guiding users
-through the **entire diffraction data analysis workflow** in EasyDiffraction.
diff --git a/pixi.lock b/pixi.lock
index 1685316c..1b3db850 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -14,14 +14,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda
@@ -32,15 +32,15 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.12-hc97d973_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -53,16 +53,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -70,77 +70,86 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/0a/af49691938dfe175d71b8a929bd7e4ace2809c0c5134e28bc535660d5262/charset_normalizer-3.4.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/d1/3b/6103194ea934f1c3a4ea080905c8849f71e83de455c16cb625d25f49b779/chardet-7.4.0.post1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/2b/58/a199d245894b12db0b957d627516c78e055adc3a0d978bc7f65ddaf7c399/charset_normalizer-3.4.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/e4/dc/b2442d10020c2f52617828862d8b6ee337859cd8f3a1f13d607dddda9cf7/coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/af/3b86dbd18d8dab5646f5b7c7db5bd9c43108e093864032aabd35d41b127d/diffpy_pdffit2-1.5.2.tar.gz
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fb/bc/60d93477b653eeb1ddf5f9ec34be689b79234d82dbdded269ac0252715b8/fonttools-4.62.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e2/98/8b1e801939839d405f1f122e7d175cebe9aeb4e114f95bfc45e3152af9a7/fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/8c/db8e79c4c744ebae1dcf25f7dbcc5d7df912cdbcdf7221e761479e8bd04b/gemmi-0.7.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/98/ef2b6fe2903e377cbe870c3b2800d62552f1e3dbe81ce49e1923c53d1c5c/h5py-3.16.0-cp313-cp313-manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -164,10 +173,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -178,7 +187,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/28/83/36557b04cfdc317ed8a525c4993b23e43a8fbcddaddd78619112ca07138c/msgspec-0.20.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -202,12 +211,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/71/24/538bff45bde96535d7d998c6fed1a751c75ac7c53c37c90dc2601b243893/pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -226,15 +235,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -242,18 +252,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/d3/01/a10fe54b653061585e655f5286c2662ebddb68831ed3eaebfb0eb08c0a16/ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f8/22/d7f2fabdba4fae9f3b570e5605d5eb4500dcb7b770d3217dca4428484b17/ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/98/aa2d4b9d28969cc7f62409f9f9fc5b5a853af651255eba03e9bee8546dd9/scipp-25.12.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/2e/75/5604f4d17ab607510d4702f156329194d8edfff7e29644ca9200b085e9a2/scipp-26.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -262,7 +273,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/01/1c0485ae02e645bc517bf5d5a6ca674f62c97e247890b954cbfe85c64dae/spglib-2.6.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fe/88/cb59509e4668d8001818d7355d9995be90c321313078c912420603a7cb95/sqlalchemy-2.0.48-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -270,11 +283,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -284,10 +297,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/79/34/b104c413079874493eed7bf11838b47b697cf1f0ed7e9de374ea37b4e4e0/uv-0.10.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -309,14 +320,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/gsl-2.8-hc707ee6_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.2-h14c5de8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-6_he492b99_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.0-h19cb2f5_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-6_h9b27e0a_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.2-h19cb2f5_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.4-h991f03e_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda
@@ -325,14 +336,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.32-openmp_h9e49c7b_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.51.0-h58003a5_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.0-h0d3cbff_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.1-h0d3cbff_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.7.0-hf6efa0e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.8.2-hf3170e9_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.12-h894a449_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -345,17 +356,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -363,77 +374,86 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/48/9f34ec4bb24aa3fdba1890c1bddb97c8a4be1bd84ef5c42ac2352563ad05/charset_normalizer-3.4.5-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/e9/32/83a15c6077e7f240834ffd9ed78ef12f20f6e1924d7d7986d33f3d2af905/chardet-7.4.0.post1-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/1e/1d/4fdabeef4e231153b6ed7567602f3b68265ec4e5b76d6024cf647d43d981/charset_normalizer-3.4.6-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/db/23/aad45061a31677d68e47499197a131eea55da4875d16c1f42021ab963503/coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/19/eb/bb3ff420acdaf9bcaf94c510f42df11974bc3fc475ef50d619366f33fda3/diffpy_pdffit2-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c1/dc/c409c8ceec0d3119e9ab0b7b1a2e3c76d1f4d66e4a9db5c59e6b7652e7df/fonttools-4.62.0-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/03/c5/0e3966edd5ec668d41dfe418787726752bc07e2f5fd8c8f208615e61fa89/fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/80/fd758344a72ca7b5e1c5bbdc1d263f3b215d3897941b5f450380445ca0a9/gemmi-0.7.5-cp313-cp313-macosx_10_14_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/9e/6142ebfda0cb6e9349c091eae73c2e01a770b7659255248d637bec54a88b/h5py-3.16.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -457,10 +477,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -471,7 +491,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/8a/d1/b902d38b6e5ba3bdddbec469bba388d647f960aeed7b5b3623a8debe8a76/msgspec-0.20.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -495,12 +515,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/a1/16c4b823838ba4c9c52c0e6bbda903a3fe5a1bdbf1b8eb4fff7156f3e318/pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -519,15 +539,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -535,18 +556,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/44/ed/e81dd668547da281e5dce710cf0bc60193f8d3d43833e8241d006720e42b/ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/eb/92/f1c662784d149ad1414cae450b082cf736430c12ca78367f20f5ed569d65/ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/22/75e119e0a200914f88f121cd956e1eb7f72c8ace4b63171f52ba0334d142/scipp-25.12.0-cp313-cp313-macosx_11_0_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/e2/69/1dcb8e967f62759578938db5b29792b82ea8939a2d712e79491fa3e1cf0a/scipp-26.3.1-cp313-cp313-macosx_14_0_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl
@@ -555,7 +577,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a5/174d33068d4383df4be9ee1ea9251f17820a622f3be744ca2ab7334818ee/spglib-2.6.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -563,11 +587,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -577,10 +601,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6f/34/2e5cd576d312eb1131b615f49ee95ff6efb740965324843617adae729cf2/uv-0.10.9-py3-none-macosx_10_12_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -602,14 +624,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-hef89b57_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-6_h51639a9_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.0-h55c6f16_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-6_hb0561ab_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.2-h55c6f16_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda
@@ -618,14 +640,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.32-openmp_he657e61_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.0-hc7d1edf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.1-hc7d1edf_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.12-h20e6be0_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -638,17 +660,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -656,76 +678,85 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/48/9f34ec4bb24aa3fdba1890c1bddb97c8a4be1bd84ef5c42ac2352563ad05/charset_normalizer-3.4.5-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/83/d3/80554c1cc15631446c9b90aec6fe63b7310aa0b82d3004f7ba38bd8a8270/chardet-7.4.0.post1-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/1e/1d/4fdabeef4e231153b6ed7567602f3b68265ec4e5b76d6024cf647d43d981/charset_normalizer-3.4.6-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/a5/70/9b8b67a0945f3dfec1fd896c5cefb7c19d5a3a6d74630b99a895170999ae/coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/28/d050c2716c74c6fce9ace360e727e6f86b68212fb6b0ea57c005ebe574ea/diffpy_pdffit2-1.5.2-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/82/c7/985c1670aa6d82ef270f04cde11394c168f2002700353bd2bde405e59b8f/fonttools-4.62.0-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3b/56/6f389de21c49555553d6a5aeed5ac9767631497ac836c4f076273d15bd72/fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/9c/1236dd7d22ed48527286b613c84e3376ea731b65e6734b6e6a0b4d03744c/gemmi-0.7.5-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b0/65/5e088a45d0f43cd814bc5bec521c051d42005a472e804b1a36c48dada09b/h5py-3.16.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -749,10 +780,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -763,7 +794,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/57/b6/eff0305961a1d9447ec2b02f8c73c8946f22564d302a504185b730c9a761/msgspec-0.20.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -787,12 +818,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/ad/ad9dc98ff24f485008aa5cdedaf1a219876f6f6c42a4626c08bc4e80b120/pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -811,15 +842,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -827,18 +859,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/c4/8f/533075f00aaf19b07c5cd6aa6e5d89424b06b3b3f4583bfa9c640a079059/ruff-0.15.5-py3-none-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/ca/f2/7a631a8af6d88bcef997eb1bf87cc3da158294c57044aafd3e17030613de/ruff-0.15.8-py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/18/5c/bc0ca94bff65fe0d206a369b54625f8ec7852dfd1d835174692026f34df9/scipp-25.12.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/79/fe/b14d806894cf05178f1e77d0d619f071db50cf698bc654c54f9241223bcf/scipp-26.3.1-cp313-cp313-macosx_14_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl
@@ -847,7 +880,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/47/634fe8323c6c2bfa86e10eb41ebfe410db5e6231aa1727a31ce4f002480f/spglib-2.6.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/d1/c6/569dc8bf3cd375abc5907e82235923e986799f301cd79a903f784b996fca/sqlalchemy-2.0.48-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -855,11 +890,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -869,10 +904,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/89/35/684f641de4de2b20db7d2163c735b2bb211e3b3c84c241706d6448e5e868/uv-0.10.9-py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -892,8 +925,8 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-6_hf2e6a31_mkl.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-6_h2a3cdd5_mkl.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda
@@ -904,10 +937,10 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.0-h4fa8253_0.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.7.0-h80d1838_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.1-h4fa8253_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.1-hac47afa_11.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.12-h09917c8_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -923,16 +956,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -940,77 +973,86 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/0f/57072b253af40c8aa6636e6de7d75985624c1eb392815b2f934199340a89/charset_normalizer-3.4.5-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/91/d7/47988d40231b41376f5a66346ef3b322c81091dfd4c0f84df5a1e3bb06b5/chardet-7.4.0.post1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a1/5c/724b6b363603e419829f561c854b87ed7c7e31231a7908708ac086cdf3e2/charset_normalizer-3.4.6-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/e2/0c/dbfafbe90a185943dcfbc766fe0e1909f658811492d79b741523a414a6cc/coverage-7.13.4-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1f/0c/6826cb2151628c59cca66ca6089ff910ab3ccd62b0524c2b398dc145ee52/diffpy_pdffit2-1.5.2-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/7a/e25245a30457595740041dba9d0ea8ec1b2517f2f1a6a741f15eba1a4edc/fonttools-4.62.0-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/60/35186529de1db3c01f5ad625bde07c1f576305eab6d86bbda4c58445f721/fonttools-4.62.1-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/ab/7d7463cda94f8b68b969ea97aaad679655a0e436efd6a643e528a8de114e/gemmi-0.7.5-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/39/5ef5aa23bc545aa0d31e1b9b55822b32c8da93ba657295840b6b34124009/greenlet-3.3.2-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c3/d9/a27997f84341fc0dfcdd1fe4179b6ba6c32a7aa880fdb8c514d4dad6fba3/h5py-3.16.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -1034,10 +1076,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -1048,7 +1090,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f1/25/5e8080fe0117f799b1b68008dc29a65862077296b92550632de015128579/msgspec-0.20.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -1071,12 +1113,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/eb/b0834ad8b583d7d9d42b80becff092082a1c3c156bb582590fcc973f1c7c/pillow-12.1.1-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -1094,35 +1136,38 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d8/8b/e2bbeb42068f0c48899e8eddd34902afc0f7429d4d2a152d2dc2670dc661/pythreejs-2.4.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/b8/00/bf077a505b4e649bdd3c47ff8ec967735ce2544c8e4a43aba42ee9bf935d/ruff-0.15.5-py3-none-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/1f/a2/ef467cb77099062317154c63f234b8a7baf7cb690b99af760c5b68b9ee7f/ruff-0.15.8-py3-none-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/eb/d1/b3cd2733a96a36c54c36889b2cfdd0331c1e5b57fa1757485a22d0ec3142/scipp-25.12.0-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/37/fd/22621d3ee9e3ee87ef4c89b63bba55b265ab85039b3c1ba88ed2380a24c1/scipp-26.3.1-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl
@@ -1131,7 +1176,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/56/a31e8d3c9e8d21100b83bbe1c1f3f7c94db317393a229e193461e5e6d2a4/spglib-2.6.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/b7/2b/b9040bec58c58225f073f5b0c1870defe1940835549dafec680cbd58c3c3/sqlalchemy-2.0.48-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -1139,11 +1186,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -1153,10 +1200,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c9/e9/adf7a12136573937d12ac189569e2e90e7fad18b458192083df6986f3013/uv-0.10.9-py3-none-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -1172,7 +1217,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/84/266e8da36879c6edcd37b02b547e2d9ecdfea776be49598e75696e3316e1/yarl-1.23.0-cp313-cp313-win_amd64.whl
- pypi: ./
- py311-dev:
+ py-311-env:
channels:
- url: https://conda.anaconda.org/conda-forge/
indexes:
@@ -1186,14 +1231,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda
@@ -1203,17 +1248,17 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.15-hd63d673_0_cpython.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
@@ -1225,16 +1270,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/f0/35240571e1b67ffb19dafb29ab34150b6f59f93f717b041082cdb1bfceb1/backrefs-6.2-py311-none-any.whl
@@ -1242,78 +1287,87 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/f4/44d3b830a20e89ff82a3134912d9a1cf6084d64f3b95dcad40f74449a654/charset_normalizer-3.4.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/e3/a2/dab58511fbeef06dd88866568ea1a11b2f15654223cafc2681e2da84b1f2/chardet-7.4.0.post1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/60/ac/3233d262a310c1b12633536a07cde5ddd16985e6e7e238e9f3f9423d8eb9/charset_normalizer-3.4.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/76/53/c16972708cbb79f2942922571a687c52bd109a7bd51175aeb7558dff2236/coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/92/be/b1afb692be85b947f3401375851484496134c5554e67e822c35f28bf2fbc/coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/af/3b86dbd18d8dab5646f5b7c7db5bd9c43108e093864032aabd35d41b127d/diffpy_pdffit2-1.5.2.tar.gz
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/8a/d7/8e4845993ee233c2023d11babe9b3dae7d30333da1d792eeccebcb77baab/fonttools-4.62.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/cc/a1/40a5c4d8e28b0851d53a8eeeb46fbd73c325a2a9a165f290a5ed90e6c597/fonttools-4.62.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/48/eb/46e443fc70b4aabe6e775521ff476aefb051db9acabb16a5cb51f04e3e2b/gemmi-0.7.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/a0/c1f604538ff6db22a0690be2dc44ab59178e115f63c917794e529356ab23/h5py-3.16.0-cp311-cp311-manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -1337,10 +1391,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -1351,7 +1405,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/da/e0/6cc2e852837cd6086fe7d8406af4294e66827a60a4cf60b86575a4a65ca8/msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/6b/96/5c095b940de3aa6b43a71ec76275ac3537b21bd45c7499b5a17a429110fa/msgspec-0.20.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -1376,12 +1430,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a2/c8/46dfeac5825e600579157eea177be43e2f7ff4a99da9d0d0a49533509ac5/pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -1400,15 +1454,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -1416,18 +1471,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/c4/2a6fe5111a01005fc7af3878259ce17684fabb8852815eda6225620f3c59/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f8/1e/372195d326549bb51f0ba0f2ecb9874579906b97e08880e7a65c3bef1a99/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/d3/01/a10fe54b653061585e655f5286c2662ebddb68831ed3eaebfb0eb08c0a16/ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f8/22/d7f2fabdba4fae9f3b570e5605d5eb4500dcb7b770d3217dca4428484b17/ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4e/b6/ffe0bb67cec66cd450acff599bb07507bbf5ffda1a3a15dd2d8dbe7a6da7/scipp-25.12.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/d4/06/19ff1efd58b85906149ce83dfddce23252cea5bec7e0fa5f834336cfe836/scipp-26.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/7d/af933f0f6e0767995b4e2d705a0665e454d1c19402aa7e895de3951ebb04/scipy-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -1436,7 +1492,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/55/41/591cd1e94254c20f00bb1f32c0b1a6de68c03d54e6daf78dd7b146d0b3fc/spglib-2.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/21/dd/3b7c53f1dbbf736fd27041aee68f8ac52226b610f914085b1652c2323442/sqlalchemy-2.0.48-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -1444,11 +1502,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -1458,10 +1516,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/79/34/b104c413079874493eed7bf11838b47b697cf1f0ed7e9de374ea37b4e4e0/uv-0.10.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -1484,14 +1540,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/gsl-2.8-hc707ee6_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.2-h14c5de8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-6_he492b99_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.0-h19cb2f5_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-6_h9b27e0a_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.2-h19cb2f5_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.4-h991f03e_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda
@@ -1499,14 +1555,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.32-openmp_h9e49c7b_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.51.0-h58003a5_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.0-h0d3cbff_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.1-h0d3cbff_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.7.0-hf6efa0e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.8.2-hf3170e9_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.15-ha9537fe_0_cpython.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda
@@ -1518,17 +1574,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/f0/35240571e1b67ffb19dafb29ab34150b6f59f93f717b041082cdb1bfceb1/backrefs-6.2-py311-none-any.whl
@@ -1536,78 +1592,87 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/8f/9e/bcec3b22c64ecec47d39bf5167c2613efd41898c019dccd4183f6aa5d6a7/charset_normalizer-3.4.5-cp311-cp311-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/38/fe380893cbba72febb24d5dc0c2f9ac99f437153c36a409a8e254ed77bb6/chardet-7.4.0.post1-cp311-cp311-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/62/28/ff6f234e628a2de61c458be2779cb182bc03f6eec12200d4a525bbfc9741/charset_normalizer-3.4.6-cp311-cp311-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/b4/ad/b59e5b451cf7172b8d1043dc0fa718f23aab379bc1521ee13d4bd9bfa960/coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/9e/0e27056c6165ab3e2536d5efbc358cf495e6cd57fbaf51e68b1113fa7771/diffpy_pdffit2-1.5.2-cp311-cp311-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c0/7a/9aeec114bc9fc00d757a41f092f7107863d372e684a5b5724c043654477c/fonttools-4.62.0-cp311-cp311-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/24/7f/66d3f8a9338a9b67fe6e1739f47e1cd5cee78bd3bc1206ef9b0b982289a5/fonttools-4.62.1-cp311-cp311-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7f/79/b13830a65bf9fc85474a984604f094cc18817dc93a784f4c567a2dc05169/gemmi-0.7.5-cp311-cp311-macosx_10_14_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/95/a825894f3e45cbac7554c4e97314ce886b233a20033787eda755ca8fecc7/h5py-3.16.0-cp311-cp311-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -1631,10 +1696,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -1645,7 +1710,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2c/97/560d11202bcd537abca693fd85d81cebe2107ba17301de42b01ac1677b69/msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/03/59/fdcb3af72f750a8de2bcf39d62ada70b5eb17b06d7f63860e0a679cb656b/msgspec-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -1670,12 +1735,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/46/5da1ec4a5171ee7bf1a0efa064aba70ba3d6e0788ce3f5acd1375d23c8c0/pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -1694,15 +1759,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -1710,18 +1776,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4d/6e/f964e88b3d2abee2a82c1ac8366da848fce1c6d834dc2132c3fda3970290/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/44/ed/e81dd668547da281e5dce710cf0bc60193f8d3d43833e8241d006720e42b/ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/eb/92/f1c662784d149ad1414cae450b082cf736430c12ca78367f20f5ed569d65/ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/12/0d/3f98a936a30bff4a460b51b9f85c4d994f94249930b2d8bedeb8111a359e/scipp-25.12.0-cp311-cp311-macosx_11_0_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/81/21/4962b1daddf0422e56c5ed4c41bea1ccb6d2a9ab72b795196835a20969c7/scipp-26.3.1-cp311-cp311-macosx_14_0_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/e6/cef1cf3557f0c54954198554a10016b6a03b2ec9e22a4e1df734936bd99c/scipy-1.17.1-cp311-cp311-macosx_14_0_x86_64.whl
@@ -1730,7 +1797,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6c/44/30888e2a5b2fa2e6df18606b442cb8b126b0bea5a2f1ec4a2a82538ffecf/spglib-2.6.0-cp311-cp311-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -1738,11 +1807,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -1752,10 +1821,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6f/34/2e5cd576d312eb1131b615f49ee95ff6efb740965324843617adae729cf2/uv-0.10.9-py3-none-macosx_10_12_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -1778,14 +1845,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-hef89b57_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-6_h51639a9_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.0-h55c6f16_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-6_hb0561ab_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.2-h55c6f16_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda
@@ -1793,14 +1860,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.32-openmp_he657e61_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.0-hc7d1edf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.1-hc7d1edf_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.15-h8561d8f_0_cpython.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
@@ -1812,17 +1879,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/f0/35240571e1b67ffb19dafb29ab34150b6f59f93f717b041082cdb1bfceb1/backrefs-6.2-py311-none-any.whl
@@ -1830,77 +1897,86 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/8f/9e/bcec3b22c64ecec47d39bf5167c2613efd41898c019dccd4183f6aa5d6a7/charset_normalizer-3.4.5-cp311-cp311-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/5e/24/3c1522d777b66e2e3615ee33d1d4291c47b0ec258a9471b559339b01fac5/chardet-7.4.0.post1-cp311-cp311-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/62/28/ff6f234e628a2de61c458be2779cb182bc03f6eec12200d4a525bbfc9741/charset_normalizer-3.4.6-cp311-cp311-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/f1/17/0cb7ca3de72e5f4ef2ec2fa0089beafbcaaaead1844e8b8a63d35173d77d/coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ce/c9/7b61255980383781774d9857aa9e97fe7e9b8b08f97c0974afeef3083dd9/diffpy_pdffit2-1.5.2-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e4/33/63d79ca41020dd460b51f1e0f58ad1ff0a36b7bcbdf8f3971d52836581e9/fonttools-4.62.0-cp311-cp311-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/39/23ff32561ec8d45a4d48578b4d241369d9270dc50926c017570e60893701/fonttools-4.62.1-cp311-cp311-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/15/26cac702cdf6281ddeb185d5912ce14e555e277c6e4caeb1d36966e43822/gemmi-0.7.5-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bf/3b/38ff88b347c3e346cda1d3fc1b65a7aa75d40632228d8b8a5d7b58508c24/h5py-3.16.0-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -1924,10 +2000,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -1938,7 +2014,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/83/04/28a41024ccbd67467380b6fb440ae916c1e4f25e2cd4c63abe6835ac566e/msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/5a/15/3c225610da9f02505d37d69a77f4a2e7daae2a125f99d638df211ba84e59/msgspec-0.20.0-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -1963,12 +2039,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/93/a29e9bc02d1cf557a834da780ceccd54e02421627200696fcf805ebdc3fb/pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -1987,15 +2063,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -2003,18 +2080,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/ba/24e5ebb7c1c82e74c4e4f33b2112a5573ddc703915b13a073737b59b86e0/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/c4/8f/533075f00aaf19b07c5cd6aa6e5d89424b06b3b3f4583bfa9c640a079059/ruff-0.15.5-py3-none-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/ca/f2/7a631a8af6d88bcef997eb1bf87cc3da158294c57044aafd3e17030613de/ruff-0.15.8-py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6a/3a/ab0eb61593569d5a0d080002e4b8c0998cb1116d8710781b7225c304b880/scipp-25.12.0-cp311-cp311-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/60/54/5011adb56853caabfd90686c2e543d1e3c76a8ef2755809b7e12e3f3583b/scipp-26.3.1-cp311-cp311-macosx_14_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/ee/18146b7757ed4976276b9c9819108adbc73c5aad636e5353e20746b73069/scipy-1.17.1-cp311-cp311-macosx_14_0_arm64.whl
@@ -2023,7 +2101,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f6/ca/270d463f6c34f539bb55acdab14099c092d3be28c8af64d61399aa07610c/spglib-2.6.0-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/d7/6d/b8b78b5b80f3c3ab3f7fa90faa195ec3401f6d884b60221260fd4d51864c/sqlalchemy-2.0.48-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -2031,11 +2111,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -2045,10 +2125,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/89/35/684f641de4de2b20db7d2163c735b2bb211e3b3c84c241706d6448e5e868/uv-0.10.9-py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -2069,8 +2147,8 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-6_hf2e6a31_mkl.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-6_h2a3cdd5_mkl.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda
@@ -2080,10 +2158,10 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.0-h4fa8253_0.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.7.0-h80d1838_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.1-h4fa8253_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.1-hac47afa_11.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.15-h0159041_0_cpython.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda
@@ -2098,16 +2176,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/f0/35240571e1b67ffb19dafb29ab34150b6f59f93f717b041082cdb1bfceb1/backrefs-6.2-py311-none-any.whl
@@ -2115,78 +2193,87 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fe/1f/a853b73d386521fd44b7f67ded6b17b7b2367067d9106a5c4b44f9a34274/charset_normalizer-3.4.5-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/91/d7/47988d40231b41376f5a66346ef3b322c81091dfd4c0f84df5a1e3bb06b5/chardet-7.4.0.post1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c6/e3/76f2facfe8eddee0bbd38d2594e709033338eae44ebf1738bcefe0a06185/charset_normalizer-3.4.6-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/61/08/3d9c8613079d2b11c185b865de9a4c1a68850cfda2b357fae365cf609f29/coverage-7.13.4-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/af/7f/4cd8a92531253f9d7c1bbecd9fa1b472907fb54446ca768c59b531248dc5/coverage-7.13.5-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d5/92/1cb532e88560cbee973396254b21bece8c5d7c2ece958a67afa08c9f10dc/debugpy-1.8.20-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/33/fae9a52a6cb97efd21176303dfef44e487b56e3473c1329e019d5682d158/diffpy_pdffit2-1.5.2-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/77/ce/f5a4c42c117f8113ce04048053c128d17426751a508f26398110c993a074/fonttools-4.62.0-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d3/97/bf54c5b3f2be34e1f143e6db838dfdc54f2ffa3e68c738934c82f3b2a08d/fonttools-4.62.1-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b9/5e/62402bf021183bc6122cb01b8f1be17cac67545713fb30f888f59357a782/gemmi-0.7.5-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/3a/efb2cf697fbccdf75b24e2c18025e7dfa54c4f31fab75c51d0fe79942cef/greenlet-3.3.2-cp311-cp311-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f7/20/e6c0ff62ca2ad1a396a34f4380bafccaaf8791ff8fccf3d995a1fc12d417/h5py-3.16.0-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -2210,10 +2297,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -2224,7 +2311,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2a/79/309d0e637f6f37e83c711f547308b91af02b72d2326ddd860b966080ef29/msgpack-1.1.2-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/89/5e/406b7d578926b68790e390d83a1165a9bfc2d95612a1a9c1c4d5c72ea815/msgspec-0.20.0-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -2248,12 +2335,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/03/bef822e4f2d8f9d7448c133d0a18185d3cce3e70472774fffefe8b0ed562/pillow-12.1.1-cp311-cp311-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -2271,35 +2358,38 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d8/8b/e2bbeb42068f0c48899e8eddd34902afc0f7429d4d2a152d2dc2670dc661/pythreejs-2.4.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/79/c3/3e75075c7f71735f22b66fab0481f2c98e3a4d58cba55cb50ba29114bcf6/pywinpty-3.0.3-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fa/5b/e7b7aa136f28462b344e652ee010d4de26ee9fd16f1bfd5811f5153ccf89/rpds_py-0.30.0-cp311-cp311-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/b8/00/bf077a505b4e649bdd3c47ff8ec967735ce2544c8e4a43aba42ee9bf935d/ruff-0.15.5-py3-none-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/1f/a2/ef467cb77099062317154c63f234b8a7baf7cb690b99af760c5b68b9ee7f/ruff-0.15.8-py3-none-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/bd/75/6a3786de6645ac2ccd94fbf83c59cc6b929bfa3a89cb62c8cb3be4de0606/scipp-25.12.0-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/e6/0d/8882a4c7a5ebe59a46b709e82411d9c730d67250d41a2e11bc4bcd4d431d/scipp-26.3.1-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/95/da/0d1df507cf574b3f224ccc3d45244c9a1d732c81dcb26b1e8a766ae271a8/scipy-1.17.1-cp311-cp311-win_amd64.whl
@@ -2308,7 +2398,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/a8/d89e1bde525baba10eb8d0be79a5bbaf56c59a47b32bb954866d96a228e3/spglib-2.6.0-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/58/d5/dd767277f6feef12d05651538f280277e661698f617fa4d086cce6055416/sqlalchemy-2.0.48-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -2316,11 +2408,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -2330,10 +2422,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c9/e9/adf7a12136573937d12ac189569e2e90e7fad18b458192083df6986f3013/uv-0.10.9-py3-none-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -2350,7 +2440,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/93/22/b85eca6fa2ad9491af48c973e4c8cf6b103a73dbb271fe3346949449fca0/yarl-1.23.0-cp311-cp311-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl
- pypi: ./
- py313-dev:
+ py-313-env:
channels:
- url: https://conda.anaconda.org/conda-forge/
indexes:
@@ -2364,14 +2454,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda
@@ -2382,15 +2472,15 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.12-hc97d973_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -2403,16 +2493,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -2420,77 +2510,86 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/0a/af49691938dfe175d71b8a929bd7e4ace2809c0c5134e28bc535660d5262/charset_normalizer-3.4.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/d1/3b/6103194ea934f1c3a4ea080905c8849f71e83de455c16cb625d25f49b779/chardet-7.4.0.post1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/2b/58/a199d245894b12db0b957d627516c78e055adc3a0d978bc7f65ddaf7c399/charset_normalizer-3.4.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/e4/dc/b2442d10020c2f52617828862d8b6ee337859cd8f3a1f13d607dddda9cf7/coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/af/3b86dbd18d8dab5646f5b7c7db5bd9c43108e093864032aabd35d41b127d/diffpy_pdffit2-1.5.2.tar.gz
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fb/bc/60d93477b653eeb1ddf5f9ec34be689b79234d82dbdded269ac0252715b8/fonttools-4.62.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e2/98/8b1e801939839d405f1f122e7d175cebe9aeb4e114f95bfc45e3152af9a7/fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/8c/db8e79c4c744ebae1dcf25f7dbcc5d7df912cdbcdf7221e761479e8bd04b/gemmi-0.7.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/98/ef2b6fe2903e377cbe870c3b2800d62552f1e3dbe81ce49e1923c53d1c5c/h5py-3.16.0-cp313-cp313-manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -2514,10 +2613,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -2528,7 +2627,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/28/83/36557b04cfdc317ed8a525c4993b23e43a8fbcddaddd78619112ca07138c/msgspec-0.20.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -2552,12 +2651,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/71/24/538bff45bde96535d7d998c6fed1a751c75ac7c53c37c90dc2601b243893/pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -2576,15 +2675,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -2592,18 +2692,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/d3/01/a10fe54b653061585e655f5286c2662ebddb68831ed3eaebfb0eb08c0a16/ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f8/22/d7f2fabdba4fae9f3b570e5605d5eb4500dcb7b770d3217dca4428484b17/ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/98/aa2d4b9d28969cc7f62409f9f9fc5b5a853af651255eba03e9bee8546dd9/scipp-25.12.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/2e/75/5604f4d17ab607510d4702f156329194d8edfff7e29644ca9200b085e9a2/scipp-26.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -2612,7 +2713,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/01/1c0485ae02e645bc517bf5d5a6ca674f62c97e247890b954cbfe85c64dae/spglib-2.6.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fe/88/cb59509e4668d8001818d7355d9995be90c321313078c912420603a7cb95/sqlalchemy-2.0.48-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -2620,11 +2723,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -2634,10 +2737,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/79/34/b104c413079874493eed7bf11838b47b697cf1f0ed7e9de374ea37b4e4e0/uv-0.10.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -2659,14 +2760,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/gsl-2.8-hc707ee6_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.2-h14c5de8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260107.1-cxx17_h7ed6875_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-6_he492b99_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.0-h19cb2f5_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-6_h9b27e0a_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.2-h19cb2f5_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.4-h991f03e_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda
@@ -2675,14 +2776,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.32-openmp_h9e49c7b_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.51.0-h58003a5_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.0-h0d3cbff_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.1-h0d3cbff_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.7.0-hf6efa0e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.8.2-hf3170e9_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.12-h894a449_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -2695,17 +2796,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -2713,77 +2814,86 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/48/9f34ec4bb24aa3fdba1890c1bddb97c8a4be1bd84ef5c42ac2352563ad05/charset_normalizer-3.4.5-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/e9/32/83a15c6077e7f240834ffd9ed78ef12f20f6e1924d7d7986d33f3d2af905/chardet-7.4.0.post1-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/1e/1d/4fdabeef4e231153b6ed7567602f3b68265ec4e5b76d6024cf647d43d981/charset_normalizer-3.4.6-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/db/23/aad45061a31677d68e47499197a131eea55da4875d16c1f42021ab963503/coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/19/eb/bb3ff420acdaf9bcaf94c510f42df11974bc3fc475ef50d619366f33fda3/diffpy_pdffit2-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c1/dc/c409c8ceec0d3119e9ab0b7b1a2e3c76d1f4d66e4a9db5c59e6b7652e7df/fonttools-4.62.0-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/03/c5/0e3966edd5ec668d41dfe418787726752bc07e2f5fd8c8f208615e61fa89/fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/80/fd758344a72ca7b5e1c5bbdc1d263f3b215d3897941b5f450380445ca0a9/gemmi-0.7.5-cp313-cp313-macosx_10_14_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/9e/6142ebfda0cb6e9349c091eae73c2e01a770b7659255248d637bec54a88b/h5py-3.16.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -2807,10 +2917,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -2821,7 +2931,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/8a/d1/b902d38b6e5ba3bdddbec469bba388d647f960aeed7b5b3623a8debe8a76/msgspec-0.20.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -2845,12 +2955,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/a1/16c4b823838ba4c9c52c0e6bbda903a3fe5a1bdbf1b8eb4fff7156f3e318/pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -2869,15 +2979,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -2885,18 +2996,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/44/ed/e81dd668547da281e5dce710cf0bc60193f8d3d43833e8241d006720e42b/ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/eb/92/f1c662784d149ad1414cae450b082cf736430c12ca78367f20f5ed569d65/ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/22/75e119e0a200914f88f121cd956e1eb7f72c8ace4b63171f52ba0334d142/scipp-25.12.0-cp313-cp313-macosx_11_0_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/e2/69/1dcb8e967f62759578938db5b29792b82ea8939a2d712e79491fa3e1cf0a/scipp-26.3.1-cp313-cp313-macosx_14_0_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl
@@ -2905,7 +3017,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a5/174d33068d4383df4be9ee1ea9251f17820a622f3be744ca2ab7334818ee/spglib-2.6.0-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -2913,11 +3027,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -2927,10 +3041,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6f/34/2e5cd576d312eb1131b615f49ee95ff6efb740965324843617adae729cf2/uv-0.10.9-py3-none-macosx_10_12_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -2952,14 +3064,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-hef89b57_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-6_h51639a9_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.0-h55c6f16_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-6_hb0561ab_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.2-h55c6f16_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda
@@ -2968,14 +3080,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_18.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.32-openmp_he657e61_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.0-hc7d1edf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.1-hc7d1edf_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.12-h20e6be0_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -2988,17 +3100,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -3006,76 +3118,85 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/48/9f34ec4bb24aa3fdba1890c1bddb97c8a4be1bd84ef5c42ac2352563ad05/charset_normalizer-3.4.5-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/83/d3/80554c1cc15631446c9b90aec6fe63b7310aa0b82d3004f7ba38bd8a8270/chardet-7.4.0.post1-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/1e/1d/4fdabeef4e231153b6ed7567602f3b68265ec4e5b76d6024cf647d43d981/charset_normalizer-3.4.6-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/a5/70/9b8b67a0945f3dfec1fd896c5cefb7c19d5a3a6d74630b99a895170999ae/coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/28/d050c2716c74c6fce9ace360e727e6f86b68212fb6b0ea57c005ebe574ea/diffpy_pdffit2-1.5.2-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/82/c7/985c1670aa6d82ef270f04cde11394c168f2002700353bd2bde405e59b8f/fonttools-4.62.0-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3b/56/6f389de21c49555553d6a5aeed5ac9767631497ac836c4f076273d15bd72/fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/9c/1236dd7d22ed48527286b613c84e3376ea731b65e6734b6e6a0b4d03744c/gemmi-0.7.5-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b0/65/5e088a45d0f43cd814bc5bec521c051d42005a472e804b1a36c48dada09b/h5py-3.16.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -3099,10 +3220,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -3113,7 +3234,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/57/b6/eff0305961a1d9447ec2b02f8c73c8946f22564d302a504185b730c9a761/msgspec-0.20.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -3137,12 +3258,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/ad/ad9dc98ff24f485008aa5cdedaf1a219876f6f6c42a4626c08bc4e80b120/pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -3161,15 +3282,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
@@ -3177,18 +3299,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/c4/8f/533075f00aaf19b07c5cd6aa6e5d89424b06b3b3f4583bfa9c640a079059/ruff-0.15.5-py3-none-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/ca/f2/7a631a8af6d88bcef997eb1bf87cc3da158294c57044aafd3e17030613de/ruff-0.15.8-py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/18/5c/bc0ca94bff65fe0d206a369b54625f8ec7852dfd1d835174692026f34df9/scipp-25.12.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/79/fe/b14d806894cf05178f1e77d0d619f071db50cf698bc654c54f9241223bcf/scipp-26.3.1-cp313-cp313-macosx_14_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl
@@ -3197,7 +3320,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/47/634fe8323c6c2bfa86e10eb41ebfe410db5e6231aa1727a31ce4f002480f/spglib-2.6.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/d1/c6/569dc8bf3cd375abc5907e82235923e986799f301cd79a903f784b996fca/sqlalchemy-2.0.48-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -3205,11 +3330,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -3219,10 +3344,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/89/35/684f641de4de2b20db7d2163c735b2bb211e3b3c84c241706d6448e5e868/uv-0.10.9-py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -3242,8 +3365,8 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-6_hf2e6a31_mkl.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-6_h2a3cdd5_mkl.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda
@@ -3254,10 +3377,10 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.0-h4fa8253_0.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda
- - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.7.0-h80d1838_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.1-h4fa8253_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.1-hac47afa_11.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.12-h09917c8_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
@@ -3273,16 +3396,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c5/71/c754b1737ad99102e03fa3235acb6cb6d3ac9d6f596cbc3e5f236705abd8/backrefs-6.2-py313-none-any.whl
@@ -3290,77 +3413,86 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/0f/57072b253af40c8aa6636e6de7d75985624c1eb392815b2f934199340a89/charset_normalizer-3.4.5-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/91/d7/47988d40231b41376f5a66346ef3b322c81091dfd4c0f84df5a1e3bb06b5/chardet-7.4.0.post1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a1/5c/724b6b363603e419829f561c854b87ed7c7e31231a7908708ac086cdf3e2/charset_normalizer-3.4.6-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/e2/0c/dbfafbe90a185943dcfbc766fe0e1909f658811492d79b741523a414a6cc/coverage-7.13.4-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/52/e8/c14cc8af8cd38e86887053843382629bd8ebd117f83f15eb1194d65a2c9d/cryspy-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1f/0c/6826cb2151628c59cca66ca6089ff910ab3ccd62b0524c2b398dc145ee52/diffpy_pdffit2-1.5.2-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/8e/52/39914bf42bb01901c91781def35c1aeffa431a59299e9748c0cfae3e5493/diffpy_structure-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/7a/e25245a30457595740041dba9d0ea8ec1b2517f2f1a6a741f15eba1a4edc/fonttools-4.62.0-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/60/35186529de1db3c01f5ad625bde07c1f576305eab6d86bbda4c58445f721/fonttools-4.62.1-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/ab/7d7463cda94f8b68b969ea97aaad679655a0e436efd6a643e528a8de114e/gemmi-0.7.5-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/39/5ef5aa23bc545aa0d31e1b9b55822b32c8da93ba657295840b6b34124009/greenlet-3.3.2-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c3/d9/a27997f84341fc0dfcdd1fe4179b6ba6c32a7aa880fdb8c514d4dad6fba3/h5py-3.16.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/90/45c72becc57158facc6a6404f663b77bbcea2519ca57f760e2879ae1315d/ipython-9.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl
@@ -3384,10 +3516,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/41/1cf02e3df279d2dd846a1bf235a928254eba9006dd22b4a14caa71aed0f7/mkdocstrings-1.0.3-py3-none-any.whl
@@ -3398,7 +3530,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f1/25/5e8080fe0117f799b1b68008dc29a65862077296b92550632de015128579/msgspec-0.20.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl
@@ -3421,12 +3553,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3f/eb/b0834ad8b583d7d9d42b80becff092082a1c3c156bb582590fcc973f1c7c/pillow-12.1.1-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl
@@ -3444,35 +3576,38 @@ environments:
- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6f/2c/5b079febdc65e1c3fb2729bf958d18b45be7113828528e8a0b5850dd819a/pymdown_extensions-10.21-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d8/8b/e2bbeb42068f0c48899e8eddd34902afc0f7429d4d2a152d2dc2670dc661/pythreejs-2.4.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl
- - pypi: https://files.pythonhosted.org/packages/b8/00/bf077a505b4e649bdd3c47ff8ec967735ce2544c8e4a43aba42ee9bf935d/ruff-0.15.5-py3-none-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/1f/a2/ef467cb77099062317154c63f234b8a7baf7cb690b99af760c5b68b9ee7f/ruff-0.15.8-py3-none-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/eb/d1/b3cd2733a96a36c54c36889b2cfdd0331c1e5b57fa1757485a22d0ec3142/scipp-25.12.0-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/37/fd/22621d3ee9e3ee87ef4c89b63bba55b265ab85039b3c1ba88ed2380a24c1/scipp-26.3.1-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/fb/46/e50b38629e9e3f4a1dd55fb36d8b8abd1d59768c31151c1c8ed696f7b865/scippneutron-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl
@@ -3481,7 +3616,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/56/a31e8d3c9e8d21100b83bbe1c1f3f7c94db317393a229e193461e5e6d2a4/spglib-2.6.0-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/b7/2b/b9040bec58c58225f073f5b0c1870defe1940835549dafec680cbd58c3c3/sqlalchemy-2.0.48-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
@@ -3489,11 +3626,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl
@@ -3503,10 +3640,8 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c9/e9/adf7a12136573937d12ac189569e2e90e7fad18b458192083df6986f3013/uv-0.10.9-py3-none-win_amd64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bc/4a/c6fd02a642bbe4e9f25cdd3714a328e3fc3eb6bd7b5e96f1a2285bd928b9/varname-0.15.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl
@@ -3728,17 +3863,16 @@ packages:
requires_dist:
- typing-extensions>=4.0.0 ; python_full_version < '3.9'
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl
name: anyio
- version: 4.12.1
- sha256: d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c
+ version: 4.13.0
+ sha256: 08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708
requires_dist:
- exceptiongroup>=1.0.2 ; python_full_version < '3.11'
- idna>=2.8
- typing-extensions>=4.5 ; python_full_version < '3.13'
- - trio>=0.32.0 ; python_full_version >= '3.10' and extra == 'trio'
- - trio>=0.31.0 ; python_full_version < '3.10' and extra == 'trio'
- requires_python: '>=3.9'
+ - trio>=0.32.0 ; extra == 'trio'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
name: appnope
version: 0.1.4
@@ -3811,16 +3945,17 @@ packages:
requires_dist:
- setuptools
- flake8 ; extra == 'qa'
-- pypi: https://files.pythonhosted.org/packages/3e/9b/9b55b4d4855743de61ba91566d03b2560285ed8fc0387b9cf914795d4abf/ase-3.27.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl
name: ase
- version: 3.27.0
- sha256: 058c48ea504fe7fbbe7c932f778415243ef2df45b1ab869866f24efcc17f0538
+ version: 3.28.0
+ sha256: 0e24056302d7307b7247f90de281de15e3031c14cf400bedb1116c3b0d0e50b8
requires_dist:
- numpy>=1.21.6
- scipy>=1.8.1
- matplotlib>=3.5.2
- sphinx ; extra == 'docs'
- sphinx-book-theme ; extra == 'docs'
+ - sphinxcontrib-video ; extra == 'docs'
- sphinx-gallery ; extra == 'docs'
- pillow ; extra == 'docs'
- pytest>=7.4.0 ; extra == 'test'
@@ -3855,17 +3990,17 @@ packages:
- pytest-cov ; extra == 'test'
- pytest-xdist ; extra == 'test'
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl
name: async-lru
- version: 2.2.0
- sha256: e2c1cf731eba202b59c5feedaef14ffd9d02ad0037fcda64938699f2c380eafe
+ version: 2.3.0
+ sha256: eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315
requires_dist:
- typing-extensions>=4.0.0 ; python_full_version < '3.11'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl
name: attrs
- version: 25.4.0
- sha256: adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373
+ version: 26.1.0
+ sha256: c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309
requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl
name: autopep8
@@ -3935,10 +4070,10 @@ packages:
version: 1.9.0
sha256: ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl
name: build
- version: 1.4.0
- sha256: 6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596
+ version: 1.4.2
+ sha256: 7a4d8651ea877cb2a89458b1b198f2e69f536c95e89129dbf5d448045d60db88
requires_dist:
- packaging>=24.0
- pyproject-hooks
@@ -4136,35 +4271,70 @@ packages:
version: 3.5.0
sha256: a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/03/f4/44d3b830a20e89ff82a3134912d9a1cf6084d64f3b95dcad40f74449a654/charset_normalizer-3.4.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/3e/38/fe380893cbba72febb24d5dc0c2f9ac99f437153c36a409a8e254ed77bb6/chardet-7.4.0.post1-cp311-cp311-macosx_10_9_x86_64.whl
+ name: chardet
+ version: 7.4.0.post1
+ sha256: 2769be12361a6c7873392e435c708eca88c9f0fb6a647af75fa1386db64032d6
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/5e/24/3c1522d777b66e2e3615ee33d1d4291c47b0ec258a9471b559339b01fac5/chardet-7.4.0.post1-cp311-cp311-macosx_11_0_arm64.whl
+ name: chardet
+ version: 7.4.0.post1
+ sha256: 8e1eaa942ae81d43d535092ff3ba660c967344178cc3876b54834a56c1207f3a
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/83/d3/80554c1cc15631446c9b90aec6fe63b7310aa0b82d3004f7ba38bd8a8270/chardet-7.4.0.post1-cp313-cp313-macosx_11_0_arm64.whl
+ name: chardet
+ version: 7.4.0.post1
+ sha256: e6285d35f79d0cdc8838d3cb01876f979c8419a74662e8de39444e40639e0b2b
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/91/d7/47988d40231b41376f5a66346ef3b322c81091dfd4c0f84df5a1e3bb06b5/chardet-7.4.0.post1-py3-none-any.whl
+ name: chardet
+ version: 7.4.0.post1
+ sha256: 57a62ef50f69bc2fb3a3ea1ffffec6d10f3d2112d3b05d6e3cb15c2c9b55f6cc
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/d1/3b/6103194ea934f1c3a4ea080905c8849f71e83de455c16cb625d25f49b779/chardet-7.4.0.post1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: chardet
+ version: 7.4.0.post1
+ sha256: 329aa8766c4917d3acc1b1d0462f0b2e820e24e9f341d0f858aee85396ae3002
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/e3/a2/dab58511fbeef06dd88866568ea1a11b2f15654223cafc2681e2da84b1f2/chardet-7.4.0.post1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: chardet
+ version: 7.4.0.post1
+ sha256: ad98a6c2e61624b1120919353d222121b8f5848b9d33c885d949fe0235575682
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/e9/32/83a15c6077e7f240834ffd9ed78ef12f20f6e1924d7d7986d33f3d2af905/chardet-7.4.0.post1-cp313-cp313-macosx_10_13_x86_64.whl
+ name: chardet
+ version: 7.4.0.post1
+ sha256: efdb3785c8700b3d0b354553827a166480a439f9754f7366f795bbe8b42d6daf
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/1e/1d/4fdabeef4e231153b6ed7567602f3b68265ec4e5b76d6024cf647d43d981/charset_normalizer-3.4.6-cp313-cp313-macosx_10_13_universal2.whl
name: charset-normalizer
- version: 3.4.5
- sha256: 5bcb3227c3d9aaf73eaaab1db7ccd80a8995c509ee9941e2aae060ca6e4e5d81
+ version: 3.4.6
+ sha256: 11afb56037cbc4b1555a34dd69151e8e069bee82e613a73bef6e714ce733585f
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/8f/9e/bcec3b22c64ecec47d39bf5167c2613efd41898c019dccd4183f6aa5d6a7/charset_normalizer-3.4.5-cp311-cp311-macosx_10_9_universal2.whl
+- pypi: https://files.pythonhosted.org/packages/2b/58/a199d245894b12db0b957d627516c78e055adc3a0d978bc7f65ddaf7c399/charset_normalizer-3.4.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: charset-normalizer
- version: 3.4.5
- sha256: 610f72c0ee565dfb8ae1241b666119582fdbfe7c0975c175be719f940e110694
+ version: 3.4.6
+ sha256: 530e8cebeea0d76bdcf93357aa5e41336f48c3dc709ac52da2bb167c5b8271d9
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/94/0a/af49691938dfe175d71b8a929bd7e4ace2809c0c5134e28bc535660d5262/charset_normalizer-3.4.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/60/ac/3233d262a310c1b12633536a07cde5ddd16985e6e7e238e9f3f9423d8eb9/charset_normalizer-3.4.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: charset-normalizer
- version: 3.4.5
- sha256: 0625665e4ebdddb553ab185de5db7054393af8879fb0c87bd5690d14379d6819
+ version: 3.4.6
+ sha256: 9cc4fc6c196d6a8b76629a70ddfcd4635a6898756e2d9cac5565cf0654605d73
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/b9/0f/57072b253af40c8aa6636e6de7d75985624c1eb392815b2f934199340a89/charset_normalizer-3.4.5-cp313-cp313-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/62/28/ff6f234e628a2de61c458be2779cb182bc03f6eec12200d4a525bbfc9741/charset_normalizer-3.4.6-cp311-cp311-macosx_10_9_universal2.whl
name: charset-normalizer
- version: 3.4.5
- sha256: e37bd100d2c5d3ba35db9c7c5ba5a9228cbcffe5c4778dc824b164e5257813d7
+ version: 3.4.6
+ sha256: 82060f995ab5003a2d6e0f4ad29065b7672b6593c8c63559beefe5b443242c3e
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/f5/48/9f34ec4bb24aa3fdba1890c1bddb97c8a4be1bd84ef5c42ac2352563ad05/charset_normalizer-3.4.5-cp313-cp313-macosx_10_13_universal2.whl
+- pypi: https://files.pythonhosted.org/packages/a1/5c/724b6b363603e419829f561c854b87ed7c7e31231a7908708ac086cdf3e2/charset_normalizer-3.4.6-cp313-cp313-win_amd64.whl
name: charset-normalizer
- version: 3.4.5
- sha256: ac59c15e3f1465f722607800c68713f9fbc2f672b9eb649fe831da4019ae9b23
+ version: 3.4.6
+ sha256: 572d7c822caf521f0525ba1bce1a622a0b85cf47ffbdae6c9c19e3b5ac3c4389
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/fe/1f/a853b73d386521fd44b7f67ded6b17b7b2367067d9106a5c4b44f9a34274/charset_normalizer-3.4.5-cp311-cp311-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/c6/e3/76f2facfe8eddee0bbd38d2594e709033338eae44ebf1738bcefe0a06185/charset_normalizer-3.4.6-cp311-cp311-win_amd64.whl
name: charset-normalizer
- version: 3.4.5
- sha256: f8102ae93c0bc863b1d41ea0f4499c20a83229f52ed870850892df555187154a
+ version: 3.4.6
+ sha256: a9e68c9d88823b274cf1e72f28cb5dc89c990edf430b0bfd3e2fb0785bfeabf4
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
name: click
@@ -4390,59 +4560,79 @@ packages:
- pytest-xdist ; extra == 'test-no-images'
- wurlitzer ; extra == 'test-no-images'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/61/08/3d9c8613079d2b11c185b865de9a4c1a68850cfda2b357fae365cf609f29/coverage-7.13.4-cp311-cp311-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/df/91/4a151c94320458895049a3e23b7b2cfc08953c60b14892de837e8eb51d0a/copier-9.14.0-py3-none-any.whl
+ name: copier
+ version: 9.14.0
+ sha256: e12a18cfef22e67254e5229f0b4bdab85e1e3e82926e448226be0b70d0f4de53
+ requires_dist:
+ - colorama>=0.4.6
+ - dunamai>=1.7.0
+ - funcy>=1.17
+ - jinja2-ansible-filters>=1.3.1
+ - jinja2>=3.1.5
+ - packaging>=23.0
+ - pathspec>=0.9.0
+ - platformdirs>=4.3.6
+ - plumbum>=1.6.9
+ - pydantic>=2.4.2
+ - pygments>=2.7.1
+ - pyyaml>=5.3.1
+ - questionary>=1.8.1
+ - typing-extensions>=4.0.0,<5.0.0 ; python_full_version < '3.11'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl
name: coverage
- version: 7.13.4
- sha256: 2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f
+ version: 7.13.5
+ sha256: 941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/76/53/c16972708cbb79f2942922571a687c52bd109a7bd51175aeb7558dff2236/coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl
name: coverage
- version: 7.13.4
- sha256: 8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7
+ version: 7.13.5
+ sha256: 145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/a5/70/9b8b67a0945f3dfec1fd896c5cefb7c19d5a3a6d74630b99a895170999ae/coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl
name: coverage
- version: 7.13.4
- sha256: 3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac
+ version: 7.13.5
+ sha256: 66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/b4/ad/b59e5b451cf7172b8d1043dc0fa718f23aab379bc1521ee13d4bd9bfa960/coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl
name: coverage
- version: 7.13.4
- sha256: d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053
+ version: 7.13.5
+ sha256: 631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/db/23/aad45061a31677d68e47499197a131eea55da4875d16c1f42021ab963503/coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl
name: coverage
- version: 7.13.4
- sha256: b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9
+ version: 7.13.5
+ sha256: 5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/e2/0c/dbfafbe90a185943dcfbc766fe0e1909f658811492d79b741523a414a6cc/coverage-7.13.4-cp313-cp313-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/92/be/b1afb692be85b947f3401375851484496134c5554e67e822c35f28bf2fbc/coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
name: coverage
- version: 7.13.4
- sha256: e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd
+ version: 7.13.5
+ sha256: ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/e4/dc/b2442d10020c2f52617828862d8b6ee337859cd8f3a1f13d607dddda9cf7/coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
name: coverage
- version: 7.13.4
- sha256: b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b
+ version: 7.13.5
+ sha256: 78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/f1/17/0cb7ca3de72e5f4ef2ec2fa0089beafbcaaaead1844e8b8a63d35173d77d/coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/af/7f/4cd8a92531253f9d7c1bbecd9fa1b472907fb54446ca768c59b531248dc5/coverage-7.13.5-cp311-cp311-win_amd64.whl
name: coverage
- version: 7.13.4
- sha256: 19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11
+ version: 7.13.5
+ sha256: 258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9
requires_dist:
- tomli ; python_full_version <= '3.11' and extra == 'toml'
requires_python: '>=3.10'
@@ -4482,10 +4672,10 @@ packages:
requires_dist:
- pyobjc-framework-cocoa ; sys_platform == 'darwin' and extra == 'macos-listener'
requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl
name: dask
- version: 2026.1.2
- sha256: 46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91
+ version: 2026.3.0
+ sha256: be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d
requires_dist:
- click>=8.1
- cloudpickle>=3.0.0
@@ -4499,7 +4689,7 @@ packages:
- dask[array] ; extra == 'dataframe'
- pandas>=2.0 ; extra == 'dataframe'
- pyarrow>=16.0 ; extra == 'dataframe'
- - distributed>=2026.1.2,<2026.1.3 ; extra == 'distributed'
+ - distributed>=2026.3.0,<2026.3.1 ; extra == 'distributed'
- bokeh>=3.1.0 ; extra == 'diagnostics'
- jinja2>=2.10.3 ; extra == 'diagnostics'
- dask[array,dataframe,diagnostics,distributed] ; extra == 'complete'
@@ -4539,10 +4729,10 @@ packages:
version: 0.7.1
sha256: a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*'
-- pypi: https://files.pythonhosted.org/packages/13/40/e412e277c43983693456d7f11f2bc72ca9209aa1342255bb446496d2fb48/dfo_ls-1.6.2-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl
name: dfo-ls
- version: 1.6.2
- sha256: 961d15e7194f3868e9e48da45010cb6d24d85491007fbee4e38a9f3ab8050cef
+ version: 1.6.5
+ sha256: d147d42e471e240f9abf8bc38351a88f555ea6a8fcfd83119bbbf93c36f75ab2
requires_dist:
- setuptools
- numpy
@@ -4610,15 +4800,15 @@ packages:
- numpy
- pycifrw
requires_python: '>=3.11,<3.14'
-- pypi: https://files.pythonhosted.org/packages/3f/5e/fcb9a14641d65d9fc79efd7c97eef38aa8f1d99c7cef657b6aedd742efef/diffpy_utils-3.7.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl
name: diffpy-utils
- version: 3.7.1
- sha256: 8bf33eb3e228bf6a18242e4cc01cf4b7bff307fbef90f745bf7d680c7ed4d3b7
+ version: 3.7.2
+ sha256: 6100600736791a8e4638e3dd476704f4dabe3cab75bcb5c60c83c16a2032519a
requires_dist:
- numpy
- xraydb
- scipy
- requires_python: '>=3.11,<3.15'
+ requires_python: '>=3.10,<3.15'
- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl
name: dill
version: 0.4.1
@@ -4658,33 +4848,49 @@ packages:
- trio>=0.30 ; extra == 'trio'
- wmi>=1.5.1 ; sys_platform == 'win32' and extra == 'wmi'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl
- name: docformatter
- version: 1.7.7
- sha256: 7af49f8a46346a77858f6651f431b882c503c2f4442c8b4524b920c863277834
- requires_dist:
- - charset-normalizer>=3.0.0,<4.0.0
- - tomli>=2.0.0,<3.0.0 ; python_full_version < '3.11' and extra == 'tomli'
- - untokenize>=0.1.1,<0.2.0
- requires_python: '>=3.9,<4.0'
+- pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl
+ name: docstring-parser-fork
+ version: 0.0.14
+ sha256: 4c544f234ef2cc2749a3df32b70c437d77888b1099143a1ad5454452c574b9af
+ requires_dist:
+ - docstring-parser[docs] ; extra == 'dev'
+ - docstring-parser[test] ; extra == 'dev'
+ - pre-commit>=2.16.0 ; python_full_version >= '3.9' and extra == 'dev'
+ - pydoctor>=25.4.0 ; extra == 'docs'
+ - pytest ; extra == 'test'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl
+ name: dunamai
+ version: 1.26.0
+ sha256: f584edf0fda0d308cce0961f807bc90a8fe3d9ff4d62f94e72eca7b43f0ed5f6
+ requires_dist:
+ - importlib-metadata>=1.6.0 ; python_full_version < '3.8'
+ - packaging>=20.9
+ requires_python: '>=3.5'
- pypi: ./
name: easydiffraction
- version: 0.10.2+devdirty36
- sha256: c26412f987f3f60607ea00f77d4f12aadc3b38ea31833f634b218e09965dbdbc
+ version: 0.10.2+dev46
+ sha256: 9ada6af993ed7303fd58593648683db9afb40a7c191b5f5f7384f37934362c42
requires_dist:
- asciichartpy
- asteval
- bumps
- colorama
- cryspy
+ - darkdetect
- dfo-ls
- diffpy-pdffit2
- diffpy-utils
- essdiffraction
- gemmi
+ - jupyterlab
- lmfit
- numpy
+ - pandas
+ - pixi-kernel
+ - plotly
- pooch
+ - py3dmol
- rich
- scipy
- sympy
@@ -4693,67 +4899,37 @@ packages:
- typer
- uncertainties
- varname
- - build ; extra == 'all'
- - darkdetect ; extra == 'all'
- - docformatter ; extra == 'all'
- - interrogate ; extra == 'all'
- - jinja2 ; extra == 'all'
- - jupyterquiz ; extra == 'all'
- - jupytext ; extra == 'all'
- - mike ; extra == 'all'
- - mkdocs ; extra == 'all'
- - mkdocs-autorefs ; extra == 'all'
- - mkdocs-jupyter ; extra == 'all'
- - mkdocs-markdownextradata-plugin ; extra == 'all'
- - mkdocs-material ; extra == 'all'
- - mkdocs-plugin-inline-svg ; extra == 'all'
- - mkdocstrings-python ; extra == 'all'
- - nbmake ; extra == 'all'
- - nbqa ; extra == 'all'
- - nbstripout ; extra == 'all'
- - pandas ; extra == 'all'
- - plotly ; extra == 'all'
- - pre-commit ; extra == 'all'
- - py3dmol ; extra == 'all'
- - pytest ; extra == 'all'
- - pytest-cov ; extra == 'all'
- - pytest-xdist ; extra == 'all'
- - pyyaml ; extra == 'all'
- - radon ; extra == 'all'
- - ruff ; extra == 'all'
- - validate-pyproject[all] ; extra == 'all'
- - versioningit ; extra == 'all'
- build ; extra == 'dev'
- - docformatter ; extra == 'dev'
+ - copier ; extra == 'dev'
+ - format-docstring ; extra == 'dev'
+ - gitpython ; extra == 'dev'
- interrogate ; extra == 'dev'
- jinja2 ; extra == 'dev'
- jupyterquiz ; extra == 'dev'
- jupytext ; extra == 'dev'
+ - mike ; extra == 'dev'
+ - mkdocs ; extra == 'dev'
+ - mkdocs-autorefs ; extra == 'dev'
+ - mkdocs-jupyter ; extra == 'dev'
+ - mkdocs-markdownextradata-plugin ; extra == 'dev'
+ - mkdocs-material ; extra == 'dev'
+ - mkdocs-plugin-inline-svg ; extra == 'dev'
+ - mkdocstrings-python ; extra == 'dev'
- nbmake ; extra == 'dev'
- nbqa ; extra == 'dev'
- nbstripout ; extra == 'dev'
- pre-commit ; extra == 'dev'
+ - pydoclint ; extra == 'dev'
- pytest ; extra == 'dev'
- pytest-cov ; extra == 'dev'
- pytest-xdist ; extra == 'dev'
+ - pyyaml ; extra == 'dev'
- radon ; extra == 'dev'
- ruff ; extra == 'dev'
+ - spdx-headers ; extra == 'dev'
- validate-pyproject[all] ; extra == 'dev'
- versioningit ; extra == 'dev'
- - mike ; extra == 'docs'
- - mkdocs ; extra == 'docs'
- - mkdocs-autorefs ; extra == 'docs'
- - mkdocs-jupyter ; extra == 'docs'
- - mkdocs-markdownextradata-plugin ; extra == 'docs'
- - mkdocs-material ; extra == 'docs'
- - mkdocs-plugin-inline-svg ; extra == 'docs'
- - mkdocstrings-python ; extra == 'docs'
- - pyyaml ; extra == 'docs'
- - darkdetect ; extra == 'visualization'
- - pandas ; extra == 'visualization'
- - plotly ; extra == 'visualization'
- - py3dmol ; extra == 'visualization'
- requires_python: '>=3.11,<3.14'
+ requires_python: '>=3.11'
- pypi: https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl
name: email-validator
version: 2.3.0
@@ -4762,20 +4938,20 @@ packages:
- dnspython>=2.0.0
- idna>=2.0.0
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/06/42/75a6098682e3d4d7d5dfcb94d0dd48dccd9e106112992a99524243bc63e6/essdiffraction-26.3.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/55/cd/d729a1bb63fa95387228cc508552dea4685ea0116e484e73238db10f9521/essdiffraction-26.4.0-py3-none-any.whl
name: essdiffraction
- version: 26.3.0
- sha256: 3e3063d8af817ece183258b35579491d7edf85c4ca95fa3f1cef7877ad24365a
+ version: 26.4.0
+ sha256: a58c1ac09c2196ae3769ab8c2d1f8c0152e4e1a69a02bc286caf419cdaa9ec1d
requires_dist:
- dask>=2022.1.0
- - essreduce>=26.2.1
+ - essreduce>=26.4.0
- graphviz
- numpy>=2
- plopp>=26.2.0
- pythreejs>=2.4.1
- sciline>=25.4.1
- scipp>=25.11.0
- - scippneutron>=25.2.0
+ - scippneutron>=26.3.0
- scippnexus>=23.12.0
- tof>=25.12.0
- ncrystal[cif]>=4.1.0
@@ -4785,13 +4961,13 @@ packages:
- pytest>=7.0 ; extra == 'test'
- ipywidgets>=8.1.7 ; extra == 'test'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/a8/bf/530a2b63de72bdb8e518049a1e6639d1e6d79e591bfcdaaae08a9a3a7b84/essreduce-26.3.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/f1/bb/66c80d7f801b191f7b3ee6149a39be9d1a8a81c233e20adaf796d171f93a/essreduce-26.4.0-py3-none-any.whl
name: essreduce
- version: 26.3.1
- sha256: 0f629a52ad1793904cc41f6298229321f249f87e972b35f0b0fcfad8f280a78b
+ version: 26.4.0
+ sha256: 06a9ebf58cba3cc29ac70f7b89a3e596be92d6a61130361b8c19fa8afec2b1b5
requires_dist:
- sciline>=25.11.0
- - scipp>=25.4.0
+ - scipp>=26.3.0
- scippneutron>=25.11.1
- scippnexus>=25.6.0
- graphviz>=0.20 ; extra == 'test'
@@ -4854,15 +5030,15 @@ packages:
- pytest-benchmark ; extra == 'devel'
- pytest-cache ; extra == 'devel'
- validictory ; extra == 'devel'
-- pypi: https://files.pythonhosted.org/packages/a9/b8/2f664b56a3b4b32d28d3d106c71783073f712ba43ff6d34b9ea0ce36dc7b/filelock-3.25.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl
name: filelock
- version: 3.25.1
- sha256: 18972df45473c4aa2c7921b609ee9ca4925910cc3a0fb226c96b92fc224ef7bf
+ version: 3.25.2
+ sha256: ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/77/ce/f5a4c42c117f8113ce04048053c128d17426751a508f26398110c993a074/fonttools-4.62.0-cp311-cp311-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/03/c5/0e3966edd5ec668d41dfe418787726752bc07e2f5fd8c8f208615e61fa89/fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl
name: fonttools
- version: 4.62.0
- sha256: 4da779e8f342a32856075ddb193b2a024ad900bc04ecb744014c32409ae871ed
+ version: 4.62.1
+ sha256: 68959f5fc58ed4599b44aad161c2837477d7f35f5f79402d97439974faebfebe
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -4893,10 +5069,10 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/82/c7/985c1670aa6d82ef270f04cde11394c168f2002700353bd2bde405e59b8f/fonttools-4.62.0-cp313-cp313-macosx_10_13_universal2.whl
+- pypi: https://files.pythonhosted.org/packages/24/7f/66d3f8a9338a9b67fe6e1739f47e1cd5cee78bd3bc1206ef9b0b982289a5/fonttools-4.62.1-cp311-cp311-macosx_10_9_x86_64.whl
name: fonttools
- version: 4.62.0
- sha256: 274c8b8a87e439faf565d3bcd3f9f9e31bca7740755776a4a90a4bfeaa722efa
+ version: 4.62.1
+ sha256: 9dde91633f77fa576879a0c76b1d89de373cae751a98ddf0109d54e173b40f14
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -4927,10 +5103,10 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/8a/d7/8e4845993ee233c2023d11babe9b3dae7d30333da1d792eeccebcb77baab/fonttools-4.62.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/38/60/35186529de1db3c01f5ad625bde07c1f576305eab6d86bbda4c58445f721/fonttools-4.62.1-cp313-cp313-win_amd64.whl
name: fonttools
- version: 4.62.0
- sha256: 591220d5333264b1df0d3285adbdfe2af4f6a45bbf9ca2b485f97c9f577c49ff
+ version: 4.62.1
+ sha256: 7aa21ff53e28a9c2157acbc44e5b401149d3c9178107130e82d74ceb500e5056
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -4961,10 +5137,10 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/c0/7a/9aeec114bc9fc00d757a41f092f7107863d372e684a5b5724c043654477c/fonttools-4.62.0-cp311-cp311-macosx_10_9_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/3b/56/6f389de21c49555553d6a5aeed5ac9767631497ac836c4f076273d15bd72/fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl
name: fonttools
- version: 4.62.0
- sha256: 153afc3012ff8761b1733e8fbe5d98623409774c44ffd88fbcb780e240c11d13
+ version: 4.62.1
+ sha256: c22b1014017111c401469e3acc5433e6acf6ebcc6aa9efb538a533c800971c79
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -4995,10 +5171,10 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/c1/dc/c409c8ceec0d3119e9ab0b7b1a2e3c76d1f4d66e4a9db5c59e6b7652e7df/fonttools-4.62.0-cp313-cp313-macosx_10_13_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/88/39/23ff32561ec8d45a4d48578b4d241369d9270dc50926c017570e60893701/fonttools-4.62.1-cp311-cp311-macosx_10_9_universal2.whl
name: fonttools
- version: 4.62.0
- sha256: 93e27131a5a0ae82aaadcffe309b1bae195f6711689722af026862bede05c07c
+ version: 4.62.1
+ sha256: 40975849bac44fb0b9253d77420c6d8b523ac4dcdcefeff6e4d706838a5b80f7
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -5029,10 +5205,10 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/e4/33/63d79ca41020dd460b51f1e0f58ad1ff0a36b7bcbdf8f3971d52836581e9/fonttools-4.62.0-cp311-cp311-macosx_10_9_universal2.whl
+- pypi: https://files.pythonhosted.org/packages/cc/a1/40a5c4d8e28b0851d53a8eeeb46fbd73c325a2a9a165f290a5ed90e6c597/fonttools-4.62.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
name: fonttools
- version: 4.62.0
- sha256: 196cafef9aeec5258425bd31a4e9a414b2ee0d1557bca184d7923d3d3bcd90f9
+ version: 4.62.1
+ sha256: 1c5c25671ce8805e0d080e2ffdeca7f1e86778c5cbfbeae86d7f866d8830517b
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -5063,10 +5239,10 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/f5/7a/e25245a30457595740041dba9d0ea8ec1b2517f2f1a6a741f15eba1a4edc/fonttools-4.62.0-cp313-cp313-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/d3/97/bf54c5b3f2be34e1f143e6db838dfdc54f2ffa3e68c738934c82f3b2a08d/fonttools-4.62.1-cp311-cp311-win_amd64.whl
name: fonttools
- version: 4.62.0
- sha256: 6826a5aa53fb6def8a66bf423939745f415546c4e92478a7c531b8b6282b6c3b
+ version: 4.62.1
+ sha256: e8514f4924375f77084e81467e63238b095abda5107620f49421c368a6017ed2
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -5097,10 +5273,10 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/fb/bc/60d93477b653eeb1ddf5f9ec34be689b79234d82dbdded269ac0252715b8/fonttools-4.62.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/e2/98/8b1e801939839d405f1f122e7d175cebe9aeb4e114f95bfc45e3152af9a7/fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
name: fonttools
- version: 4.62.0
- sha256: 106aec9226f9498fc5345125ff7200842c01eda273ae038f5049b0916907acee
+ version: 4.62.1
+ sha256: 6706d1cb1d5e6251a97ad3c1b9347505c5615c112e66047abbef0f8545fa30d1
requires_dist:
- lxml>=4.0 ; extra == 'lxml'
- brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
@@ -5131,6 +5307,15 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl
+ name: format-docstring
+ version: 0.2.7
+ sha256: c9d50eafebe0f260e3270ca662ff3a0ed4050f64d95e352f8c5f88d9aede42d6
+ requires_dist:
+ - click>=8.0
+ - jupyter-notebook-parser>=0.1.4
+ - tomli>=1.1.0 ; python_full_version < '3.11'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl
name: fqdn
version: 1.5.1
@@ -5286,6 +5471,10 @@ packages:
- zstandard ; python_full_version < '3.14' and extra == 'test-full'
- tqdm ; extra == 'tqdm'
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl
+ name: funcy
+ version: '2.0'
+ sha256: 53df23c8bb1651b12f095df764bfb057935d49537a56de211b098f4c79614bb0
- pypi: https://files.pythonhosted.org/packages/42/15/26cac702cdf6281ddeb185d5912ce14e555e277c6e4caeb1d36966e43822/gemmi-0.7.5-cp311-cp311-macosx_11_0_arm64.whl
name: gemmi
version: 0.7.5
@@ -5336,6 +5525,35 @@ packages:
- markdown ; extra == 'dev'
- flake8 ; extra == 'dev'
- wheel ; extra == 'dev'
+- pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
+ name: gitdb
+ version: 4.0.12
+ sha256: 67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf
+ requires_dist:
+ - smmap>=3.0.1,<6
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
+ name: gitpython
+ version: 3.1.46
+ sha256: 79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058
+ requires_dist:
+ - gitdb>=4.0.1,<5
+ - typing-extensions>=3.10.0.2 ; python_full_version < '3.10'
+ - coverage[toml] ; extra == 'test'
+ - ddt>=1.1.1,!=1.4.3 ; extra == 'test'
+ - mock ; python_full_version < '3.8' and extra == 'test'
+ - mypy==1.18.2 ; python_full_version >= '3.9' and extra == 'test'
+ - pre-commit ; extra == 'test'
+ - pytest>=7.3.1 ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - pytest-instafail ; extra == 'test'
+ - pytest-mock ; extra == 'test'
+ - pytest-sugar ; extra == 'test'
+ - typing-extensions ; python_full_version < '3.11' and extra == 'test'
+ - sphinx>=7.1.2,<7.2 ; extra == 'doc'
+ - sphinx-rtd-theme ; extra == 'doc'
+ - sphinx-autodoc-typehints ; extra == 'doc'
+ requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl
name: graphviz
version: '0.21'
@@ -5422,10 +5640,10 @@ packages:
- psutil ; extra == 'test'
- setuptools ; extra == 'test'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/4b/4c/cc8c68196db727cfc1432f2ad5de50aa6707e630d44b2e6361dc06d8f134/griffelib-2.0.1-py3-none-any.whl
name: griffelib
- version: 2.0.0
- sha256: 01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f
+ version: 2.0.1
+ sha256: b769eed581c0e857d362fc8fcd8e57ecd2330c124b6104ac8b4c1c86d76970aa
requires_dist:
- pip>=24.0 ; extra == 'pypi'
- platformdirs>=4.2 ; extra == 'pypi'
@@ -5573,9 +5791,9 @@ packages:
- socksio==1.* ; extra == 'socks'
- zstandard>=0.18.0 ; extra == 'zstd'
requires_python: '>=3.8'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda
- sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329
- md5: 186a18e3ba246eccfc7cff00cd19a870
+- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda
+ sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a
+ md5: c80d8a3b84358cb967fa81e7075fbc8a
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=14
@@ -5583,32 +5801,32 @@ packages:
license: MIT
license_family: MIT
purls: []
- size: 12728445
- timestamp: 1767969922681
-- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.2-h14c5de8_0.conda
- sha256: f3066beae7fe3002f09c8a412cdf1819f49a2c9a485f720ec11664330cf9f1fe
- md5: 30334add4de016489b731c6662511684
+ size: 12723451
+ timestamp: 1773822285671
+- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda
+ sha256: 1294117122d55246bb83ad5b589e2a031aacdf2d0b1f99fd338aa4394f881735
+ md5: 627eca44e62e2b665eeec57a984a7f00
depends:
- - __osx >=10.13
+ - __osx >=11.0
license: MIT
license_family: MIT
purls: []
- size: 12263724
- timestamp: 1767970604977
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-hef89b57_0.conda
- sha256: 24bc62335106c30fecbcc1dba62c5eba06d18b90ea1061abd111af7b9c89c2d7
- md5: 114e6bfe7c5ad2525eb3597acdbf2300
+ size: 12273764
+ timestamp: 1773822733780
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda
+ sha256: 3a7907a17e9937d3a46dfd41cffaf815abad59a569440d1e25177c15fd0684e5
+ md5: f1182c91c0de31a7abd40cedf6a5ebef
depends:
- __osx >=11.0
license: MIT
license_family: MIT
purls: []
- size: 12389400
- timestamp: 1772209104304
-- pypi: https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl
+ size: 12361647
+ timestamp: 1773822915649
+- pypi: https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl
name: identify
- version: 2.6.17
- sha256: be5f8412d5ed4b20f2bd41a65f920990bdccaa6a4a18a08f1eefdcd0bdd885f0
+ version: 2.6.18
+ sha256: 8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737
requires_dist:
- ukkonen ; extra == 'license'
requires_python: '>=3.10'
@@ -5622,18 +5840,16 @@ packages:
- pytest>=8.3.2 ; extra == 'all'
- flake8>=7.1.1 ; extra == 'all'
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl
name: importlib-metadata
- version: 8.7.1
- sha256: 5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151
+ version: 9.0.0
+ sha256: 2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7
requires_dist:
- zipp>=3.20
- pytest>=6,!=8.1.* ; extra == 'test'
- packaging ; extra == 'test'
- pyfakefs ; extra == 'test'
- - flufl-flake8 ; extra == 'test'
- pytest-perf>=0.9.2 ; extra == 'test'
- - jaraco-test>=5.4 ; extra == 'test'
- sphinx>=3.5 ; extra == 'doc'
- jaraco-packaging>=9.3 ; extra == 'doc'
- rst-linker>=1.9 ; extra == 'doc'
@@ -5641,13 +5857,12 @@ packages:
- sphinx-lint ; extra == 'doc'
- jaraco-tidelift>=1.4 ; extra == 'doc'
- ipython ; extra == 'perf'
- - pytest-checkdocs>=2.4 ; extra == 'check'
+ - pytest-checkdocs>=2.14 ; extra == 'check'
- pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check'
- pytest-cov ; extra == 'cover'
- pytest-enabler>=3.4 ; extra == 'enabler'
- - pytest-mypy>=1.0.1 ; extra == 'type'
- - mypy<1.19 ; platform_python_implementation == 'PyPy' and extra == 'type'
- requires_python: '>=3.9'
+ - pytest-mypy>=1.0.1 ; platform_python_implementation != 'PyPy' and extra == 'type'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
name: iniconfig
version: 2.3.0
@@ -5696,23 +5911,23 @@ packages:
- pytest-cov ; extra == 'test'
- nbval>=0.9.2 ; extra == 'test'
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/f6/d8/502954a4ec0efcf264f99b65b41c3c54e65a647d9f0d6f62cd02227d242c/ipykernel-6.31.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl
name: ipykernel
- version: 6.31.0
- sha256: abe5386f6ced727a70e0eb0cf1da801fa7c5fa6ff82147747d5a0406cd8c94af
+ version: 7.2.0
+ sha256: 3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661
requires_dist:
- appnope>=0.1.2 ; sys_platform == 'darwin'
- comm>=0.1.1
- debugpy>=1.6.5
- ipython>=7.23.1
- - jupyter-client>=8.0.0
- - jupyter-core>=4.12,!=5.0.*
+ - jupyter-client>=8.8.0
+ - jupyter-core>=5.1,!=6.0.*
- matplotlib-inline>=0.1
- nest-asyncio>=1.4
- packaging>=22
- psutil>=5.7
- pyzmq>=25
- - tornado>=6.2
+ - tornado>=6.4.1
- traitlets>=5.4.0
- coverage[toml] ; extra == 'cov'
- matplotlib ; extra == 'cov'
@@ -5721,8 +5936,8 @@ packages:
- intersphinx-registry ; extra == 'docs'
- myst-parser ; extra == 'docs'
- pydata-sphinx-theme ; extra == 'docs'
- - sphinx ; extra == 'docs'
- sphinx-autodoc-typehints ; extra == 'docs'
+ - sphinx<8.2.0 ; extra == 'docs'
- sphinxcontrib-github-alt ; extra == 'docs'
- sphinxcontrib-spelling ; extra == 'docs'
- trio ; extra == 'docs'
@@ -5734,8 +5949,8 @@ packages:
- pytest-asyncio>=0.23.5 ; extra == 'test'
- pytest-cov ; extra == 'test'
- pytest-timeout ; extra == 'test'
- - pytest>=7.0,<9 ; extra == 'test'
- requires_python: '>=3.9'
+ - pytest>=7.0,<10 ; extra == 'test'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl
name: ipython
version: 9.10.0
@@ -5906,16 +6121,25 @@ packages:
- markupsafe>=2.0
- babel>=2.7 ; extra == 'i18n'
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl
+ name: jinja2-ansible-filters
+ version: 1.3.2
+ sha256: e1082f5564917649c76fed239117820610516ec10f87735d0338688800a55b34
+ requires_dist:
+ - jinja2
+ - pyyaml
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
- pypi: https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl
name: json5
version: 0.13.0
sha256: 9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc
requires_python: '>=3.8.0'
-- pypi: https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl
name: jsonpointer
- version: 3.0.0
- sha256: 13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942
- requires_python: '>=3.7'
+ version: 3.1.1
+ sha256: 8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl
name: jsonschema
version: 4.26.0
@@ -6034,6 +6258,11 @@ packages:
- jupyter-server>=1.1.2
- importlib-metadata>=4.8.3 ; python_full_version < '3.10'
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl
+ name: jupyter-notebook-parser
+ version: 0.1.4
+ sha256: 27b3b67cf898684e646d569f017cb27046774ad23866cb0bdf51d5f76a46476b
+ requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl
name: jupyter-server
version: 2.17.0
@@ -6106,10 +6335,10 @@ packages:
- pytest-timeout ; extra == 'test'
- pytest>=7.0 ; extra == 'test'
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl
name: jupyterlab
- version: 4.5.5
- sha256: a35694a40a8e7f2e82f387472af24e61b22adcce87b5a8ab97a5d9c486202a6d
+ version: 4.5.6
+ sha256: d6b3dac883aa4d9993348e0f8e95b24624f75099aed64eab6a4351a9cdd1e580
requires_dist:
- async-lru>=1.0.0
- httpx>=0.25.0,<1
@@ -6360,9 +6589,9 @@ packages:
- changelist==0.5 ; extra == 'dev'
- spin==0.15 ; extra == 'dev'
requires_python: '>=3.9'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda
- sha256: 565941ac1f8b0d2f2e8f02827cbca648f4d18cd461afc31f15604cd291b5c5f3
- md5: 12bd9a3f089ee6c9266a37dab82afabd
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda
+ sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c
+ md5: 18335a698559cdbcd86150a48bf54ba6
depends:
- __glibc >=2.17,<3.0.a0
- zstd >=1.5.7,<1.6.0a0
@@ -6371,8 +6600,8 @@ packages:
license: GPL-3.0-only
license_family: GPL
purls: []
- size: 725507
- timestamp: 1770267139900
+ size: 728002
+ timestamp: 1774197446916
- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda
sha256: a7a4481a4d217a3eadea0ec489826a69070fcc3153f00443aa491ed21527d239
md5: 6f7b4302263347698fd24565fbf11310
@@ -6416,76 +6645,72 @@ packages:
purls: []
size: 1229639
timestamp: 1770863511331
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda
- build_number: 5
- sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c
- md5: c160954f7418d7b6e87eaf05a8913fa9
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda
+ build_number: 6
+ sha256: 7bfe936dbb5db04820cf300a9cc1f5ee8d5302fc896c2d66e30f1ee2f20fbfd6
+ md5: 6d6d225559bfa6e2f3c90ee9c03d4e2e
depends:
- - libopenblas >=0.3.30,<0.3.31.0a0
- - libopenblas >=0.3.30,<1.0a0
+ - libopenblas >=0.3.32,<0.3.33.0a0
+ - libopenblas >=0.3.32,<1.0a0
constrains:
+ - blas 2.306 openblas
+ - liblapack 3.11.0 6*_openblas
+ - liblapacke 3.11.0 6*_openblas
+ - libcblas 3.11.0 6*_openblas
- mkl <2026
- - liblapack 3.11.0 5*_openblas
- - libcblas 3.11.0 5*_openblas
- - blas 2.305 openblas
- - liblapacke 3.11.0 5*_openblas
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 18213
- timestamp: 1765818813880
-- conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda
- build_number: 5
- sha256: 4754de83feafa6c0b41385f8dab1b13f13476232e16f524564a340871a9fc3bc
- md5: 36d2e68a156692cbae776b75d6ca6eae
+ size: 18621
+ timestamp: 1774503034895
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-6_he492b99_openblas.conda
+ build_number: 6
+ sha256: 6865098475f3804208038d0c424edf926f4dc9eacaa568d14e29f59df53731fd
+ md5: 93e7fc07b395c9e1341d3944dcf2aced
depends:
- - libopenblas >=0.3.30,<0.3.31.0a0
- - libopenblas >=0.3.30,<1.0a0
+ - libopenblas >=0.3.32,<0.3.33.0a0
+ - libopenblas >=0.3.32,<1.0a0
constrains:
- - liblapack 3.11.0 5*_openblas
- - blas 2.305 openblas
- - libcblas 3.11.0 5*_openblas
+ - libcblas 3.11.0 6*_openblas
+ - blas 2.306 openblas
- mkl <2026
- - liblapacke 3.11.0 5*_openblas
+ - liblapacke 3.11.0 6*_openblas
+ - liblapack 3.11.0 6*_openblas
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 18476
- timestamp: 1765819054657
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda
- build_number: 5
- sha256: 620a6278f194dcabc7962277da6835b1e968e46ad0c8e757736255f5ddbfca8d
- md5: bcc025e2bbaf8a92982d20863fe1fb69
+ size: 18724
+ timestamp: 1774503646078
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-6_h51639a9_openblas.conda
+ build_number: 6
+ sha256: 979227fc03628925037ab2dfda008eb7b5592644d9c2c21dd285cefe8c42553d
+ md5: e551103471911260488a02155cef9c94
depends:
- - libopenblas >=0.3.30,<0.3.31.0a0
- - libopenblas >=0.3.30,<1.0a0
+ - libopenblas >=0.3.32,<0.3.33.0a0
+ - libopenblas >=0.3.32,<1.0a0
constrains:
- - libcblas 3.11.0 5*_openblas
- - liblapack 3.11.0 5*_openblas
- - liblapacke 3.11.0 5*_openblas
- - blas 2.305 openblas
+ - liblapacke 3.11.0 6*_openblas
+ - liblapack 3.11.0 6*_openblas
+ - blas 2.306 openblas
+ - libcblas 3.11.0 6*_openblas
- mkl <2026
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 18546
- timestamp: 1765819094137
-- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda
- build_number: 5
- sha256: f0cb7b2697461a306341f7ff32d5b361bb84f3e94478464c1e27ee01fc8f276b
- md5: f9decf88743af85c9c9e05556a4c47c0
+ size: 18859
+ timestamp: 1774504387211
+- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-6_hf2e6a31_mkl.conda
+ build_number: 6
+ sha256: 10c8054f007adca8c780cd8bb9335fa5d990f0494b825158d3157983a25b1ea2
+ md5: 95543eec964b4a4a7ca3c4c9be481aa1
depends:
- - mkl >=2025.3.0,<2026.0a0
+ - mkl >=2025.3.1,<2026.0a0
constrains:
- - liblapack 3.11.0 5*_mkl
- - libcblas 3.11.0 5*_mkl
- - blas 2.305 mkl
- - liblapacke 3.11.0 5*_mkl
+ - blas 2.306 mkl
+ - liblapacke 3.11.0 6*_mkl
+ - liblapack 3.11.0 6*_mkl
+ - libcblas 3.11.0 6*_mkl
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 67438
- timestamp: 1765819100043
+ size: 68082
+ timestamp: 1774503684284
- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda
sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e
md5: 72c8fd1af66bd67bf580645b426513ed
@@ -6585,86 +6810,82 @@ packages:
purls: []
size: 290754
timestamp: 1764018009077
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda
- build_number: 5
- sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8
- md5: 6636a2b6f1a87572df2970d3ebc87cc0
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda
+ build_number: 6
+ sha256: 57edafa7796f6fa3ebbd5367692dd4c7f552be42109c2dd1a7c89b55089bf374
+ md5: 36ae340a916635b97ac8a0655ace2a35
depends:
- - libblas 3.11.0 5_h4a7cf45_openblas
+ - libblas 3.11.0 6_h4a7cf45_openblas
constrains:
- - liblapacke 3.11.0 5*_openblas
- - blas 2.305 openblas
- - liblapack 3.11.0 5*_openblas
+ - blas 2.306 openblas
+ - liblapack 3.11.0 6*_openblas
+ - liblapacke 3.11.0 6*_openblas
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 18194
- timestamp: 1765818837135
-- conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda
- build_number: 5
- sha256: 8077c29ea720bd152be6e6859a3765228cde51301fe62a3b3f505b377c2cb48c
- md5: b31d771cbccff686e01a687708a7ca41
+ size: 18622
+ timestamp: 1774503050205
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-6_h9b27e0a_openblas.conda
+ build_number: 6
+ sha256: 8422e1ce083e015bdb44addd25c9a8fe99aa9b0edbd9b7f1239b7ac1e3d04f77
+ md5: 2a174868cb9e136c4e92b3ffc2815f04
depends:
- - libblas 3.11.0 5_he492b99_openblas
+ - libblas 3.11.0 6_he492b99_openblas
constrains:
- - liblapack 3.11.0 5*_openblas
- - blas 2.305 openblas
- - liblapacke 3.11.0 5*_openblas
+ - liblapacke 3.11.0 6*_openblas
+ - blas 2.306 openblas
+ - liblapack 3.11.0 6*_openblas
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 18484
- timestamp: 1765819073006
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda
- build_number: 5
- sha256: 38809c361bbd165ecf83f7f05fae9b791e1baa11e4447367f38ae1327f402fc0
- md5: efd8bd15ca56e9d01748a3beab8404eb
+ size: 18713
+ timestamp: 1774503667477
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-6_hb0561ab_openblas.conda
+ build_number: 6
+ sha256: 2e6b3e9b1ab672133b70fc6730e42290e952793f132cb5e72eee22835463eba0
+ md5: 805c6d31c5621fd75e53dfcf21fb243a
depends:
- - libblas 3.11.0 5_h51639a9_openblas
+ - libblas 3.11.0 6_h51639a9_openblas
constrains:
- - liblapacke 3.11.0 5*_openblas
- - liblapack 3.11.0 5*_openblas
- - blas 2.305 openblas
+ - liblapacke 3.11.0 6*_openblas
+ - blas 2.306 openblas
+ - liblapack 3.11.0 6*_openblas
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 18548
- timestamp: 1765819108956
-- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda
- build_number: 5
- sha256: 49dc59d8e58360920314b8d276dd80da7866a1484a9abae4ee2760bc68f3e68d
- md5: b3fa8e8b55310ba8ef0060103afb02b5
+ size: 18863
+ timestamp: 1774504433388
+- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-6_h2a3cdd5_mkl.conda
+ build_number: 6
+ sha256: 02b2a2225f4899c6aaa1dc723e06b3f7a4903d2129988f91fc1527409b07b0a5
+ md5: 9e4bf521c07f4d423cba9296b7927e3c
depends:
- - libblas 3.11.0 5_hf2e6a31_mkl
+ - libblas 3.11.0 6_hf2e6a31_mkl
constrains:
- - liblapack 3.11.0 5*_mkl
- - liblapacke 3.11.0 5*_mkl
- - blas 2.305 mkl
+ - blas 2.306 mkl
+ - liblapacke 3.11.0 6*_mkl
+ - liblapack 3.11.0 6*_mkl
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 68079
- timestamp: 1765819124349
-- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.0-h19cb2f5_1.conda
- sha256: fa002b43752fe5860e588435525195324fe250287105ebd472ac138e97de45e6
- md5: 836389b6b9ae58f3fbcf7cafebd5c7f2
+ size: 68221
+ timestamp: 1774503722413
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.2-h19cb2f5_0.conda
+ sha256: 46561199545890e050a8a90edcfce984e5f881da86b09388926e3a6c6b759dec
+ md5: ed6f7b7a35f942a0301e581d72616f7d
depends:
- __osx >=11.0
license: Apache-2.0 WITH LLVM-exception
license_family: Apache
purls: []
- size: 570141
- timestamp: 1772001147762
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.0-h55c6f16_1.conda
- sha256: ce1049fa6fda9cf08ff1c50fb39573b5b0ea6958375d8ea7ccd8456ab81a0bcb
- md5: e9c56daea841013e7774b5cd46f41564
+ size: 564908
+ timestamp: 1774439353713
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.2-h55c6f16_0.conda
+ sha256: d1402087c8792461bfc081629e8aa97e6e577a31ae0b84e6b9cc144a18f48067
+ md5: 4280e0a7fd613b271e022e60dea0138c
depends:
- __osx >=11.0
license: Apache-2.0 WITH LLVM-exception
license_family: Apache
purls: []
- size: 568910
- timestamp: 1772001095642
+ size: 568094
+ timestamp: 1774439202359
- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda
sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4
md5: 172bf1cd1ff8629f2b1179945ed45055
@@ -7034,55 +7255,55 @@ packages:
purls: []
size: 89411
timestamp: 1769482314283
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda
- sha256: a4a7dab8db4dc81c736e9a9b42bdfd97b087816e029e221380511960ac46c690
- md5: b499ce4b026493a13774bcf0f4c33849
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda
+ sha256: 663444d77a42f2265f54fb8b48c5450bfff4388d9c0f8253dd7855f0d993153f
+ md5: 2a45e7f8af083626f009645a6481f12d
depends:
- __glibc >=2.17,<3.0.a0
- - c-ares >=1.34.5,<2.0a0
+ - c-ares >=1.34.6,<2.0a0
- libev >=4.33,<4.34.0a0
- libev >=4.33,<5.0a0
- libgcc >=14
- libstdcxx >=14
- libzlib >=1.3.1,<2.0a0
- - openssl >=3.5.2,<4.0a0
+ - openssl >=3.5.5,<4.0a0
license: MIT
license_family: MIT
purls: []
- size: 666600
- timestamp: 1756834976695
-- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda
- sha256: c48d7e1cc927aef83ff9c48ae34dd1d7495c6ccc1edc4a3a6ba6aff1624be9ac
- md5: e7630cef881b1174d40f3e69a883e55f
+ size: 663344
+ timestamp: 1773854035739
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda
+ sha256: 899551e16aac9dfb85bfc2fd98b655f4d1b7fea45720ec04ccb93d95b4d24798
+ md5: dba4c95e2fe24adcae4b77ebf33559ae
depends:
- - __osx >=10.13
- - c-ares >=1.34.5,<2.0a0
+ - __osx >=11.0
+ - c-ares >=1.34.6,<2.0a0
- libcxx >=19
- libev >=4.33,<4.34.0a0
- libev >=4.33,<5.0a0
- libzlib >=1.3.1,<2.0a0
- - openssl >=3.5.2,<4.0a0
+ - openssl >=3.5.5,<4.0a0
license: MIT
license_family: MIT
purls: []
- size: 605680
- timestamp: 1756835898134
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda
- sha256: a07cb53b5ffa2d5a18afc6fd5a526a5a53dd9523fbc022148bd2f9395697c46d
- md5: a4b4dd73c67df470d091312ab87bf6ae
+ size: 606749
+ timestamp: 1773854765508
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda
+ sha256: 2bc7bc3978066f2c274ebcbf711850cc9ab92e023e433b9631958a098d11e10a
+ md5: 6ea18834adbc3b33df9bd9fb45eaf95b
depends:
- __osx >=11.0
- - c-ares >=1.34.5,<2.0a0
+ - c-ares >=1.34.6,<2.0a0
- libcxx >=19
- libev >=4.33,<4.34.0a0
- libev >=4.33,<5.0a0
- libzlib >=1.3.1,<2.0a0
- - openssl >=3.5.2,<4.0a0
+ - openssl >=3.5.5,<4.0a0
license: MIT
license_family: MIT
purls: []
- size: 575454
- timestamp: 1756835746393
+ size: 576526
+ timestamp: 1773854624224
- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda
sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5
md5: d864d34357c3b65a4b731f78c0801dc4
@@ -7094,51 +7315,48 @@ packages:
purls: []
size: 33731
timestamp: 1750274110928
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda
- sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5
- md5: be43915efc66345cccb3c310b6ed0374
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda
+ sha256: 6dc30b28f32737a1c52dada10c8f3a41bc9e021854215efca04a7f00487d09d9
+ md5: 89d61bc91d3f39fda0ca10fcd3c68594
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=14
- libgfortran
- libgfortran5 >=14.3.0
constrains:
- - openblas >=0.3.30,<0.3.31.0a0
+ - openblas >=0.3.32,<0.3.33.0a0
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 5927939
- timestamp: 1763114673331
-- conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda
- sha256: ba642353f7f41ab2d2eb6410fbe522238f0f4483bcd07df30b3222b4454ee7cd
- md5: 9241a65e6e9605e4581a2a8005d7f789
+ size: 5928890
+ timestamp: 1774471724897
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.32-openmp_h9e49c7b_0.conda
+ sha256: 6764229359cd927c9efc036930ba28f83436b8d6759c5ac4ea9242fc29a7184e
+ md5: 4058c5f8dbef6d28cb069f96b95ae6df
depends:
- - __osx >=10.13
+ - __osx >=11.0
- libgfortran
- libgfortran5 >=14.3.0
- llvm-openmp >=19.1.7
constrains:
- - openblas >=0.3.30,<0.3.31.0a0
+ - openblas >=0.3.32,<0.3.33.0a0
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 6268795
- timestamp: 1763117623665
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda
- sha256: ebbbc089b70bcde87c4121a083c724330f02a690fb9d7c6cd18c30f1b12504fa
- md5: a6f6d3a31bb29e48d37ce65de54e2df0
+ size: 6289730
+ timestamp: 1774474444702
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.32-openmp_he657e61_0.conda
+ sha256: 713e453bde3531c22a660577e59bf91ef578dcdfd5edb1253a399fa23514949a
+ md5: 3a1111a4b6626abebe8b978bb5a323bf
depends:
- __osx >=11.0
- libgfortran
- libgfortran5 >=14.3.0
- llvm-openmp >=19.1.7
constrains:
- - openblas >=0.3.30,<0.3.31.0a0
+ - openblas >=0.3.32,<0.3.33.0a0
license: BSD-3-Clause
- license_family: BSD
purls: []
- size: 4284132
- timestamp: 1768547079205
+ size: 4308797
+ timestamp: 1774472508546
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda
sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993
md5: fd893f6a3002a635b5e50ceb9dd2c0f4
@@ -7295,98 +7513,97 @@ packages:
purls: []
size: 520078
timestamp: 1772704728534
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
- sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4
- md5: edb0dca6bc32e4f4789199455a1dbeb8
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda
+ sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9
+ md5: d87ff7921124eccd67248aa483c23fec
depends:
- __glibc >=2.17,<3.0.a0
- - libgcc >=13
constrains:
- - zlib 1.3.1 *_2
+ - zlib 1.3.2 *_2
license: Zlib
license_family: Other
purls: []
- size: 60963
- timestamp: 1727963148474
-- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda
- sha256: 8412f96504fc5993a63edf1e211d042a1fd5b1d51dedec755d2058948fcced09
- md5: 003a54a4e32b02f7355b50a837e699da
+ size: 63629
+ timestamp: 1774072609062
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda
+ sha256: 4c6da089952b2d70150c74234679d6f7ac04f4a98f9432dec724968f912691e7
+ md5: 30439ff30578e504ee5e0b390afc8c65
depends:
- - __osx >=10.13
+ - __osx >=11.0
constrains:
- - zlib 1.3.1 *_2
+ - zlib 1.3.2 *_2
license: Zlib
license_family: Other
purls: []
- size: 57133
- timestamp: 1727963183990
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
- sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b
- md5: 369964e85dc26bfe78f41399b366c435
+ size: 59000
+ timestamp: 1774073052242
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda
+ sha256: 361415a698514b19a852f5d1123c5da746d4642139904156ddfca7c922d23a05
+ md5: bc5a5721b6439f2f62a84f2548136082
depends:
- __osx >=11.0
constrains:
- - zlib 1.3.1 *_2
+ - zlib 1.3.2 *_2
license: Zlib
license_family: Other
purls: []
- size: 46438
- timestamp: 1727963202283
-- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda
- sha256: ba945c6493449bed0e6e29883c4943817f7c79cbff52b83360f7b341277c6402
- md5: 41fbfac52c601159df6c01f875de31b9
+ size: 47759
+ timestamp: 1774072956767
+- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda
+ sha256: 88609816e0cc7452bac637aaf65783e5edf4fee8a9f8e22bdc3a75882c536061
+ md5: dbabbd6234dea34040e631f87676292f
depends:
- ucrt >=10.0.20348.0
- - vc >=14.2,<15
- - vc14_runtime >=14.29.30139
+ - vc >=14.3,<15
+ - vc14_runtime >=14.44.35208
constrains:
- - zlib 1.3.1 *_2
+ - zlib 1.3.2 *_2
license: Zlib
license_family: Other
purls: []
- size: 55476
- timestamp: 1727963768015
-- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.0-h0d3cbff_0.conda
- sha256: b63df4e592b3362e7d13e3d1cf8e55ce932ff4f17611c8514b5d36368ec2094c
- md5: 3921780bab286f2439ba483c22b90345
+ size: 58347
+ timestamp: 1774072851498
+- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.1-h0d3cbff_0.conda
+ sha256: 65c30298a921b3f6d49e2f4ec220bc2d2237cbdabd1c19031f4fafbfdad8aa5e
+ md5: d5e67fb9aeb3f32fc474ca7859a5583b
depends:
- __osx >=11.0
constrains:
- - openmp 22.1.0|22.1.0.*
- intel-openmp <0.0a0
+ - openmp 22.1.1|22.1.1.*
license: Apache-2.0 WITH LLVM-exception
license_family: APACHE
purls: []
- size: 311938
- timestamp: 1772024731611
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.0-hc7d1edf_0.conda
- sha256: 0daeedb3872ad0fdd6f0d7e7165c63488e8a315d7057907434145fba0c1e7b3d
- md5: ff0820b5588b20be3b858552ecf8ffae
+ size: 311088
+ timestamp: 1774349643537
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.1-hc7d1edf_0.conda
+ sha256: c6f67e928f47603aca7e4b83632d8f3e82bd698051c7c0b34fcce3796eb9b63c
+ md5: 5a44f53783d87427790fc8692542f1bb
depends:
- __osx >=11.0
constrains:
- - openmp 22.1.0|22.1.0.*
- intel-openmp <0.0a0
+ - openmp 22.1.1|22.1.1.*
license: Apache-2.0 WITH LLVM-exception
license_family: APACHE
purls: []
- size: 285558
- timestamp: 1772028716784
-- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.0-h4fa8253_0.conda
- sha256: bb55a3736380759d338f87aac68df4fd7d845ae090b94400525f5d21a55eea31
- md5: e5505e0b7d6ef5c19d5c0c1884a2f494
+ size: 285912
+ timestamp: 1774349644882
+- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.1-h4fa8253_0.conda
+ sha256: 64c7fe6490583f3c49c36c2f413e681072102db8abea13a3e1832f44eaf55518
+ md5: d9f479404fe316e575f4a4575f3df406
depends:
- ucrt >=10.0.20348.0
- vc >=14.3,<15
- vc14_runtime >=14.44.35208
constrains:
- - openmp 22.1.0|22.1.0.*
+ - openmp 22.1.1|22.1.1.*
- intel-openmp <0.0a0
license: Apache-2.0 WITH LLVM-exception
license_family: APACHE
purls: []
- size: 347404
- timestamp: 1772025050288
+ size: 347138
+ timestamp: 1774349485844
- pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl
name: lmfit
version: 1.3.4
@@ -7785,22 +8002,22 @@ packages:
- markupsafe>=2.0.1
- mkdocs>=1.1
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ca/fa/ab291bbb8f7453f8449a982843b044b37050c85f5895ef97f599683a1249/mkdocs_get_deps-0.2.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl
name: mkdocs-get-deps
- version: 0.2.1
- sha256: 07d6076298715dfcb8232e7dec083d09015b4e65482ce7f6743cb07cd1da847e
+ version: 0.2.2
+ sha256: e7878cbeac04860b8b5e0ca31d3abad3df9411a75a32cde82f8e44b6c16ff650
requires_dist:
- importlib-metadata>=4.3 ; python_full_version < '3.10'
- mergedeep>=1.3.4
- platformdirs>=2.2.0
- pyyaml>=5.1
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/08/37/5f1fd5c3f6954b3256f8126275e62af493b96fb6aef6c0dbc4ee326032ad/mkdocs_jupyter-0.25.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/93/89/eb601278b12c471235860992f5973cf3c55ca3f77d1d6127389eb045a021/mkdocs_jupyter-0.26.1-py3-none-any.whl
name: mkdocs-jupyter
- version: 0.25.1
- sha256: 3f679a857609885d322880e72533ef5255561bbfdb13cfee2a1e92ef4d4ad8d8
+ version: 0.26.1
+ sha256: 527242c2c8f1d30970764bbab752de41243e5703f458d8bc05336ec53828192e
requires_dist:
- - ipykernel>6.0.0,<7.0.0
+ - ipykernel>6.0.0,<8
- jupytext>1.13.8,<2
- mkdocs-material>9.0.0
- mkdocs>=1.4.0,<2
@@ -7815,10 +8032,10 @@ packages:
- mkdocs
- pyyaml
requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/e7/94/e3535a9ed078b238df3df75a44694ca0ff5772fd538df4939c658a58c59d/mkdocs_material-9.7.4-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
name: mkdocs-material
- version: 9.7.4
- sha256: 6549ad95e4d130ed5099759dfa76ea34c593eefdb9c18c97273605518e99cfbf
+ version: 9.7.6
+ sha256: 71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba
requires_dist:
- babel>=2.10
- backrefs>=5.7.post1
@@ -7826,7 +8043,7 @@ packages:
- jinja2>=3.1
- markdown>=3.2
- mkdocs-material-extensions>=1.3
- - mkdocs>=1.6
+ - mkdocs>=1.6,<2
- paginate>=0.5
- pygments>=2.16
- pymdown-extensions>=10.2
@@ -7876,11 +8093,11 @@ packages:
- griffelib>=2.0
- typing-extensions>=4.0 ; python_full_version < '3.11'
requires_python: '>=3.10'
-- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda
- sha256: b2b4c84b95210760e4d12319416c60ab66e03674ccdcbd14aeb59f82ebb1318d
- md5: fd05d1e894497b012d05a804232254ed
+- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.1-hac47afa_11.conda
+ sha256: f2c2b2a3c2e7d08d78c10bef7c135a4262c80d1d48c85fb5902ca30d61d645f4
+ md5: 3fd3009cef89c36e9898a6feeb0f5530
depends:
- - llvm-openmp >=21.1.8
+ - llvm-openmp >=22.1.1
- tbb >=2022.3.0
- ucrt >=10.0.20348.0
- vc >=14.3,<15
@@ -7888,8 +8105,8 @@ packages:
license: LicenseRef-IntelSimplifiedSoftwareOct2022
license_family: Proprietary
purls: []
- size: 100224829
- timestamp: 1767634557029
+ size: 99997309
+ timestamp: 1774449747739
- pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl
name: mpld3
version: 0.5.12
@@ -8087,10 +8304,10 @@ packages:
requires_dist:
- typing-extensions>=4.1.0 ; python_full_version < '3.11'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/3f/c3/06490e98393dcb4d6ce2bf331a39335375c300afaef526897881fbeae6ab/narwhals-2.18.1-py3-none-any.whl
name: narwhals
- version: 2.17.0
- sha256: 2ac5307b7c2b275a7d66eeda906b8605e3d7a760951e188dcfff86e8ebe083dd
+ version: 2.18.1
+ sha256: a0a8bb80205323851338888ba3a12b4f65d352362c8a94be591244faf36504ad
requires_dist:
- cudf-cu12>=24.10.0 ; extra == 'cudf'
- dask[dataframe]>=2024.8 ; extra == 'dask'
@@ -8394,87 +8611,83 @@ packages:
version: 1.10.0
sha256: 5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda
- sha256: 4791285a34195615e22a94dc62cbd43181548b34eb34e6cb1dcf8f469476a32e
- md5: ba562095149fde99c700365d90e6d632
+- conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda
+ sha256: d1a673d1418d9e956b6e4e46c23e72a511c5c1d45dc5519c947457427036d5e2
+ md5: baffb1570b3918c784d4490babc52fbf
depends:
- - __glibc >=2.28,<3.0.a0
- - libstdcxx >=14
- libgcc >=14
- - libnghttp2 >=1.67.0,<2.0a0
+ - libstdcxx >=14
+ - __glibc >=2.28,<3.0.a0
+ - libnghttp2 >=1.68.1,<2.0a0
+ - libuv >=1.51.0,<2.0a0
- c-ares >=1.34.6,<2.0a0
+ - openssl >=3.5.5,<4.0a0
+ - libsqlite >=3.52.0,<4.0a0
+ - icu >=78.3,<79.0a0
+ - libzlib >=1.3.2,<2.0a0
+ - libabseil >=20260107.1,<20260108.0a0
+ - libabseil * cxx17*
- zstd >=1.5.7,<1.6.0a0
- libbrotlicommon >=1.2.0,<1.3.0a0
- libbrotlienc >=1.2.0,<1.3.0a0
- libbrotlidec >=1.2.0,<1.3.0a0
- - libuv >=1.51.0,<2.0a0
- - openssl >=3.5.5,<4.0a0
- - libabseil >=20260107.1,<20260108.0a0
- - libabseil * cxx17*
- - icu >=78.2,<79.0a0
- - libzlib >=1.3.1,<2.0a0
- - libsqlite >=3.51.2,<4.0a0
license: MIT
- license_family: MIT
purls: []
- size: 18875002
- timestamp: 1772300115686
-- conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.7.0-hf6efa0e_0.conda
- sha256: a23a3b536f1ccd3c10a2cbdf8c638b601c51f6e9bbf1e6c708610cf5b1df3d0f
- md5: 448185eb18358e4b5fe2a157cc7e415f
+ size: 18829340
+ timestamp: 1774514313036
+- conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-25.8.2-hf3170e9_0.conda
+ sha256: 6e82ed9c2de2e5a472a9c25f7a4a3a296d33aa38b94151acbbb5a28754962d8d
+ md5: de36be6257a15d17e85c96b47d290f82
depends:
- libcxx >=19
- - __osx >=10.15
- - openssl >=3.5.5,<4.0a0
- - c-ares >=1.34.6,<2.0a0
- - libuv >=1.51.0,<2.0a0
+ - __osx >=11.0
+ - libzlib >=1.3.2,<2.0a0
+ - libnghttp2 >=1.68.1,<2.0a0
+ - libabseil >=20260107.1,<20260108.0a0
+ - libabseil * cxx17*
+ - icu >=78.3,<79.0a0
- libbrotlicommon >=1.2.0,<1.3.0a0
- libbrotlienc >=1.2.0,<1.3.0a0
- libbrotlidec >=1.2.0,<1.3.0a0
- - libabseil >=20260107.1,<20260108.0a0
- - libabseil * cxx17*
- - libnghttp2 >=1.67.0,<2.0a0
- - icu >=78.2,<79.0a0
- - libsqlite >=3.51.2,<4.0a0
- - libzlib >=1.3.1,<2.0a0
+ - libsqlite >=3.52.0,<4.0a0
+ - libuv >=1.51.0,<2.0a0
+ - c-ares >=1.34.6,<2.0a0
+ - openssl >=3.5.5,<4.0a0
- zstd >=1.5.7,<1.6.0a0
license: MIT
- license_family: MIT
purls: []
- size: 18342335
- timestamp: 1772299132495
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda
- sha256: 6398a45d2bb943585540d98a9b1b3bed1fb48fabd327b56eba2ece00e3dd202f
- md5: 22a4a51f30590f274bb3f831d911c09a
+ size: 18382168
+ timestamp: 1774517889949
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda
+ sha256: 4782b172b3b8a557b60bf5f591821cf100e2092ba7a5494ce047dfa41626de26
+ md5: ca8277c52fdface8bb8ebff7cd9a6f56
depends:
- - __osx >=11.0
- libcxx >=19
- - libsqlite >=3.51.2,<4.0a0
- - zstd >=1.5.7,<1.6.0a0
+ - __osx >=11.0
+ - icu >=78.3,<79.0a0
- libbrotlicommon >=1.2.0,<1.3.0a0
- libbrotlienc >=1.2.0,<1.3.0a0
- libbrotlidec >=1.2.0,<1.3.0a0
+ - libnghttp2 >=1.68.1,<2.0a0
- libuv >=1.51.0,<2.0a0
+ - libsqlite >=3.52.0,<4.0a0
+ - libzlib >=1.3.2,<2.0a0
+ - openssl >=3.5.5,<4.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ - c-ares >=1.34.6,<2.0a0
- libabseil >=20260107.1,<20260108.0a0
- libabseil * cxx17*
- - icu >=78.2,<79.0a0
- - c-ares >=1.34.6,<2.0a0
- - openssl >=3.5.5,<4.0a0
- - libnghttp2 >=1.67.0,<2.0a0
- - libzlib >=1.3.1,<2.0a0
license: MIT
- license_family: MIT
purls: []
- size: 17351648
- timestamp: 1772299122966
-- conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.7.0-h80d1838_0.conda
- sha256: 0ea0ddad32366396d1beda7ce93ddd3d9f705286c1a4f99f05ec0049183c1e97
- md5: 61b62d3be12c9edbe34f202d51891927
+ size: 17101803
+ timestamp: 1774517834028
+- conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda
+ sha256: 5e38e51da1aa4bc352db9b4cec1c3e25811de0f4408edaa24e009a64de6dbfdf
+ md5: e626ee7934e4b7cb21ce6b721cff8677
license: MIT
- license_family: MIT
purls: []
- size: 31254428
- timestamp: 1772299132945
+ size: 31271315
+ timestamp: 1774517904472
- pypi: https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl
name: notebook-shim
version: 0.2.4
@@ -9614,11 +9827,6 @@ packages:
- trove-classifiers>=2024.10.12 ; extra == 'tests'
- defusedxml ; extra == 'xmp'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl
- name: pip
- version: 26.0.1
- sha256: bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b
- requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/c4/36/ce5f75aa7c736a663a901766edc3580098c7ea3959a0e878363a54a3714e/pixi_kernel-0.7.1-py3-none-any.whl
name: pixi-kernel
version: 0.7.1
@@ -9636,10 +9844,10 @@ packages:
version: 4.9.4
sha256: 68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/ab/f2/11ebc9b4cc8aaa23423a082c738b27792b88ebe0a8a6590ca6993c09a258/plopp-26.3.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/31/8b/9e8baf7dacac8d0c174925c38ff43c6d94bc9abb35503f67762caccb6869/plopp-26.3.1-py3-none-any.whl
name: plopp
- version: 26.3.0
- sha256: 44e231f202e8e9bfba4556762e7a49ec4832c5c1df0c96a744f87e7d50fddc11
+ version: 26.3.1
+ sha256: 56531f2f71fa4f7f33c172312d2423d969deb9b9dd29b2524ad3ed7e33d220eb
requires_dist:
- lazy-loader>=0.4
- matplotlib>=3.8
@@ -9718,6 +9926,14 @@ packages:
- pytest-benchmark ; extra == 'testing'
- coverage ; extra == 'testing'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl
+ name: plumbum
+ version: 1.10.0
+ sha256: 9583d737ac901c474d99d030e4d5eec4c4e6d2d7417b1cf49728cf3be34f6dc8
+ requires_dist:
+ - pywin32 ; platform_python_implementation != 'PyPy' and sys_platform == 'win32'
+ - paramiko ; extra == 'ssh'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
name: ply
version: '3.11'
@@ -10156,6 +10372,16 @@ packages:
requires_dist:
- typing-extensions>=4.14.1
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl
+ name: pydoclint
+ version: 0.8.3
+ sha256: 5fc9b82d0d515afce0908cb70e8ff695a68b19042785c248c4f227ad66b4a164
+ requires_dist:
+ - click>=8.1.0
+ - docstring-parser-fork>=0.0.12
+ - tomli>=2.0.1 ; python_full_version < '3.11'
+ - flake8>=4 ; extra == 'flake8'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
name: pygments
version: 2.19.2
@@ -10205,10 +10431,10 @@ packages:
- setuptools ; extra == 'dev'
- xmlschema ; extra == 'dev'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl
name: pytest-cov
- version: 7.0.0
- sha256: 3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861
+ version: 7.1.0
+ sha256: a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678
requires_dist:
- coverage[toml]>=7.10.6
- pluggy>=1.2
@@ -10427,10 +10653,10 @@ packages:
requires_dist:
- six>=1.5
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
-- pypi: https://files.pythonhosted.org/packages/03/48/8bdfaec240edb1a79b79201eff38b737fc3c29ce59e2e71271bdd8bafdda/python_discovery-1.1.2-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/67/0f/019d3949a40280f6193b62bc010177d4ce702d0fce424322286488569cd3/python_discovery-1.2.1-py3-none-any.whl
name: python-discovery
- version: 1.1.2
- sha256: d18edd61b382d62f8bcd004a71ebaabc87df31dbefb30aeed59f4fc6afa005be
+ version: 1.2.1
+ sha256: b6a957b24c1cd79252484d3566d1b49527581d46e789aaf43181005e56201502
requires_dist:
- filelock>=3.15.4
- platformdirs>=4.3.6,<5
@@ -10529,6 +10755,14 @@ packages:
- pytest-check-links ; extra == 'test'
- numpy>=1.14 ; extra == 'test'
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl
+ name: pywin32
+ version: '311'
+ sha256: 3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503
+- pypi: https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl
+ name: pywin32
+ version: '311'
+ sha256: 718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d
- pypi: https://files.pythonhosted.org/packages/79/c3/3e75075c7f71735f22b66fab0481f2c98e3a4d58cba55cb50ba29114bcf6/pywinpty-3.0.3-cp311-cp311-win_amd64.whl
name: pywinpty
version: 3.0.3
@@ -10628,6 +10862,13 @@ packages:
requires_dist:
- cffi ; implementation_name == 'pypy'
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl
+ name: questionary
+ version: 2.1.1
+ sha256: a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59
+ requires_dist:
+ - prompt-toolkit>=2.0,<4.0
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl
name: radon
version: 6.0.1
@@ -10680,18 +10921,24 @@ packages:
- rpds-py>=0.7.0
- typing-extensions>=4.4.0 ; python_full_version < '3.13'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl
name: requests
- version: 2.32.5
- sha256: 2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6
+ version: 2.33.0
+ sha256: 3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b
requires_dist:
- charset-normalizer>=2,<4
- idna>=2.5,<4
- - urllib3>=1.21.1,<3
- - certifi>=2017.4.17
+ - urllib3>=1.26,<3
+ - certifi>=2023.5.7
- pysocks>=1.5.6,!=1.5.7 ; extra == 'socks'
- - chardet>=3.0.2,<6 ; extra == 'use-chardet-on-py3'
- requires_python: '>=3.9'
+ - chardet>=3.0.2,<8 ; extra == 'use-chardet-on-py3'
+ - pytest-httpbin==2.1.0 ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - pytest-mock ; extra == 'test'
+ - pytest-xdist ; extra == 'test'
+ - pysocks>=1.5.6,!=1.5.7 ; extra == 'test'
+ - pytest>=3 ; extra == 'test'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/57/4d/a7545bf6c62b0dbe5795f22ea9e88cc070fdced5c34663ebc5bed2f610c0/returns-0.26.0-py3-none-any.whl
name: returns
version: 0.26.0
@@ -10771,25 +11018,25 @@ packages:
version: 0.30.0
sha256: e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/44/ed/e81dd668547da281e5dce710cf0bc60193f8d3d43833e8241d006720e42b/ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/1f/a2/ef467cb77099062317154c63f234b8a7baf7cb690b99af760c5b68b9ee7f/ruff-0.15.8-py3-none-win_amd64.whl
name: ruff
- version: 0.15.5
- sha256: 6edd3792d408ebcf61adabc01822da687579a1a023f297618ac27a5b51ef0080
+ version: 0.15.8
+ sha256: 04f79eff02a72db209d47d665ba7ebcad609d8918a134f86cb13dd132159fc89
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/b8/00/bf077a505b4e649bdd3c47ff8ec967735ce2544c8e4a43aba42ee9bf935d/ruff-0.15.5-py3-none-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/ca/f2/7a631a8af6d88bcef997eb1bf87cc3da158294c57044aafd3e17030613de/ruff-0.15.8-py3-none-macosx_11_0_arm64.whl
name: ruff
- version: 0.15.5
- sha256: 821d41c5fa9e19117616c35eaa3f4b75046ec76c65e7ae20a333e9a8696bc7fe
+ version: 0.15.8
+ sha256: 6ee3ae5c65a42f273f126686353f2e08ff29927b7b7e203b711514370d500de3
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/c4/8f/533075f00aaf19b07c5cd6aa6e5d89424b06b3b3f4583bfa9c640a079059/ruff-0.15.5-py3-none-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/eb/92/f1c662784d149ad1414cae450b082cf736430c12ca78367f20f5ed569d65/ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl
name: ruff
- version: 0.15.5
- sha256: 89f463f7c8205a9f8dea9d658d59eff49db05f88f89cc3047fb1a02d9f344010
+ version: 0.15.8
+ sha256: d3e3d0b6ba8dca1b7ef9ab80a28e840a20070c4b62e56d675c24f366ef330570
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/d3/01/a10fe54b653061585e655f5286c2662ebddb68831ed3eaebfb0eb08c0a16/ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/f8/22/d7f2fabdba4fae9f3b570e5605d5eb4500dcb7b770d3217dca4428484b17/ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
name: ruff
- version: 0.15.5
- sha256: c1cb7169f53c1ddb06e71a9aebd7e98fc0fea936b39afb36d8e86d36ecc2636a
+ version: 0.15.8
+ sha256: 0f29b989a55572fb885b77464cf24af05500806ab4edf9a0fd8977f9759d85b1
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl
name: sciline
@@ -10808,10 +11055,10 @@ packages:
- rich ; extra == 'test'
- rich ; extra == 'progress'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/12/0d/3f98a936a30bff4a460b51b9f85c4d994f94249930b2d8bedeb8111a359e/scipp-25.12.0-cp311-cp311-macosx_11_0_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/2e/75/5604f4d17ab607510d4702f156329194d8edfff7e29644ca9200b085e9a2/scipp-26.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
name: scipp
- version: 25.12.0
- sha256: 6391dc46739006e1e4eb7f2fcbcdbdd40f11a3cbae53e93b63b5ba32909bd792
+ version: 26.3.1
+ sha256: 993706e7c31f0317be2db5f528f9142ba67b2e52d7af174fcad195f702e1d6c7
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -10834,10 +11081,10 @@ packages:
- nodejs ; extra == 'all'
- pythreejs ; extra == 'all'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/18/5c/bc0ca94bff65fe0d206a369b54625f8ec7852dfd1d835174692026f34df9/scipp-25.12.0-cp313-cp313-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/37/fd/22621d3ee9e3ee87ef4c89b63bba55b265ab85039b3c1ba88ed2380a24c1/scipp-26.3.1-cp313-cp313-win_amd64.whl
name: scipp
- version: 25.12.0
- sha256: 0285c91b202dea9aeb18f29d73ff135208a19b2068cd30e17ee81fc435b1943c
+ version: 26.3.1
+ sha256: 03c6dbf8936a2ed62587c5abe8ab5266a5098834a0709321ce799bd1328eb3e6
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -10860,10 +11107,10 @@ packages:
- nodejs ; extra == 'all'
- pythreejs ; extra == 'all'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/4e/b6/ffe0bb67cec66cd450acff599bb07507bbf5ffda1a3a15dd2d8dbe7a6da7/scipp-25.12.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/60/54/5011adb56853caabfd90686c2e543d1e3c76a8ef2755809b7e12e3f3583b/scipp-26.3.1-cp311-cp311-macosx_14_0_arm64.whl
name: scipp
- version: 25.12.0
- sha256: 9ec0200eeb660965056b27f5f05505a961d8921b78d0a92c04743d1c22ce7203
+ version: 26.3.1
+ sha256: 67d275fc83b062053df9aa7ce3af4d2205109c2bc3ab22467bcd73ceb0a83df2
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -10886,10 +11133,10 @@ packages:
- nodejs ; extra == 'all'
- pythreejs ; extra == 'all'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/6a/3a/ab0eb61593569d5a0d080002e4b8c0998cb1116d8710781b7225c304b880/scipp-25.12.0-cp311-cp311-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/79/fe/b14d806894cf05178f1e77d0d619f071db50cf698bc654c54f9241223bcf/scipp-26.3.1-cp313-cp313-macosx_14_0_arm64.whl
name: scipp
- version: 25.12.0
- sha256: e27082f5bd3655f15479ce87be495235b9bcd9b5db654a7219261be0c6117b31
+ version: 26.3.1
+ sha256: 8dfe8adedb5cba05acaaea15e3b6fe1820ac2f497e87c1e581ba4be9d82c53bb
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -10912,10 +11159,10 @@ packages:
- nodejs ; extra == 'all'
- pythreejs ; extra == 'all'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/94/98/aa2d4b9d28969cc7f62409f9f9fc5b5a853af651255eba03e9bee8546dd9/scipp-25.12.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/81/21/4962b1daddf0422e56c5ed4c41bea1ccb6d2a9ab72b795196835a20969c7/scipp-26.3.1-cp311-cp311-macosx_14_0_x86_64.whl
name: scipp
- version: 25.12.0
- sha256: e5694bef45299c4813ee2fe863fab600c3b0f5e13e2735072dbbb5cf1804d0e0
+ version: 26.3.1
+ sha256: 7c90e78fcba1d272df059fc01350c9e18f017aec26369b03def723a3702d763d
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -10938,10 +11185,10 @@ packages:
- nodejs ; extra == 'all'
- pythreejs ; extra == 'all'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/bd/75/6a3786de6645ac2ccd94fbf83c59cc6b929bfa3a89cb62c8cb3be4de0606/scipp-25.12.0-cp311-cp311-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/d4/06/19ff1efd58b85906149ce83dfddce23252cea5bec7e0fa5f834336cfe836/scipp-26.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
name: scipp
- version: 25.12.0
- sha256: aee5f585232e2a7a664f57bb9695164715271b74896704e7ee8a669dd7b06008
+ version: 26.3.1
+ sha256: ab5859a24b3150b588dd2c67e68b0c7f07c9444eae501f3b6326d6b4a34cbf10
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -10964,10 +11211,10 @@ packages:
- nodejs ; extra == 'all'
- pythreejs ; extra == 'all'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/e5/22/75e119e0a200914f88f121cd956e1eb7f72c8ace4b63171f52ba0334d142/scipp-25.12.0-cp313-cp313-macosx_11_0_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/e2/69/1dcb8e967f62759578938db5b29792b82ea8939a2d712e79491fa3e1cf0a/scipp-26.3.1-cp313-cp313-macosx_14_0_x86_64.whl
name: scipp
- version: 25.12.0
- sha256: 27ebc37f3b7e20c9dca9cf1a0ac53c4ffaea31c02dfc8ba2b5aa008a252cbcba
+ version: 26.3.1
+ sha256: 4c9c8632ba24ce74bd98430a1376310fa5b3fcd2c3467a7e6a484ebb091e915f
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -10990,10 +11237,10 @@ packages:
- nodejs ; extra == 'all'
- pythreejs ; extra == 'all'
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/eb/d1/b3cd2733a96a36c54c36889b2cfdd0331c1e5b57fa1757485a22d0ec3142/scipp-25.12.0-cp313-cp313-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/e6/0d/8882a4c7a5ebe59a46b709e82411d9c730d67250d41a2e11bc4bcd4d431d/scipp-26.3.1-cp311-cp311-win_amd64.whl
name: scipp
- version: 25.12.0
- sha256: 015db5035749750cf026db56fe537af10f159dc3cd0f51f0ea9f4ecc3a7a5da8
+ version: 26.3.1
+ sha256: 37877cf07b4f54f224d5465c265d6a1e591d605d0c23dd350a4b48d95c26ab7b
requires_dist:
- numpy>=2
- pytest ; extra == 'test'
@@ -11494,11 +11741,38 @@ packages:
version: 1.17.0
sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl
+ name: smmap
+ version: 5.0.3
+ sha256: c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f
+ requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl
name: soupsieve
version: 2.8.3
sha256: ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl
+ name: spdx-headers
+ version: 1.5.1
+ sha256: 73bcb1ed087824b55ccaa497d03d8f0f0b0eaf30e5f0f7d5bbd29d2c4fe78fcf
+ requires_dist:
+ - chardet>=5.2.0
+ - requests>=2.32.3
+ - black>=23.0.0 ; extra == 'dev'
+ - build>=0.10.0 ; extra == 'dev'
+ - hatch>=1.9.0 ; extra == 'dev'
+ - isort>=5.12.0 ; extra == 'dev'
+ - mypy>=1.0.0 ; extra == 'dev'
+ - pre-commit>=4.3.0 ; extra == 'dev'
+ - pytest-cov>=4.0.0 ; extra == 'dev'
+ - pytest>=7.0.0 ; extra == 'dev'
+ - ruff>=0.5.0 ; extra == 'dev'
+ - twine>=4.0.0 ; extra == 'dev'
+ - types-requests>=2.31.0.6 ; extra == 'dev'
+ - pytest-cov>=4.0.0 ; extra == 'test'
+ - pytest-mock>=3.10.0 ; extra == 'test'
+ - pytest>=7.0.0 ; extra == 'test'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/16/56/a31e8d3c9e8d21100b83bbe1c1f3f7c94db317393a229e193461e5e6d2a4/spglib-2.6.0-cp313-cp313-win_amd64.whl
name: spglib
version: 2.6.0
@@ -12091,10 +12365,10 @@ packages:
purls: []
size: 3526350
timestamp: 1769460339384
-- pypi: https://files.pythonhosted.org/packages/7c/b9/ac773f87400bce0637b5f87bb272d0b347c91d7063bff09fb7055b65dd2f/tof-26.1.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl
name: tof
- version: 26.1.0
- sha256: 2603a7b94a7296ee503a0edadb314701431808c8ededb5c442334f89633962a5
+ version: 26.3.0
+ sha256: e89783a072b05fdb53d9e76fbf919dc8935e75e118fdaf17ca5cc33727ef002b
requires_dist:
- plopp>=23.10.0
- pooch>=1.5.0
@@ -12108,70 +12382,70 @@ packages:
version: 6.2.0
sha256: a152bf4f249c847a66497a4a95f63376ed68ac6abf092a2f7cfb29d044ecff44
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl
name: tomli
- version: 2.4.0
- sha256: d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa
+ version: 2.4.1
+ sha256: 36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: tomli
- version: 2.4.0
- sha256: 9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e
+ version: 2.4.1
+ sha256: f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl
name: tomli
- version: 2.4.0
- sha256: 84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0
+ version: 2.4.1
+ sha256: eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl
name: tomli
- version: 2.4.0
- sha256: 3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87
+ version: 2.4.1
+ sha256: 5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: tomli
- version: 2.4.0
- sha256: b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867
+ version: 2.4.1
+ sha256: 5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl
name: tomli
- version: 2.4.0
- sha256: 5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9
+ version: 2.4.1
+ sha256: 8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl
name: tomli
- version: 2.4.0
- sha256: 1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e
+ version: 2.4.1
+ sha256: 4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl
name: tomli
- version: 2.4.0
- sha256: 5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76
+ version: 2.4.1
+ sha256: f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl
name: toolz
version: 1.1.0
sha256: 15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl
name: tornado
- version: 6.5.4
- sha256: e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f
+ version: 6.5.5
+ sha256: 6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
+- pypi: https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl
name: tornado
- version: 6.5.4
- sha256: d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9
+ version: 6.5.5
+ sha256: 487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl
+- pypi: https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl
name: tornado
- version: 6.5.4
- sha256: fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc
+ version: 6.5.5
+ sha256: 65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
name: tornado
- version: 6.5.4
- sha256: 2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843
+ version: 6.5.5
+ sha256: e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5
requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
name: traitlets
@@ -12269,10 +12543,6 @@ packages:
- python-docs-theme ; extra == 'doc'
- uncertainties[arrays,doc,test] ; extra == 'all'
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz
- name: untokenize
- version: 0.1.1
- sha256: 3865dbbbb8efb4bb5eaa72f1be7f3e0be00ea8b7f125c69cbd1f5fda926f37a2
- pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl
name: uri-template
version: 1.3.0
@@ -12310,26 +12580,6 @@ packages:
- pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks'
- backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/6f/34/2e5cd576d312eb1131b615f49ee95ff6efb740965324843617adae729cf2/uv-0.10.9-py3-none-macosx_10_12_x86_64.whl
- name: uv
- version: 0.10.9
- sha256: 880dd4cffe4bd184e8871ddf4c7d3c3b042e1f16d2682310644aa8d61eaea3e6
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/79/34/b104c413079874493eed7bf11838b47b697cf1f0ed7e9de374ea37b4e4e0/uv-0.10.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- name: uv
- version: 0.10.9
- sha256: 7c9d6deb30edbc22123be75479f99fb476613eaf38a8034c0e98bba24a344179
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/89/35/684f641de4de2b20db7d2163c735b2bb211e3b3c84c241706d6448e5e868/uv-0.10.9-py3-none-macosx_11_0_arm64.whl
- name: uv
- version: 0.10.9
- sha256: a7a784254380552398a6baf4149faf5b31a4003275f685c28421cf8197178a08
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/c9/e9/adf7a12136573937d12ac189569e2e90e7fad18b458192083df6986f3013/uv-0.10.9-py3-none-win_amd64.whl
- name: uv
- version: 0.10.9
- sha256: af79552276d8bd622048ab2d67ec22120a6af64d83963c46b1482218c27b571f
- requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl
name: validate-pyproject
version: '0.25'
diff --git a/pixi.toml b/pixi.toml
index c0a8608e..2cbf09c5 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -5,7 +5,7 @@
# Platform-independent
[activation.env]
-PYTHONIOENCODING = "utf-8"
+PYTHONIOENCODING = 'utf-8'
# Platform-specific
@@ -27,6 +27,7 @@ PYTHONPATH = "${PIXI_PROJECT_ROOT}/src;%PYTHONPATH%"
###########
[workspace]
+
# Supported platforms for the lock file (pixi.lock)
platforms = ['win-64', 'linux-64', 'osx-64', 'osx-arm64']
@@ -34,7 +35,7 @@ platforms = ['win-64', 'linux-64', 'osx-64', 'osx-arm64']
channels = ['conda-forge']
#####################
-# System requirements
+# SYSTEM REQUIREMENTS
#####################
[system-requirements]
@@ -52,34 +53,20 @@ macos = '14.0'
# Default feature configuration
[dependencies]
-gsl = '*' # GNU Scientific Library; required for pdffit2.
-
-#[target.win-64.dependencies]
-#libcblas = '*' # CBLAS library for linear algebra; required for pdffit2.
+nodejs = '*' # Required for Prettier (non-Python formatting)
+gsl = '*' # GNU Scientific Library; required for diffpy.pdffit2
[pypi-dependencies] # == [feature.default.pypi-dependencies]
-pip = '*' # Native package installer
-uv = '*' # Package manager
-jupyterlab = '*' # Jupyter notebooks
-pixi-kernel = '*' # Pixi Jupyter kernel
-#easydiffraction = { version = '*', extras = ['all'] } # Main package
-easydiffraction = { path = ".", editable = true, extras = ['all'] }
-
-# Specific features
+#pip = '*' # Native package installer
+easydiffraction = { path = '.', editable = true, extras = ['dev'] }
-# Each feature sets a specific Python version for the environment.
+# Specific features: Set specific Python versions
-[feature.py311.dependencies]
+[feature.py-min.dependencies]
python = '3.11.*'
-
-[feature.py313.dependencies]
+[feature.py-max.dependencies]
python = '3.13.*'
-# This feature installs Node.js for formatting non-Python files with Prettier.
-
-[feature.nodejs.dependencies]
-nodejs = '*'
-
##############
# ENVIRONMENTS
##############
@@ -88,13 +75,12 @@ nodejs = '*'
# The `default` feature is always included in all environments.
# Additional features can be specified per environment.
+py-311-env = { features = ['default', 'py-min'] }
+py-313-env = { features = ['default', 'py-max'] }
# The `default` environment is always created and includes the `default` feature.
# It does not need to be specified explicitly unless non-default features are included.
-
-default = { features = ['py313', 'nodejs'] }
-py311-dev = { features = ['py311', 'nodejs'] }
-py313-dev = { features = ['py313', 'nodejs'] }
+default = { features = ['default', 'py-max'] }
#######
# TASKS
@@ -102,59 +88,59 @@ py313-dev = { features = ['py313', 'nodejs'] }
[tasks]
-## 🧪 Testing Tasks
+##################
+# 🧪 Testing Tasks
+##################
+
unit-tests = 'python -m pytest tests/unit/ --color=yes -v'
integration-tests = 'python -m pytest tests/integration/ --color=yes -n auto -v'
-notebook-tests = 'python -m pytest --nbmake tutorials/ --nbmake-timeout=600 --color=yes -n auto -v'
script-tests = 'python -m pytest tools/test_scripts.py --color=yes -n auto -v'
-extra = 'python -m pytest tests/unit/extra.py -q --tb=no --disable-warnings --color=yes'
+notebook-tests = 'python -m pytest --nbmake docs/docs/tutorials/ --nbmake-timeout=600 --color=yes -n auto -v'
test = { depends-on = ['unit-tests'] }
-# 🧹 Code Quality
+###########
+# ✔️ Checks
+###########
-### ✔️ Checks
pyproject-check = 'python -m validate_pyproject pyproject.toml'
-py-lint-check-pre = "python -m ruff check"
-py-lint-check = 'pixi run py-lint-check-pre .'
-py-format-check-pre = "python -m ruff format --check"
-py-format-check = "pixi run py-format-check-pre ."
-nonpy-format-check-pre = "npx prettier --list-different --config=prettierrc.toml"
-nonpy-format-check-modified = "pixi run nonpy-format-check-pre $(git diff --diff-filter=d --name-only HEAD | grep -E '\\.(json|ya?ml|toml|md|css|html)$' || echo .)"
-nonpy-format-check = "pixi run nonpy-format-check-pre ."
-notebook-format-check = 'nbqa ruff tutorials/'
-docs-format-check = 'docformatter src/ tutorials/ --check'
-# Run like a real commit: staged files only (almost)
-pre-commit-check = 'pre-commit run --hook-stage pre-commit'
-# CI check: lint/format everything
-pre-commit-check-all = 'pre-commit run --all-files --hook-stage pre-commit'
-# Pre-push check: lint/format everything
-pre-push-check = 'pre-commit run --all-files --hook-stage pre-push'
-
-check = { depends-on = [
- 'docs-format-check',
- 'py-format-check',
- 'py-lint-check',
- 'nonpy-format-check-modified',
-] }
+param-docstring-check = 'python tools/param_consistency.py src/ --check'
+docstring-lint-check = 'pydoclint --quiet src/'
+notebook-lint-check = 'nbqa ruff docs/docs/tutorials/'
+py-lint-check = 'ruff check src/ tests/ docs/docs/tutorials/'
+py-format-check = 'ruff format --check src/ tests/ docs/docs/tutorials/'
+nonpy-format-check = 'npx prettier --list-different --config=prettierrc.toml --ignore-unknown .'
+nonpy-format-check-modified = 'python tools/nonpy_prettier_modified.py'
+
+check = 'pre-commit run --hook-stage manual --all-files'
+
+##########
+# 🛠️ Fixes
+##########
-### 🛠️ Fixes
-py-lint-fix = 'pixi run py-lint-check --fix'
-#py-format-fix = "python -m ruff format $(git diff --cached --name-only -- '*.py')"
-py-format-fix = "python -m ruff format"
-nonpy-format-fix = 'pixi run nonpy-format-check --write'
-nonpy-format-fix-modified = "pixi run nonpy-format-check-modified --write"
-notebook-format-fix = 'pixi run notebook-format-check --fix'
-docs-format-fix = 'docformatter src/ tutorials/ --in-place'
+param-docstring-fix = 'python tools/param_consistency.py src/ --fix'
+docstring-format-fix = 'format-docstring src/'
+notebook-lint-fix = 'nbqa ruff --fix docs/docs/tutorials/'
+py-lint-fix = 'ruff check --fix src/ tests/ docs/docs/tutorials/'
+py-format-fix = 'ruff format src/ tests/ docs/docs/tutorials/'
+nonpy-format-fix = 'npx prettier --write --list-different --config=prettierrc.toml --ignore-unknown .'
+nonpy-format-fix-modified = 'python tools/nonpy_prettier_modified.py --write'
+success-message = 'echo "✅ All auto-formatting steps completed successfully!"'
fix = { depends-on = [
+ #'param-docstring-fix', # ED only
+ 'docstring-format-fix',
'py-format-fix',
- 'docs-format-fix',
'py-lint-fix',
'nonpy-format-fix',
+ 'notebook-lint-fix',
+ 'success-message',
] }
-## 🧮 Code Complexity
+####################
+# 🧮 Code Complexity
+####################
+
complexity-check = 'radon cc -s src/'
complexity-check-json = 'radon cc -s -j src/'
maintainability-check = 'radon mi src/'
@@ -162,62 +148,127 @@ maintainability-check-json = 'radon mi -j src/'
raw-metrics = 'radon raw -s src/'
raw-metrics-json = 'radon raw -s -j src/'
-## 📊 Coverage
+#############
+# 📊 Coverage
+#############
+
unit-tests-coverage = 'pixi run unit-tests --cov=src/easydiffraction --cov-report=term-missing'
integration-tests-coverage = 'pixi run integration-tests --cov=src/easydiffraction --cov-report=term-missing'
-docstring-coverage = 'interrogate -c pyproject.toml src/'
+docstring-coverage = 'interrogate -c pyproject.toml src/easydiffraction'
-cov = { depends-on = ['docstring-coverage', 'integration-tests-coverage'] }
+cov = { depends-on = [
+ 'docstring-coverage',
+ 'unit-tests-coverage',
+ 'integration-tests-coverage',
+] }
-## 📓 Notebook Management
-notebook-convert = 'jupytext tutorials/*.py --from py:percent --to ipynb'
-notebook-strip = 'nbstripout tutorials/*.ipynb'
+########################
+# 📓 Notebook Management
+########################
+
+notebook-convert = 'jupytext docs/docs/tutorials/*.py --from py:percent --to ipynb'
+notebook-strip = 'nbstripout docs/docs/tutorials/*.ipynb'
notebook-tweak = 'python tools/tweak_notebooks.py tutorials/'
-notebook-clean = 'rm -f tutorials/*.ipynb'
-notebook-exec = 'python -m pytest --nbmake tutorials/ --nbmake-timeout=600 --overwrite --color=yes -n auto -v'
+notebook-exec = 'python -m pytest --nbmake docs/docs/tutorials/ --nbmake-timeout=600 --overwrite --color=yes -n auto -v'
notebook-prepare = { depends-on = [
- 'notebook-convert',
+ #'notebook-convert',
'notebook-strip',
- 'notebook-tweak',
+ #'notebook-tweak',
+] }
+
+########################
+# 📚 Documentation Tasks
+########################
+
+docs-vars = "JUPYTER_PLATFORM_DIRS=1 PYTHONWARNINGS='ignore::RuntimeWarning'"
+docs-pre = 'pixi run docs-vars python -m mkdocs'
+docs-serve = 'pixi run docs-pre serve -f docs/mkdocs.yml'
+docs-serve-dirty = 'pixi run docs-serve --dirty'
+docs-build = 'pixi run docs-pre build -f docs/mkdocs.yml'
+docs-build-local = 'pixi run docs-build --no-directory-urls'
+
+docs-deploy-pre = 'mike deploy -F docs/mkdocs.yml --push --branch gh-pages --update-aliases --alias-type redirect'
+docs-set-default-pre = 'mike set-default -F docs/mkdocs.yml --push --branch gh-pages'
+
+docs-update-assets = 'python tools/update_docs_assets.py'
+
+##############################
+# 📦 Template Management Tasks
+##############################
+
+copier-copy = 'copier copy gh:easyscience/templates . --data-file ../diffraction/.copier-answers.yml --data template_type=lib'
+copier-recopy = 'copier recopy --data-file ../diffraction/.copier-answers.yml --data template_type=lib'
+copier-update = 'copier update --data-file ../diffraction/.copier-answers.yml --data template_type=lib'
+
+#####################
+# 🪝 Pre-commit Hooks
+#####################
+
+pre-commit-clean = 'pre-commit clean'
+pre-commit-install = 'pre-commit install --hook-type pre-commit --hook-type pre-push --overwrite'
+pre-commit-uninstall = 'pre-commit uninstall --hook-type pre-commit --hook-type pre-push'
+pre-commit-setup = { depends-on = [
+ 'pre-commit-clean',
+ 'pre-commit-uninstall',
+ 'pre-commit-install',
] }
-## 📚 Documentation Tasks
-docs-assets = 'tools/add_assets_to_docs.sh'
-docs-notebooks = 'mv tutorials/*.* docs/tutorials/' # *.py, *.ipynb, index.json
-docs-config = 'python tools/create_mkdocs_yml.py'
-docs-deploy = 'mike deploy --push --branch gh-pages --update-aliases --alias-type redirect'
-docs-set-default = 'mike set-default --push --branch gh-pages'
-docs-serve = "JUPYTER_PLATFORM_DIRS=1 PYTHONWARNINGS='ignore::RuntimeWarning' python -m mkdocs serve --dirty"
-docs-build = "JUPYTER_PLATFORM_DIRS=1 PYTHONWARNINGS='ignore::RuntimeWarning' python -m mkdocs build"
-docs-local = "pixi run docs-build --no-directory-urls"
-docs-clean = 'tools/cleanup_docs.sh'
-docs-setup = { depends-on = [
- 'docs-config',
- 'docs-assets',
- 'notebook-prepare',
- 'docs-notebooks',
+#################
+# 🐙️ GitHub Tasks
+#################
+
+repo-wiki = 'gh api -X PATCH repos/easyscience/diffraction-lib -f has_wiki=false'
+repo-discussions = 'gh api -X PATCH repos/easyscience/diffraction-lib -f has_discussions=true'
+repo-description = "gh api -X PATCH repos/easyscience/diffraction-lib -f description='Diffraction data analysis'"
+repo-homepage = "gh api -X PATCH repos/easyscience/diffraction-lib -f homepage='https://easyscience.github.io/diffraction-lib'"
+repo-config = { depends-on = [
+ 'repo-wiki',
+ 'repo-discussions',
+ 'repo-description',
+ 'repo-homepage',
] }
-## 🚀 Development & Build Tasks
+master-protection = 'gh api -X POST repos/easyscience/diffraction-lib/rulesets --input .github/configs/rulesets-master.json'
+develop-protection = 'gh api -X POST repos/easyscience/diffraction-lib/rulesets --input .github/configs/rulesets-develop.json'
+gh-pages-protection = 'gh api -X POST repos/easyscience/diffraction-lib/rulesets --input .github/configs/rulesets-gh-pages.json'
+branch-protection = { depends-on = [
+ 'master-protection',
+ 'develop-protection',
+ 'gh-pages-protection',
+] }
+
+pages-deployment = 'gh api -X POST repos/easyscience/diffraction-lib/pages --input .github/configs/pages-deployment.json'
+
+github-labels = 'python tools/update_github_labels.py'
+
+#########################
+# ⚖️ SPDX License Headers
+#########################
+
+license-remove = 'python tools/license_headers.py remove src/ tests/ --exclude-from-pyproject-toml tool.ruff.exclude'
+license-add = 'python tools/license_headers.py add src/ tests/ --exclude-from-pyproject-toml tool.ruff.exclude'
+license-check = 'python tools/license_headers.py check src/ tests/ --exclude-from-pyproject-toml tool.ruff.exclude'
+
+####################################
+# 🚀 Other Development & Build Tasks
+####################################
+
+default-build = 'python -m build'
dist-build = 'python -m build --wheel --outdir dist'
-spdx-update = 'python tools/update_spdx.py'
-#dev-install = 'uv pip install --requirements pyproject.toml --extra all'
-#dev-install = "python -m uv pip install --force-reinstall --editable '.[all]'"
+
npm-config = 'npm config set registry https://registry.npmjs.org/'
prettier-install = 'npm install --no-save --no-audit --no-fund prettier prettier-plugin-toml'
-pre-commit-setup = 'pre-commit clean && pre-commit uninstall && pre-commit install --hook-type pre-commit --hook-type pre-push --overwrite'
-pre-commit-update = 'pre-commit autoupdate'
+
clean-pycache = "find . -type d -name '__pycache__' -prune -exec rm -rf '{}' +"
-dev = { depends-on = [
- #'dev-install',
+post-install = { depends-on = [
'npm-config',
'prettier-install',
#'pre-commit-setup',
] }
-wheel = { depends-on = ['npm-config', 'prettier-install'] }
-
-## 🔗 Main Package Shortcut
+##########################
+# 🔗 Main Package Shortcut
+##########################
easydiffraction = 'python -m easydiffraction'
diff --git a/prettierrc.toml b/prettierrc.toml
index 6874d28d..b98c86eb 100644
--- a/prettierrc.toml
+++ b/prettierrc.toml
@@ -1,11 +1,22 @@
+plugins = [
+ "prettier-plugin-toml", # use the TOML plugin
+]
+
endOfLine = 'lf' # change line endings to LF
-printWidth = 80 # wrap Markdown files at 80 characters
proseWrap = 'always' # change wrapping in Markdown files
semi = false # remove semicolons
singleQuote = true # use single quotes instead of double quotes
tabWidth = 2 # change tab width to 2 spaces
useTabs = false # use spaces instead of tabs
-plugins = [
- 'prettier-plugin-toml', # use the TOML plugin
-]
+printWidth = 79 # wrap lines at 79 characters
+
+[[overrides]]
+files = ["*.md"]
+[overrides.options]
+printWidth = 72 # wrap Markdown files at 72 characters
+
+[[overrides]]
+files = ["*.yml", "*.yaml"]
+[overrides.options]
+printWidth = 88 # wrap YAML files at 88 characters
diff --git a/pycrysfml.md b/pycrysfml.md
index af681478..de9bc4d0 100644
--- a/pycrysfml.md
+++ b/pycrysfml.md
@@ -12,7 +12,8 @@
```bash
otool -L .venv/lib/python3.12/site-packages/pycrysfml/crysfml08lib.so
```
-- If the library is linked to the wrong Python version, you can fix it with:
+- If the library is linked to the wrong Python version, you can fix it
+ with:
```bash
install_name_tool -change `python3-config --prefix`/Python `python3-config --prefix`/lib/libpython3.12.dylib .venv/lib/python3.12/site-packages/pycrysfml/crysfml08lib.so
```
diff --git a/pyproject.toml b/pyproject.toml
index dd645c71..16d18621 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,9 +6,10 @@
name = 'easydiffraction'
dynamic = ['version'] # Use versioningit to manage the version
description = 'Diffraction data analysis'
-authors = [{ name = 'EasyDiffraction contributors' }]
+authors = [{ name = 'EasyScience contributors' }]
readme = 'README.md'
-license = { file = 'LICENSE' }
+license = 'BSD-3-Clause'
+license-files = ['LICENSE']
classifiers = [
'Intended Audience :: Science/Research',
'Topic :: Scientific/Engineering',
@@ -20,7 +21,7 @@ classifiers = [
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
]
-requires-python = '>=3.11,<3.14'
+requires-python = '>=3.11'
dependencies = [
'essdiffraction', # ESS-specific diffraction library
'numpy', # Numerical computing library
@@ -43,29 +44,36 @@ dependencies = [
'diffpy.utils', # Utilities for PDF calculations
'uncertainties', # Propagation of uncertainties
'typeguard', # Runtime type checking
+ 'darkdetect', # Detecting dark mode (system-level)
+ 'pandas', # Displaying tables in Jupyter notebooks
+ 'plotly', # Interactive plots
+ 'py3Dmol', # Visualisation of crystal structures
+ 'jupyterlab', # Jupyter notebooks
+ 'pixi-kernel', # Pixi Jupyter kernel
]
[project.optional-dependencies]
dev = [
- 'build', # Building the package
- 'pre-commit', # Pre-commit hooks
- 'jinja2', # Templating
- 'nbmake', # Building notebooks
- 'nbstripout', # Strip output from notebooks
- 'nbqa', # Linting and formatting notebooks
- 'pytest', # Testing
- 'pytest-cov', # Test coverage
- 'pytest-xdist', # Enable parallel testing
- 'ruff', # Linting and formatting code
- 'radon', # Code complexity and maintainability
- 'validate-pyproject[all]', # Validate pyproject.toml
- 'versioningit', # Automatic versioning from git tags
- 'jupytext', # Jupyter notebook text format support
- 'jupyterquiz', # Quizzes in Jupyter notebooks
- 'docformatter', # Code formatter for docstrings
- 'interrogate', # Check for missing docstrings
-]
-docs = [
+ 'GitPython', # Interact with Git repositories
+ 'build', # Building the package
+ 'pre-commit', # Pre-commit hooks
+ 'jinja2', # Templating
+ 'nbmake', # Building notebooks
+ 'nbstripout', # Strip output from notebooks
+ 'nbqa', # Linting and formatting notebooks
+ 'pytest', # Testing
+ 'pytest-cov', # Test coverage
+ 'pytest-xdist', # Enable parallel testing
+ 'ruff', # Linting and formatting code
+ 'radon', # Code complexity and maintainability
+ 'validate-pyproject[all]', # Validate pyproject.toml
+ 'versioningit', # Automatic versioning from git tags
+ 'jupytext', # Jupyter notebook text format support
+ 'jupyterquiz', # Quizzes in Jupyter notebooks
+ 'pydoclint', # Docstring linter
+ 'format-docstring', # Docstring formatter
+ 'interrogate', # Docstring coverage checker
+ 'copier', # Template management
'mike', # MkDocs: Versioned documentation support
'mkdocs', # Static site generator
'mkdocs-material', # Documentation framework on top of MkDocs
@@ -75,35 +83,20 @@ docs = [
'mkdocs-markdownextradata-plugin', # MkDocs: Markdown extra data support, such as global variables
'mkdocstrings-python', # MkDocs: Python docstring support
'pyyaml', # YAML parser
-]
-visualization = [
- 'darkdetect', # Detecting dark mode (system-level)
- 'pandas', # Displaying tables in Jupyter notebooks
- 'plotly', # Interactive plots
- 'py3Dmol', # Visualisation of crystal structures
-]
-all = [
- 'easydiffraction[dev]',
- 'easydiffraction[docs]',
- 'easydiffraction[visualization]',
+ 'spdx-headers', # SPDX license header validation
]
[project.urls]
-homepage = 'https://easydiffraction.org'
-documentation = 'https://docs.easydiffraction.org/lib'
-source = 'https://github.com/easyscience/diffraction-lib'
-tracker = 'https://github.com/easyscience/diffraction-lib/issues'
+Homepage = 'https://easydiffraction.org'
+Documentation = 'https://easyscience.github.io/diffraction-lib'
+'Release Notes' = 'https://github.com/easyscience/diffraction-lib/releases'
+'Source Code' = 'https://github.com/easyscience/diffraction-lib'
+'Issue Tracker' = 'https://github.com/easyscience/diffraction-lib/issues'
############################
# Build system configuration
############################
-# Build system 'hatch' -- Python project manager
-# https://hatch.pypa.io/
-
-# Versioning system 'versioningit' -- Versioning from git tags
-# https://versioningit.readthedocs.io/
-
[build-system]
build-backend = 'hatchling.build'
requires = ['hatchling', 'versioningit']
@@ -112,6 +105,9 @@ requires = ['hatchling', 'versioningit']
# Configuration for hatchling
#############################
+# 'hatch' -- Build system for Python
+# https://hatch.pypa.io/
+
[tool.hatch.build.targets.wheel]
packages = ['src/easydiffraction']
@@ -125,6 +121,9 @@ source = 'versioningit' # Use versioningit to manage the version
# Configuration for versioningit
################################
+# 'versioningit' -- Versioning from git tags
+# https://versioningit.readthedocs.io/
+
# Versioningit generates versions from git tags, so we don't need to
# either specify them statically in pyproject.toml or save them in the
# source code. Do not use {distance} in the version format, as it
@@ -144,43 +143,45 @@ method = 'git'
match = ['v*']
default-tag = 'v999.0.0'
-################################
-# Configuration for docformatter
-################################
-
-# 'docformatter' -- Code formatter for docstrings
-# https://docformatter.readthedocs.io/en/latest/
-
-[tool.docformatter]
-recursive = true
-wrap-summaries = 72
-wrap-descriptions = 72
-close-quotes-on-newline = true
-
################################
# Configuration for interrogate
################################
-# 'interrogate' -- Check for missing docstrings
+# 'interrogate' -- Docstring coverage checker
# https://interrogate.readthedocs.io/en/latest/
[tool.interrogate]
-fail-under = 35 # Temporarily reduce to allow gradual improvement
+fail-under = 35 # Minimum docstring coverage percentage to pass
verbose = 1
-exclude = ["src/**/__init__.py"]
+#exclude = ['src/**/__init__.py']
#######################################
# Configuration for coverage/pytest-cov
#######################################
+# 'coverage' -- Code coverage measurement tool
+# https://coverage.readthedocs.io/en/latest/
+
[tool.coverage.run]
-branch = true # Measure branch coverage as well
-source = ['src/easydiffraction'] # Limit coverage to the source code directory
+branch = true # Measure branch coverage as well
+source = ['src'] # Limit coverage to the source code directory
[tool.coverage.report]
-show_missing = true # Show missing lines
-skip_covered = true # Skip files with 100% coverage in the report
-fail_under = 60 # Temporarily reduce to allow gradual improvement
+show_missing = true # Show missing lines
+skip_covered = false # Skip files with 100% coverage in the report
+fail_under = 60 # Minimum coverage percentage to pass
+
+##########################
+# Configuration for pytest
+##########################
+
+# 'pytest' -- Testing framework
+# https://docs.pytest.org/en/stable/
+
+[tool.pytest.ini_options]
+addopts = '--import-mode=importlib'
+markers = ['fast: mark test as fast (should be run on every push)']
+testpaths = ['tests']
########################
# Configuration for ruff
@@ -190,107 +191,197 @@ fail_under = 60 # Temporarily reduce to allow gradual improvement
# https://docs.astral.sh/ruff/rules/
[tool.ruff]
-# Temporarily exclude some directories until we have improved the code quality there
-exclude = ['tmp', 'tests/unit']
+exclude = [
+ 'tmp',
+ # Vendored jupyter_dark_detect: keep as-is from upstream for easy updates
+ # https://github.com/OpenMined/jupyter-dark-detect/tree/main/jupyter_dark_detect
+ 'src/easydiffraction/utils/_vendored/jupyter_dark_detect',
+]
indent-width = 4
-line-length = 99
-# Enable new rules that are not yet stable, like DOC
-preview = true
+line-length = 99 # See also `max-line-length` in [tool.ruff.lint.pycodestyle]
+preview = true # Enable new rules that are not yet stable, like DOC
+
+# Formatting options for Ruff
+
+[tool.ruff.format]
+docstring-code-format = true # Whether to format code snippets in docstrings
+docstring-code-line-length = 72 # Line length for code snippets in docstrings
+indent-style = 'space' # PEP 8 recommends using spaces over tabs
+line-ending = 'lf' # Line endings will be converted to \n
+quote-style = 'single' # But double quotes in docstrings (PEP 8, PEP 257)
+
+# Linting rules to use with Ruff
-# https://docs.astral.sh/ruff/rules/
[tool.ruff.lint]
select = [
- 'ARG', # Argument-related issues (e.g., unused arguments)
- 'B', # Bugbear-specific checks (e.g., likely bugs, bad patterns)
- 'C', # Complexity-related issues (e.g., high McCabe complexity)
- 'D', # Docstring formatting issues (old rules)
- 'DOC', # Docstring formatting issues (new rules)
- 'DTZ', # Datetime timezone issues (e.g., inconsistent timezone formats)
- 'E', # General PEP 8 style errors
- 'F', # Pyflakes-specific checks (e.g., unused variables, imports)
- 'FLY', # Flynt-specific checks (e.g., enforcing f-strings)
- 'G', # Type annotation issues (e.g., missing or incorrect type hints)
- 'I', # Import sorting issues (e.g., unsorted imports)
- 'ICN', # Import conventions (e.g., enforce aliasing like import numpy as np)
- 'N', # Naming convention issues (e.g., variable names, function names)
- 'NPY', # NumPy-specific checks (e.g., array operations, broadcasting)
- 'PGH', # Misc text patterns checks
- 'PTH', # Encourages using pathlib over os.path
- 'S', # Security-related issues (e.g., use of insecure functions or libraries)
- 'SIM', # Simplification issues (e.g., redundant code, unnecessary constructs)
- 'TCH', # Type checking issues (e.g., incompatible types, missing type annotations)
- 'TID252', # Enforces absolute imports over relative imports
- 'W', # General PEP 8 warnings (e.g., lines too long, trailing whitespace)
- #'ANN', # Missing or incorrect type annotations
- #'COM', # Comment formatting issues
- #'PERF', # Performance-related issues (e.g., inefficient code patterns)
- #'PIE', # Potentially problematic idioms and errors
- #'PL', # PyLint-specific checks (e.g., code smells, potential errors)
- #'PT', # Pytest-related issues
- #'RET', # Return statement issues (e.g., inconsistent returns)
- #'RUF', # Ruff-specific checks (e.g., enforcing best practices)
- #'SLF', # Self argument-related issues (e.g., missing or misused self)
- #'T20', # Flake8-print-specific checks (e.g., print statements left in code)
- #'TD', # Type definition issues (e.g., incorrect or missing type definitions)
- #'TRY', # Tryceratops Try/Except-related issues (e.g., broad exceptions, empty except blocks)
- #'UP', # Pyupgrade-specific checks
+ # Various rules
+ #'C90', # https://docs.astral.sh/ruff/rules/#mccabe-c90
+ 'D', # https://docs.astral.sh/ruff/rules/#pydocstyle-d
+ 'F', # https://docs.astral.sh/ruff/rules/#pyflakes-f
+ 'FLY', # https://docs.astral.sh/ruff/rules/#flynt-fly
+ #'FURB', # https://docs.astral.sh/ruff/rules/#refurb-furb
+ 'I', # https://docs.astral.sh/ruff/rules/#isort-i
+ 'N', # https://docs.astral.sh/ruff/rules/#pep8-naming-n
+ 'NPY', # https://docs.astral.sh/ruff/rules/#numpy-specific-rules-npy
+ 'PGH', # https://docs.astral.sh/ruff/rules/#pygrep-hooks-pgh
+ #'PERF', # https://docs.astral.sh/ruff/rules/#perflint-perf
+ #'RUF', # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
+ #'TRY', # https://docs.astral.sh/ruff/rules/#tryceratops-try
+ #'UP', # https://docs.astral.sh/ruff/rules/#pyupgrade-up
+ # pycodestyle (E, W) rules
+ 'E', # https://docs.astral.sh/ruff/rules/#error-e
+ 'W', # https://docs.astral.sh/ruff/rules/#warning-w
+ # Pylint (PL) rules
+ #'PLC', # https://docs.astral.sh/ruff/rules/#convention-plc
+ #'PLE', # https://docs.astral.sh/ruff/rules/#error-ple
+ #'PLR', # https://docs.astral.sh/ruff/rules/#refactor-plr
+ #'PLW', # https://docs.astral.sh/ruff/rules/#warning-plw
+ # flake8 rules
+ #'A', # https://docs.astral.sh/ruff/rules/#flake8-builtins-a
+ 'ANN', # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann
+ 'ARG', # https://docs.astral.sh/ruff/rules/#flake8-unused-arguments-arg
+ #'ASYNC', # https://docs.astral.sh/ruff/rules/#flake8-async-async
+ 'B', # https://docs.astral.sh/ruff/rules/#flake8-bugbear-b
+ #'BLE', # https://docs.astral.sh/ruff/rules/#flake8-blind-except-ble
+ #'C4', # https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4
+ #'COM', # https://docs.astral.sh/ruff/rules/#flake8-commas-com
+ 'DTZ', # https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz
+ #'EM', # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em
+ #'FA', # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa
+ #'FBT', # https://docs.astral.sh/ruff/rules/#flake8-boolean-trap-fbt
+ #'FIX', # https://docs.astral.sh/ruff/rules/#flake8-fixme-fix
+ 'G', # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g
+ 'ICN', # https://docs.astral.sh/ruff/rules/#flake8-import-conventions-icn
+ #'INP', # https://docs.astral.sh/ruff/rules/#flake8-no-pep420-inp
+ #'ISC', # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc
+ #'LOG', # https://docs.astral.sh/ruff/rules/#flake8-logging-log
+ #'PIE', # https://docs.astral.sh/ruff/rules/#flake8-pie-pie
+ #'PT', # https://docs.astral.sh/ruff/rules/#flake8-pytest-style-pt
+ 'PTH', # https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth
+ #'PYI', # https://docs.astral.sh/ruff/rules/#flake8-pyi-pyi
+ #'RET', # https://docs.astral.sh/ruff/rules/#flake8-return-ret
+ #'RSE', # https://docs.astral.sh/ruff/rules/#flake8-raise-rse
+ 'S', # https://docs.astral.sh/ruff/rules/#flake8-bandit-s
+ 'SIM', # https://docs.astral.sh/ruff/rules/#flake8-simplify-sim
+ #'SLF', # https://docs.astral.sh/ruff/rules/#flake8-self-slf
+ #'SLOT', # https://docs.astral.sh/ruff/rules/#flake8-slots-slot
+ #'T20', # https://docs.astral.sh/ruff/rules/#flake8-print-t20
+ #'TC', # https://docs.astral.sh/ruff/rules/#flake8-type-checking-tc
+ #'TD', # https://docs.astral.sh/ruff/rules/#flake8-todos-td
+ #'TID', # https://docs.astral.sh/ruff/rules/#flake8-tidy-imports-tid
]
-# Temporarily disable some docstring checks until we have improved the docstring coverage
+
+# Exceptions to the linting rules
+
+# Ignore specific rules globally
ignore = [
- 'C408', # Ignore: Unnecessary `dict()` call
- 'C416', # Ignore: Unnecessary list comprehension
- 'D100', # Ignore: Missing docstring in public module
- 'D101', # Ignore: Missing docstring in class
- 'D102', # Ignore: Missing docstring in public method
- 'D103', # Ignore: Missing docstring in public function
- 'D104', # Ignore: Missing docstring in public package
- 'D105', # Ignore: Missing docstring in magic method
- 'D107', # Ignore: Missing docstring in __init__
- 'D205', # Ignore: 1 blank line required between summary and description
- 'DOC201', # Ignore: `return` is not documented in docstring
- 'DOC501', # Ignore: Raised exception `ValueError` missing from docstring
- 'DOC502', # Ignore: Raised exception is not explicitly raised: `TypeError`
- 'DTZ005', # Ignore: `datetime.datetime.now()` called without a `tz` argument
+ 'COM812', # https://docs.astral.sh/ruff/rules/missing-trailing-comma/
+ # The following is replaced by 'D'/[tool.ruff.lint.pydocstyle] and [tool.pydoclint]
+ 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc
+ # Disable, as [tool.format_docstring] split one-line docstrings into the canonical multi-line layout
+ 'D200', # https://docs.astral.sh/ruff/rules/unnecessary-multiline-docstring/
+ # Temporary:
+ 'D100', # https://docs.astral.sh/ruff/rules/undocumented-public-module/#undocumented-publi-module-d100
+ 'D104', # https://docs.astral.sh/ruff/rules/undocumented-public-package/#undocumented-public-package-d104
+ 'DTZ005', # https://docs.astral.sh/ruff/rules/call-datetime-now-without-tzinfo/#call-datetime-now-without-tzinfo-dtz005
]
-# Temporarily increase McCabe complexity limit to 19 to allow
-# refactoring in smaller steps.
-[tool.ruff.lint.mccabe]
-max-complexity = 37 # 19 # default is 10
+# Ignore specific rules in certain files or directories
+[tool.ruff.lint.per-file-ignores]
+'*/__init__.py' = [
+ 'F401', # re-exports are intentional in __init__.py
+]
+'tests/**' = [
+ 'ANN', # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann
+ 'D', # https://docs.astral.sh/ruff/rules/#pydocstyle-d
+ 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc
+ 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/
+ 'S101', # https://docs.astral.sh/ruff/rules/assert/
+ # Temporary:
+ 'ARG001',
+ 'ARG002',
+ 'ARG004',
+ 'ARG005',
+ 'B011',
+ 'B017',
+ 'B018',
+ 'E501',
+ 'E741',
+ 'F841',
+ 'I001',
+ 'N801',
+ 'N805',
+ 'N812',
+ 'PLC',
+ 'PLE',
+ 'PLR',
+ 'PLW',
+ 'SIM117',
+ 'W505',
+]
+'docs/**' = [
+ 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/
+ 'T201', # https://docs.astral.sh/ruff/rules/print/
+]
+
+# Specific options for certain rules
[tool.ruff.lint.flake8-tidy-imports]
+# Disallow all relative imports
ban-relative-imports = 'all'
[tool.ruff.lint.isort]
+# Forces all from imports to appear on their own line
force-single-line = true
-[tool.ruff.lint.per-file-ignores]
-'*test_*.py' = ['S101'] # allow asserts in test files
-'conftest.py' = ['S101'] # allow asserts in test files
-'*/__init__.py' = ['F401'] # re-exports are intentional in __init__.py
-# Vendored jupyter_dark_detect: keep as-is from upstream for easy updates
-# https://github.com/OpenMined/jupyter-dark-detect/tree/main/jupyter_dark_detect
-'src/easydiffraction/utils/_vendored/jupyter_dark_detect/*' = [
- 'S110', # try-except-pass
- 'S112', # try-except-continue
- 'S404', # subprocess module
- 'S607', # partial executable path
- 'TID252', # relative imports
- 'W291', # trailing whitespace (in JS strings)
- 'W505', # doc line too long
- 'E501', # line too long (in JS strings)
-]
+[tool.ruff.lint.mccabe]
+# Cyclomatic complexity threshold (default is 10)
+max-complexity = 10
[tool.ruff.lint.pycodestyle]
-max-line-length = 100 #99# https://peps.python.org/pep-0008/#maximum-line-length
-max-doc-length = 72 # https://peps.python.org/pep-0008/#maximum-line-length
+# PEP 8 line length guidance:
+# https://peps.python.org/pep-0008/#maximum-line-length
+# Use 99 characters as the project-wide maximum for regular code lines.
+# Use 72 characters for docstrings.
+max-line-length = 99 # See also `line-length` in [tool.ruff]
+max-doc-length = 72
[tool.ruff.lint.pydocstyle]
-convention = 'google'
+convention = 'numpy'
-[tool.ruff.format]
-docstring-code-format = true # Whether to format code snippets in docstrings
-docstring-code-line-length = 72 # Line length for code snippets in docstrings
-indent-style = 'space' # PEP 8 recommends using spaces over tabs
-line-ending = 'lf' # Line endings will be converted to \n
-quote-style = 'single' # But double quotes in docstrings (PEP 8, PEP 257)
+#############################
+# Configuration for pydoclint
+#############################
+
+# 'pydoclint' -- Docstring linter, a faster alternative to
+# 'darglint' or 'darglint2'.
+# https://pypi.org/project/pydoclint/
+
+# This is a more advanced docstring linter compared to Ruff's built-in
+# docstring check rules D or DOC. For example, among many other things,
+# it can check that arguments in the docstring, which are used by MkDocs
+# and IDEs to render parameter documentation, remain synchronized with
+# the parameter declarations in the code (in function's signature).
+
+[tool.pydoclint]
+#exclude = '\.' # Temporarily disable pydoclint until we are ready
+exclude = 'src/easydiffraction/utils/_vendored/jupyter_dark_detect' # ED only
+style = 'numpy'
+check-style-mismatch = true
+check-arg-defaults = true
+allow-init-docstring = true
+
+####################################
+# Configuration for format-docstring
+####################################
+
+# 'format-docstring' -- Code formatter for docstrings
+# https://github.com/jsh9/format-docstring
+
+[tool.format_docstring]
+#exclude = '\.' # Temporarily disable format-docstring until we are ready
+exclude = 'src/easydiffraction/utils/_vendored/jupyter_dark_detect' # ED only
+docstring_style = 'numpy'
+line_length = 72
+fix_rst_backticks = true
+verbose = 'default'
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index 907883e8..00000000
--- a/pytest.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[pytest]
-addopts = --import-mode=importlib
-markers =
- fast: mark test as fast (should be run on every push)
- integration: mark test as integration (slow; opt-in)
-testpaths =
- tests
-filterwarnings =
- ignore::DeprecationWarning:cryspy\.
- ignore:.*scipy\.misc is deprecated.*:DeprecationWarning
- # Suppress expected UserWarnings emitted during tutorial list fetching in tests
- ignore:Falling back to latest release info\...:UserWarning:easydiffraction\.utils\.logging
- ignore:'tutorials\.zip' not found in the release\.:UserWarning:easydiffraction\.utils\.logging
diff --git a/src/easydiffraction/__init__.py b/src/easydiffraction/__init__.py
index d15d6682..e2fb3c4e 100644
--- a/src/easydiffraction/__init__.py
+++ b/src/easydiffraction/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.item.factory import ExperimentFactory
diff --git a/src/easydiffraction/__main__.py b/src/easydiffraction/__main__.py
index c850b1fa..1a058dd6 100644
--- a/src/easydiffraction/__main__.py
+++ b/src/easydiffraction/__main__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
import sys
@@ -25,7 +25,7 @@ def main(
help='Show easydiffraction version and exit.',
is_eager=True,
),
-):
+) -> None:
"""EasyDiffraction command-line interface."""
if version:
ed.show_version()
@@ -38,7 +38,7 @@ def main(
@app.command('list-tutorials')
-def list_tutorials():
+def list_tutorials() -> None:
"""List available tutorial notebooks."""
ed.list_tutorials()
@@ -58,7 +58,7 @@ def download_tutorial(
'-o',
help='Overwrite existing file if present.',
),
-):
+) -> None:
"""Download a specific tutorial notebook by ID."""
ed.download_tutorial(id=id, destination=destination, overwrite=overwrite)
@@ -77,7 +77,7 @@ def download_all_tutorials(
'-o',
help='Overwrite existing files if present.',
),
-):
+) -> None:
"""Download all available tutorial notebooks."""
ed.download_all_tutorials(destination=destination, overwrite=overwrite)
diff --git a/src/easydiffraction/analysis/__init__.py b/src/easydiffraction/analysis/__init__.py
index 429f2648..78150ea5 100644
--- a/src/easydiffraction/analysis/__init__.py
+++ b/src/easydiffraction/analysis/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/analysis/analysis.py b/src/easydiffraction/analysis/analysis.py
index bf403247..874017cb 100644
--- a/src/easydiffraction/analysis/analysis.py
+++ b/src/easydiffraction/analysis/analysis.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from typing import List
@@ -27,31 +27,27 @@
class Analysis:
- """High-level orchestration of analysis tasks for a Project.
+ """
+ High-level orchestration of analysis tasks for a Project.
This class wires calculators and minimizers, exposes a compact
interface for parameters, constraints and results, and coordinates
computations across the project's structures and experiments.
Typical usage:
-
- Display or filter parameters to fit.
- Select a calculator/minimizer implementation.
- Calculate patterns and run single or joint fits.
-
- Attributes:
- project: The parent Project object.
- aliases: A registry of human-friendly aliases for parameters.
- constraints: Symbolic constraints between parameters.
- calculator: Active calculator used for computations.
- fitter: Active fitter/minimizer driver.
"""
- def __init__(self, project) -> None:
- """Create a new Analysis instance bound to a project.
+ def __init__(self, project: object) -> None:
+ """
+ Create a new Analysis instance bound to a project.
- Args:
- project: The project that owns models and experiments.
+ Parameters
+ ----------
+ project : object
+ The project that owns models and experiments.
"""
self.project = project
self._aliases_type: str = AliasesFactory.default_tag()
@@ -136,10 +132,13 @@ def aliases_type(self) -> str:
@aliases_type.setter
def aliases_type(self, new_type: str) -> None:
- """Switch to a different aliases collection type.
+ """
+ Switch to a different aliases collection type.
- Args:
- new_type: Aliases tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Aliases tag (e.g. ``'default'``).
"""
supported_tags = AliasesFactory.supported_tags()
if new_type not in supported_tags:
@@ -174,10 +173,13 @@ def constraints_type(self) -> str:
@constraints_type.setter
def constraints_type(self, new_type: str) -> None:
- """Switch to a different constraints collection type.
+ """
+ Switch to a different constraints collection type.
- Args:
- new_type: Constraints tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Constraints tag (e.g. ``'default'``).
"""
supported_tags = ConstraintsFactory.supported_tags()
if new_type not in supported_tags:
@@ -205,12 +207,17 @@ def _get_params_as_dataframe(
self,
params: List[Union[NumericDescriptor, Parameter]],
) -> pd.DataFrame:
- """Convert a list of parameters to a DataFrame.
+ """
+ Convert a list of parameters to a DataFrame.
- Args:
- params: List of DescriptorFloat or Parameter objects.
+ Parameters
+ ----------
+ params : List[Union[NumericDescriptor, Parameter]]
+ List of DescriptorFloat or Parameter objects.
- Returns:
+ Returns
+ -------
+ pd.DataFrame
A pandas DataFrame containing parameter information.
"""
records = []
@@ -246,9 +253,7 @@ def _get_params_as_dataframe(
return df
def show_all_params(self) -> None:
- """Print a table with all parameters for structures and
- experiments.
- """
+ """Print all parameters for structures and experiments."""
structures_params = self.project.structures.parameters
experiments_params = self.project.experiments.parameters
@@ -278,9 +283,7 @@ def show_all_params(self) -> None:
tabler.render(filtered_df)
def show_fittable_params(self) -> None:
- """Print a table with parameters that can be included in
- fitting.
- """
+ """Print all fittable parameters."""
structures_params = self.project.structures.fittable_parameters
experiments_params = self.project.experiments.fittable_parameters
@@ -312,9 +315,7 @@ def show_fittable_params(self) -> None:
tabler.render(filtered_df)
def show_free_params(self) -> None:
- """Print a table with only currently-free (varying)
- parameters.
- """
+ """Print only currently free (varying) parameters."""
structures_params = self.project.structures.free_parameters
experiments_params = self.project.experiments.free_parameters
free_params = structures_params + experiments_params
@@ -345,7 +346,8 @@ def show_free_params(self) -> None:
tabler.render(filtered_df)
def how_to_access_parameters(self) -> None:
- """Show Python access paths for all parameters.
+ """
+ Show Python access paths for all parameters.
The output explains how to reference specific parameters in
code.
@@ -409,7 +411,8 @@ def how_to_access_parameters(self) -> None:
)
def show_parameter_cif_uids(self) -> None:
- """Show CIF unique IDs for all parameters.
+ """
+ Show CIF unique IDs for all parameters.
The output explains which unique identifiers are used when
creating CIF-based constraints.
@@ -472,9 +475,7 @@ def show_current_minimizer(self) -> None:
@staticmethod
def show_available_minimizers() -> None:
- """Print a table of available minimizer drivers on this
- system.
- """
+ """Print available minimizer drivers on this system."""
MinimizerFactory.show_supported()
@property
@@ -484,10 +485,13 @@ def current_minimizer(self) -> Optional[str]:
@current_minimizer.setter
def current_minimizer(self, selection: str) -> None:
- """Switch to a different minimizer implementation.
+ """
+ Switch to a different minimizer implementation.
- Args:
- selection: Minimizer selection string, e.g. 'lmfit'.
+ Parameters
+ ----------
+ selection : str
+ Minimizer selection string, e.g. 'lmfit'.
"""
self.fitter = Fitter(selection)
console.paragraph('Current minimizer changed to')
@@ -498,7 +502,7 @@ def current_minimizer(self, selection: str) -> None:
# ------------------------------------------------------------------
@property
- def fit_mode(self):
+ def fit_mode(self) -> object:
"""Fit-mode category item holding the active strategy."""
return self._fit_mode
@@ -509,10 +513,13 @@ def fit_mode_type(self) -> str:
@fit_mode_type.setter
def fit_mode_type(self, new_type: str) -> None:
- """Switch to a different fit-mode category type.
+ """
+ Switch to a different fit-mode category type.
- Args:
- new_type: Fit-mode tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Fit-mode tag (e.g. ``'default'``).
"""
supported_tags = FitModeFactory.supported_tags()
if new_type not in supported_tags:
@@ -541,7 +548,7 @@ def show_current_fit_mode_type(self) -> None:
# ------------------------------------------------------------------
@property
- def joint_fit_experiments(self):
+ def joint_fit_experiments(self) -> object:
"""Per-experiment weight collection for joint fitting."""
return self._joint_fit_experiments
@@ -573,10 +580,8 @@ def show_constraints(self) -> None:
columns_data=rows,
)
- def apply_constraints(self):
- """Apply the currently defined constraints to the active
- project.
- """
+ def apply_constraints(self) -> None:
+ """Apply currently defined constraints to the project."""
if not self.constraints._items:
log.warning('No constraints defined.')
return
@@ -585,27 +590,27 @@ def apply_constraints(self):
self.constraints_handler.set_constraints(self.constraints)
self.constraints_handler.apply()
- def fit(self):
- """Execute fitting using the selected mode, calculator and
- minimizer.
+ def fit(self) -> None:
+ """
+ Execute fitting for all experiments.
This method performs the optimization but does not display
results automatically. Call :meth:`show_fit_results` after
fitting to see a summary of the fit quality and parameter
values.
- In 'single' mode, fits each experiment independently. In
- 'joint' mode, performs a simultaneous fit across experiments
- with weights.
+ In 'single' mode, fits each experiment independently. In 'joint'
+ mode, performs a simultaneous fit across experiments with
+ weights.
Sets :attr:`fit_results` on success, which can be accessed
- programmatically
- (e.g., ``analysis.fit_results.reduced_chi_square``).
+ programmatically (e.g.,
+ ``analysis.fit_results.reduced_chi_square``).
Example::
- project.analysis.fit()
- project.analysis.show_fit_results() # Display results
+ project.analysis.fit() project.analysis.show_fit_results() #
+ Display results
"""
structures = self.project.structures
if not structures:
@@ -659,7 +664,8 @@ def fit(self):
self.fit_results = self.fitter.results
def show_fit_results(self) -> None:
- """Display a summary of the fit results.
+ """
+ Display a summary of the fit results.
Renders the fit quality metrics (reduced χ², R-factors) and a
table of fitted parameters with their starting values, final
@@ -670,8 +676,7 @@ def show_fit_results(self) -> None:
Example::
- project.analysis.fit()
- project.analysis.show_fit_results()
+ project.analysis.fit() project.analysis.show_fit_results()
"""
if not hasattr(self, 'fit_results') or self.fit_results is None:
log.warning('No fit results available. Run fit() first.')
@@ -682,14 +687,17 @@ def show_fit_results(self) -> None:
self.fitter._process_fit_results(structures, experiments)
- def _update_categories(self, called_by_minimizer=False) -> None:
- """Update all categories owned by Analysis.
+ def _update_categories(self, called_by_minimizer: bool = False) -> None:
+ """
+ Update all categories owned by Analysis.
This ensures aliases and constraints are up-to-date before
serialization or after parameter changes.
- Args:
- called_by_minimizer: Whether this is called during fitting.
+ Parameters
+ ----------
+ called_by_minimizer : bool, default=False
+ Whether this is called during fitting.
"""
# Apply constraints to sync dependent parameters
if self.constraints._items:
@@ -701,10 +709,13 @@ def _update_categories(self, called_by_minimizer=False) -> None:
if hasattr(category, '_update'):
category._update(called_by_minimizer=called_by_minimizer)
- def as_cif(self):
- """Serialize the analysis section to a CIF string.
+ def as_cif(self) -> str:
+ """
+ Serialize the analysis section to a CIF string.
- Returns:
+ Returns
+ -------
+ str
The analysis section represented as a CIF document string.
"""
from easydiffraction.io.cif.serialize import analysis_to_cif
@@ -713,9 +724,7 @@ def as_cif(self):
return analysis_to_cif(self)
def show_as_cif(self) -> None:
- """Render the analysis section as CIF in a formatted console
- view.
- """
+ """Render the analysis section as CIF in console."""
cif_text: str = self.as_cif()
paragraph_title: str = 'Analysis 🧮 info as cif'
console.paragraph(paragraph_title)
diff --git a/src/easydiffraction/analysis/calculators/__init__.py b/src/easydiffraction/analysis/calculators/__init__.py
index 5874b1a4..38bd1aa0 100644
--- a/src/easydiffraction/analysis/calculators/__init__.py
+++ b/src/easydiffraction/analysis/calculators/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.analysis.calculators.crysfml import CrysfmlCalculator
diff --git a/src/easydiffraction/analysis/calculators/base.py b/src/easydiffraction/analysis/calculators/base.py
index 5ebd3086..bd667ac8 100644
--- a/src/easydiffraction/analysis/calculators/base.py
+++ b/src/easydiffraction/analysis/calculators/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from abc import ABC
@@ -17,11 +17,13 @@ class CalculatorBase(ABC):
@property
@abstractmethod
def name(self) -> str:
+ """Short identifier of the calculation engine."""
pass
@property
@abstractmethod
def engine_imported(self) -> bool:
+ """True if the underlying calculation library is available."""
pass
@abstractmethod
@@ -31,9 +33,7 @@ def calculate_structure_factors(
experiment: ExperimentBase,
called_by_minimizer: bool,
) -> None:
- """Calculate structure factors for a single structure and
- experiment.
- """
+ """Calculate structure factors for one experiment."""
pass
@abstractmethod
@@ -43,16 +43,22 @@ def calculate_pattern(
experiment: ExperimentBase,
called_by_minimizer: bool,
) -> np.ndarray:
- """Calculate the diffraction pattern for a single structure and
- experiment.
+ """
+ Calculate diffraction pattern for one structure-experiment pair.
- Args:
- structure: The structure object.
- experiment: The experiment object.
- called_by_minimizer: Whether the calculation is called by a
- minimizer.
+ Parameters
+ ----------
+ structure : Structures
+ The structure object.
+ experiment : ExperimentBase
+ The experiment object.
+ called_by_minimizer : bool
+ Whether the calculation is called by a minimizer. Default is
+ False.
- Returns:
+ Returns
+ -------
+ np.ndarray
The calculated diffraction pattern as a NumPy array.
"""
pass
diff --git a/src/easydiffraction/analysis/calculators/crysfml.py b/src/easydiffraction/analysis/calculators/crysfml.py
index 5d47300e..34624e2b 100644
--- a/src/easydiffraction/analysis/calculators/crysfml.py
+++ b/src/easydiffraction/analysis/calculators/crysfml.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from typing import Any
@@ -41,6 +41,7 @@ class CrysfmlCalculator(CalculatorBase):
@property
def name(self) -> str:
+ """Short identifier of this calculator engine."""
return 'crysfml'
def calculate_structure_factors(
@@ -48,13 +49,20 @@ def calculate_structure_factors(
structures: Structures,
experiments: Experiments,
) -> None:
- """Call Crysfml to calculate structure factors.
-
- Args:
- structures: The structures to calculate structure
- factors for.
- experiments: The experiments associated with the sample
- models.
+ """
+ Call Crysfml to calculate structure factors.
+
+ Parameters
+ ----------
+ structures : Structures
+ The structures to calculate structure factors for.
+ experiments : Experiments
+ The experiments associated with the sample models.
+
+ Raises
+ ------
+ NotImplementedError
+ HKL calculation is not implemented for CrysfmlCalculator.
"""
raise NotImplementedError('HKL calculation is not implemented for CrysfmlCalculator.')
@@ -64,18 +72,23 @@ def calculate_pattern(
experiment: ExperimentBase,
called_by_minimizer: bool = False,
) -> Union[np.ndarray, List[float]]:
- """Calculates the diffraction pattern using Crysfml for the
- given structure and experiment.
-
- Args:
- structure: The structure to calculate the pattern for.
- experiment: The experiment associated with the structure.
- called_by_minimizer: Whether the calculation is called by a
- minimizer.
-
- Returns:
+ """
+ Calculate the diffraction pattern using Crysfml.
+
+ Parameters
+ ----------
+ structure : Structures
+ The structure to calculate the pattern for.
+ experiment : ExperimentBase
+ The experiment associated with the structure.
+ called_by_minimizer : bool, default=False
+ Whether the calculation is called by a minimizer.
+
+ Returns
+ -------
+ Union[np.ndarray, List[float]]
The calculated diffraction pattern as a NumPy array or a
- list of floats.
+ list of floats.
"""
# Intentionally unused, required by public API/signature
del called_by_minimizer
@@ -94,13 +107,19 @@ def _adjust_pattern_length(
pattern: List[float],
target_length: int,
) -> List[float]:
- """Adjusts the length of the pattern to match the target length.
-
- Args:
- pattern: The pattern to adjust.
- target_length: The desired length of the pattern.
-
- Returns:
+ """
+ Adjust the pattern length to match the target length.
+
+ Parameters
+ ----------
+ pattern : List[float]
+ The pattern to adjust.
+ target_length : int
+ The desired length of the pattern.
+
+ Returns
+ -------
+ List[float]
The adjusted pattern.
"""
# TODO: Check the origin of this discrepancy coming from
@@ -114,16 +133,20 @@ def _crysfml_dict(
structure: Structures,
experiment: ExperimentBase,
) -> Dict[str, Union[ExperimentBase, Structure]]:
- """Converts the structure and experiment into a dictionary
- format for Crysfml.
-
- Args:
- structure: The structure to convert.
- experiment: The experiment to convert.
-
- Returns:
- A dictionary representation of the structure and
- experiment.
+ """
+ Convert structure and experiment into a Crysfml dictionary.
+
+ Parameters
+ ----------
+ structure : Structures
+ The structure to convert.
+ experiment : ExperimentBase
+ The experiment to convert.
+
+ Returns
+ -------
+ Dict[str, Union[ExperimentBase, Structure]]
+ A dictionary representation of the structure and experiment.
"""
structure_dict = self._convert_structure_to_dict(structure)
experiment_dict = self._convert_experiment_to_dict(experiment)
@@ -136,12 +159,17 @@ def _convert_structure_to_dict(
self,
structure: Structure,
) -> Dict[str, Any]:
- """Converts a structure into a dictionary format.
+ """
+ Convert a structure into a dictionary format.
- Args:
- structure: The structure to convert.
+ Parameters
+ ----------
+ structure : Structure
+ The structure to convert.
- Returns:
+ Returns
+ -------
+ Dict[str, Any]
A dictionary representation of the structure.
"""
structure_dict = {
@@ -176,12 +204,17 @@ def _convert_experiment_to_dict(
self,
experiment: ExperimentBase,
) -> Dict[str, Any]:
- """Converts an experiment into a dictionary format.
+ """
+ Convert an experiment into a dictionary format.
- Args:
- experiment: The experiment to convert.
+ Parameters
+ ----------
+ experiment : ExperimentBase
+ The experiment to convert.
- Returns:
+ Returns
+ -------
+ Dict[str, Any]
A dictionary representation of the experiment.
"""
expt_type = getattr(experiment, 'type', None)
diff --git a/src/easydiffraction/analysis/calculators/cryspy.py b/src/easydiffraction/analysis/calculators/cryspy.py
index ad09dc2a..b6a0e4d6 100644
--- a/src/easydiffraction/analysis/calculators/cryspy.py
+++ b/src/easydiffraction/analysis/calculators/cryspy.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
import contextlib
@@ -35,7 +35,8 @@
@CalculatorFactory.register
class CryspyCalculator(CalculatorBase):
- """Cryspy-based diffraction calculator.
+ """
+ Cryspy-based diffraction calculator.
Converts EasyDiffraction models into Cryspy objects and computes
patterns.
@@ -49,6 +50,7 @@ class CryspyCalculator(CalculatorBase):
@property
def name(self) -> str:
+ """Short identifier of this calculator engine."""
return 'cryspy'
def __init__(self) -> None:
@@ -60,17 +62,18 @@ def calculate_structure_factors(
structure: Structure,
experiment: ExperimentBase,
called_by_minimizer: bool = False,
- ):
- """Raises a NotImplementedError as HKL calculation is not
- implemented.
-
- Args:
- structure: The structure to calculate structure
- factors for.
- experiment: The experiment associated with the sample
- models.
- called_by_minimizer: Whether the calculation is called by a
- minimizer.
+ ) -> None:
+ """
+ Raise NotImplementedError as HKL calculation is not implemented.
+
+ Parameters
+ ----------
+ structure : Structure
+ The structure to calculate structure factors for.
+ experiment : ExperimentBase
+ The experiment associated with the sample models.
+ called_by_minimizer : bool, default=False
+ Whether the calculation is called by a minimizer.
"""
combined_name = f'{structure.name}_{experiment.name}'
@@ -119,24 +122,28 @@ def calculate_pattern(
experiment: ExperimentBase,
called_by_minimizer: bool = False,
) -> Union[np.ndarray, List[float]]:
- """Calculates the diffraction pattern using Cryspy for the given
- structure and experiment.
-
- We only recreate the cryspy_obj if this method is
- - NOT called by the minimizer, or
- - the cryspy_dict is NOT yet created.
- In other cases, we are modifying the existing cryspy_dict
- This allows significantly speeding up the calculation
-
- Args:
- structure: The structure to calculate the pattern for.
- experiment: The experiment associated with the structure.
- called_by_minimizer: Whether the calculation is called by a
- minimizer.
-
- Returns:
+ """
+ Calculate the diffraction pattern using Cryspy.
+
+ We only recreate the cryspy_obj if this method is - NOT called
+ by the minimizer, or - the cryspy_dict is NOT yet created. In
+ other cases, we are modifying the existing cryspy_dict This
+ allows significantly speeding up the calculation
+
+ Parameters
+ ----------
+ structure : Structure
+ The structure to calculate the pattern for.
+ experiment : ExperimentBase
+ The experiment associated with the structure.
+ called_by_minimizer : bool, default=False
+ Whether the calculation is called by a minimizer.
+
+ Returns
+ -------
+ Union[np.ndarray, List[float]]
The calculated diffraction pattern as a NumPy array or a
- list of floats.
+ list of floats.
"""
combined_name = f'{structure.name}_{experiment.name}'
@@ -194,14 +201,19 @@ def _recreate_cryspy_dict(
structure: Structure,
experiment: ExperimentBase,
) -> Dict[str, Any]:
- """Recreates the Cryspy dictionary for the given structure and
- experiment.
-
- Args:
- structure: The structure to update.
- experiment: The experiment to update.
-
- Returns:
+ """
+ Recreate the Cryspy dictionary for structure and experiment.
+
+ Parameters
+ ----------
+ structure : Structure
+ The structure to update.
+ experiment : ExperimentBase
+ The experiment to update.
+
+ Returns
+ -------
+ Dict[str, Any]
The updated Cryspy dictionary.
"""
combined_name = f'{structure.name}_{experiment.name}'
@@ -307,15 +319,20 @@ def _recreate_cryspy_obj(
self,
structure: Structure,
experiment: ExperimentBase,
- ) -> Any:
- """Recreates the Cryspy object for the given structure and
- experiment.
-
- Args:
- structure: The structure to recreate.
- experiment: The experiment to recreate.
-
- Returns:
+ ) -> object:
+ """
+ Recreate the Cryspy object for structure and experiment.
+
+ Parameters
+ ----------
+ structure : Structure
+ The structure to recreate.
+ experiment : ExperimentBase
+ The experiment to recreate.
+
+ Returns
+ -------
+ object
The recreated Cryspy object.
"""
cryspy_obj = str_to_globaln('')
@@ -339,12 +356,17 @@ def _convert_structure_to_cryspy_cif(
self,
structure: Structure,
) -> str:
- """Converts a structure to a Cryspy CIF string.
+ """
+ Convert a structure to a Cryspy CIF string.
- Args:
- structure: The structure to convert.
+ Parameters
+ ----------
+ structure : Structure
+ The structure to convert.
- Returns:
+ Returns
+ -------
+ str
The Cryspy CIF string representation of the structure.
"""
return structure.as_cif
@@ -352,16 +374,21 @@ def _convert_structure_to_cryspy_cif(
def _convert_experiment_to_cryspy_cif(
self,
experiment: ExperimentBase,
- linked_structure: Any,
+ linked_structure: object,
) -> str:
- """Converts an experiment to a Cryspy CIF string.
-
- Args:
- experiment: The experiment to convert.
- linked_structure: The structure linked to the
- experiment.
-
- Returns:
+ """
+ Convert an experiment to a Cryspy CIF string.
+
+ Parameters
+ ----------
+ experiment : ExperimentBase
+ The experiment to convert.
+ linked_structure : object
+ The structure linked to the experiment.
+
+ Returns
+ -------
+ str
The Cryspy CIF string representation of the experiment.
"""
# Try to get experiment attributes
diff --git a/src/easydiffraction/analysis/calculators/factory.py b/src/easydiffraction/analysis/calculators/factory.py
index fa3812da..f9860f81 100644
--- a/src/easydiffraction/analysis/calculators/factory.py
+++ b/src/easydiffraction/analysis/calculators/factory.py
@@ -1,9 +1,10 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Calculator factory — delegates to ``FactoryBase``.
+"""
+Calculator factory — delegates to ``FactoryBase``.
-Overrides ``_supported_map`` to filter out calculators whose engines
-are not importable in the current environment.
+Overrides ``_supported_map`` to filter out calculators whose engines are
+not importable in the current environment.
"""
from __future__ import annotations
@@ -17,7 +18,8 @@
class CalculatorFactory(FactoryBase):
- """Factory for creating calculation engine instances.
+ """
+ Factory for creating calculation engine instances.
Only calculators whose ``engine_imported`` flag is ``True`` are
available for creation.
diff --git a/src/easydiffraction/analysis/calculators/pdffit.py b/src/easydiffraction/analysis/calculators/pdffit.py
index debd90de..4ce20276 100644
--- a/src/easydiffraction/analysis/calculators/pdffit.py
+++ b/src/easydiffraction/analysis/calculators/pdffit.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""PDF calculation backend using diffpy.pdffit2 if available.
+"""
+PDF calculation backend using diffpy.pdffit2 if available.
The class adapts the engine to EasyDiffraction calculator interface and
silences stdio on import to avoid noisy output in notebooks and logs.
@@ -38,6 +39,9 @@
# print("⚠️ 'pdffit' module not found. This calculation engine will
# not be available.")
PdfFit = None
+ redirect_stdout = None
+ pdffit_cif_parser = None
+ _pdffit_devnull = None
@CalculatorFactory.register
@@ -51,10 +55,30 @@ class PdffitCalculator(CalculatorBase):
engine_imported: bool = PdfFit is not None
@property
- def name(self):
+ def name(self) -> str:
+ """Short identifier of this calculator engine."""
return 'pdffit'
- def calculate_structure_factors(self, structures, experiments):
+ def calculate_structure_factors(
+ self,
+ structures: object,
+ experiments: object,
+ ) -> list:
+ """
+ Return an empty list; PDF does not compute structure factors.
+
+ Parameters
+ ----------
+ structures : object
+ Unused; kept for interface consistency.
+ experiments : object
+ Unused; kept for interface consistency.
+
+ Returns
+ -------
+ list
+ An empty list.
+ """
# PDF doesn't compute HKL but we keep interface consistent
# Intentionally unused, required by public API/signature
del structures, experiments
@@ -66,7 +90,21 @@ def calculate_pattern(
structure: Structure,
experiment: ExperimentBase,
called_by_minimizer: bool = False,
- ):
+ ) -> None:
+ """
+ Calculate the PDF pattern using PDFfit2.
+
+ Parameters
+ ----------
+ structure : Structure
+ The structure object supplying atom sites and cell
+ parameters.
+ experiment : ExperimentBase
+ The experiment object supplying instrument and peak
+ parameters.
+ called_by_minimizer : bool, default=False
+ Unused; kept for interface consistency.
+ """
# Intentionally unused, required by public API/signature
del called_by_minimizer
diff --git a/src/easydiffraction/analysis/categories/__init__.py b/src/easydiffraction/analysis/categories/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/analysis/categories/__init__.py
+++ b/src/easydiffraction/analysis/categories/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/analysis/categories/aliases/__init__.py b/src/easydiffraction/analysis/categories/aliases/__init__.py
index aa72de6b..6ca3a859 100644
--- a/src/easydiffraction/analysis/categories/aliases/__init__.py
+++ b/src/easydiffraction/analysis/categories/aliases/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.analysis.categories.aliases.default import Alias
diff --git a/src/easydiffraction/analysis/categories/aliases/default.py b/src/easydiffraction/analysis/categories/aliases/default.py
index 49b263f4..63cc5f28 100644
--- a/src/easydiffraction/analysis/categories/aliases/default.py
+++ b/src/easydiffraction/analysis/categories/aliases/default.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Alias category for mapping friendly names to parameter UIDs.
+"""
+Alias category for mapping friendly names to parameter UIDs.
Defines a small record type used by analysis configuration to refer to
parameters via readable labels instead of raw unique identifiers.
@@ -19,15 +20,11 @@
class Alias(CategoryItem):
- """Single alias entry.
+ """
+ Single alias entry.
Maps a human-readable ``label`` to a concrete ``param_uid`` used by
the engine.
-
- Args:
- label: Alias label. Must match ``^[A-Za-z_][A-Za-z0-9_]*$``.
- param_uid: Target parameter uid. Same identifier pattern as
- ``label``.
"""
def __init__(self) -> None:
@@ -60,19 +57,33 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
@property
- def label(self):
+ def label(self) -> StringDescriptor:
+ """
+ ...
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._label
@label.setter
- def label(self, value):
+ def label(self, value: str) -> None:
self._label.value = value
@property
- def param_uid(self):
+ def param_uid(self) -> StringDescriptor:
+ """
+ ...
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._param_uid
@param_uid.setter
- def param_uid(self, value):
+ def param_uid(self, value: str) -> None:
self._param_uid.value = value
@@ -85,6 +96,6 @@ class Aliases(CategoryCollection):
description='Parameter alias mappings',
)
- def __init__(self):
+ def __init__(self) -> None:
"""Create an empty collection of aliases."""
super().__init__(item_type=Alias)
diff --git a/src/easydiffraction/analysis/categories/aliases/factory.py b/src/easydiffraction/analysis/categories/aliases/factory.py
index 07e1fe38..f2bebe43 100644
--- a/src/easydiffraction/analysis/categories/aliases/factory.py
+++ b/src/easydiffraction/analysis/categories/aliases/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Aliases factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/analysis/categories/constraints/__init__.py b/src/easydiffraction/analysis/categories/constraints/__init__.py
index ded70ca6..97d8c03c 100644
--- a/src/easydiffraction/analysis/categories/constraints/__init__.py
+++ b/src/easydiffraction/analysis/categories/constraints/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.analysis.categories.constraints.default import Constraint
diff --git a/src/easydiffraction/analysis/categories/constraints/default.py b/src/easydiffraction/analysis/categories/constraints/default.py
index 647dd273..71d61d95 100644
--- a/src/easydiffraction/analysis/categories/constraints/default.py
+++ b/src/easydiffraction/analysis/categories/constraints/default.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Simple symbolic constraint between parameters.
+"""
+Simple symbolic constraint between parameters.
Represents an equation of the form ``lhs_alias = rhs_expr`` where
``rhs_expr`` is evaluated elsewhere by the analysis engine.
@@ -20,12 +21,7 @@
class Constraint(CategoryItem):
- """Single constraint item.
-
- Args:
- lhs_alias: Left-hand side alias name being constrained.
- rhs_expr: Right-hand side expression as a string.
- """
+ """Single constraint item."""
def __init__(self) -> None:
super().__init__()
@@ -57,19 +53,33 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
@property
- def lhs_alias(self):
+ def lhs_alias(self) -> StringDescriptor:
+ """
+ Left-hand side of the equation.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._lhs_alias
@lhs_alias.setter
- def lhs_alias(self, value):
+ def lhs_alias(self, value: str) -> None:
self._lhs_alias.value = value
@property
- def rhs_expr(self):
+ def rhs_expr(self) -> StringDescriptor:
+ """
+ Right-hand side expression.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._rhs_expr
@rhs_expr.setter
- def rhs_expr(self, value):
+ def rhs_expr(self, value: str) -> None:
self._rhs_expr.value = value
@@ -84,11 +94,11 @@ class Constraints(CategoryCollection):
_update_priority = 90 # After most others, but before data categories
- def __init__(self):
+ def __init__(self) -> None:
"""Create an empty constraints collection."""
super().__init__(item_type=Constraint)
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
del called_by_minimizer
constraints = ConstraintsHandler.get()
diff --git a/src/easydiffraction/analysis/categories/constraints/factory.py b/src/easydiffraction/analysis/categories/constraints/factory.py
index 829260f4..682c9684 100644
--- a/src/easydiffraction/analysis/categories/constraints/factory.py
+++ b/src/easydiffraction/analysis/categories/constraints/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Constraints factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/analysis/categories/fit_mode/__init__.py b/src/easydiffraction/analysis/categories/fit_mode/__init__.py
index 45267810..058d054c 100644
--- a/src/easydiffraction/analysis/categories/fit_mode/__init__.py
+++ b/src/easydiffraction/analysis/categories/fit_mode/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.analysis.categories.fit_mode.enums import FitModeEnum
diff --git a/src/easydiffraction/analysis/categories/fit_mode/enums.py b/src/easydiffraction/analysis/categories/fit_mode/enums.py
index 156e9c30..5e904eae 100644
--- a/src/easydiffraction/analysis/categories/fit_mode/enums.py
+++ b/src/easydiffraction/analysis/categories/fit_mode/enums.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Enumeration for fit-mode values."""
@@ -15,9 +15,11 @@ class FitModeEnum(str, Enum):
@classmethod
def default(cls) -> FitModeEnum:
+ """Return the default fit mode (SINGLE)."""
return cls.SINGLE
def description(self) -> str:
+ """Return a human-readable description of this fit mode."""
if self is FitModeEnum.SINGLE:
return 'Independent fitting of each experiment; no shared parameters'
elif self is FitModeEnum.JOINT:
diff --git a/src/easydiffraction/analysis/categories/fit_mode/factory.py b/src/easydiffraction/analysis/categories/fit_mode/factory.py
index 48edef66..f10485f8 100644
--- a/src/easydiffraction/analysis/categories/fit_mode/factory.py
+++ b/src/easydiffraction/analysis/categories/fit_mode/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Fit-mode factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/analysis/categories/fit_mode/fit_mode.py b/src/easydiffraction/analysis/categories/fit_mode/fit_mode.py
index 8a5bd24b..b0589a2e 100644
--- a/src/easydiffraction/analysis/categories/fit_mode/fit_mode.py
+++ b/src/easydiffraction/analysis/categories/fit_mode/fit_mode.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Fit-mode category item.
+"""
+Fit-mode category item.
Stores the active fitting strategy as a CIF-serializable descriptor
validated by ``FitModeEnum``.
@@ -20,7 +21,8 @@
@FitModeFactory.register
class FitMode(CategoryItem):
- """Fitting strategy selector.
+ """
+ Fitting strategy selector.
Holds a single ``mode`` descriptor whose value is one of
``FitModeEnum`` members (``'single'`` or ``'joint'``).
@@ -47,15 +49,16 @@ def __init__(self) -> None:
self._identity.category_code = 'fit_mode'
@property
- def mode(self):
- """Active fitting strategy descriptor."""
+ def mode(self) -> StringDescriptor:
+ """
+ Fitting strategy.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._mode
@mode.setter
def mode(self, value: str) -> None:
- """Set the fitting strategy value.
-
- Args:
- value: ``'single'`` or ``'joint'``.
- """
self._mode.value = value
diff --git a/src/easydiffraction/analysis/categories/joint_fit_experiments/__init__.py b/src/easydiffraction/analysis/categories/joint_fit_experiments/__init__.py
index 2857b28d..1aa8f0ae 100644
--- a/src/easydiffraction/analysis/categories/joint_fit_experiments/__init__.py
+++ b/src/easydiffraction/analysis/categories/joint_fit_experiments/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.analysis.categories.joint_fit_experiments.default import JointFitExperiment
diff --git a/src/easydiffraction/analysis/categories/joint_fit_experiments/default.py b/src/easydiffraction/analysis/categories/joint_fit_experiments/default.py
index 6acf4f44..b94bd7de 100644
--- a/src/easydiffraction/analysis/categories/joint_fit_experiments/default.py
+++ b/src/easydiffraction/analysis/categories/joint_fit_experiments/default.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Joint-fit experiment weighting configuration.
+"""
+Joint-fit experiment weighting configuration.
Stores per-experiment weights to be used when multiple experiments are
fitted simultaneously.
@@ -23,12 +24,7 @@
class JointFitExperiment(CategoryItem):
- """A single joint-fit entry.
-
- Args:
- id: Experiment identifier used in the fit session.
- weight: Relative weight factor in the combined objective.
- """
+ """A single joint-fit entry."""
def __init__(self) -> None:
super().__init__()
@@ -60,19 +56,33 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
@property
- def id(self):
+ def id(self) -> StringDescriptor:
+ """
+ Experiment identifier.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._id
@id.setter
- def id(self, value):
+ def id(self, value: str) -> None:
self._id.value = value
@property
- def weight(self):
+ def weight(self) -> NumericDescriptor:
+ """
+ Weight factor.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._weight
@weight.setter
- def weight(self, value):
+ def weight(self, value: float) -> None:
self._weight.value = value
@@ -85,6 +95,6 @@ class JointFitExperiments(CategoryCollection):
description='Joint-fit experiment weights',
)
- def __init__(self):
+ def __init__(self) -> None:
"""Create an empty joint-fit experiments collection."""
super().__init__(item_type=JointFitExperiment)
diff --git a/src/easydiffraction/analysis/categories/joint_fit_experiments/factory.py b/src/easydiffraction/analysis/categories/joint_fit_experiments/factory.py
index 2919c741..57666098 100644
--- a/src/easydiffraction/analysis/categories/joint_fit_experiments/factory.py
+++ b/src/easydiffraction/analysis/categories/joint_fit_experiments/factory.py
@@ -1,8 +1,6 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Joint-fit-experiments factory — delegates entirely to
-``FactoryBase``.
-"""
+"""Joint-fit-experiments factory — delegates to ``FactoryBase``."""
from __future__ import annotations
diff --git a/src/easydiffraction/analysis/fit_helpers/__init__.py b/src/easydiffraction/analysis/fit_helpers/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/analysis/fit_helpers/__init__.py
+++ b/src/easydiffraction/analysis/fit_helpers/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/analysis/fit_helpers/metrics.py b/src/easydiffraction/analysis/fit_helpers/metrics.py
index 97c715d8..dee08f86 100644
--- a/src/easydiffraction/analysis/fit_helpers/metrics.py
+++ b/src/easydiffraction/analysis/fit_helpers/metrics.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from typing import Optional
@@ -14,14 +14,19 @@ def calculate_r_factor(
y_obs: np.ndarray,
y_calc: np.ndarray,
) -> float:
- """Calculate the R-factor (reliability factor) between observed and
- calculated data.
-
- Args:
- y_obs: Observed data points.
- y_calc: Calculated data points.
-
- Returns:
+ """
+ Calculate the R-factor between observed and calculated data.
+
+ Parameters
+ ----------
+ y_obs : np.ndarray
+ Observed data points.
+ y_calc : np.ndarray
+ Calculated data points.
+
+ Returns
+ -------
+ float
R-factor value.
"""
y_obs = np.asarray(y_obs)
@@ -36,15 +41,21 @@ def calculate_weighted_r_factor(
y_calc: np.ndarray,
weights: np.ndarray,
) -> float:
- """Calculate the weighted R-factor between observed and calculated
- data.
-
- Args:
- y_obs: Observed data points.
- y_calc: Calculated data points.
- weights: Weights for each data point.
-
- Returns:
+ """
+ Calculate weighted R-factor between observed and calculated data.
+
+ Parameters
+ ----------
+ y_obs : np.ndarray
+ Observed data points.
+ y_calc : np.ndarray
+ Calculated data points.
+ weights : np.ndarray
+ Weights for each data point.
+
+ Returns
+ -------
+ float
Weighted R-factor value.
"""
y_obs = np.asarray(y_obs)
@@ -59,14 +70,19 @@ def calculate_rb_factor(
y_obs: np.ndarray,
y_calc: np.ndarray,
) -> float:
- """Calculate the Bragg R-factor between observed and calculated
- data.
-
- Args:
- y_obs: Observed data points.
- y_calc: Calculated data points.
-
- Returns:
+ """
+ Calculate the Bragg R-factor between observed and calculated data.
+
+ Parameters
+ ----------
+ y_obs : np.ndarray
+ Observed data points.
+ y_calc : np.ndarray
+ Calculated data points.
+
+ Returns
+ -------
+ float
Bragg R-factor value.
"""
y_obs = np.asarray(y_obs)
@@ -80,14 +96,19 @@ def calculate_r_factor_squared(
y_obs: np.ndarray,
y_calc: np.ndarray,
) -> float:
- """Calculate the R-factor squared between observed and calculated
- data.
-
- Args:
- y_obs: Observed data points.
- y_calc: Calculated data points.
-
- Returns:
+ """
+ Calculate the R-factor squared between observed and calculated data.
+
+ Parameters
+ ----------
+ y_obs : np.ndarray
+ Observed data points.
+ y_calc : np.ndarray
+ Calculated data points.
+
+ Returns
+ -------
+ float
R-factor squared value.
"""
y_obs = np.asarray(y_obs)
@@ -101,13 +122,19 @@ def calculate_reduced_chi_square(
residuals: np.ndarray,
num_parameters: int,
) -> float:
- """Calculate the reduced chi-square statistic.
-
- Args:
- residuals: Residuals between observed and calculated data.
- num_parameters: Number of free parameters used in the model.
-
- Returns:
+ """
+ Calculate the reduced chi-square statistic.
+
+ Parameters
+ ----------
+ residuals : np.ndarray
+ Residuals between observed and calculated data.
+ num_parameters : int
+ Number of free parameters used in the model.
+
+ Returns
+ -------
+ float
Reduced chi-square value.
"""
residuals = np.asarray(residuals)
@@ -124,16 +151,24 @@ def get_reliability_inputs(
structures: Structures,
experiments: Experiments,
) -> Tuple[np.ndarray, np.ndarray, Optional[np.ndarray]]:
- """Collect observed and calculated data points for reliability
- calculations.
-
- Args:
- structures: Collection of structures.
- experiments: Collection of experiments.
-
- Returns:
- Tuple containing arrays of (observed values, calculated values,
- error values)
+ """
+ Collect observed and calculated data for reliability calculations.
+
+ Parameters
+ ----------
+ structures : Structures
+ Collection of structures.
+ experiments : Experiments
+ Collection of experiments.
+
+ Returns
+ -------
+ np.ndarray
+ Observed values.
+ np.ndarray
+ Calculated values.
+ Optional[np.ndarray]
+ Error values, or None if not available.
"""
y_obs_all = []
y_calc_all = []
diff --git a/src/easydiffraction/analysis/fit_helpers/reporting.py b/src/easydiffraction/analysis/fit_helpers/reporting.py
index d9dbc40e..a1468aa5 100644
--- a/src/easydiffraction/analysis/fit_helpers/reporting.py
+++ b/src/easydiffraction/analysis/fit_helpers/reporting.py
@@ -1,7 +1,6 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-from typing import Any
from typing import List
from typing import Optional
@@ -14,7 +13,8 @@
class FitResults:
- """Container for results of a single optimization run.
+ """
+ Container for results of a single optimization run.
Holds success flag, chi-square metrics, iteration counts, timing,
and parameter objects. Provides a printer to summarize key
@@ -24,41 +24,53 @@ class FitResults:
def __init__(
self,
success: bool = False,
- parameters: Optional[List[Any]] = None,
+ parameters: Optional[List[object]] = None,
chi_square: Optional[float] = None,
reduced_chi_square: Optional[float] = None,
message: str = '',
iterations: int = 0,
- engine_result: Optional[Any] = None,
- starting_parameters: Optional[List[Any]] = None,
+ engine_result: Optional[object] = None,
+ starting_parameters: Optional[List[object]] = None,
fitting_time: Optional[float] = None,
- **kwargs: Any,
+ **kwargs: object,
) -> None:
- """Initialize FitResults with the given parameters.
-
- Args:
- success: Indicates if the fit was successful.
- parameters: List of parameters used in the fit.
- chi_square: Chi-square value of the fit.
- reduced_chi_square: Reduced chi-square value of the fit.
- message: Message related to the fit.
- iterations: Number of iterations performed.
- engine_result: Result from the fitting engine.
- starting_parameters: Initial parameters for the fit.
- fitting_time: Time taken for the fitting process.
- **kwargs: Additional engine-specific fields. If ``redchi``
- is provided and ``reduced_chi_square`` is not set, it is
- used as the reduced chi-square value.
+ """
+ Initialize FitResults with the given parameters.
+
+ Parameters
+ ----------
+ success : bool, default=False
+ Indicates if the fit was successful.
+ parameters : Optional[List[object]], default=None
+ List of parameters used in the fit.
+ chi_square : Optional[float], default=None
+ Chi-square value of the fit.
+ reduced_chi_square : Optional[float], default=None
+ Reduced chi-square value of the fit.
+ message : str, default=''
+ Message related to the fit.
+ iterations : int, default=0
+ Number of iterations performed.
+ engine_result : Optional[object], default=None
+ Result from the fitting engine.
+ starting_parameters : Optional[List[object]], default=None
+ Initial parameters for the fit.
+ fitting_time : Optional[float], default=None
+ Time taken for the fitting process.
+ **kwargs : object
+ Additional engine-specific fields. If ``redchi`` is provided
+ and ``reduced_chi_square`` is not set, it is used as the
+ reduced chi-square value.
"""
self.success: bool = success
- self.parameters: List[Any] = parameters if parameters is not None else []
+ self.parameters: List[object] = parameters if parameters is not None else []
self.chi_square: Optional[float] = chi_square
self.reduced_chi_square: Optional[float] = reduced_chi_square
self.message: str = message
self.iterations: int = iterations
- self.engine_result: Optional[Any] = engine_result
- self.result: Optional[Any] = None
- self.starting_parameters: List[Any] = (
+ self.engine_result: Optional[object] = engine_result
+ self.result: Optional[object] = None
+ self.starting_parameters: List[object] = (
starting_parameters if starting_parameters is not None else []
)
self.fitting_time: Optional[float] = fitting_time
@@ -77,14 +89,21 @@ def display_results(
f_obs: Optional[List[float]] = None,
f_calc: Optional[List[float]] = None,
) -> None:
- """Render a human-readable summary of the fit.
-
- Args:
- y_obs: Observed intensities for pattern R-factor metrics.
- y_calc: Calculated intensities for pattern R-factor metrics.
- y_err: Standard deviations of observed intensities for wR.
- f_obs: Observed structure-factor magnitudes for Bragg R.
- f_calc: Calculated structure-factor magnitudes for Bragg R.
+ """
+ Render a human-readable summary of the fit.
+
+ Parameters
+ ----------
+ y_obs : Optional[List[float]], default=None
+ Observed intensities for pattern R-factor metrics.
+ y_calc : Optional[List[float]], default=None
+ Calculated intensities for pattern R-factor metrics.
+ y_err : Optional[List[float]], default=None
+ Standard deviations of observed intensities for wR.
+ f_obs : Optional[List[float]], default=None
+ Observed structure-factor magnitudes for Bragg R.
+ f_calc : Optional[List[float]], default=None
+ Calculated structure-factor magnitudes for Bragg R.
"""
status_icon = '✅' if self.success else '❌'
rf = rf2 = wr = br = None
diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py
index 438fd46d..eb32f3ea 100644
--- a/src/easydiffraction/analysis/fit_helpers/tracking.py
+++ b/src/easydiffraction/analysis/fit_helpers/tracking.py
@@ -1,9 +1,8 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
import time
from contextlib import suppress
-from typing import Any
from typing import List
from typing import Optional
@@ -36,31 +35,40 @@
class _TerminalLiveHandle:
- """Adapter that exposes update()/close() for terminal live updates.
+ """
+ Adapter that exposes update()/close() for terminal live updates.
Wraps a rich.live.Live instance but keeps the tracker decoupled from
the underlying UI mechanism.
"""
- def __init__(self, live) -> None:
+ def __init__(self, live: object) -> None:
self._live = live
- def update(self, renderable) -> None:
+ def update(self, renderable: object) -> None:
+ """
+ Refresh the live display with a new renderable.
+
+ Parameters
+ ----------
+ renderable : object
+ A Rich-compatible renderable to display.
+ """
self._live.update(renderable, refresh=True)
def close(self) -> None:
+ """Stop the live display, suppressing any errors."""
with suppress(Exception):
self._live.stop()
-def _make_display_handle() -> Any | None:
- """Create and initialize a display/update handle for the
- environment.
+def _make_display_handle() -> object | None:
+ """
+ Create and initialize a display/update handle for the environment.
- In Jupyter, returns an IPython DisplayHandle and creates a
- placeholder.
- - In terminal, returns a _TerminalLiveHandle backed by rich Live.
- - If neither applies, returns None.
+ placeholder. - In terminal, returns a _TerminalLiveHandle backed by
+ rich Live. - If neither applies, returns None.
"""
if in_jupyter() and display is not None and HTML is not None:
h = DisplayHandle()
@@ -77,7 +85,8 @@ def _make_display_handle() -> Any | None:
class FitProgressTracker:
- """Track and report reduced chi-square during optimization.
+ """
+ Track and report reduced chi-square during optimization.
The tracker keeps iteration counters, remembers the best observed
reduced chi-square and when it occurred, and can display progress as
@@ -94,8 +103,8 @@ def __init__(self) -> None:
self._fitting_time: Optional[float] = None
self._df_rows: List[List[str]] = []
- self._display_handle: Optional[Any] = None
- self._live: Optional[Any] = None
+ self._display_handle: Optional[object] = None
+ self._live: Optional[object] = None
def reset(self) -> None:
"""Reset internal state before a new optimization run."""
@@ -112,13 +121,19 @@ def track(
residuals: np.ndarray,
parameters: List[float],
) -> np.ndarray:
- """Update progress with current residuals and parameters.
-
- Args:
- residuals: Residuals between measured and calculated data.
- parameters: Current free parameters being fitted.
-
- Returns:
+ """
+ Update progress with current residuals and parameters.
+
+ Parameters
+ ----------
+ residuals : np.ndarray
+ Residuals between measured and calculated data.
+ parameters : List[float]
+ Current free parameters being fitted.
+
+ Returns
+ -------
+ np.ndarray
Residuals unchanged, for optimizer consumption.
"""
self._iteration += 1
@@ -200,10 +215,13 @@ def stop_timer(self) -> None:
self._fitting_time = self._end_time - self._start_time
def start_tracking(self, minimizer_name: str) -> None:
- """Initialize display and headers and announce the minimizer.
+ """
+ Initialize display and headers and announce the minimizer.
- Args:
- minimizer_name: Name of the minimizer used for the run.
+ Parameters
+ ----------
+ minimizer_name : str
+ Name of the minimizer used for the run.
"""
console.print(f"🚀 Starting fit process with '{minimizer_name}'...")
console.print('📈 Goodness-of-fit (reduced χ²) change:')
@@ -221,10 +239,13 @@ def start_tracking(self, minimizer_name: str) -> None:
)
def add_tracking_info(self, row: List[str]) -> None:
- """Append a formatted row to the progress display.
+ """
+ Append a formatted row to the progress display.
- Args:
- row: Columns corresponding to DEFAULT_HEADERS.
+ Parameters
+ ----------
+ row : List[str]
+ Columns corresponding to DEFAULT_HEADERS.
"""
# Append and update via the active handle (Jupyter or
# terminal live)
diff --git a/src/easydiffraction/analysis/fitting.py b/src/easydiffraction/analysis/fitting.py
index 453aaf1a..fa6c0368 100644
--- a/src/easydiffraction/analysis/fitting.py
+++ b/src/easydiffraction/analysis/fitting.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from typing import TYPE_CHECKING
@@ -33,20 +33,26 @@ def fit(
structures: Structures,
experiments: Experiments,
weights: Optional[np.array] = None,
- analysis=None,
+ analysis: object = None,
) -> None:
- """Run the fitting process.
+ """
+ Run the fitting process.
This method performs the optimization but does not display
- results. Use :meth:`show_fit_results` on the Analysis object
- to display the fit results after fitting is complete.
-
- Args:
- structures: Collection of structures.
- experiments: Collection of experiments.
- weights: Optional weights for joint fitting.
- analysis: Optional Analysis object to update its categories
- during fitting.
+ results. Use :meth:`show_fit_results` on the Analysis object to
+ display the fit results after fitting is complete.
+
+ Parameters
+ ----------
+ structures : Structures
+ Collection of structures.
+ experiments : Experiments
+ Collection of experiments.
+ weights : Optional[np.array], default=None
+ Optional weights for joint fitting.
+ analysis : object, default=None
+ Optional Analysis object to update its categories during
+ fitting.
"""
params = structures.free_parameters + experiments.free_parameters
@@ -58,6 +64,19 @@ def fit(
param._fit_start_value = param.value
def objective_function(engine_params: Dict[str, Any]) -> np.ndarray:
+ """
+ Evaluate the residual for the current minimizer parameters.
+
+ Parameters
+ ----------
+ engine_params : Dict[str, Any]
+ Parameter values provided by the minimizer engine.
+
+ Returns
+ -------
+ np.ndarray
+ Residual array passed back to the minimizer.
+ """
return self._residual_function(
engine_params=engine_params,
parameters=params,
@@ -75,16 +94,20 @@ def _process_fit_results(
structures: Structures,
experiments: Experiments,
) -> None:
- """Collect reliability inputs and display fit results.
+ """
+ Collect reliability inputs and display fit results.
This method is typically called by
:meth:`Analysis.show_fit_results` rather than directly. It
- calculates R-factors and other metrics, then renders them to
- the console.
-
- Args:
- structures: Collection of structures.
- experiments: Collection of experiments.
+ calculates R-factors and other metrics, then renders them to the
+ console.
+
+ Parameters
+ ----------
+ structures : Structures
+ Collection of structures.
+ experiments : Experiments
+ Collection of experiments.
"""
y_obs, y_calc, y_err = get_reliability_inputs(
structures,
@@ -108,13 +131,19 @@ def _collect_free_parameters(
structures: Structures,
experiments: Experiments,
) -> List[Parameter]:
- """Collect free parameters from structures and experiments.
-
- Args:
- structures: Collection of structures.
- experiments: Collection of experiments.
-
- Returns:
+ """
+ Collect free parameters from structures and experiments.
+
+ Parameters
+ ----------
+ structures : Structures
+ Collection of structures.
+ experiments : Experiments
+ Collection of experiments.
+
+ Returns
+ -------
+ List[Parameter]
List of free parameters.
"""
free_params: List[Parameter] = structures.free_parameters + experiments.free_parameters
@@ -127,22 +156,33 @@ def _residual_function(
structures: Structures,
experiments: Experiments,
weights: Optional[np.array] = None,
- analysis=None,
+ analysis: object = None,
) -> np.ndarray:
- """Residual function computes the difference between measured
- and calculated patterns. It updates the parameter values
- according to the optimizer-provided engine_params.
-
- Args:
- engine_params: Engine-specific parameter dict.
- parameters: List of parameters being optimized.
- structures: Collection of structures.
- experiments: Collection of experiments.
- weights: Optional weights for joint fitting.
- analysis: Optional Analysis object to update its categories
- during fitting.
-
- Returns:
+ """
+ Compute residuals between measured and calculated patterns.
+
+ It updates the parameter values according to the
+ optimizer-provided engine_params.
+
+ Parameters
+ ----------
+ engine_params : Dict[str, Any]
+ Engine-specific parameter dict.
+ parameters : List[Parameter]
+ List of parameters being optimized.
+ structures : Structures
+ Collection of structures.
+ experiments : Experiments
+ Collection of experiments.
+ weights : Optional[np.array], default=None
+ Optional weights for joint fitting.
+ analysis : object, default=None
+ Optional Analysis object to update its categories during
+ fitting.
+
+ Returns
+ -------
+ np.ndarray
Array of weighted residuals.
"""
# Sync parameters back to objects
diff --git a/src/easydiffraction/analysis/minimizers/__init__.py b/src/easydiffraction/analysis/minimizers/__init__.py
index 8a41a6f2..01fbc136 100644
--- a/src/easydiffraction/analysis/minimizers/__init__.py
+++ b/src/easydiffraction/analysis/minimizers/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.analysis.minimizers.dfols import DfolsMinimizer
diff --git a/src/easydiffraction/analysis/minimizers/base.py b/src/easydiffraction/analysis/minimizers/base.py
index 069601ed..f8499dad 100644
--- a/src/easydiffraction/analysis/minimizers/base.py
+++ b/src/easydiffraction/analysis/minimizers/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from abc import ABC
@@ -16,14 +16,13 @@
class MinimizerBase(ABC):
- """Abstract base for concrete minimizers.
-
- Contract:
- - Subclasses must implement ``_prepare_solver_args``,
- ``_run_solver``, ``_sync_result_to_parameters`` and
- ``_check_success``.
- - The ``fit`` method orchestrates the full workflow and returns
- :class:`FitResults`.
+ """
+ Abstract base for concrete minimizers.
+
+ Contract: - Subclasses must implement ``_prepare_solver_args``,
+ ``_run_solver``, ``_sync_result_to_parameters`` and
+ ``_check_success``. - The ``fit`` method orchestrates the full
+ workflow and returns :class:`FitResults`.
"""
def __init__(
@@ -44,10 +43,13 @@ def __init__(
self.tracker: FitProgressTracker = FitProgressTracker()
def _start_tracking(self, minimizer_name: str) -> None:
- """Initialize progress tracking and timer.
+ """
+ Initialize progress tracking and timer.
- Args:
- minimizer_name: Human-readable name shown in progress.
+ Parameters
+ ----------
+ minimizer_name : str
+ Human-readable name shown in progress.
"""
self.tracker.reset()
self.tracker.start_tracking(minimizer_name)
@@ -60,12 +62,17 @@ def _stop_tracking(self) -> None:
@abstractmethod
def _prepare_solver_args(self, parameters: List[Any]) -> Dict[str, Any]:
- """Prepare keyword-arguments for the underlying solver.
+ """
+ Prepare keyword-arguments for the underlying solver.
- Args:
- parameters: List of free parameters to be fitted.
+ Parameters
+ ----------
+ parameters : List[Any]
+ List of free parameters to be fitted.
- Returns:
+ Returns
+ -------
+ Dict[str, Any]
Mapping of keyword arguments to pass into ``_run_solver``.
"""
pass
@@ -73,36 +80,40 @@ def _prepare_solver_args(self, parameters: List[Any]) -> Dict[str, Any]:
@abstractmethod
def _run_solver(
self,
- objective_function: Callable[..., Any],
- engine_parameters: Dict[str, Any],
- ) -> Any:
+ objective_function: Callable[..., object],
+ engine_parameters: Dict[str, object],
+ ) -> object:
"""Execute the concrete solver and return its raw result."""
pass
@abstractmethod
def _sync_result_to_parameters(
self,
- raw_result: Any,
- parameters: List[Any],
+ raw_result: object,
+ parameters: List[object],
) -> None:
- """Copy values from ``raw_result`` back to ``parameters`` in-
- place.
- """
+ """Copy raw_result values back to parameters in-place."""
pass
def _finalize_fit(
self,
- parameters: List[Any],
- raw_result: Any,
+ parameters: List[object],
+ raw_result: object,
) -> FitResults:
- """Build :class:`FitResults` and store it on ``self.result``.
-
- Args:
- parameters: Parameters after the solver finished.
- raw_result: Backend-specific solver output object.
-
- Returns:
- FitResults: Aggregated outcome of the fit.
+ """
+ Build :class:`FitResults` and store it on ``self.result``.
+
+ Parameters
+ ----------
+ parameters : List[object]
+ Parameters after the solver finished.
+ raw_result : object
+ Backend-specific solver output object.
+
+ Returns
+ -------
+ FitResults
+ Aggregated outcome of the fit.
"""
self._sync_result_to_parameters(parameters, raw_result)
success = self._check_success(raw_result)
@@ -117,23 +128,29 @@ def _finalize_fit(
return self.result
@abstractmethod
- def _check_success(self, raw_result: Any) -> bool:
+ def _check_success(self, raw_result: object) -> bool:
"""Determine whether the fit was successful."""
pass
def fit(
self,
- parameters: List[Any],
- objective_function: Callable[..., Any],
+ parameters: List[object],
+ objective_function: Callable[..., object],
) -> FitResults:
- """Run the full minimization workflow.
-
- Args:
- parameters: Free parameters to optimize.
- objective_function: Callable returning residuals for a given
- set of engine arguments.
-
- Returns:
+ """
+ Run the full minimization workflow.
+
+ Parameters
+ ----------
+ parameters : List[object]
+ Free parameters to optimize.
+ objective_function : Callable[..., object]
+ Callable returning residuals for a given set of engine
+ arguments.
+
+ Returns
+ -------
+ FitResults
FitResults with success flag, best chi2 and timing.
"""
minimizer_name = self.name or 'Unnamed Minimizer'
@@ -153,11 +170,11 @@ def fit(
def _objective_function(
self,
- engine_params: Dict[str, Any],
- parameters: List[Any],
- structures: Any,
- experiments: Any,
- calculator: Any,
+ engine_params: Dict[str, object],
+ parameters: List[object],
+ structures: object,
+ experiments: object,
+ calculator: object,
) -> np.ndarray:
"""Default objective helper computing residuals array."""
return self._compute_residuals(
@@ -170,11 +187,11 @@ def _objective_function(
def _create_objective_function(
self,
- parameters: List[Any],
- structures: Any,
- experiments: Any,
- calculator: Any,
- ) -> Callable[[Dict[str, Any]], np.ndarray]:
+ parameters: List[object],
+ structures: object,
+ experiments: object,
+ calculator: object,
+ ) -> Callable[[Dict[str, object]], np.ndarray]:
"""Return a closure capturing problem context for the solver."""
return lambda engine_params: self._objective_function(
engine_params,
diff --git a/src/easydiffraction/analysis/minimizers/dfols.py b/src/easydiffraction/analysis/minimizers/dfols.py
index b68a034a..fad9ad06 100644
--- a/src/easydiffraction/analysis/minimizers/dfols.py
+++ b/src/easydiffraction/analysis/minimizers/dfols.py
@@ -1,7 +1,6 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-from typing import Any
from typing import Dict
from typing import List
@@ -17,9 +16,7 @@
@MinimizerFactory.register
class DfolsMinimizer(MinimizerBase):
- """Minimizer using the DFO-LS package (Derivative-Free Optimization
- for Least-Squares).
- """
+ """Minimizer using DFO-LS (derivative-free least-squares)."""
type_info = TypeInfo(
tag='dfols',
@@ -30,13 +27,13 @@ def __init__(
self,
name: str = 'dfols',
max_iterations: int = DEFAULT_MAX_ITERATIONS,
- **kwargs: Any,
+ **kwargs: object,
) -> None:
super().__init__(name=name, method=None, max_iterations=max_iterations)
# Intentionally unused, accepted for API compatibility
del kwargs
- def _prepare_solver_args(self, parameters: List[Any]) -> Dict[str, Any]:
+ def _prepare_solver_args(self, parameters: List[object]) -> Dict[str, object]:
x0 = []
bounds_lower = []
bounds_upper = []
@@ -47,21 +44,25 @@ def _prepare_solver_args(self, parameters: List[Any]) -> Dict[str, Any]:
bounds = (np.array(bounds_lower), np.array(bounds_upper))
return {'x0': np.array(x0), 'bounds': bounds}
- def _run_solver(self, objective_function: Any, **kwargs: Any) -> Any:
+ def _run_solver(self, objective_function: object, **kwargs: object) -> object:
x0 = kwargs.get('x0')
bounds = kwargs.get('bounds')
return solve(objective_function, x0=x0, bounds=bounds, maxfun=self.max_iterations)
def _sync_result_to_parameters(
self,
- parameters: List[Any],
- raw_result: Any,
+ parameters: List[object],
+ raw_result: object,
) -> None:
- """Synchronizes the result from the solver to the parameters.
-
- Args:
- parameters: List of parameters being optimized.
- raw_result: The result object returned by the solver.
+ """
+ Synchronize the solver result back to the parameters.
+
+ Parameters
+ ----------
+ parameters : List[object]
+ List of parameters being optimized.
+ raw_result : object
+ The result object returned by the solver.
"""
# Ensure compatibility with raw_result coming from dfols.solve()
result_values = raw_result.x if hasattr(raw_result, 'x') else raw_result
@@ -74,13 +75,18 @@ def _sync_result_to_parameters(
# calculate later if needed
param.uncertainty = None
- def _check_success(self, raw_result: Any) -> bool:
- """Determines success from DFO-LS result dictionary.
+ def _check_success(self, raw_result: object) -> bool:
+ """
+ Determine success from DFO-LS result dictionary.
- Args:
- raw_result: The result object returned by the solver.
+ Parameters
+ ----------
+ raw_result : object
+ The result object returned by the solver.
- Returns:
+ Returns
+ -------
+ bool
True if the optimization was successful, False otherwise.
"""
return raw_result.flag == raw_result.EXIT_SUCCESS
diff --git a/src/easydiffraction/analysis/minimizers/factory.py b/src/easydiffraction/analysis/minimizers/factory.py
index e12a9533..18f67cc6 100644
--- a/src/easydiffraction/analysis/minimizers/factory.py
+++ b/src/easydiffraction/analysis/minimizers/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Minimizer factory — delegates to ``FactoryBase``."""
diff --git a/src/easydiffraction/analysis/minimizers/lmfit.py b/src/easydiffraction/analysis/minimizers/lmfit.py
index cb0a59fd..771bacad 100644
--- a/src/easydiffraction/analysis/minimizers/lmfit.py
+++ b/src/easydiffraction/analysis/minimizers/lmfit.py
@@ -1,7 +1,6 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-from typing import Any
from typing import Dict
from typing import List
@@ -38,16 +37,21 @@ def __init__(
def _prepare_solver_args(
self,
- parameters: List[Any],
- ) -> Dict[str, Any]:
- """Prepares the solver arguments for the lmfit minimizer.
+ parameters: List[object],
+ ) -> Dict[str, object]:
+ """
+ Prepare the solver arguments for the lmfit minimizer.
- Args:
- parameters: List of parameters to be optimized.
+ Parameters
+ ----------
+ parameters : List[object]
+ List of parameters to be optimized.
- Returns:
+ Returns
+ -------
+ Dict[str, object]
A dictionary containing the prepared lmfit. Parameters
- object.
+ object.
"""
engine_parameters = lmfit.Parameters()
for param in parameters:
@@ -60,14 +64,20 @@ def _prepare_solver_args(
)
return {'engine_parameters': engine_parameters}
- def _run_solver(self, objective_function: Any, **kwargs: Any) -> Any:
- """Runs the lmfit solver.
-
- Args:
- objective_function: The objective function to minimize.
- **kwargs: Additional arguments for the solver.
-
- Returns:
+ def _run_solver(self, objective_function: object, **kwargs: object) -> object:
+ """
+ Run the lmfit solver.
+
+ Parameters
+ ----------
+ objective_function : object
+ The objective function to minimize.
+ **kwargs : object
+ Additional arguments for the solver.
+
+ Returns
+ -------
+ object
The result of the lmfit minimization.
"""
engine_parameters = kwargs.get('engine_parameters')
@@ -82,14 +92,18 @@ def _run_solver(self, objective_function: Any, **kwargs: Any) -> Any:
def _sync_result_to_parameters(
self,
- parameters: List[Any],
- raw_result: Any,
+ parameters: List[object],
+ raw_result: object,
) -> None:
- """Synchronizes the result from the solver to the parameters.
-
- Args:
- parameters: List of parameters being optimized.
- raw_result: The result object returned by the solver.
+ """
+ Synchronize the result from the solver to the parameters.
+
+ Parameters
+ ----------
+ parameters : List[object]
+ List of parameters being optimized.
+ raw_result : object
+ The result object returned by the solver.
"""
param_values = raw_result.params if hasattr(raw_result, 'params') else raw_result
@@ -101,13 +115,18 @@ def _sync_result_to_parameters(
param._set_value_from_minimizer(param_result.value)
param.uncertainty = getattr(param_result, 'stderr', None)
- def _check_success(self, raw_result: Any) -> bool:
- """Determines success from lmfit MinimizerResult.
+ def _check_success(self, raw_result: object) -> bool:
+ """
+ Determine success from lmfit MinimizerResult.
- Args:
- raw_result: The result object returned by the solver.
+ Parameters
+ ----------
+ raw_result : object
+ The result object returned by the solver.
- Returns:
+ Returns
+ -------
+ bool
True if the optimization was successful, False otherwise.
"""
return getattr(raw_result, 'success', False)
@@ -116,18 +135,25 @@ def _iteration_callback(
self,
params: lmfit.Parameters,
iter: int,
- resid: Any,
- *args: Any,
- **kwargs: Any,
+ resid: object,
+ *args: object,
+ **kwargs: object,
) -> None:
- """Callback function for each iteration of the minimizer.
-
- Args:
- params: The current parameters.
- iter: The current iteration number.
- resid: The residuals.
- *args: Additional positional arguments.
- **kwargs: Additional keyword arguments.
+ """
+ Handle each iteration callback of the minimizer.
+
+ Parameters
+ ----------
+ params : lmfit.Parameters
+ The current parameters.
+ iter : int
+ The current iteration number.
+ resid : object
+ The residuals.
+ *args : object
+ Additional positional arguments.
+ **kwargs : object
+ Additional keyword arguments.
"""
# Intentionally unused, required by callback signature
del params, resid, args, kwargs
diff --git a/src/easydiffraction/core/__init__.py b/src/easydiffraction/core/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/core/__init__.py
+++ b/src/easydiffraction/core/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/core/category.py b/src/easydiffraction/core/category.py
index d4b57dc3..25e81894 100644
--- a/src/easydiffraction/core/category.py
+++ b/src/easydiffraction/core/category.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -30,12 +30,13 @@ def __str__(self) -> str:
return f'<{name} ({params})>'
# TODO: Common for all categories
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
del called_by_minimizer
pass
@property
- def unique_name(self):
+ def unique_name(self) -> str:
+ """Fully qualified name: datablock, category, entry."""
parts = [
self._identity.datablock_entry_name,
self._identity.category_code,
@@ -46,7 +47,8 @@ def unique_name(self):
return '.'.join(str_parts)
@property
- def parameters(self):
+ def parameters(self) -> list:
+ """All GenericDescriptorBase instances on this item."""
return [v for v in vars(self).values() if isinstance(v, GenericDescriptorBase)]
@property
@@ -54,7 +56,7 @@ def as_cif(self) -> str:
"""Return CIF representation of this object."""
return category_item_to_cif(self)
- def from_cif(self, block, idx=0):
+ def from_cif(self, block: object, idx: int = 0) -> None:
"""Populate this item from a CIF block."""
category_item_from_cif(self, block, idx)
@@ -160,7 +162,8 @@ def help(self) -> None:
class CategoryCollection(CollectionBase):
- """Handles loop-style category containers (e.g. AtomSites).
+ """
+ Handles loop-style category containers (e.g. AtomSites).
Each item is a CategoryItem (component).
"""
@@ -168,16 +171,17 @@ class CategoryCollection(CollectionBase):
# TODO: Common for all categories
_update_priority = 10 # Default. Lower values run first.
- def _key_for(self, item):
+ def _key_for(self, item: object) -> str | None:
"""Return the category-level identity key for *item*."""
return item._identity.category_entry_name
def _mark_parent_dirty(self) -> None:
- """Set ``_need_categories_update`` on the parent datablock.
+ """
+ Set ``_need_categories_update`` on the parent datablock.
Called whenever the collection content changes (items added or
- removed) so that subsequent ``_update_categories()`` calls
- re-run all category updates.
+ removed) so that subsequent ``_update_categories()`` calls re-
+ run all category updates.
"""
parent = getattr(self, '_parent', None)
if parent is not None and hasattr(parent, '_need_categories_update'):
@@ -190,16 +194,17 @@ def __str__(self) -> str:
return f'<{name} collection ({size} items)>'
# TODO: Common for all categories
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
del called_by_minimizer
pass
@property
- def unique_name(self):
+ def unique_name(self) -> str | None:
+ """Return None; collections have no unique name."""
return None
@property
- def parameters(self):
+ def parameters(self) -> list:
"""All parameters from all items in this collection."""
params = []
for item in self._items:
@@ -211,27 +216,33 @@ def as_cif(self) -> str:
"""Return CIF representation of this object."""
return category_collection_to_cif(self)
- def from_cif(self, block):
+ def from_cif(self, block: object) -> None:
"""Populate this collection from a CIF block."""
category_collection_from_cif(self, block)
- def add(self, item) -> None:
- """Insert or replace a pre-built item into the collection.
+ def add(self, item: object) -> None:
+ """
+ Insert or replace a pre-built item into the collection.
- Args:
- item: A ``CategoryItem`` instance to add.
+ Parameters
+ ----------
+ item : object
+ A ``CategoryItem`` instance to add.
"""
self[item._identity.category_entry_name] = item
self._mark_parent_dirty()
- def create(self, **kwargs) -> None:
- """Create a new item with the given attributes and add it.
+ def create(self, **kwargs: object) -> None:
+ """
+ Create a new item with the given attributes and add it.
A default instance of the collection's item type is created,
then each keyword argument is applied via ``setattr``.
- Args:
- **kwargs: Attribute names and values for the new item.
+ Parameters
+ ----------
+ **kwargs : object
+ Attribute names and values for the new item.
"""
child_obj = self._item_type()
diff --git a/src/easydiffraction/core/collection.py b/src/easydiffraction/core/collection.py
index 164f3d77..0560a37e 100644
--- a/src/easydiffraction/core/collection.py
+++ b/src/easydiffraction/core/collection.py
@@ -1,33 +1,41 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Lightweight container for guarded items with name-based indexing.
+"""
+Lightweight container for guarded items with name-based indexing.
-`CollectionBase` maintains an ordered list of items and a lazily rebuilt
-index by the item's identity key. It supports dict-like access for get,
-set and delete, along with iteration over the items.
+``CollectionBase`` maintains an ordered list of items and a lazily
+rebuilt index by the item's identity key. It supports dict-like access
+for get, set and delete, along with iteration over the items.
"""
from __future__ import annotations
+from typing import Generator
+from typing import Iterator
+
from easydiffraction.core.guard import GuardedBase
class CollectionBase(GuardedBase):
- """A minimal collection with stable iteration and name indexing.
+ """
+ A minimal collection with stable iteration and name indexing.
- Args:
- item_type: Type of items accepted by the collection. Used for
- validation and tooling; not enforced at runtime here.
+ Parameters
+ ----------
+ item_type : type
+ Type of items accepted by the collection. Used for validation
+ and tooling; not enforced at runtime here.
"""
- def __init__(self, item_type) -> None:
+ def __init__(self, item_type: type) -> None:
super().__init__()
self._items: list = []
self._index: dict = {}
self._item_type = item_type
- def __getitem__(self, name: str):
- """Return an item by its identity key.
+ def __getitem__(self, name: str) -> GuardedBase:
+ """
+ Return an item by its identity key.
Rebuilds the internal index on a cache miss to stay consistent
with recent mutations.
@@ -38,7 +46,7 @@ def __getitem__(self, name: str):
self._rebuild_index()
return self._index[name]
- def __setitem__(self, name: str, item) -> None:
+ def __setitem__(self, name: str, item: GuardedBase) -> None:
"""Insert or replace an item under the given identity key."""
# Check if item with same key exists; if so, replace it
for i, existing_item in enumerate(self._items):
@@ -66,7 +74,7 @@ def __contains__(self, name: str) -> bool:
self._rebuild_index()
return name in self._index
- def __iter__(self):
+ def __iter__(self) -> Iterator[GuardedBase]:
"""Iterate over items in insertion order."""
return iter(self._items)
@@ -75,18 +83,27 @@ def __len__(self) -> int:
return len(self._items)
def remove(self, name: str) -> None:
- """Remove an item by its key.
+ """
+ Remove an item by its key.
- Args:
- name: Identity key of the item to remove.
+ Parameters
+ ----------
+ name : str
+ Identity key of the item to remove.
- Raises:
- KeyError: If no item with the given key exists.
+ Raises
+ ------
+ KeyError
+ If no item with the given key exists.
"""
- del self[name]
+ try:
+ del self[name]
+ except KeyError:
+ raise
- def _key_for(self, item):
- """Return the identity key for *item*.
+ def _key_for(self, item: GuardedBase) -> str | None:
+ """
+ Return the identity key for *item*.
Subclasses must override to return the appropriate key
(``category_entry_name`` or ``datablock_entry_name``).
@@ -101,20 +118,20 @@ def _rebuild_index(self) -> None:
if key:
self._index[key] = item
- def keys(self):
+ def keys(self) -> Generator[str | None, None, None]:
"""Yield keys for all items in insertion order."""
return (self._key_for(item) for item in self._items)
- def values(self):
+ def values(self) -> Generator[GuardedBase, None, None]:
"""Yield items in insertion order."""
return (item for item in self._items)
- def items(self):
+ def items(self) -> Generator[tuple[str | None, GuardedBase], None, None]:
"""Yield ``(key, item)`` pairs in insertion order."""
return ((self._key_for(item), item) for item in self._items)
@property
- def names(self):
+ def names(self) -> list[str | None]:
"""List of all item keys in the collection."""
return list(self.keys())
diff --git a/src/easydiffraction/core/datablock.py b/src/easydiffraction/core/datablock.py
index 221845b6..6a1ef289 100644
--- a/src/easydiffraction/core/datablock.py
+++ b/src/easydiffraction/core/datablock.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -13,7 +13,7 @@
class DatablockItem(GuardedBase):
"""Base class for items in a datablock collection."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._need_categories_update = True
@@ -33,7 +33,7 @@ def __repr__(self) -> str:
def _update_categories(
self,
- called_by_minimizer=False,
+ called_by_minimizer: bool = False,
) -> None:
# TODO: Make abstract method and implement in subclasses.
# This should call apply_symmetry and apply_constraints in the
@@ -62,11 +62,13 @@ def _update_categories(
self._need_categories_update = False
@property
- def unique_name(self):
+ def unique_name(self) -> str | None:
+ """Unique name of this datablock item (from identity)."""
return self._identity.datablock_entry_name
@property
- def categories(self):
+ def categories(self) -> list:
+ """All category objects in this datablock by priority."""
cats = [
v for v in vars(self).values() if isinstance(v, (CategoryItem, CategoryCollection))
]
@@ -74,10 +76,8 @@ def categories(self):
return sorted(cats, key=lambda c: type(c)._update_priority)
@property
- def parameters(self):
- """All parameters from all categories contained in this
- datablock.
- """
+ def parameters(self) -> list:
+ """All parameters from all categories in this datablock."""
params = []
for v in self.categories:
params.extend(v.parameters)
@@ -118,26 +118,29 @@ def help(self) -> None:
class DatablockCollection(CollectionBase):
- """Handles top-level category collections (e.g. Structures,
- Experiments).
+ """
+ Collection of top-level datablocks (e.g. Structures, Experiments).
Each item is a DatablockItem.
- Subclasses provide explicit ``add_from_*`` convenience methods
- that delegate to the corresponding factory classmethods, then
- call :meth:`add` with the resulting item.
+ Subclasses provide explicit ``add_from_*`` convenience methods that
+ delegate to the corresponding factory classmethods, then call
+ :meth:`add` with the resulting item.
"""
- def _key_for(self, item):
+ def _key_for(self, item: object) -> str | None:
"""Return the datablock-level identity key for *item*."""
return item._identity.datablock_entry_name
- def add(self, item) -> None:
- """Add a pre-built item to the collection.
+ def add(self, item: object) -> None:
+ """
+ Add a pre-built item to the collection.
- Args:
- item: A ``DatablockItem`` instance (e.g. a ``Structure``
- or ``ExperimentBase`` subclass).
+ Parameters
+ ----------
+ item : object
+ A ``DatablockItem`` instance (e.g. a ``Structure`` or
+ ``ExperimentBase`` subclass).
"""
self[item._identity.datablock_entry_name] = item
@@ -148,25 +151,26 @@ def __str__(self) -> str:
return f'<{name} collection ({size} items)>'
@property
- def unique_name(self):
+ def unique_name(self) -> str | None:
+ """Return None; collections have no unique name."""
return None
@property
- def parameters(self):
+ def parameters(self) -> list:
"""All parameters from all datablocks in this collection."""
params = []
for db in self._items:
params.extend(db.parameters)
return params
- # was in class AbstractDatablock(ABC):
@property
def fittable_parameters(self) -> list:
+ """All non-constrained Parameters in this collection."""
return [p for p in self.parameters if isinstance(p, Parameter) and not p.constrained]
- # was in class AbstractDatablock(ABC):
@property
def free_parameters(self) -> list:
+ """All fittable parameters that are currently marked as free."""
return [p for p in self.fittable_parameters if p.free]
@property
diff --git a/src/easydiffraction/core/diagnostic.py b/src/easydiffraction/core/diagnostic.py
index 74c2ab3b..dc5ea4c4 100644
--- a/src/easydiffraction/core/diagnostic.py
+++ b/src/easydiffraction/core/diagnostic.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Diagnostics helpers for logging validation messages.
+"""
+Diagnostics helpers for logging validation messages.
This module centralizes human-friendly error and debug logs for
attribute validation and configuration checks.
@@ -19,8 +20,9 @@ class Diagnostics:
# ==============================================================
@staticmethod
- def type_override_error(cls_name: str, expected, got):
- """Report an invalid DataTypes override.
+ def type_override_error(cls_name: str, expected: object, got: object) -> None:
+ """
+ Report an invalid DataTypes override.
Used when descriptor and AttributeSpec types conflict.
"""
@@ -41,7 +43,7 @@ def type_override_error(cls_name: str, expected, got):
def readonly_error(
name: str,
key: str | None = None,
- ):
+ ) -> None:
"""Log an attempt to change a read-only attribute."""
Diagnostics._log_error(
f"Cannot modify read-only attribute '{key}' of <{name}>.",
@@ -53,11 +55,9 @@ def attr_error(
name: str,
key: str,
allowed: set[str],
- label='Allowed',
- ):
- """Log access to an unknown attribute and suggest closest
- key.
- """
+ label: str = 'Allowed',
+ ) -> None:
+ """Log unknown attribute access and suggest closest key."""
suggestion = Diagnostics._build_suggestion(key, allowed)
# Use consistent (label) logic for allowed
hint = suggestion or Diagnostics._build_allowed(allowed, label=label)
@@ -73,11 +73,11 @@ def attr_error(
@staticmethod
def type_mismatch(
name: str,
- value,
- expected_type,
- current=None,
- default=None,
- ):
+ value: object,
+ expected_type: object,
+ current: object = None,
+ default: object = None,
+ ) -> None:
"""Log a type mismatch and keep current or default value."""
got_type = type(value).__name__
msg = (
@@ -91,12 +91,12 @@ def type_mismatch(
@staticmethod
def range_mismatch(
name: str,
- value,
- ge,
- le,
- current=None,
- default=None,
- ):
+ value: object,
+ ge: float,
+ le: float,
+ current: object = None,
+ default: object = None,
+ ) -> None:
"""Log range violation for a numeric value."""
msg = f'Value mismatch for <{name}>. Provided {value!r} outside [{ge}, {le}].'
Diagnostics._log_error_with_fallback(
@@ -106,11 +106,11 @@ def range_mismatch(
@staticmethod
def choice_mismatch(
name: str,
- value,
- allowed,
- current=None,
- default=None,
- ):
+ value: object,
+ allowed: object,
+ current: object = None,
+ default: object = None,
+ ) -> None:
"""Log an invalid choice against allowed values."""
msg = f'Value mismatch for <{name}>. Provided {value!r} is unknown.'
if allowed is not None:
@@ -122,11 +122,11 @@ def choice_mismatch(
@staticmethod
def regex_mismatch(
name: str,
- value,
- pattern,
- current=None,
- default=None,
- ):
+ value: object,
+ pattern: str,
+ current: object = None,
+ default: object = None,
+ ) -> None:
"""Log a regex mismatch with the expected pattern."""
msg = (
f"Value mismatch for <{name}>. Provided {value!r} does not match pattern '{pattern}'."
@@ -136,24 +136,24 @@ def regex_mismatch(
)
@staticmethod
- def no_value(name, default):
+ def no_value(name: str, default: object) -> None:
"""Log that default will be used due to missing value."""
Diagnostics._log_debug(f'No value provided for <{name}>. Using default {default!r}.')
@staticmethod
- def none_value(name):
+ def none_value(name: str) -> None:
"""Log explicit None provided by a user."""
Diagnostics._log_debug(f'Using `None` explicitly provided for <{name}>.')
@staticmethod
- def none_value_skip_range(name):
+ def none_value_skip_range(name: str) -> None:
"""Log that range validation is skipped due to None."""
Diagnostics._log_debug(
f'Skipping range validation as `None` is explicitly provided for <{name}>.'
)
@staticmethod
- def validated(name, value, stage: str | None = None):
+ def validated(name: str, value: object, stage: str | None = None) -> None:
"""Log that a value passed a validation stage."""
stage_info = f' {stage}' if stage else ''
Diagnostics._log_debug(f'Value {value!r} for <{name}> passed{stage_info} validation.')
@@ -163,17 +163,17 @@ def validated(name, value, stage: str | None = None):
# ==============================================================
@staticmethod
- def _log_error(msg, exc_type=Exception):
+ def _log_error(msg: str, exc_type: type[Exception] = Exception) -> None:
"""Emit an error-level message via shared logger."""
log.error(msg, exc_type=exc_type)
@staticmethod
def _log_error_with_fallback(
- msg,
- current=None,
- default=None,
- exc_type=Exception,
- ):
+ msg: str,
+ current: object = None,
+ default: object = None,
+ exc_type: type[Exception] = Exception,
+ ) -> None:
"""Emit an error message and mention kept or default value."""
if current is not None:
msg += f' Keeping current {current!r}.'
@@ -182,7 +182,7 @@ def _log_error_with_fallback(
log.error(msg, exc_type=exc_type)
@staticmethod
- def _log_debug(msg):
+ def _log_debug(msg: str) -> None:
"""Emit a debug-level message via shared logger."""
log.debug(msg)
@@ -191,7 +191,7 @@ def _log_debug(msg):
# ==============================================================
@staticmethod
- def _suggest(key: str, allowed: set[str]):
+ def _suggest(key: str, allowed: set[str]) -> str | None:
"""Suggest closest allowed key using string similarity."""
if not allowed:
return None
@@ -200,12 +200,12 @@ def _suggest(key: str, allowed: set[str]):
return matches[0] if matches else None
@staticmethod
- def _build_suggestion(key: str, allowed: set[str]):
+ def _build_suggestion(key: str, allowed: set[str]) -> str:
s = Diagnostics._suggest(key, allowed)
return f" Did you mean '{s}'?" if s else ''
@staticmethod
- def _build_allowed(allowed, label='Allowed attributes'):
+ def _build_allowed(allowed: object, label: str = 'Allowed attributes') -> str:
# allowed may be a set, list, or other iterable
if allowed:
allowed_list = list(allowed)
diff --git a/src/easydiffraction/core/factory.py b/src/easydiffraction/core/factory.py
index 8e699085..af99217a 100644
--- a/src/easydiffraction/core/factory.py
+++ b/src/easydiffraction/core/factory.py
@@ -1,10 +1,10 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Base factory with registration, lookup, and context-dependent
-defaults.
+"""
+Base factory with registration, lookup, and context-dependent defaults.
-Concrete factories inherit from ``FactoryBase`` and only need to
-define ``_default_rules``.
+Concrete factories inherit from ``FactoryBase`` and only need to define
+``_default_rules``.
"""
from __future__ import annotations
@@ -21,12 +21,13 @@
class FactoryBase:
- """Shared base for all factories.
+ """
+ Shared base for all factories.
Subclasses must set:
* ``_default_rules`` -- mapping of ``frozenset`` conditions to tag
- strings. Use ``frozenset(): 'tag'`` for a universal default.
+ strings. Use ``frozenset(): 'tag'`` for a universal default.
The ``__init_subclass__`` hook ensures every subclass gets its own
independent ``_registry`` list.
@@ -35,7 +36,7 @@ class FactoryBase:
_registry: List[Type] = []
_default_rules: Dict[FrozenSet[Tuple[str, Any]], str] = {}
- def __init_subclass__(cls, **kwargs):
+ def __init_subclass__(cls, **kwargs: object) -> None:
"""Give each subclass its own independent registry and rules."""
super().__init_subclass__(**kwargs)
cls._registry = []
@@ -47,14 +48,14 @@ def __init_subclass__(cls, **kwargs):
# ------------------------------------------------------------------
@classmethod
- def register(cls, klass):
- """Class decorator to register a concrete class.
+ def register(cls, klass: type) -> type:
+ """
+ Class decorator to register a concrete class.
Usage::
- @SomeFactory.register
- class MyClass(SomeBase):
- type_info = TypeInfo(...)
+ @SomeFactory.register class MyClass(SomeBase): type_info =
+ TypeInfo(...)
Returns the class unmodified.
"""
@@ -80,22 +81,29 @@ def supported_tags(cls) -> List[str]:
# ------------------------------------------------------------------
@classmethod
- def default_tag(cls, **conditions) -> str:
- """Resolve the default tag for a given experimental context.
+ def default_tag(cls, **conditions: object) -> str:
+ """
+ Resolve the default tag for a given experimental context.
Uses *largest-subset matching*: the rule whose key is the
- biggest subset of the given conditions wins. A rule with an
+ biggest subset of the given conditions wins. A rule with an
empty key (``frozenset()``) acts as a universal fallback.
- Args:
- **conditions: Experimental-axis values, e.g.
- ``scattering_type=ScatteringTypeEnum.BRAGG``.
+ Parameters
+ ----------
+ **conditions : object
+ Experimental-axis values, e.g.
+ ``scattering_type=ScatteringTypeEnum.BRAGG``.
- Returns:
+ Returns
+ -------
+ str
The resolved default tag string.
- Raises:
- ValueError: If no rule matches the given conditions.
+ Raises
+ ------
+ ValueError
+ If no rule matches the given conditions.
"""
condition_set = frozenset(conditions.items())
best_match_tag: str | None = None
@@ -118,15 +126,26 @@ def default_tag(cls, **conditions) -> str:
# ------------------------------------------------------------------
@classmethod
- def create(cls, tag: str, **kwargs) -> Any:
- """Instantiate a registered class by *tag*.
-
- Args:
- tag: ``type_info.tag`` value.
- **kwargs: Forwarded to the class constructor.
-
- Raises:
- ValueError: If *tag* is not in the registry.
+ def create(cls, tag: str, **kwargs: object) -> object:
+ """
+ Instantiate a registered class by *tag*.
+
+ Parameters
+ ----------
+ tag : str
+ ``type_info.tag`` value.
+ **kwargs : object
+ Forwarded to the class constructor.
+
+ Returns
+ -------
+ object
+ A new instance of the registered class.
+
+ Raises
+ ------
+ ValueError
+ If *tag* is not in the registry.
"""
supported = cls._supported_map()
if tag not in supported:
@@ -134,13 +153,21 @@ def create(cls, tag: str, **kwargs) -> Any:
return supported[tag](**kwargs)
@classmethod
- def create_default_for(cls, **conditions) -> Any:
- """Instantiate the default class for a given context.
+ def create_default_for(cls, **conditions: object) -> object:
+ """
+ Instantiate the default class for a given context.
Combines ``default_tag(**conditions)`` with ``create(tag)``.
- Args:
- **conditions: Experimental-axis values.
+ Parameters
+ ----------
+ **conditions : object
+ Experimental-axis values.
+
+ Returns
+ -------
+ object
+ A new instance of the default class.
"""
tag = cls.default_tag(**conditions)
return cls.create(tag)
@@ -153,20 +180,32 @@ def create_default_for(cls, **conditions) -> Any:
def supported_for(
cls,
*,
- calculator=None,
- sample_form=None,
- scattering_type=None,
- beam_mode=None,
- radiation_probe=None,
+ calculator: object = None,
+ sample_form: object = None,
+ scattering_type: object = None,
+ beam_mode: object = None,
+ radiation_probe: object = None,
) -> List[Type]:
- """Return classes matching conditions and/or calculator.
-
- Args:
- calculator: Optional ``CalculatorEnum`` value.
- sample_form: Optional ``SampleFormEnum`` value.
- scattering_type: Optional ``ScatteringTypeEnum`` value.
- beam_mode: Optional ``BeamModeEnum`` value.
- radiation_probe: Optional ``RadiationProbeEnum`` value.
+ """
+ Return classes matching conditions and/or calculator.
+
+ Parameters
+ ----------
+ calculator : object, default=None
+ Optional ``CalculatorEnum`` value.
+ sample_form : object, default=None
+ Optional ``SampleFormEnum`` value.
+ scattering_type : object, default=None
+ Optional ``ScatteringTypeEnum`` value.
+ beam_mode : object, default=None
+ Optional ``BeamModeEnum`` value.
+ radiation_probe : object, default=None
+ Optional ``RadiationProbeEnum`` value.
+
+ Returns
+ -------
+ List[Type]
+ Classes matching the given conditions.
"""
result = []
for klass in cls._supported_map().values():
@@ -192,20 +231,27 @@ def supported_for(
def show_supported(
cls,
*,
- calculator=None,
- sample_form=None,
- scattering_type=None,
- beam_mode=None,
- radiation_probe=None,
+ calculator: object = None,
+ sample_form: object = None,
+ scattering_type: object = None,
+ beam_mode: object = None,
+ radiation_probe: object = None,
) -> None:
- """Pretty-print a table of supported types.
-
- Args:
- calculator: Optional ``CalculatorEnum`` filter.
- sample_form: Optional ``SampleFormEnum`` filter.
- scattering_type: Optional ``ScatteringTypeEnum`` filter.
- beam_mode: Optional ``BeamModeEnum`` filter.
- radiation_probe: Optional ``RadiationProbeEnum`` filter.
+ """
+ Pretty-print a table of supported types.
+
+ Parameters
+ ----------
+ calculator : object, default=None
+ Optional ``CalculatorEnum`` filter.
+ sample_form : object, default=None
+ Optional ``SampleFormEnum`` filter.
+ scattering_type : object, default=None
+ Optional ``ScatteringTypeEnum`` filter.
+ beam_mode : object, default=None
+ Optional ``BeamModeEnum`` filter.
+ radiation_probe : object, default=None
+ Optional ``RadiationProbeEnum`` filter.
"""
matching = cls.supported_for(
calculator=calculator,
diff --git a/src/easydiffraction/core/guard.py b/src/easydiffraction/core/guard.py
index a0033d14..17b60fb5 100644
--- a/src/easydiffraction/core/guard.py
+++ b/src/easydiffraction/core/guard.py
@@ -1,33 +1,35 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
from abc import ABC
from abc import abstractmethod
+from typing import Generator
from easydiffraction.core.diagnostic import Diagnostics
from easydiffraction.core.identity import Identity
class GuardedBase(ABC):
- """Base class enforcing controlled attribute access and parent
- linkage.
- """
+ """Base class enforcing controlled attribute access and linkage."""
_diagnoser = Diagnostics()
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._identity = Identity(owner=self)
def __str__(self) -> str:
+ """Return the string representation of this object."""
return f'<{self.unique_name}>'
def __repr__(self) -> str:
+ """Return the developer representation of this object."""
return self.__str__()
- def __getattr__(self, key: str):
+ def __getattr__(self, key: str) -> None:
+ """Raise a descriptive error for unknown attribute access."""
cls = type(self)
allowed = cls._public_attrs()
if key not in allowed:
@@ -38,7 +40,8 @@ def __getattr__(self, key: str):
label='Allowed readable/writable',
)
- def __setattr__(self, key: str, value):
+ def __setattr__(self, key: str, value: object) -> None:
+ """Set an attribute with access-control diagnostics."""
# Always allow private or special attributes without diagnostics
if key.startswith('_'):
object.__setattr__(self, key, value)
@@ -70,20 +73,21 @@ def __setattr__(self, key: str, value):
self._assign_attr(key, value)
- def _assign_attr(self, key, value):
+ def _assign_attr(self, key: str, value: object) -> None:
"""Low-level assignment with parent linkage."""
object.__setattr__(self, key, value)
if key != '_parent' and isinstance(value, GuardedBase):
object.__setattr__(value, '_parent', self)
@classmethod
- def _iter_properties(cls):
- """Iterate over all public properties defined in the class
- hierarchy.
+ def _iter_properties(cls) -> Generator[tuple[str, property], None, None]:
+ """
+ Iterate over all public properties in the class hierarchy.
- Yields:
- tuple[str, property]: Each (key, property) pair for public
- attributes.
+ Yields
+ ------
+ tuple[str, property]
+ Each (key, property) pair for public attributes.
"""
for base in cls.mro():
for key, attr in base.__dict__.items():
@@ -92,12 +96,12 @@ def _iter_properties(cls):
yield key, attr
@classmethod
- def _public_attrs(cls):
+ def _public_attrs(cls) -> set[str]:
"""All public properties (read-only + writable)."""
return {key for key, _ in cls._iter_properties()}
@classmethod
- def _public_readonly_attrs(cls):
+ def _public_readonly_attrs(cls) -> set[str]:
"""Public properties without a setter."""
return {key for key, prop in cls._iter_properties() if prop.fset is None}
@@ -106,18 +110,19 @@ def _public_writable_attrs(cls) -> set[str]:
"""Public properties with a setter."""
return {key for key, prop in cls._iter_properties() if prop.fset is not None}
- def _allowed_attrs(self, writable_only=False):
+ def _allowed_attrs(self, writable_only: bool = False) -> set[str]:
cls = type(self)
if writable_only:
return cls._public_writable_attrs()
return cls._public_attrs()
@property
- def _log_name(self):
+ def _log_name(self) -> str:
return self.unique_name or type(self).__name__
@property
- def unique_name(self):
+ def unique_name(self) -> str:
+ """Fallback unique name: the class name."""
return type(self).__name__
# @property
@@ -131,23 +136,20 @@ def unique_name(self):
@property
@abstractmethod
- def parameters(self):
- """Return a list of parameter objects (to be implemented by
- subclasses).
- """
+ def parameters(self) -> list:
+ """Return a list of parameters (implemented by subclasses)."""
raise NotImplementedError
@property
@abstractmethod
def as_cif(self) -> str:
- """Return CIF representation of this object (to be implemented
- by subclasses).
- """
+ """Return CIF representation (implemented by subclasses)."""
raise NotImplementedError
@staticmethod
def _first_sentence(docstring: str | None) -> str:
- """Extract the first paragraph from a docstring.
+ """
+ Extract the first paragraph from a docstring.
Returns text before the first blank line, with continuation
lines joined into a single string.
@@ -158,11 +160,14 @@ def _first_sentence(docstring: str | None) -> str:
return ' '.join(line.strip() for line in first_para.splitlines())
@classmethod
- def _iter_methods(cls):
- """Iterate over public methods in the class hierarchy.
+ def _iter_methods(cls) -> Generator[tuple[str, object], None, None]:
+ """
+ Iterate over public methods in the class hierarchy.
- Yields:
- tuple[str, callable]: Each (name, function) pair.
+ Yields
+ ------
+ tuple[str, object]
+ Each (name, function) pair.
"""
seen: set = set()
for base in cls.mro():
diff --git a/src/easydiffraction/core/identity.py b/src/easydiffraction/core/identity.py
index 5848bf18..d64fce81 100644
--- a/src/easydiffraction/core/identity.py
+++ b/src/easydiffraction/core/identity.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Identity helpers to build CIF-like hierarchical names.
+"""
+Identity helpers to build CIF-like hierarchical names.
Used by containers and items to expose datablock/category/entry names
without tight coupling.
@@ -19,13 +20,13 @@ def __init__(
datablock_entry: Callable | None = None,
category_code: str | None = None,
category_entry: Callable | None = None,
- ):
+ ) -> None:
self._owner = owner
self._datablock_entry = datablock_entry
self._category_code = category_code
self._category_entry = category_entry
- def _resolve_up(self, attr: str, visited=None):
+ def _resolve_up(self, attr: str, visited: set[int] | None = None) -> str | None:
"""Resolve attribute by walking up parent chain safely."""
if visited is None:
visited = set()
@@ -47,31 +48,31 @@ def _resolve_up(self, attr: str, visited=None):
return None
@property
- def datablock_entry_name(self):
+ def datablock_entry_name(self) -> str | None:
"""Datablock entry name or None if not set."""
return self._resolve_up('datablock_entry')
@datablock_entry_name.setter
- def datablock_entry_name(self, func: callable):
+ def datablock_entry_name(self, func: callable) -> None:
"""Set callable returning datablock entry name."""
self._datablock_entry = func
@property
- def category_code(self):
+ def category_code(self) -> str | None:
"""Category code like 'atom_site' or 'background'."""
return self._resolve_up('category_code')
@category_code.setter
- def category_code(self, value: str):
+ def category_code(self, value: str) -> None:
"""Set category code value."""
self._category_code = value
@property
- def category_entry_name(self):
+ def category_entry_name(self) -> str | None:
"""Category entry name or None if not set."""
return self._resolve_up('category_entry')
@category_entry_name.setter
- def category_entry_name(self, func: callable):
+ def category_entry_name(self, func: callable) -> None:
"""Set callable returning category entry name."""
self._category_entry = func
diff --git a/src/easydiffraction/core/metadata.py b/src/easydiffraction/core/metadata.py
index 4a820515..318d64bb 100644
--- a/src/easydiffraction/core/metadata.py
+++ b/src/easydiffraction/core/metadata.py
@@ -1,12 +1,13 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Metadata dataclasses for factory-created classes.
+"""
+Metadata dataclasses for factory-created classes.
Three frozen dataclasses describe a concrete class:
-- ``TypeInfo`` — stable tag and human-readable description.
-- ``Compatibility`` — experimental conditions (multiple fields).
-- ``CalculatorSupport`` — which calculation engines can handle it.
+- ``TypeInfo`` — stable tag and human-readable description. -
+``Compatibility`` — experimental conditions (multiple fields). -
+``CalculatorSupport`` — which calculation engines can handle it.
"""
from __future__ import annotations
@@ -17,16 +18,19 @@
@dataclass(frozen=True)
class TypeInfo:
- """Stable identity and human-readable description for a factory-
- created class.
-
- Attributes:
- tag: Short, stable string identifier used for serialization,
- user-facing selection, and factory lookup. Must be unique
- within a factory's registry. Examples: ``'line-segment'``,
- ``'pseudo-voigt'``, ``'cryspy'``.
- description: One-line human-readable explanation. Used in
- ``show_supported()`` tables and documentation.
+ """
+ Stable identity and description for a factory-created class.
+
+ Attributes
+ ----------
+ tag : str
+ Short, stable string identifier used for serialization,
+ user-facing selection, and factory lookup. Must be unique within
+ a factory's registry. Examples: ``'line-segment'``,
+ ``'pseudo-voigt'``, ``'cryspy'``.
+ description : str, default=''
+ One-line human-readable explanation. Used in
+ ``show_supported()`` tables and documentation.
"""
tag: str
@@ -35,7 +39,8 @@ class TypeInfo:
@dataclass(frozen=True)
class Compatibility:
- """Experimental conditions under which a class can be used.
+ """
+ Experimental conditions under which a class can be used.
Each field is a frozenset of enum values representing the set of
supported values for that axis. An empty frozenset means
@@ -49,12 +54,13 @@ class Compatibility:
def supports(
self,
- sample_form=None,
- scattering_type=None,
- beam_mode=None,
- radiation_probe=None,
+ sample_form: object = None,
+ scattering_type: object = None,
+ beam_mode: object = None,
+ radiation_probe: object = None,
) -> bool:
- """Check if this compatibility matches the given conditions.
+ """
+ Check if this compatibility matches the given conditions.
Each argument is an optional enum member. Returns ``True`` if
every provided value is in the corresponding frozenset (or the
@@ -62,10 +68,8 @@ def supports(
Example::
- compat.supports(
- scattering_type=ScatteringTypeEnum.BRAGG,
- beam_mode=BeamModeEnum.CONSTANT_WAVELENGTH,
- )
+ compat.supports( scattering_type=ScatteringTypeEnum.BRAGG,
+ beam_mode=BeamModeEnum.CONSTANT_WAVELENGTH, )
"""
for axis, value in (
('sample_form', sample_form),
@@ -83,22 +87,30 @@ def supports(
@dataclass(frozen=True)
class CalculatorSupport:
- """Which calculation engines can handle this class.
+ """
+ Which calculation engines can handle this class.
- Attributes:
- calculators: Frozenset of ``CalculatorEnum`` values. Empty
- means "any calculator" (no restriction).
+ Attributes
+ ----------
+ calculators : FrozenSet, default=frozenset()
+ Frozenset of ``CalculatorEnum`` values. Empty means "any
+ calculator" (no restriction).
"""
calculators: FrozenSet = frozenset()
- def supports(self, calculator) -> bool:
- """Check if a specific calculator can handle this class.
+ def supports(self, calculator: object) -> bool:
+ """
+ Check if a specific calculator can handle this class.
- Args:
- calculator: A ``CalculatorEnum`` value.
+ Parameters
+ ----------
+ calculator : object
+ A ``CalculatorEnum`` value.
- Returns:
+ Returns
+ -------
+ bool
``True`` if the calculator is in the set, or if the set is
empty (meaning any calculator is accepted).
"""
diff --git a/src/easydiffraction/core/singleton.py b/src/easydiffraction/core/singleton.py
index 10af4667..9033822a 100644
--- a/src/easydiffraction/core/singleton.py
+++ b/src/easydiffraction/core/singleton.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from typing import Any
@@ -16,7 +16,8 @@
class SingletonBase:
- """Base class to implement Singleton pattern.
+ """
+ Base class to implement Singleton pattern.
Ensures only one shared instance of a class is ever created. Useful
for managing shared state across the library.
@@ -26,7 +27,7 @@ class SingletonBase:
@classmethod
def get(cls: Type[T]) -> T:
- """Returns the shared instance, creating it if needed."""
+ """Return the shared instance, creating it if needed."""
if cls._instance is None:
cls._instance = cls()
return cls._instance
@@ -43,11 +44,12 @@ def __init__(self) -> None:
self._uid_map: Dict[str, Any] = {}
def get_uid_map(self) -> Dict[str, Any]:
- """Returns the current UID-to-Parameter map."""
+ """Return the current UID-to-Parameter map."""
return self._uid_map
- def add_to_uid_map(self, parameter):
- """Adds a single Parameter or Descriptor object to the UID map.
+ def add_to_uid_map(self, parameter: object) -> None:
+ """
+ Add a single Parameter or Descriptor object to the UID map.
Only Descriptor or Parameter instances are allowed (not
Components or others).
@@ -61,8 +63,9 @@ def add_to_uid_map(self, parameter):
)
self._uid_map[parameter.uid] = parameter
- def replace_uid(self, old_uid, new_uid):
- """Replaces an existing UID key in the UID map with a new UID.
+ def replace_uid(self, old_uid: str, new_uid: str) -> None:
+ """
+ Replace an existing UID key in the UID map with a new UID.
Moves the associated parameter from old_uid to new_uid. Raises a
KeyError if the old_uid doesn't exist.
@@ -82,8 +85,8 @@ def replace_uid(self, old_uid, new_uid):
# TODO: Implement changing atrr '.constrained' back to False
# when removing constraints
class ConstraintsHandler(SingletonBase):
- """Manages user-defined parameter constraints using aliases and
- expressions.
+ """
+ Manage parameter constraints using aliases and expressions.
Uses the asteval interpreter for safe evaluation of mathematical
expressions. Constraints are defined as: lhs_alias =
@@ -102,29 +105,27 @@ def __init__(self) -> None:
# Internally parsed constraints as (lhs_alias, rhs_expr) tuples
self._parsed_constraints: List[Tuple[str, str]] = []
- def set_aliases(self, aliases):
- """Sets the alias map (name → parameter wrapper).
+ def set_aliases(self, aliases: object) -> None:
+ """
+ Set the alias map (name → parameter wrapper).
Called when user registers parameter aliases like:
- alias='biso_La', param=model.atom_sites['La'].b_iso
+ alias='biso_La', param=model.atom_sites['La'].b_iso
"""
self._alias_to_param = dict(aliases.items())
- def set_constraints(self, constraints):
- """Sets the constraints and triggers parsing into internal
- format.
+ def set_constraints(self, constraints: object) -> None:
+ """
+ Set the constraints and triggers parsing into internal format.
- Called when user registers expressions like:
- lhs_alias='occ_Ba', rhs_expr='1 - occ_La'
+ Called when user registers expressions like: lhs_alias='occ_Ba',
+ rhs_expr='1 - occ_La'
"""
self._constraints = constraints._items
self._parse_constraints()
def _parse_constraints(self) -> None:
- """Converts raw expression input into a normalized internal list
- of (lhs_alias, rhs_expr) pairs, stripping whitespace and
- skipping invalid entries.
- """
+ """Parse raw expressions into (lhs_alias, rhs_expr) pairs."""
self._parsed_constraints = []
for expr_obj in self._constraints:
@@ -136,12 +137,11 @@ def _parse_constraints(self) -> None:
self._parsed_constraints.append(constraint)
def apply(self) -> None:
- """Evaluates constraints and applies them to dependent
- parameters.
+ """
+ Evaluate constraints and applies them to dependent parameters.
- For each constraint:
- - Evaluate RHS using current values of aliases
- - Locate the dependent parameter by alias → uid → param
+ For each constraint: - Evaluate RHS using current values of
+ aliases - Locate the dependent parameter by alias → uid → param
- Update its value and mark it as constrained
"""
if not self._parsed_constraints:
diff --git a/src/easydiffraction/core/validation.py b/src/easydiffraction/core/validation.py
index 1fd268d9..d3c411af 100644
--- a/src/easydiffraction/core/validation.py
+++ b/src/easydiffraction/core/validation.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Lightweight runtime validation utilities.
+"""
+Lightweight runtime validation utilities.
Provides DataTypes, type/content validators, and AttributeSpec used by
descriptors and parameters. Only documentation was added here.
@@ -23,6 +24,8 @@
# TODO: MkDocs doesn't unpack types
class DataTypeHints:
+ """Type hint aliases for numeric, string, and boolean types."""
+
Numeric = int | float | np.integer | np.floating
String = str
Bool = bool
@@ -32,16 +35,19 @@ class DataTypeHints:
class DataTypes(Enum):
+ """Enumeration of supported data types for descriptors."""
+
NUMERIC = (int, float, np.integer, np.floating)
STRING = (str,)
BOOL = (bool,)
ANY = (object,) # fallback for unconstrained
- def __str__(self):
+ def __str__(self) -> str:
+ """Return the lowercase name of the data type."""
return self.name.lower()
@property
- def expected_type(self):
+ def expected_type(self) -> tuple:
"""Convenience alias for tuple of allowed Python types."""
return self.value
@@ -59,7 +65,8 @@ class ValidationStage(Enum):
MEMBERSHIP = auto()
REGEX = auto()
- def __str__(self):
+ def __str__(self) -> str:
+ """Return the lowercase name of the validation stage."""
return self.name.lower()
@@ -72,8 +79,15 @@ class ValidatorBase(ABC):
"""Abstract base class for all validators."""
@abstractmethod
- def validated(self, value, name, default=None, current=None):
- """Return a validated value or fallback.
+ def validated(
+ self,
+ value: object,
+ name: str,
+ default: object = None,
+ current: object = None,
+ ) -> object:
+ """
+ Return a validated value or fallback.
Subclasses must implement this method.
"""
@@ -81,9 +95,9 @@ def validated(self, value, name, default=None, current=None):
def _fallback(
self,
- current=None,
- default=None,
- ):
+ current: object = None,
+ default: object = None,
+ ) -> object:
"""Return current if set, else default."""
return current if current is not None else default
@@ -94,7 +108,7 @@ def _fallback(
class TypeValidator(ValidatorBase):
"""Ensure a value is of the expected data type."""
- def __init__(self, expected_type: DataTypes):
+ def __init__(self, expected_type: DataTypes) -> None:
if isinstance(expected_type, DataTypes):
self.expected_type = expected_type
self.expected_label = str(expected_type)
@@ -103,13 +117,14 @@ def __init__(self, expected_type: DataTypes):
def validated(
self,
- value,
- name,
- default=None,
- current=None,
- allow_none=False,
- ):
- """Validate type and return value or fallback.
+ value: object,
+ name: str,
+ default: object = None,
+ current: object = None,
+ allow_none: bool = False,
+ ) -> object:
+ """
+ Validate type and return value or fallback.
If allow_none is True, None bypasses content checks.
"""
@@ -151,18 +166,18 @@ class RangeValidator(ValidatorBase):
def __init__(
self,
*,
- ge=-np.inf,
- le=np.inf,
- ):
+ ge: float = -np.inf,
+ le: float = np.inf,
+ ) -> None:
self.ge, self.le = ge, le
def validated(
self,
- value,
- name,
- default=None,
- current=None,
- ):
+ value: object,
+ name: str,
+ default: object = None,
+ current: object = None,
+ ) -> object:
"""Validate range and return value or fallback."""
if not (self.ge <= value <= self.le):
Diagnostics.range_mismatch(
@@ -187,22 +202,23 @@ def validated(
class MembershipValidator(ValidatorBase):
- """Ensure that a value is among allowed choices.
+ """
+ Ensure that a value is among allowed choices.
- `allowed` may be an iterable or a callable returning a collection.
+ ``allowed`` may be an iterable or a callable returning a collection.
"""
- def __init__(self, allowed):
+ def __init__(self, allowed: object) -> None:
# Do not convert immediately to list — may be callable
self.allowed = allowed
def validated(
self,
- value,
- name,
- default=None,
- current=None,
- ):
+ value: object,
+ name: str,
+ default: object = None,
+ current: object = None,
+ ) -> object:
"""Validate membership and return value or fallback."""
# Dynamically evaluate allowed if callable (e.g. lambda)
allowed_values = self.allowed() if callable(self.allowed) else self.allowed
@@ -231,16 +247,16 @@ def validated(
class RegexValidator(ValidatorBase):
"""Ensure that a string matches a given regular expression."""
- def __init__(self, pattern):
+ def __init__(self, pattern: str) -> None:
self.pattern = re.compile(pattern)
def validated(
self,
- value,
- name,
- default=None,
- current=None,
- ):
+ value: object,
+ name: str,
+ default: object = None,
+ current: object = None,
+ ) -> object:
"""Validate regex and return value or fallback."""
if not self.pattern.fullmatch(value):
Diagnostics.regex_mismatch(
@@ -271,11 +287,11 @@ class AttributeSpec:
def __init__(
self,
*,
- default=None,
- data_type=None,
- validator=None,
+ default: object = None,
+ data_type: DataTypes | None = None,
+ validator: ValidatorBase | None = None,
allow_none: bool = False,
- ):
+ ) -> None:
self.default = default
self.allow_none = allow_none
self._data_type_validator = TypeValidator(data_type) if data_type else None
@@ -283,11 +299,12 @@ def __init__(
def validated(
self,
- value,
- name,
- current=None,
- ):
- """Validate through type and content validators.
+ value: object,
+ name: str,
+ current: object = None,
+ ) -> object:
+ """
+ Validate through type and content validators.
Returns validated value, possibly default or current if errors
occur. None may short-circuit further checks when allowed.
diff --git a/src/easydiffraction/core/variable.py b/src/easydiffraction/core/variable.py
index 6b33a39e..8e06b2a9 100644
--- a/src/easydiffraction/core/variable.py
+++ b/src/easydiffraction/core/variable.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -6,7 +6,6 @@
import secrets
import string
from typing import TYPE_CHECKING
-from typing import Any
import numpy as np
@@ -27,18 +26,14 @@
class GenericDescriptorBase(GuardedBase):
- """Base class for all parameter-like descriptors.
+ """
+ Base class for all parameter-like descriptors.
A descriptor encapsulates a typed value with validation,
human-readable name/description and a globally unique identifier
that is stable across the session. Concrete subclasses specialize
- the expected data type and can extend the public API with
- additional behavior (e.g. units).
-
- Attributes:
- name: Local parameter name (e.g. 'a', 'b_iso').
- description: Optional human-readable description.
- uid: Stable random identifier for external references.
+ the expected data type and can extend the public API with additional
+ behavior (e.g. units).
"""
_BOOL_SPEC_TEMPLATE = AttributeSpec(
@@ -52,13 +47,18 @@ def __init__(
value_spec: AttributeSpec,
name: str,
description: str = None,
- ):
- """Initialize the descriptor with validation and identity.
-
- Args:
- value_spec: Validation specification for the value.
- name: Local name of the descriptor within its category.
- description: Optional human-readable description.
+ ) -> None:
+ """
+ Initialize the descriptor with validation and identity.
+
+ Parameters
+ ----------
+ value_spec : AttributeSpec
+ Validation specification for the value.
+ name : str
+ Local name of the descriptor within its category.
+ description : str, default=None
+ Optional human-readable description.
"""
super().__init__()
@@ -98,6 +98,7 @@ def __init__(
self._value = default() if callable(default) else default
def __str__(self) -> str:
+ """Return the string representation of this descriptor."""
return f'<{self.unique_name} = {self.value!r}>'
@property
@@ -106,11 +107,8 @@ def name(self) -> str:
return self._name
@property
- def unique_name(self):
- """Fully qualified name including datablock, category and entry
- name.
- """
- # 7c: Use filter(None, [...])
+ def unique_name(self) -> str:
+ """Fully qualified name: datablock, category and entry."""
parts = [
self._identity.datablock_entry_name,
self._identity.category_code,
@@ -119,10 +117,8 @@ def unique_name(self):
]
return '.'.join(filter(None, parts))
- def _parent_of_type(self, cls):
- """Walk up the parent chain and return the first parent of type
- `cls`.
- """
+ def _parent_of_type(self, cls: type) -> object | None:
+ """Traverse parents and return the first of type cls."""
obj = getattr(self, '_parent', None)
visited = set()
while obj is not None and id(obj) not in visited:
@@ -132,19 +128,19 @@ def _parent_of_type(self, cls):
obj = getattr(obj, '_parent', None)
return None
- def _datablock_item(self):
+ def _datablock_item(self) -> object | None:
"""Return the DatablockItem ancestor, if any."""
from easydiffraction.core.datablock import DatablockItem
return self._parent_of_type(DatablockItem)
@property
- def value(self):
+ def value(self) -> object:
"""Current validated value."""
return self._value
@value.setter
- def value(self, v):
+ def value(self, v: object) -> None:
"""Set a new value after validating against the spec."""
# Do nothing if the value is unchanged
if self._value == v:
@@ -163,19 +159,20 @@ def value(self, v):
if parent_datablock is not None:
parent_datablock._need_categories_update = True
- def _set_value_from_minimizer(self, v) -> None:
- """Set the value from a minimizer, bypassing validation.
+ def _set_value_from_minimizer(self, v: object) -> None:
+ """
+ Set the value from a minimizer, bypassing validation.
- Writes ``_value`` directly — no type or range checks — but
- still marks the owning :class:`DatablockItem` dirty so that
+ Writes ``_value`` directly — no type or range checks — but still
+ marks the owning :class:`DatablockItem` dirty so that
``_update_categories()`` knows work is needed.
This exists because:
1. Physical-range validators (e.g. intensity ≥ 0) would reject
- trial values the minimizer needs to explore.
- 2. Validation overhead is measurable over thousands of
- objective-function evaluations.
+ trial values the minimizer needs to explore. 2. Validation
+ overhead is measurable over thousands of objective-function
+ evaluations.
"""
self._value = v
parent_datablock = self._datablock_item()
@@ -183,13 +180,14 @@ def _set_value_from_minimizer(self, v) -> None:
parent_datablock._need_categories_update = True
@property
- def description(self):
+ def description(self) -> str | None:
"""Optional human-readable description."""
return self._description
@property
- def parameters(self):
- """Return a flat list of parameters contained by this object.
+ def parameters(self) -> list[GenericDescriptorBase]:
+ """
+ Return a flat list of parameters contained by this object.
For a single descriptor, it returns a one-element list with
itself. Composite objects override this to flatten nested
@@ -202,7 +200,7 @@ def as_cif(self) -> str:
"""Serialize this descriptor to a CIF-formatted string."""
return param_to_cif(self)
- def from_cif(self, block, idx=0):
+ def from_cif(self, block: object, idx: int = 0) -> None:
"""Populate this parameter from a CIF block."""
param_from_cif(self, block, idx)
@@ -211,11 +209,13 @@ def from_cif(self, block, idx=0):
class GenericStringDescriptor(GenericDescriptorBase):
+ """Base descriptor that constrains values to strings."""
+
_value_type = DataTypes.STRING
def __init__(
self,
- **kwargs: Any,
+ **kwargs: object,
) -> None:
super().__init__(**kwargs)
@@ -224,18 +224,21 @@ def __init__(
class GenericNumericDescriptor(GenericDescriptorBase):
+ """Base descriptor that constrains values to numbers."""
+
_value_type = DataTypes.NUMERIC
def __init__(
self,
*,
units: str = '',
- **kwargs: Any,
+ **kwargs: object,
) -> None:
super().__init__(**kwargs)
self._units: str = units
def __str__(self) -> str:
+ """Return the string representation including units."""
s: str = super().__str__()
s = s[1:-1] # strip <>
if self.units:
@@ -252,7 +255,8 @@ def units(self) -> str:
class GenericParameter(GenericNumericDescriptor):
- """Numeric descriptor extended with fitting-related attributes.
+ """
+ Numeric descriptor extended with fitting-related attributes.
Adds standard attributes used by minimizers: "free" flag,
uncertainty, bounds and an optional starting value. Subclasses can
@@ -261,8 +265,8 @@ class GenericParameter(GenericNumericDescriptor):
def __init__(
self,
- **kwargs: Any,
- ):
+ **kwargs: object,
+ ) -> None:
super().__init__(**kwargs)
# Initial validated states
@@ -287,6 +291,7 @@ def __init__(
UidMapHandler.get().add_to_uid_map(self)
def __str__(self) -> str:
+ """Return string representation with uncertainty and free."""
s = GenericDescriptorBase.__str__(self)
s = s[1:-1] # strip <>
if self.uncertainty is not None:
@@ -302,23 +307,24 @@ def _generate_uid(length: int = 16) -> str:
return ''.join(secrets.choice(letters) for _ in range(length))
@property
- def uid(self):
+ def uid(self) -> str:
"""Stable random identifier for this descriptor."""
return self._uid
@property
- def _minimizer_uid(self):
+ def _minimizer_uid(self) -> str:
"""Variant of uid that is safe for minimizer engines."""
# return self.unique_name.replace('.', '__')
return self.uid
@property
- def constrained(self):
+ def constrained(self) -> bool:
"""Whether this parameter is part of a constraint expression."""
return self._constrained
- def _set_value_constrained(self, v) -> None:
- """Set the value from a constraint expression.
+ def _set_value_constrained(self, v: object) -> None:
+ """
+ Set the value from a constraint expression.
Validates against the spec, marks the parent datablock dirty,
and flags the parameter as constrained. Used exclusively by
@@ -328,50 +334,48 @@ def _set_value_constrained(self, v) -> None:
self._constrained = True
@property
- def free(self):
+ def free(self) -> bool:
"""Whether this parameter is currently varied during fitting."""
return self._free
@free.setter
- def free(self, v):
+ def free(self, v: bool) -> None:
"""Set the "free" flag after validation."""
self._free = self._free_spec.validated(
v, name=f'{self.unique_name}.free', current=self._free
)
@property
- def uncertainty(self):
- """Estimated standard uncertainty of the fitted value, if
- available.
- """
+ def uncertainty(self) -> float | None:
+ """Estimated standard uncertainty of the fitted value."""
return self._uncertainty
@uncertainty.setter
- def uncertainty(self, v):
+ def uncertainty(self, v: float | None) -> None:
"""Set the uncertainty value (must be non-negative or None)."""
self._uncertainty = self._uncertainty_spec.validated(
v, name=f'{self.unique_name}.uncertainty', current=self._uncertainty
)
@property
- def fit_min(self):
+ def fit_min(self) -> float:
"""Lower fitting bound."""
return self._fit_min
@fit_min.setter
- def fit_min(self, v):
+ def fit_min(self, v: float) -> None:
"""Set the lower bound for the parameter value."""
self._fit_min = self._fit_min_spec.validated(
v, name=f'{self.unique_name}.fit_min', current=self._fit_min
)
@property
- def fit_max(self):
+ def fit_max(self) -> float:
"""Upper fitting bound."""
return self._fit_max
@fit_max.setter
- def fit_max(self, v):
+ def fit_max(self, v: float) -> None:
"""Set the upper bound for the parameter value."""
self._fit_max = self._fit_max_spec.validated(
v, name=f'{self.unique_name}.fit_max', current=self._fit_max
@@ -382,17 +386,23 @@ def fit_max(self, v):
class StringDescriptor(GenericStringDescriptor):
+ """String descriptor bound to a CIF handler."""
+
def __init__(
self,
*,
cif_handler: CifHandler,
- **kwargs: Any,
+ **kwargs: object,
) -> None:
- """String descriptor bound to a CIF handler.
-
- Args:
- cif_handler: Object that tracks CIF identifiers.
- **kwargs: Forwarded to GenericStringDescriptor.
+ """
+ Initialize a string descriptor bound to a CIF handler.
+
+ Parameters
+ ----------
+ cif_handler : CifHandler
+ Object that tracks CIF identifiers.
+ **kwargs : object
+ Forwarded to GenericStringDescriptor.
"""
super().__init__(**kwargs)
self._cif_handler = cif_handler
@@ -403,17 +413,23 @@ def __init__(
class NumericDescriptor(GenericNumericDescriptor):
+ """Numeric descriptor bound to a CIF handler."""
+
def __init__(
self,
*,
cif_handler: CifHandler,
- **kwargs: Any,
+ **kwargs: object,
) -> None:
- """Numeric descriptor bound to a CIF handler.
-
- Args:
- cif_handler: Object that tracks CIF identifiers.
- **kwargs: Forwarded to GenericNumericDescriptor.
+ """
+ Numeric descriptor bound to a CIF handler.
+
+ Parameters
+ ----------
+ cif_handler : CifHandler
+ Object that tracks CIF identifiers.
+ **kwargs : object
+ Forwarded to GenericNumericDescriptor.
"""
super().__init__(**kwargs)
self._cif_handler = cif_handler
@@ -424,17 +440,23 @@ def __init__(
class Parameter(GenericParameter):
+ """Fittable parameter bound to a CIF handler."""
+
def __init__(
self,
*,
cif_handler: CifHandler,
- **kwargs: Any,
+ **kwargs: object,
) -> None:
- """Fittable parameter bound to a CIF handler.
-
- Args:
- cif_handler: Object that tracks CIF identifiers.
- **kwargs: Forwarded to GenericParameter.
+ """
+ Fittable parameter bound to a CIF handler.
+
+ Parameters
+ ----------
+ cif_handler : CifHandler
+ Object that tracks CIF identifiers.
+ **kwargs : object
+ Forwarded to GenericParameter.
"""
super().__init__(**kwargs)
self._cif_handler = cif_handler
diff --git a/src/easydiffraction/crystallography/__init__.py b/src/easydiffraction/crystallography/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/crystallography/__init__.py
+++ b/src/easydiffraction/crystallography/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/crystallography/crystallography.py b/src/easydiffraction/crystallography/crystallography.py
index c7ff6203..bc90383f 100644
--- a/src/easydiffraction/crystallography/crystallography.py
+++ b/src/easydiffraction/crystallography/crystallography.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from typing import Any
@@ -21,14 +21,19 @@ def apply_cell_symmetry_constraints(
cell: Dict[str, float],
name_hm: str,
) -> Dict[str, float]:
- """Apply symmetry constraints to unit cell parameters based on space
- group.
-
- Args:
- cell: Dictionary containing lattice parameters.
- name_hm: Hermann-Mauguin symbol of the space group.
-
- Returns:
+ """
+ Apply symmetry constraints to unit cell parameters.
+
+ Parameters
+ ----------
+ cell : Dict[str, float]
+ Dictionary containing lattice parameters.
+ name_hm : str
+ Hermann-Mauguin symbol of the space group.
+
+ Returns
+ -------
+ Dict[str, float]
The cell dictionary with applied symmetry constraints.
"""
it_number = get_it_number_by_name_hm_short(name_hm)
@@ -90,16 +95,23 @@ def apply_atom_site_symmetry_constraints(
coord_code: int,
wyckoff_letter: str,
) -> Dict[str, Any]:
- """Apply symmetry constraints to atomic coordinates based on site
- symmetry.
-
- Args:
- atom_site: Dictionary containing atom position data.
- name_hm: Hermann-Mauguin symbol of the space group.
- coord_code: Coordinate system code.
- wyckoff_letter: Wyckoff position letter.
-
- Returns:
+ """
+ Apply symmetry constraints to atom site coordinates.
+
+ Parameters
+ ----------
+ atom_site : Dict[str, Any]
+ Dictionary containing atom position data.
+ name_hm : str
+ Hermann-Mauguin symbol of the space group.
+ coord_code : int
+ Coordinate system code.
+ wyckoff_letter : str
+ Wyckoff position letter.
+
+ Returns
+ -------
+ Dict[str, Any]
The atom_site dictionary with applied symmetry constraints.
"""
it_number = get_it_number_by_name_hm_short(name_hm)
diff --git a/src/easydiffraction/crystallography/space_groups.py b/src/easydiffraction/crystallography/space_groups.py
index 114b3467..4047b8c5 100644
--- a/src/easydiffraction/crystallography/space_groups.py
+++ b/src/easydiffraction/crystallography/space_groups.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Space group reference data.
+"""
+Space group reference data.
Loads a gzipped, packaged pickle with crystallographic space-group
information. The file is part of the distribution; user input is not
@@ -10,11 +11,11 @@
import gzip
import pickle # noqa: S403 - trusted internal pickle file (package data only)
from pathlib import Path
-from typing import Any
-def _restricted_pickle_load(file_obj) -> Any:
- """Load pickle data from an internal gz file (trusted boundary).
+def _restricted_pickle_load(file_obj: object) -> object:
+ """
+ Load pickle data from an internal gz file (trusted boundary).
The archive lives in the package; no user-controlled input enters
this function. If distribution process changes, revisit.
@@ -23,7 +24,7 @@ def _restricted_pickle_load(file_obj) -> Any:
return data
-def _load():
+def _load() -> object:
"""Load space-group data from the packaged archive."""
path = Path(__file__).with_name('space_groups.pkl.gz')
with gzip.open(path, 'rb') as f:
diff --git a/src/easydiffraction/datablocks/__init__.py b/src/easydiffraction/datablocks/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/datablocks/__init__.py
+++ b/src/easydiffraction/datablocks/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/datablocks/experiment/__init__.py b/src/easydiffraction/datablocks/experiment/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/datablocks/experiment/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/datablocks/experiment/categories/__init__.py b/src/easydiffraction/datablocks/experiment/categories/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/datablocks/experiment/categories/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/datablocks/experiment/categories/background/__init__.py b/src/easydiffraction/datablocks/experiment/categories/background/__init__.py
index b7b3b47d..7ffe8f22 100644
--- a/src/easydiffraction/datablocks/experiment/categories/background/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/background/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.background.chebyshev import (
diff --git a/src/easydiffraction/datablocks/experiment/categories/background/base.py b/src/easydiffraction/datablocks/experiment/categories/background/base.py
index 78cc5ef1..913cb764 100644
--- a/src/easydiffraction/datablocks/experiment/categories/background/base.py
+++ b/src/easydiffraction/datablocks/experiment/categories/background/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -9,7 +9,8 @@
class BackgroundBase(CategoryCollection):
- """Abstract base for background subcategories in experiments.
+ """
+ Abstract base for background subcategories in experiments.
Concrete implementations provide parameterized background models and
compute background intensities on the experiment grid.
diff --git a/src/easydiffraction/datablocks/experiment/categories/background/chebyshev.py b/src/easydiffraction/datablocks/experiment/categories/background/chebyshev.py
index 4a6a714d..098c4268 100644
--- a/src/easydiffraction/datablocks/experiment/categories/background/chebyshev.py
+++ b/src/easydiffraction/datablocks/experiment/categories/background/chebyshev.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Chebyshev polynomial background model.
+"""
+Chebyshev polynomial background model.
Provides a collection of polynomial terms and evaluation helpers.
"""
@@ -34,7 +35,8 @@
class PolynomialTerm(CategoryItem):
- """Chebyshev polynomial term.
+ """
+ Chebyshev polynomial term.
New public attribute names: ``order`` and ``coef`` replacing the
longer ``chebyshev_order`` / ``chebyshev_coef``. Backward-compatible
@@ -47,7 +49,7 @@ def __init__(self) -> None:
self._id = StringDescriptor(
name='id',
- description='Identifier for this background polynomial term.',
+ description='Identifier for this background polynomial term',
value_spec=AttributeSpec(
default='0',
# TODO: the following pattern is valid for dict key
@@ -84,32 +86,54 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
@property
- def id(self):
+ def id(self) -> StringDescriptor:
+ """
+ Identifier for this background polynomial term.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._id
@id.setter
- def id(self, value):
+ def id(self, value: str) -> None:
self._id.value = value
@property
- def order(self):
+ def order(self) -> NumericDescriptor:
+ """
+ Order used in a Chebyshev polynomial background term.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._order
@order.setter
- def order(self, value):
+ def order(self, value: float) -> None:
self._order.value = value
@property
- def coef(self):
+ def coef(self) -> Parameter:
+ """
+ Coefficient used in a Chebyshev polynomial background term.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._coef
@coef.setter
- def coef(self, value):
+ def coef(self, value: float) -> None:
self._coef.value = value
@BackgroundFactory.register
class ChebyshevPolynomialBackground(BackgroundBase):
+ """Chebyshev polynomial background model."""
+
type_info = TypeInfo(
tag='chebyshev',
description='Chebyshev polynomial background',
@@ -127,10 +151,10 @@ class ChebyshevPolynomialBackground(BackgroundBase):
}),
)
- def __init__(self):
+ def __init__(self) -> None:
super().__init__(item_type=PolynomialTerm)
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
"""Evaluate polynomial background over x data."""
del called_by_minimizer
diff --git a/src/easydiffraction/datablocks/experiment/categories/background/enums.py b/src/easydiffraction/datablocks/experiment/categories/background/enums.py
index 2356702a..9e78effc 100644
--- a/src/easydiffraction/datablocks/experiment/categories/background/enums.py
+++ b/src/easydiffraction/datablocks/experiment/categories/background/enums.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Enumerations for background model types."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/background/factory.py b/src/easydiffraction/datablocks/experiment/categories/background/factory.py
index c52b7dd7..c4d300c8 100644
--- a/src/easydiffraction/datablocks/experiment/categories/background/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/background/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Background factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/background/line_segment.py b/src/easydiffraction/datablocks/experiment/categories/background/line_segment.py
index 822f6e0d..2f0a5496 100644
--- a/src/easydiffraction/datablocks/experiment/categories/background/line_segment.py
+++ b/src/easydiffraction/datablocks/experiment/categories/background/line_segment.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Line-segment background model.
+"""
+Line-segment background model.
Interpolate user-specified points to form a background curve.
"""
@@ -40,7 +41,7 @@ def __init__(self) -> None:
self._id = StringDescriptor(
name='id',
- description='Identifier for this background line segment.',
+ description='Identifier for this background line segment',
value_spec=AttributeSpec(
default='0',
# TODO: the following pattern is valid for dict key
@@ -52,10 +53,7 @@ def __init__(self) -> None:
)
self._x = NumericDescriptor(
name='x',
- description=(
- 'X-coordinates used to create many straight-line segments '
- 'representing the background in a calculated diffractogram.'
- ),
+ description='X-coordinates used to create many straight-line segments',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(),
@@ -69,10 +67,7 @@ def __init__(self) -> None:
)
self._y = Parameter(
name='y', # TODO: rename to intensity
- description=(
- 'Intensity used to create many straight-line segments '
- 'representing the background in a calculated diffractogram'
- ),
+ description='Intensity used to create many straight-line segments',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(),
@@ -93,32 +88,54 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
@property
- def id(self):
+ def id(self) -> StringDescriptor:
+ """
+ Identifier for this background line segment.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._id
@id.setter
- def id(self, value):
+ def id(self, value: str) -> None:
self._id.value = value
@property
- def x(self):
+ def x(self) -> NumericDescriptor:
+ """
+ X-coordinates used to create many straight-line segments.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._x
@x.setter
- def x(self, value):
+ def x(self, value: float) -> None:
self._x.value = value
@property
- def y(self):
+ def y(self) -> Parameter:
+ """
+ Intensity used to create many straight-line segments.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._y
@y.setter
- def y(self, value):
+ def y(self, value: float) -> None:
self._y.value = value
@BackgroundFactory.register
class LineSegmentBackground(BackgroundBase):
+ """Linear-interpolation background between user-defined points."""
+
type_info = TypeInfo(
tag='line-segment',
description='Linear interpolation between points',
@@ -130,10 +147,10 @@ class LineSegmentBackground(BackgroundBase):
calculators=frozenset({CalculatorEnum.CRYSPY, CalculatorEnum.CRYSFML}),
)
- def __init__(self):
+ def __init__(self) -> None:
super().__init__(item_type=LineSegment)
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
"""Interpolate background points over x data."""
del called_by_minimizer
diff --git a/src/easydiffraction/datablocks/experiment/categories/data/__init__.py b/src/easydiffraction/datablocks/experiment/categories/data/__init__.py
index c228ecd8..3599f3b5 100644
--- a/src/easydiffraction/datablocks/experiment/categories/data/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/data/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.data.bragg_pd import PdCwlData
diff --git a/src/easydiffraction/datablocks/experiment/categories/data/bragg_pd.py b/src/easydiffraction/datablocks/experiment/categories/data/bragg_pd.py
index 73402d30..883f7f80 100644
--- a/src/easydiffraction/datablocks/experiment/categories/data/bragg_pd.py
+++ b/src/easydiffraction/datablocks/experiment/categories/data/bragg_pd.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -29,12 +29,12 @@
class PdDataPointBaseMixin:
"""Single base data point mixin for powder diffraction data."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._point_id = StringDescriptor(
name='point_id',
- description='Identifier for this data point in the dataset.',
+ description='Identifier for this data point in the dataset',
value_spec=AttributeSpec(
default='0',
# TODO: the following pattern is valid for dict key
@@ -50,7 +50,7 @@ def __init__(self):
)
self._d_spacing = NumericDescriptor(
name='d_spacing',
- description='d-spacing value corresponding to this data point.',
+ description='d-spacing value corresponding to this data point',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(ge=0),
@@ -59,7 +59,7 @@ def __init__(self):
)
self._intensity_meas = NumericDescriptor(
name='intensity_meas',
- description='Intensity recorded at each measurement point as a function of angle/time',
+ description='Intensity recorded at each measurement point (angle/time)',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(ge=0),
@@ -73,7 +73,7 @@ def __init__(self):
)
self._intensity_meas_su = NumericDescriptor(
name='intensity_meas_su',
- description='Standard uncertainty of the measured intensity at this data point.',
+ description='Standard uncertainty of the measured intensity at this point',
value_spec=AttributeSpec(
default=1.0,
validator=RangeValidator(ge=0),
@@ -87,7 +87,7 @@ def __init__(self):
)
self._intensity_calc = NumericDescriptor(
name='intensity_calc',
- description='Intensity value for a computed diffractogram at this data point.',
+ description='Intensity of a computed diffractogram at this point',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(ge=0),
@@ -96,7 +96,7 @@ def __init__(self):
)
self._intensity_bkg = NumericDescriptor(
name='intensity_bkg',
- description='Intensity value for a computed background at this data point.',
+ description='Intensity of a computed background at this point',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(ge=0),
@@ -105,7 +105,7 @@ def __init__(self):
)
self._calc_status = StringDescriptor(
name='calc_status',
- description='Status code of the data point in the calculation process.',
+ description='Status code of the data point in the calculation process',
value_spec=AttributeSpec(
default='incl', # TODO: Make Enum
validator=MembershipValidator(allowed=['incl', 'excl']),
@@ -123,39 +123,79 @@ def __init__(self):
@property
def point_id(self) -> StringDescriptor:
+ """
+ Identifier for this data point in the dataset.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._point_id
@property
def d_spacing(self) -> NumericDescriptor:
+ """
+ d-spacing value corresponding to this data point.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._d_spacing
@property
def intensity_meas(self) -> NumericDescriptor:
+ """
+ Intensity recorded at each measurement point (angle/time).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._intensity_meas
@property
def intensity_meas_su(self) -> NumericDescriptor:
+ """
+ Standard uncertainty of the measured intensity at this point.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._intensity_meas_su
@property
def intensity_calc(self) -> NumericDescriptor:
+ """
+ Intensity of a computed diffractogram at this point.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._intensity_calc
@property
def intensity_bkg(self) -> NumericDescriptor:
+ """
+ Intensity of a computed background at this point.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._intensity_bkg
@property
def calc_status(self) -> StringDescriptor:
+ """
+ Status code of the data point in the calculation process.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._calc_status
class PdCwlDataPointMixin:
- """Mixin for powder diffraction data points with constant
- wavelength.
- """
+ """Mixin for CWL powder diffraction data points."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._two_theta = NumericDescriptor(
@@ -179,14 +219,20 @@ def __init__(self):
# ------------------------------------------------------------------
@property
- def two_theta(self):
+ def two_theta(self) -> NumericDescriptor:
+ """
+ Measured 2θ diffraction angle (deg).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._two_theta
class PdTofDataPointMixin:
"""Mixin for powder diffraction data points with time-of-flight."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._time_of_flight = NumericDescriptor(
@@ -205,7 +251,13 @@ def __init__(self):
# ------------------------------------------------------------------
@property
- def time_of_flight(self):
+ def time_of_flight(self) -> NumericDescriptor:
+ """
+ Measured time for time-of-flight neutron measurement (µs).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._time_of_flight
@@ -222,9 +274,7 @@ class PdCwlDataPoint(
# But also says, that in fact, it is just for consistency. And both
# orders work.
):
- """Powder diffraction data point for constant-wavelength
- experiments.
- """
+ """Powder diffraction data point for CWL experiments."""
def __init__(self) -> None:
super().__init__()
@@ -246,6 +296,8 @@ def __init__(self) -> None:
class PdDataBase(CategoryCollection):
+ """Base class for powder diffraction data collections."""
+
# TODO: ???
# Redefine update priority to ensure data updated after other
@@ -260,42 +312,40 @@ class PdDataBase(CategoryCollection):
# Should be set only once
- def _set_point_id(self, values) -> None:
- """Helper method to set point IDs."""
+ def _set_point_id(self, values: object) -> None:
+ """Set point IDs."""
for p, v in zip(self._items, values, strict=True):
p.point_id._value = v
- def _set_intensity_meas(self, values) -> None:
- """Helper method to set measured intensity."""
+ def _set_intensity_meas(self, values: object) -> None:
+ """Set measured intensity."""
for p, v in zip(self._items, values, strict=True):
p.intensity_meas._value = v
- def _set_intensity_meas_su(self, values) -> None:
- """Helper method to set standard uncertainty of measured
- intensity.
- """
+ def _set_intensity_meas_su(self, values: object) -> None:
+ """Set standard uncertainty of measured intensity values."""
for p, v in zip(self._items, values, strict=True):
p.intensity_meas_su._value = v
# Can be set multiple times
- def _set_d_spacing(self, values) -> None:
- """Helper method to set d-spacing values."""
+ def _set_d_spacing(self, values: object) -> None:
+ """Set d-spacing values."""
for p, v in zip(self._calc_items, values, strict=True):
p.d_spacing._value = v
- def _set_intensity_calc(self, values) -> None:
- """Helper method to set calculated intensity."""
+ def _set_intensity_calc(self, values: object) -> None:
+ """Set calculated intensity."""
for p, v in zip(self._calc_items, values, strict=True):
p.intensity_calc._value = v
- def _set_intensity_bkg(self, values) -> None:
- """Helper method to set background intensity."""
+ def _set_intensity_bkg(self, values: object) -> None:
+ """Set background intensity."""
for p, v in zip(self._calc_items, values, strict=True):
p.intensity_bkg._value = v
- def _set_calc_status(self, values) -> None:
- """Helper method to set refinement status."""
+ def _set_calc_status(self, values: object) -> None:
+ """Set refinement status."""
for p, v in zip(self._items, values, strict=True):
if v:
p.calc_status._value = 'incl'
@@ -311,13 +361,13 @@ def _calc_mask(self) -> np.ndarray:
return self.calc_status == 'incl'
@property
- def _calc_items(self):
+ def _calc_items(self) -> list:
"""Get only the items included in calculations."""
return [item for item, mask in zip(self._items, self._calc_mask, strict=False) if mask]
# Misc
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
experiment = self._parent
experiments = experiment._parent
project = experiments._parent
@@ -353,6 +403,7 @@ def _update(self, called_by_minimizer=False):
@property
def calc_status(self) -> np.ndarray:
+ """Refinement-status flags for each data point as an array."""
return np.fromiter(
(p.calc_status.value for p in self._items),
dtype=object, # TODO: needed? DataTypes.NUMERIC?
@@ -360,6 +411,7 @@ def calc_status(self) -> np.ndarray:
@property
def d_spacing(self) -> np.ndarray:
+ """D-spacing values for active (non-excluded) data points."""
return np.fromiter(
(p.d_spacing.value for p in self._calc_items),
dtype=float, # TODO: needed? DataTypes.NUMERIC?
@@ -367,6 +419,7 @@ def d_spacing(self) -> np.ndarray:
@property
def intensity_meas(self) -> np.ndarray:
+ """Measured intensities for active data points."""
return np.fromiter(
(p.intensity_meas.value for p in self._calc_items),
dtype=float, # TODO: needed? DataTypes.NUMERIC?
@@ -374,6 +427,12 @@ def intensity_meas(self) -> np.ndarray:
@property
def intensity_meas_su(self) -> np.ndarray:
+ """
+ Standard uncertainties of the measured intensities.
+
+ Values smaller than 0.0001 are replaced with 1.0 to prevent
+ fitting failures.
+ """
# TODO: The following is a temporary workaround to handle zero
# or near-zero uncertainties in the data, when dats is loaded
# from CIF files. This is necessary because zero uncertainties
@@ -396,6 +455,7 @@ def intensity_meas_su(self) -> np.ndarray:
@property
def intensity_calc(self) -> np.ndarray:
+ """Calculated intensities for active data points."""
return np.fromiter(
(p.intensity_calc.value for p in self._calc_items),
dtype=float, # TODO: needed? DataTypes.NUMERIC?
@@ -403,6 +463,7 @@ def intensity_calc(self) -> np.ndarray:
@property
def intensity_bkg(self) -> np.ndarray:
+ """Background intensities for active data points."""
return np.fromiter(
(p.intensity_bkg.value for p in self._calc_items),
dtype=float, # TODO: needed? DataTypes.NUMERIC?
@@ -411,6 +472,8 @@ def intensity_bkg(self) -> np.ndarray:
@DataFactory.register
class PdCwlData(PdDataBase):
+ """Bragg powder CWL data collection."""
+
# TODO: ???
# _description: str = 'Powder diffraction data points for
# constant-wavelength experiments.'
@@ -424,7 +487,7 @@ class PdCwlData(PdDataBase):
calculators=frozenset({CalculatorEnum.CRYSPY}),
)
- def __init__(self):
+ def __init__(self) -> None:
super().__init__(item_type=PdCwlDataPoint)
#################
@@ -433,8 +496,8 @@ def __init__(self):
# Should be set only once
- def _create_items_set_xcoord_and_id(self, values) -> None:
- """Helper method to set 2θ values."""
+ def _create_items_set_xcoord_and_id(self, values: object) -> None:
+ """Set 2θ values."""
# TODO: split into multiple methods
# Create items
@@ -449,7 +512,7 @@ def _create_items_set_xcoord_and_id(self, values) -> None:
# Misc
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
super()._update(called_by_minimizer)
experiment = self._parent
@@ -465,9 +528,7 @@ def _update(self, called_by_minimizer=False):
@property
def two_theta(self) -> np.ndarray:
- """Get the 2θ values for data points included in
- calculations.
- """
+ """Get 2θ values for data points included in calculations."""
return np.fromiter(
(p.two_theta.value for p in self._calc_items),
dtype=float, # TODO: needed? DataTypes.NUMERIC?
@@ -489,6 +550,8 @@ def unfiltered_x(self) -> np.ndarray:
@DataFactory.register
class PdTofData(PdDataBase):
+ """Bragg powder TOF data collection."""
+
type_info = TypeInfo(tag='bragg-pd-tof', description='Bragg powder TOF data')
compatibility = Compatibility(
sample_form=frozenset({SampleFormEnum.POWDER}),
@@ -499,7 +562,7 @@ class PdTofData(PdDataBase):
calculators=frozenset({CalculatorEnum.CRYSPY, CalculatorEnum.CRYSFML}),
)
- def __init__(self):
+ def __init__(self) -> None:
super().__init__(item_type=PdTofDataPoint)
#################
@@ -508,8 +571,8 @@ def __init__(self):
# Should be set only once
- def _create_items_set_xcoord_and_id(self, values) -> None:
- """Helper method to set time-of-flight values."""
+ def _create_items_set_xcoord_and_id(self, values: object) -> None:
+ """Set time-of-flight values."""
# TODO: split into multiple methods
# Create items
@@ -524,7 +587,7 @@ def _create_items_set_xcoord_and_id(self, values) -> None:
# Misc
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
super()._update(called_by_minimizer)
experiment = self._parent
@@ -542,9 +605,7 @@ def _update(self, called_by_minimizer=False):
@property
def time_of_flight(self) -> np.ndarray:
- """Get the TOF values for data points included in
- calculations.
- """
+ """Get TOF values for data points included in calculations."""
return np.fromiter(
(p.time_of_flight.value for p in self._calc_items),
dtype=float, # TODO: needed? DataTypes.NUMERIC?
diff --git a/src/easydiffraction/datablocks/experiment/categories/data/bragg_sc.py b/src/easydiffraction/datablocks/experiment/categories/data/bragg_sc.py
index 39552b63..d19eb75f 100644
--- a/src/easydiffraction/datablocks/experiment/categories/data/bragg_sc.py
+++ b/src/easydiffraction/datablocks/experiment/categories/data/bragg_sc.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -26,16 +26,14 @@
class Refln(CategoryItem):
- """Single reflection for single crystal diffraction data
- category.
- """
+ """Single reflection for single-crystal diffraction data."""
def __init__(self) -> None:
super().__init__()
self._id = StringDescriptor(
name='id',
- description='Identifier of the reflection.',
+ description='Identifier of the reflection',
value_spec=AttributeSpec(
default='0',
# TODO: the following pattern is valid for dict key
@@ -47,7 +45,7 @@ def __init__(self) -> None:
)
self._d_spacing = NumericDescriptor(
name='d_spacing',
- description='The distance between lattice planes in the crystal for this reflection.',
+ description='Distance between lattice planes for this reflection',
units='Å',
value_spec=AttributeSpec(
default=0.0,
@@ -57,7 +55,7 @@ def __init__(self) -> None:
)
self._sin_theta_over_lambda = NumericDescriptor(
name='sin_theta_over_lambda',
- description='The sin(θ)/λ value for this reflection.',
+ description='The sin(θ)/λ value for this reflection',
units='Å⁻¹',
value_spec=AttributeSpec(
default=0.0,
@@ -67,7 +65,7 @@ def __init__(self) -> None:
)
self._index_h = NumericDescriptor(
name='index_h',
- description='Miller index h of a measured reflection.',
+ description='Miller index h of a measured reflection',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(),
@@ -76,7 +74,7 @@ def __init__(self) -> None:
)
self._index_k = NumericDescriptor(
name='index_k',
- description='Miller index k of a measured reflection.',
+ description='Miller index k of a measured reflection',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(),
@@ -85,7 +83,7 @@ def __init__(self) -> None:
)
self._index_l = NumericDescriptor(
name='index_l',
- description='Miller index l of a measured reflection.',
+ description='Miller index l of a measured reflection',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(),
@@ -112,7 +110,7 @@ def __init__(self) -> None:
)
self._intensity_calc = NumericDescriptor(
name='intensity_calc',
- description='The intensity of the reflection calculated from the atom site data.',
+ description='Intensity of the reflection calculated from atom site data',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(ge=0),
@@ -121,7 +119,7 @@ def __init__(self) -> None:
)
self._wavelength = NumericDescriptor(
name='wavelength',
- description='The mean wavelength of radiation used to measure this reflection.',
+ description='Mean wavelength of radiation for this reflection',
units='Å',
value_spec=AttributeSpec(
default=0.0,
@@ -139,42 +137,102 @@ def __init__(self) -> None:
@property
def id(self) -> StringDescriptor:
+ """
+ Identifier of the reflection.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._id
@property
def d_spacing(self) -> NumericDescriptor:
+ """
+ Distance between lattice planes for this reflection (Å).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._d_spacing
@property
def sin_theta_over_lambda(self) -> NumericDescriptor:
+ """
+ The sin(θ)/λ value for this reflection (Å⁻¹).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._sin_theta_over_lambda
@property
def index_h(self) -> NumericDescriptor:
+ """
+ Miller index h of a measured reflection.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._index_h
@property
def index_k(self) -> NumericDescriptor:
+ """
+ Miller index k of a measured reflection.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._index_k
@property
def index_l(self) -> NumericDescriptor:
+ """
+ Miller index l of a measured reflection.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._index_l
@property
def intensity_meas(self) -> NumericDescriptor:
+ """
+ The intensity of the reflection derived from the measurements.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._intensity_meas
@property
def intensity_meas_su(self) -> NumericDescriptor:
+ """
+ Standard uncertainty of the measured intensity.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._intensity_meas_su
@property
def intensity_calc(self) -> NumericDescriptor:
+ """
+ Intensity of the reflection calculated from atom site data.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._intensity_calc
@property
def wavelength(self) -> NumericDescriptor:
+ """
+ Mean wavelength of radiation for this reflection (Å).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._wavelength
@@ -194,7 +252,7 @@ class ReflnData(CategoryCollection):
_update_priority = 100
- def __init__(self):
+ def __init__(self) -> None:
super().__init__(item_type=Refln)
#################
@@ -203,8 +261,13 @@ def __init__(self):
# Should be set only once
- def _create_items_set_hkl_and_id(self, indices_h, indices_k, indices_l) -> None:
- """Helper method to set Miller indices."""
+ def _create_items_set_hkl_and_id(
+ self,
+ indices_h: object,
+ indices_k: object,
+ indices_l: object,
+ ) -> None:
+ """Set Miller indices."""
# TODO: split into multiple methods
# Create items
@@ -221,48 +284,46 @@ def _create_items_set_hkl_and_id(self, indices_h, indices_k, indices_l) -> None:
# Set reflection IDs
self._set_id([str(i + 1) for i in range(indices_h.size)])
- def _set_id(self, values) -> None:
- """Helper method to set reflection IDs."""
+ def _set_id(self, values: object) -> None:
+ """Set reflection IDs."""
for p, v in zip(self._items, values, strict=True):
p.id._value = v
- def _set_intensity_meas(self, values) -> None:
- """Helper method to set measured intensity."""
+ def _set_intensity_meas(self, values: object) -> None:
+ """Set measured intensity."""
for p, v in zip(self._items, values, strict=True):
p.intensity_meas._value = v
- def _set_intensity_meas_su(self, values) -> None:
- """Helper method to set standard uncertainty of measured
- intensity.
- """
+ def _set_intensity_meas_su(self, values: object) -> None:
+ """Set standard uncertainty of measured intensity values."""
for p, v in zip(self._items, values, strict=True):
p.intensity_meas_su._value = v
- def _set_wavelength(self, values) -> None:
- """Helper method to set wavelength."""
+ def _set_wavelength(self, values: object) -> None:
+ """Set wavelength."""
for p, v in zip(self._items, values, strict=True):
p.wavelength._value = v
# Can be set multiple times
- def _set_d_spacing(self, values) -> None:
- """Helper method to set d-spacing values."""
+ def _set_d_spacing(self, values: object) -> None:
+ """Set d-spacing values."""
for p, v in zip(self._items, values, strict=True):
p.d_spacing._value = v
- def _set_sin_theta_over_lambda(self, values) -> None:
- """Helper method to set sin(theta)/lambda values."""
+ def _set_sin_theta_over_lambda(self, values: object) -> None:
+ """Set sin(theta)/lambda values."""
for p, v in zip(self._items, values, strict=True):
p.sin_theta_over_lambda._value = v
- def _set_intensity_calc(self, values) -> None:
- """Helper method to set calculated intensity."""
+ def _set_intensity_calc(self, values: object) -> None:
+ """Set calculated intensity."""
for p, v in zip(self._items, values, strict=True):
p.intensity_calc._value = v
# Misc
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
experiment = self._parent
experiments = experiment._parent
project = experiments._parent
@@ -302,63 +363,72 @@ def _update(self, called_by_minimizer=False):
@property
def d_spacing(self) -> np.ndarray:
+ """D-spacing values for all reflection data points."""
return np.fromiter(
(p.d_spacing.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def sin_theta_over_lambda(self) -> np.ndarray:
+ """sinθ/λ values for all reflection data points."""
return np.fromiter(
(p.sin_theta_over_lambda.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def index_h(self) -> np.ndarray:
+ """Miller h indices for all reflection data points."""
return np.fromiter(
(p.index_h.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def index_k(self) -> np.ndarray:
+ """Miller k indices for all reflection data points."""
return np.fromiter(
(p.index_k.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def index_l(self) -> np.ndarray:
+ """Miller l indices for all reflection data points."""
return np.fromiter(
(p.index_l.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def intensity_meas(self) -> np.ndarray:
+ """Measured structure-factor intensities for all reflections."""
return np.fromiter(
(p.intensity_meas.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def intensity_meas_su(self) -> np.ndarray:
+ """Standard uncertainties of the measured intensities."""
return np.fromiter(
(p.intensity_meas_su.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def intensity_calc(self) -> np.ndarray:
+ """Calculated intensities for all reflections."""
return np.fromiter(
(p.intensity_calc.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def wavelength(self) -> np.ndarray:
+ """Wavelengths associated with each reflection."""
return np.fromiter(
(p.wavelength.value for p in self._items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
diff --git a/src/easydiffraction/datablocks/experiment/categories/data/factory.py b/src/easydiffraction/datablocks/experiment/categories/data/factory.py
index 1ef25c0b..d8cdcf12 100644
--- a/src/easydiffraction/datablocks/experiment/categories/data/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/data/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Data collection factory — delegates to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/data/total_pd.py b/src/easydiffraction/datablocks/experiment/categories/data/total_pd.py
index 0aa63be5..c8d0aa9d 100644
--- a/src/easydiffraction/datablocks/experiment/categories/data/total_pd.py
+++ b/src/easydiffraction/datablocks/experiment/categories/data/total_pd.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Data categories for total scattering (PDF) experiments."""
@@ -26,7 +26,8 @@
class TotalDataPoint(CategoryItem):
- """Total scattering (PDF) data point in r-space (real space).
+ """
+ Total scattering (PDF) data point in r-space (real space).
Note: PDF data is always in r-space regardless of whether the
original measurement was CWL or TOF.
@@ -37,7 +38,7 @@ def __init__(self) -> None:
self._point_id = StringDescriptor(
name='point_id',
- description='Identifier for this data point in the dataset.',
+ description='Identifier for this data point in the dataset',
value_spec=AttributeSpec(
default='0',
validator=RegexValidator(pattern=r'^[A-Za-z0-9_]*$'),
@@ -50,7 +51,7 @@ def __init__(self) -> None:
)
self._r = NumericDescriptor(
name='r',
- description='Interatomic distance in real space.',
+ description='Interatomic distance in real space',
units='Å',
value_spec=AttributeSpec(
default=0.0,
@@ -64,7 +65,7 @@ def __init__(self) -> None:
)
self._g_r_meas = NumericDescriptor(
name='g_r_meas',
- description='Measured pair distribution function G(r).',
+ description='Measured pair distribution function G(r)',
value_spec=AttributeSpec(
default=0.0,
),
@@ -76,7 +77,7 @@ def __init__(self) -> None:
)
self._g_r_meas_su = NumericDescriptor(
name='g_r_meas_su',
- description='Standard uncertainty of measured G(r).',
+ description='Standard uncertainty of measured G(r)',
value_spec=AttributeSpec(
default=0.0,
validator=RangeValidator(ge=0),
@@ -89,7 +90,7 @@ def __init__(self) -> None:
)
self._g_r_calc = NumericDescriptor(
name='g_r_calc',
- description='Calculated pair distribution function G(r).',
+ description='Calculated pair distribution function G(r)',
value_spec=AttributeSpec(
default=0.0,
),
@@ -101,7 +102,7 @@ def __init__(self) -> None:
)
self._calc_status = StringDescriptor(
name='calc_status',
- description='Status code of the data point in calculation.',
+ description='Status code of the data point in calculation',
value_spec=AttributeSpec(
default='incl',
validator=MembershipValidator(allowed=['incl', 'excl']),
@@ -122,26 +123,62 @@ def __init__(self) -> None:
@property
def point_id(self) -> StringDescriptor:
+ """
+ Identifier for this data point in the dataset.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._point_id
@property
def r(self) -> NumericDescriptor:
+ """
+ Interatomic distance in real space (Å).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._r
@property
def g_r_meas(self) -> NumericDescriptor:
+ """
+ Measured pair distribution function G(r).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._g_r_meas
@property
def g_r_meas_su(self) -> NumericDescriptor:
+ """
+ Standard uncertainty of measured G(r).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._g_r_meas_su
@property
def g_r_calc(self) -> NumericDescriptor:
+ """
+ Calculated pair distribution function G(r).
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object.
+ """
return self._g_r_calc
@property
def calc_status(self) -> StringDescriptor:
+ """
+ Status code of the data point in calculation.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._calc_status
@@ -156,32 +193,30 @@ class TotalDataBase(CategoryCollection):
# Should be set only once
- def _set_point_id(self, values) -> None:
- """Helper method to set point IDs."""
+ def _set_point_id(self, values: object) -> None:
+ """Set point IDs."""
for p, v in zip(self._items, values, strict=True):
p.point_id._value = v
- def _set_g_r_meas(self, values) -> None:
- """Helper method to set measured G(r)."""
+ def _set_g_r_meas(self, values: object) -> None:
+ """Set measured G(r)."""
for p, v in zip(self._items, values, strict=True):
p.g_r_meas._value = v
- def _set_g_r_meas_su(self, values) -> None:
- """Helper method to set standard uncertainty of measured
- G(r).
- """
+ def _set_g_r_meas_su(self, values: object) -> None:
+ """Set standard uncertainty of measured G(r) values."""
for p, v in zip(self._items, values, strict=True):
p.g_r_meas_su._value = v
# Can be set multiple times
- def _set_g_r_calc(self, values) -> None:
- """Helper method to set calculated G(r)."""
+ def _set_g_r_calc(self, values: object) -> None:
+ """Set calculated G(r)."""
for p, v in zip(self._calc_items, values, strict=True):
p.g_r_calc._value = v
- def _set_calc_status(self, values) -> None:
- """Helper method to set calculation status."""
+ def _set_calc_status(self, values: object) -> None:
+ """Set calculation status."""
for p, v in zip(self._items, values, strict=True):
if v:
p.calc_status._value = 'incl'
@@ -197,13 +232,13 @@ def _calc_mask(self) -> np.ndarray:
return self.calc_status == 'incl'
@property
- def _calc_items(self):
+ def _calc_items(self) -> list:
"""Get only the items included in calculations."""
return [item for item, mask in zip(self._items, self._calc_mask, strict=False) if mask]
# Misc
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
experiment = self._parent
experiments = experiment._parent
project = experiments._parent
@@ -239,30 +274,34 @@ def _update(self, called_by_minimizer=False):
@property
def calc_status(self) -> np.ndarray:
+ """Refinement-status flags for each data point as an array."""
return np.fromiter(
(p.calc_status.value for p in self._items),
- dtype=object, # TODO: needed? DataTypes.NUMERIC?
+ dtype=object,
)
@property
def intensity_meas(self) -> np.ndarray:
+ """Measured G(r) values for active data points."""
return np.fromiter(
(p.g_r_meas.value for p in self._calc_items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def intensity_meas_su(self) -> np.ndarray:
+ """Standard uncertainties of the measured G(r) values."""
return np.fromiter(
(p.g_r_meas_su.value for p in self._calc_items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
def intensity_calc(self) -> np.ndarray:
+ """Calculated G(r) values for active data points."""
return np.fromiter(
(p.g_r_calc.value for p in self._calc_items),
- dtype=float, # TODO: needed? DataTypes.NUMERIC?
+ dtype=float,
)
@property
@@ -273,13 +312,17 @@ def intensity_bkg(self) -> np.ndarray:
@DataFactory.register
class TotalData(TotalDataBase):
- """Total scattering (PDF) data collection in r-space.
+ """
+ Total scattering (PDF) data collection in r-space.
- Note: Works for both CWL and TOF measurements as PDF data
- is always transformed to r-space.
+ Note: Works for both CWL and TOF measurements as PDF data is always
+ transformed to r-space.
"""
- type_info = TypeInfo(tag='total-pd', description='Total scattering (PDF) data')
+ type_info = TypeInfo(
+ tag='total-pd',
+ description='Total scattering (PDF) data',
+ )
compatibility = Compatibility(
sample_form=frozenset({SampleFormEnum.POWDER}),
scattering_type=frozenset({ScatteringTypeEnum.TOTAL}),
@@ -289,7 +332,7 @@ class TotalData(TotalDataBase):
calculators=frozenset({CalculatorEnum.PDFFIT}),
)
- def __init__(self):
+ def __init__(self) -> None:
super().__init__(item_type=TotalDataPoint)
#################
@@ -298,8 +341,8 @@ def __init__(self):
# Should be set only once
- def _create_items_set_xcoord_and_id(self, values) -> None:
- """Helper method to set r values."""
+ def _create_items_set_xcoord_and_id(self, values: object) -> None:
+ """Set r values."""
# TODO: split into multiple methods
# Create items
diff --git a/src/easydiffraction/datablocks/experiment/categories/excluded_regions/__init__.py b/src/easydiffraction/datablocks/experiment/categories/excluded_regions/__init__.py
index 3356f4cf..8d232629 100644
--- a/src/easydiffraction/datablocks/experiment/categories/excluded_regions/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/excluded_regions/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.excluded_regions.default import (
diff --git a/src/easydiffraction/datablocks/experiment/categories/excluded_regions/default.py b/src/easydiffraction/datablocks/experiment/categories/excluded_regions/default.py
index 2696f25c..fdf130c2 100644
--- a/src/easydiffraction/datablocks/experiment/categories/excluded_regions/default.py
+++ b/src/easydiffraction/datablocks/experiment/categories/excluded_regions/default.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Exclude ranges of x from fitting/plotting (masked regions)."""
@@ -29,13 +29,13 @@
class ExcludedRegion(CategoryItem):
"""Closed interval [start, end] to be excluded."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
# TODO: Add point_id as for the background
self._id = StringDescriptor(
name='id',
- description='Identifier for this excluded region.',
+ description='Identifier for this excluded region',
value_spec=AttributeSpec(
default='0',
# TODO: the following pattern is valid for dict key
@@ -71,33 +71,55 @@ def __init__(self):
# ------------------------------------------------------------------
@property
- def id(self):
+ def id(self) -> StringDescriptor:
+ """
+ Identifier for this excluded region.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._id
@id.setter
- def id(self, value):
+ def id(self, value: str) -> None:
self._id.value = value
@property
def start(self) -> NumericDescriptor:
+ """
+ Start of the excluded region.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._start
@start.setter
- def start(self, value: float):
+ def start(self, value: float) -> None:
self._start.value = value
@property
def end(self) -> NumericDescriptor:
+ """
+ End of the excluded region.
+
+ Reading this property returns the underlying
+ ``NumericDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._end
@end.setter
- def end(self, value: float):
+ def end(self, value: float) -> None:
self._end.value = value
@ExcludedRegionsFactory.register
class ExcludedRegions(CategoryCollection):
- """Collection of ExcludedRegion instances.
+ """
+ Collection of ExcludedRegion instances.
Excluded regions define closed intervals [start, end] on the x-axis
that are to be excluded from calculations and, as a result, from
@@ -112,10 +134,10 @@ class ExcludedRegions(CategoryCollection):
sample_form=frozenset({SampleFormEnum.POWDER}),
)
- def __init__(self):
+ def __init__(self) -> None:
super().__init__(item_type=ExcludedRegion)
- def _update(self, called_by_minimizer=False):
+ def _update(self, called_by_minimizer: bool = False) -> None:
del called_by_minimizer
data = self._parent.data
diff --git a/src/easydiffraction/datablocks/experiment/categories/excluded_regions/factory.py b/src/easydiffraction/datablocks/experiment/categories/excluded_regions/factory.py
index 789e25e7..e12fb0c0 100644
--- a/src/easydiffraction/datablocks/experiment/categories/excluded_regions/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/excluded_regions/factory.py
@@ -1,6 +1,8 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Excluded-regions factory — delegates entirely to ``FactoryBase``."""
+"""
+Excluded-regions factory — delegates entirely to ``FactoryBase``.
+"""
from __future__ import annotations
diff --git a/src/easydiffraction/datablocks/experiment/categories/experiment_type/__init__.py b/src/easydiffraction/datablocks/experiment/categories/experiment_type/__init__.py
index 63e6bb0b..197b5510 100644
--- a/src/easydiffraction/datablocks/experiment/categories/experiment_type/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/experiment_type/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.experiment_type.default import ExperimentType
diff --git a/src/easydiffraction/datablocks/experiment/categories/experiment_type/default.py b/src/easydiffraction/datablocks/experiment/categories/experiment_type/default.py
index 5221e444..1b9d3811 100644
--- a/src/easydiffraction/datablocks/experiment/categories/experiment_type/default.py
+++ b/src/easydiffraction/datablocks/experiment/categories/experiment_type/default.py
@@ -1,9 +1,10 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Experiment type descriptor (form, beam, probe, scattering).
+"""
+Experiment type descriptor (form, beam, probe, scattering).
-This lightweight container stores the categorical attributes defining
-an experiment configuration and handles CIF serialization via
+This lightweight container stores the categorical attributes defining an
+experiment configuration and handles CIF serialization via
``CifHandler``.
"""
@@ -26,27 +27,19 @@
@ExperimentTypeFactory.register
class ExperimentType(CategoryItem):
- """Container of categorical attributes defining experiment flavor.
-
- Args:
- sample_form: Powder or Single crystal.
- beam_mode: Constant wavelength (CW) or time-of-flight (TOF).
- radiation_probe: Neutrons or X-rays.
- scattering_type: Bragg or Total.
- """
+ """Container of attributes defining the experiment type."""
type_info = TypeInfo(
tag='default',
description='Experiment type descriptor',
)
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._sample_form = StringDescriptor(
name='sample_form',
- description='Specifies whether the diffraction data corresponds to '
- 'powder diffraction or single crystal diffraction',
+ description='Powder diffraction or single crystal diffraction',
value_spec=AttributeSpec(
default=SampleFormEnum.default().value,
validator=MembershipValidator(allowed=[member.value for member in SampleFormEnum]),
@@ -56,8 +49,7 @@ def __init__(self):
self._beam_mode = StringDescriptor(
name='beam_mode',
- description='Defines whether the measurement is performed with a '
- 'constant wavelength (CW) or time-of-flight (TOF) method',
+ description='Constant wavelength (CW) or time-of-flight (TOF) measurement',
value_spec=AttributeSpec(
default=BeamModeEnum.default().value,
validator=MembershipValidator(allowed=[member.value for member in BeamModeEnum]),
@@ -66,7 +58,7 @@ def __init__(self):
)
self._radiation_probe = StringDescriptor(
name='radiation_probe',
- description='Specifies whether the measurement uses neutrons or X-rays',
+ description='Neutron or X-ray diffraction measurement',
value_spec=AttributeSpec(
default=RadiationProbeEnum.default().value,
validator=MembershipValidator(
@@ -77,9 +69,7 @@ def __init__(self):
)
self._scattering_type = StringDescriptor(
name='scattering_type',
- description='Specifies whether the experiment uses Bragg scattering '
- '(for conventional structure refinement) or total scattering '
- '(for pair distribution function analysis - PDF)',
+ description='Conventional Bragg diffraction or total scattering (PDF)',
value_spec=AttributeSpec(
default=ScatteringTypeEnum.default().value,
validator=MembershipValidator(
@@ -112,17 +102,41 @@ def _set_scattering_type(self, value: str) -> None:
# ------------------------------------------------------------------
@property
- def sample_form(self):
+ def sample_form(self) -> StringDescriptor:
+ """
+ Powder diffraction or single crystal diffraction.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._sample_form
@property
- def beam_mode(self):
+ def beam_mode(self) -> StringDescriptor:
+ """
+ Constant wavelength (CW) or time-of-flight (TOF) measurement.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._beam_mode
@property
- def radiation_probe(self):
+ def radiation_probe(self) -> StringDescriptor:
+ """
+ Neutron or X-ray diffraction measurement.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._radiation_probe
@property
- def scattering_type(self):
+ def scattering_type(self) -> StringDescriptor:
+ """
+ Conventional Bragg diffraction or total scattering (PDF).
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object.
+ """
return self._scattering_type
diff --git a/src/easydiffraction/datablocks/experiment/categories/experiment_type/factory.py b/src/easydiffraction/datablocks/experiment/categories/experiment_type/factory.py
index bf78fb53..05f0d2d9 100644
--- a/src/easydiffraction/datablocks/experiment/categories/experiment_type/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/experiment_type/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Experiment-type factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/extinction/__init__.py b/src/easydiffraction/datablocks/experiment/categories/extinction/__init__.py
index f3d62fad..3e6fa39a 100644
--- a/src/easydiffraction/datablocks/experiment/categories/extinction/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/extinction/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.extinction.shelx import ShelxExtinction
diff --git a/src/easydiffraction/datablocks/experiment/categories/extinction/factory.py b/src/easydiffraction/datablocks/experiment/categories/extinction/factory.py
index fbeb32e7..4e4bd9ed 100644
--- a/src/easydiffraction/datablocks/experiment/categories/extinction/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/extinction/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Extinction factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/extinction/shelx.py b/src/easydiffraction/datablocks/experiment/categories/extinction/shelx.py
index 67dfaf94..dd736a1a 100644
--- a/src/easydiffraction/datablocks/experiment/categories/extinction/shelx.py
+++ b/src/easydiffraction/datablocks/experiment/categories/extinction/shelx.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Shelx-style isotropic extinction correction."""
@@ -17,9 +17,7 @@
@ExtinctionFactory.register
class ShelxExtinction(CategoryItem):
- """Shelx-style isotropic extinction correction for single
- crystals.
- """
+ """Shelx-style extinction correction for single crystals."""
type_info = TypeInfo(
tag='shelx',
@@ -34,7 +32,7 @@ def __init__(self) -> None:
self._mosaicity = Parameter(
name='mosaicity',
- description='Mosaicity value for extinction correction.',
+ description='Mosaicity value for extinction correction',
units='deg',
value_spec=AttributeSpec(
default=1.0,
@@ -48,7 +46,7 @@ def __init__(self) -> None:
)
self._radius = Parameter(
name='radius',
- description='Crystal radius for extinction correction.',
+ description='Crystal radius for extinction correction',
units='µm',
value_spec=AttributeSpec(
default=1.0,
@@ -68,17 +66,29 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
@property
- def mosaicity(self):
+ def mosaicity(self) -> Parameter:
+ """
+ Mosaicity value for extinction correction (deg).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._mosaicity
@mosaicity.setter
- def mosaicity(self, value):
+ def mosaicity(self, value: float) -> None:
self._mosaicity.value = value
@property
- def radius(self):
+ def radius(self) -> Parameter:
+ """
+ Crystal radius for extinction correction (µm).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._radius
@radius.setter
- def radius(self, value):
+ def radius(self, value: float) -> None:
self._radius.value = value
diff --git a/src/easydiffraction/datablocks/experiment/categories/instrument/__init__.py b/src/easydiffraction/datablocks/experiment/categories/instrument/__init__.py
index e4a03696..d12b40c3 100644
--- a/src/easydiffraction/datablocks/experiment/categories/instrument/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/instrument/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.instrument.cwl import CwlPdInstrument
diff --git a/src/easydiffraction/datablocks/experiment/categories/instrument/base.py b/src/easydiffraction/datablocks/experiment/categories/instrument/base.py
index 0d1c04d5..a2568884 100644
--- a/src/easydiffraction/datablocks/experiment/categories/instrument/base.py
+++ b/src/easydiffraction/datablocks/experiment/categories/instrument/base.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Instrument category base definitions for CWL/TOF instruments.
+"""
+Instrument category base definitions for CWL/TOF instruments.
This module provides the shared parent used by concrete instrument
implementations under the instrument category.
@@ -12,7 +13,8 @@
class InstrumentBase(CategoryItem):
- """Base class for instrument category items.
+ """
+ Base class for instrument category items.
This class sets the common ``category_code`` and is used as a base
for concrete CWL/TOF instrument definitions.
diff --git a/src/easydiffraction/datablocks/experiment/categories/instrument/cwl.py b/src/easydiffraction/datablocks/experiment/categories/instrument/cwl.py
index 924158a0..3a3628bd 100644
--- a/src/easydiffraction/datablocks/experiment/categories/instrument/cwl.py
+++ b/src/easydiffraction/datablocks/experiment/categories/instrument/cwl.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.core.metadata import CalculatorSupport
@@ -17,6 +17,8 @@
class CwlInstrumentBase(InstrumentBase):
+ """Base class for constant-wavelength instruments."""
+
def __init__(self) -> None:
super().__init__()
@@ -36,19 +38,28 @@ def __init__(self) -> None:
)
@property
- def setup_wavelength(self):
- """Incident wavelength parameter (Å)."""
+ def setup_wavelength(self) -> Parameter:
+ """
+ Incident neutron or X-ray wavelength (Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._setup_wavelength
@setup_wavelength.setter
- def setup_wavelength(self, value):
- """Set incident wavelength value (Å)."""
+ def setup_wavelength(self, value: float) -> None:
self._setup_wavelength.value = value
@InstrumentFactory.register
class CwlScInstrument(CwlInstrumentBase):
- type_info = TypeInfo(tag='cwl-sc', description='CW single-crystal diffractometer')
+ """CW single-crystal diffractometer."""
+
+ type_info = TypeInfo(
+ tag='cwl-sc',
+ description='CW single-crystal diffractometer',
+ )
compatibility = Compatibility(
scattering_type=frozenset({ScatteringTypeEnum.BRAGG}),
beam_mode=frozenset({BeamModeEnum.CONSTANT_WAVELENGTH}),
@@ -64,7 +75,12 @@ def __init__(self) -> None:
@InstrumentFactory.register
class CwlPdInstrument(CwlInstrumentBase):
- type_info = TypeInfo(tag='cwl-pd', description='CW powder diffractometer')
+ """CW powder diffractometer."""
+
+ type_info = TypeInfo(
+ tag='cwl-pd',
+ description='CW powder diffractometer',
+ )
compatibility = Compatibility(
scattering_type=frozenset({ScatteringTypeEnum.BRAGG, ScatteringTypeEnum.TOTAL}),
beam_mode=frozenset({BeamModeEnum.CONSTANT_WAVELENGTH}),
@@ -97,11 +113,15 @@ def __init__(self) -> None:
)
@property
- def calib_twotheta_offset(self):
- """Instrument misalignment two-theta offset (deg)."""
+ def calib_twotheta_offset(self) -> Parameter:
+ """
+ Instrument misalignment offset (deg).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._calib_twotheta_offset
@calib_twotheta_offset.setter
- def calib_twotheta_offset(self, value):
- """Set two-theta offset value (deg)."""
+ def calib_twotheta_offset(self, value: float) -> None:
self._calib_twotheta_offset.value = value
diff --git a/src/easydiffraction/datablocks/experiment/categories/instrument/factory.py b/src/easydiffraction/datablocks/experiment/categories/instrument/factory.py
index 7d4286af..fce8ad5c 100644
--- a/src/easydiffraction/datablocks/experiment/categories/instrument/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/instrument/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Instrument factory — delegates to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/instrument/tof.py b/src/easydiffraction/datablocks/experiment/categories/instrument/tof.py
index efbff40d..7e1db98e 100644
--- a/src/easydiffraction/datablocks/experiment/categories/instrument/tof.py
+++ b/src/easydiffraction/datablocks/experiment/categories/instrument/tof.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.core.metadata import CalculatorSupport
@@ -18,7 +18,12 @@
@InstrumentFactory.register
class TofScInstrument(InstrumentBase):
- type_info = TypeInfo(tag='tof-sc', description='TOF single-crystal diffractometer')
+ """TOF single-crystal diffractometer."""
+
+ type_info = TypeInfo(
+ tag='tof-sc',
+ description='TOF single-crystal diffractometer',
+ )
compatibility = Compatibility(
scattering_type=frozenset({ScatteringTypeEnum.BRAGG}),
beam_mode=frozenset({BeamModeEnum.TIME_OF_FLIGHT}),
@@ -34,7 +39,12 @@ def __init__(self) -> None:
@InstrumentFactory.register
class TofPdInstrument(InstrumentBase):
- type_info = TypeInfo(tag='tof-pd', description='TOF powder diffractometer')
+ """TOF powder diffractometer."""
+
+ type_info = TypeInfo(
+ tag='tof-pd',
+ description='TOF powder diffractometer',
+ )
compatibility = Compatibility(
scattering_type=frozenset({ScatteringTypeEnum.BRAGG}),
beam_mode=frozenset({BeamModeEnum.TIME_OF_FLIGHT}),
@@ -99,41 +109,71 @@ def __init__(self) -> None:
)
@property
- def setup_twotheta_bank(self):
+ def setup_twotheta_bank(self) -> Parameter:
+ """
+ Detector bank position (deg).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._setup_twotheta_bank
@setup_twotheta_bank.setter
- def setup_twotheta_bank(self, value):
+ def setup_twotheta_bank(self, value: float) -> None:
self._setup_twotheta_bank.value = value
@property
- def calib_d_to_tof_offset(self):
+ def calib_d_to_tof_offset(self) -> Parameter:
+ """
+ TOF offset (µs).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._calib_d_to_tof_offset
@calib_d_to_tof_offset.setter
- def calib_d_to_tof_offset(self, value):
+ def calib_d_to_tof_offset(self, value: float) -> None:
self._calib_d_to_tof_offset.value = value
@property
- def calib_d_to_tof_linear(self):
+ def calib_d_to_tof_linear(self) -> Parameter:
+ """
+ TOF linear conversion (µs/Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._calib_d_to_tof_linear
@calib_d_to_tof_linear.setter
- def calib_d_to_tof_linear(self, value):
+ def calib_d_to_tof_linear(self, value: float) -> None:
self._calib_d_to_tof_linear.value = value
@property
- def calib_d_to_tof_quad(self):
+ def calib_d_to_tof_quad(self) -> Parameter:
+ """
+ TOF quadratic correction (µs/Ų).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._calib_d_to_tof_quad
@calib_d_to_tof_quad.setter
- def calib_d_to_tof_quad(self, value):
+ def calib_d_to_tof_quad(self, value: float) -> None:
self._calib_d_to_tof_quad.value = value
@property
- def calib_d_to_tof_recip(self):
+ def calib_d_to_tof_recip(self) -> Parameter:
+ """
+ TOF reciprocal velocity correction (µs·Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._calib_d_to_tof_recip
@calib_d_to_tof_recip.setter
- def calib_d_to_tof_recip(self, value):
+ def calib_d_to_tof_recip(self, value: float) -> None:
self._calib_d_to_tof_recip.value = value
diff --git a/src/easydiffraction/datablocks/experiment/categories/linked_crystal/__init__.py b/src/easydiffraction/datablocks/experiment/categories/linked_crystal/__init__.py
index 1a6b0b67..4b93121b 100644
--- a/src/easydiffraction/datablocks/experiment/categories/linked_crystal/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/linked_crystal/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.linked_crystal.default import LinkedCrystal
diff --git a/src/easydiffraction/datablocks/experiment/categories/linked_crystal/default.py b/src/easydiffraction/datablocks/experiment/categories/linked_crystal/default.py
index e1fa8b6a..d441aa9c 100644
--- a/src/easydiffraction/datablocks/experiment/categories/linked_crystal/default.py
+++ b/src/easydiffraction/datablocks/experiment/categories/linked_crystal/default.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Default linked-crystal reference (id + scale)."""
@@ -21,9 +21,7 @@
@LinkedCrystalFactory.register
class LinkedCrystal(CategoryItem):
- """Linked crystal category for referencing from the experiment for
- single crystal diffraction.
- """
+ """Linked crystal reference for single-crystal diffraction."""
type_info = TypeInfo(
tag='default',
@@ -38,7 +36,7 @@ def __init__(self) -> None:
self._id = StringDescriptor(
name='id',
- description='Identifier of the linked crystal.',
+ description='Identifier of the linked crystal',
value_spec=AttributeSpec(
default='Si',
validator=RegexValidator(pattern=r'^[A-Za-z_][A-Za-z0-9_]*$'),
@@ -47,7 +45,7 @@ def __init__(self) -> None:
)
self._scale = Parameter(
name='scale',
- description='Scale factor of the linked crystal.',
+ description='Scale factor of the linked crystal',
value_spec=AttributeSpec(
default=1.0,
validator=RangeValidator(),
@@ -63,16 +61,29 @@ def __init__(self) -> None:
@property
def id(self) -> StringDescriptor:
+ """
+ Identifier of the linked crystal.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._id
@id.setter
- def id(self, value: str):
+ def id(self, value: str) -> None:
self._id.value = value
@property
def scale(self) -> Parameter:
+ """
+ Scale factor of the linked crystal.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._scale
@scale.setter
- def scale(self, value: float):
+ def scale(self, value: float) -> None:
self._scale.value = value
diff --git a/src/easydiffraction/datablocks/experiment/categories/linked_crystal/factory.py b/src/easydiffraction/datablocks/experiment/categories/linked_crystal/factory.py
index 49ac1a64..b34b8073 100644
--- a/src/easydiffraction/datablocks/experiment/categories/linked_crystal/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/linked_crystal/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Linked-crystal factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/linked_phases/__init__.py b/src/easydiffraction/datablocks/experiment/categories/linked_phases/__init__.py
index 6dd96b94..dda7d445 100644
--- a/src/easydiffraction/datablocks/experiment/categories/linked_phases/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/linked_phases/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.linked_phases.default import LinkedPhase
diff --git a/src/easydiffraction/datablocks/experiment/categories/linked_phases/default.py b/src/easydiffraction/datablocks/experiment/categories/linked_phases/default.py
index 067683a9..97d03c66 100644
--- a/src/easydiffraction/datablocks/experiment/categories/linked_phases/default.py
+++ b/src/easydiffraction/datablocks/experiment/categories/linked_phases/default.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Linked phases allow combining phases with scale factors."""
@@ -23,12 +23,12 @@
class LinkedPhase(CategoryItem):
"""Link to a phase by id with a scale factor."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._id = StringDescriptor(
name='id',
- description='Identifier of the linked phase.',
+ description='Identifier of the linked phase',
value_spec=AttributeSpec(
default='Si',
validator=RegexValidator(pattern=r'^[A-Za-z_][A-Za-z0-9_]*$'),
@@ -54,18 +54,31 @@ def __init__(self):
@property
def id(self) -> StringDescriptor:
+ """
+ Identifier of the linked phase.
+
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
+ """
return self._id
@id.setter
- def id(self, value: str):
+ def id(self, value: str) -> None:
self._id.value = value
@property
def scale(self) -> Parameter:
+ """
+ Scale factor of the linked phase.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._scale
@scale.setter
- def scale(self, value: float):
+ def scale(self, value: float) -> None:
self._scale.value = value
@@ -81,6 +94,6 @@ class LinkedPhases(CategoryCollection):
sample_form=frozenset({SampleFormEnum.POWDER}),
)
- def __init__(self):
+ def __init__(self) -> None:
"""Create an empty collection of linked phases."""
super().__init__(item_type=LinkedPhase)
diff --git a/src/easydiffraction/datablocks/experiment/categories/linked_phases/factory.py b/src/easydiffraction/datablocks/experiment/categories/linked_phases/factory.py
index 74f16616..56970ee8 100644
--- a/src/easydiffraction/datablocks/experiment/categories/linked_phases/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/linked_phases/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Linked-phases factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/__init__.py b/src/easydiffraction/datablocks/experiment/categories/peak/__init__.py
index b335b9d3..667bafb4 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.categories.peak.cwl import CwlPseudoVoigt
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/base.py b/src/easydiffraction/datablocks/experiment/categories/peak/base.py
index 5f2654a7..050411b1 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/base.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Base class for peak profile categories."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/cwl.py b/src/easydiffraction/datablocks/experiment/categories/peak/cwl.py
index aa03c80c..a2b4f63b 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/cwl.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/cwl.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Constant-wavelength peak profile classes."""
@@ -24,7 +24,10 @@ class CwlPseudoVoigt(
):
"""Constant-wavelength pseudo-Voigt peak shape."""
- type_info = TypeInfo(tag='pseudo-voigt', description='Pseudo-Voigt profile')
+ type_info = TypeInfo(
+ tag='pseudo-voigt',
+ description='Pseudo-Voigt profile',
+ )
compatibility = Compatibility(
scattering_type=frozenset({ScatteringTypeEnum.BRAGG}),
beam_mode=frozenset({BeamModeEnum.CONSTANT_WAVELENGTH}),
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/cwl_mixins.py b/src/easydiffraction/datablocks/experiment/categories/peak/cwl_mixins.py
index 2bc9c178..6e4f29c8 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/cwl_mixins.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/cwl_mixins.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Constant-wavelength (CWL) peak-profile component classes.
+"""
+Constant-wavelength (CWL) peak-profile component classes.
This module provides classes that add broadening and asymmetry
parameters. They are composed into concrete peak classes elsewhere via
@@ -16,13 +17,12 @@
class CwlBroadeningMixin:
"""CWL Gaussian and Lorentz broadening parameters."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._broad_gauss_u: Parameter = Parameter(
name='broad_gauss_u',
- description='Gaussian broadening coefficient (dependent on '
- 'sample size and instrument resolution)',
+ description='Gaussian broadening from sample size and resolution',
units='deg²',
value_spec=AttributeSpec(
default=0.01,
@@ -32,7 +32,7 @@ def __init__(self):
)
self._broad_gauss_v: Parameter = Parameter(
name='broad_gauss_v',
- description='Gaussian broadening coefficient (instrumental broadening contribution)',
+ description='Gaussian broadening instrumental contribution',
units='deg²',
value_spec=AttributeSpec(
default=-0.01,
@@ -42,7 +42,7 @@ def __init__(self):
)
self._broad_gauss_w: Parameter = Parameter(
name='broad_gauss_w',
- description='Gaussian broadening coefficient (instrumental broadening contribution)',
+ description='Gaussian broadening instrumental contribution',
units='deg²',
value_spec=AttributeSpec(
default=0.02,
@@ -52,7 +52,7 @@ def __init__(self):
)
self._broad_lorentz_x: Parameter = Parameter(
name='broad_lorentz_x',
- description='Lorentzian broadening coefficient (dependent on sample strain effects)',
+ description='Lorentzian broadening from sample strain effects',
units='deg',
value_spec=AttributeSpec(
default=0.0,
@@ -62,8 +62,7 @@ def __init__(self):
)
self._broad_lorentz_y: Parameter = Parameter(
name='broad_lorentz_y',
- description='Lorentzian broadening coefficient (dependent on '
- 'microstructural defects and strain)',
+ description='Lorentzian broadening from microstructural defects',
units='deg',
value_spec=AttributeSpec(
default=0.0,
@@ -78,49 +77,79 @@ def __init__(self):
@property
def broad_gauss_u(self) -> Parameter:
+ """
+ Gaussian broadening from sample size and resolution (deg²).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_gauss_u
@broad_gauss_u.setter
- def broad_gauss_u(self, value):
+ def broad_gauss_u(self, value: float) -> None:
self._broad_gauss_u.value = value
@property
def broad_gauss_v(self) -> Parameter:
+ """
+ Gaussian broadening instrumental contribution (deg²).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_gauss_v
@broad_gauss_v.setter
- def broad_gauss_v(self, value):
+ def broad_gauss_v(self, value: float) -> None:
self._broad_gauss_v.value = value
@property
def broad_gauss_w(self) -> Parameter:
+ """
+ Gaussian broadening instrumental contribution (deg²).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_gauss_w
@broad_gauss_w.setter
- def broad_gauss_w(self, value):
+ def broad_gauss_w(self, value: float) -> None:
self._broad_gauss_w.value = value
@property
def broad_lorentz_x(self) -> Parameter:
+ """
+ Lorentzian broadening (sample strain effects) (deg).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_lorentz_x
@broad_lorentz_x.setter
- def broad_lorentz_x(self, value):
+ def broad_lorentz_x(self, value: float) -> None:
self._broad_lorentz_x.value = value
@property
def broad_lorentz_y(self) -> Parameter:
+ """
+ Lorentzian broadening from microstructural defects (deg).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_lorentz_y
@broad_lorentz_y.setter
- def broad_lorentz_y(self, value):
+ def broad_lorentz_y(self, value: float) -> None:
self._broad_lorentz_y.value = value
class EmpiricalAsymmetryMixin:
"""Empirical CWL peak asymmetry parameters."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._asym_empir_1: Parameter = Parameter(
@@ -170,41 +199,65 @@ def __init__(self):
@property
def asym_empir_1(self) -> Parameter:
+ """
+ Empirical asymmetry coefficient p1.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_empir_1
@asym_empir_1.setter
- def asym_empir_1(self, value):
+ def asym_empir_1(self, value: float) -> None:
self._asym_empir_1.value = value
@property
def asym_empir_2(self) -> Parameter:
+ """
+ Empirical asymmetry coefficient p2.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_empir_2
@asym_empir_2.setter
- def asym_empir_2(self, value):
+ def asym_empir_2(self, value: float) -> None:
self._asym_empir_2.value = value
@property
def asym_empir_3(self) -> Parameter:
+ """
+ Empirical asymmetry coefficient p3.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_empir_3
@asym_empir_3.setter
- def asym_empir_3(self, value):
+ def asym_empir_3(self, value: float) -> None:
self._asym_empir_3.value = value
@property
def asym_empir_4(self) -> Parameter:
+ """
+ Empirical asymmetry coefficient p4.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_empir_4
@asym_empir_4.setter
- def asym_empir_4(self, value):
+ def asym_empir_4(self, value: float) -> None:
self._asym_empir_4.value = value
class FcjAsymmetryMixin:
"""Finger–Cox–Jephcoat (FCJ) asymmetry parameters."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._asym_fcj_1: Parameter = Parameter(
@@ -233,17 +286,29 @@ def __init__(self):
# ------------------------------------------------------------------
@property
- def asym_fcj_1(self):
+ def asym_fcj_1(self) -> Parameter:
+ """
+ Finger-Cox-Jephcoat asymmetry parameter 1.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_fcj_1
@asym_fcj_1.setter
- def asym_fcj_1(self, value):
+ def asym_fcj_1(self, value: float) -> None:
self._asym_fcj_1.value = value
@property
- def asym_fcj_2(self):
+ def asym_fcj_2(self) -> Parameter:
+ """
+ Finger-Cox-Jephcoat asymmetry parameter 2.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_fcj_2
@asym_fcj_2.setter
- def asym_fcj_2(self, value):
+ def asym_fcj_2(self, value: float) -> None:
self._asym_fcj_2.value = value
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/factory.py b/src/easydiffraction/datablocks/experiment/categories/peak/factory.py
index 1992b633..ca196748 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/factory.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Peak profile factory — delegates to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/tof.py b/src/easydiffraction/datablocks/experiment/categories/peak/tof.py
index 1c70b65b..59c0b9e3 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/tof.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/tof.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Time-of-flight peak profile classes."""
@@ -23,7 +23,10 @@ class TofPseudoVoigt(
):
"""Time-of-flight pseudo-Voigt peak shape."""
- type_info = TypeInfo(tag='tof-pseudo-voigt', description='TOF pseudo-Voigt profile')
+ type_info = TypeInfo(
+ tag='tof-pseudo-voigt',
+ description='TOF pseudo-Voigt profile',
+ )
compatibility = Compatibility(
scattering_type=frozenset({ScatteringTypeEnum.BRAGG}),
beam_mode=frozenset({BeamModeEnum.TIME_OF_FLIGHT}),
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/tof_mixins.py b/src/easydiffraction/datablocks/experiment/categories/peak/tof_mixins.py
index 01a10b26..8093d877 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/tof_mixins.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/tof_mixins.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Time-of-flight (TOF) peak-profile component classes.
+"""
+Time-of-flight (TOF) peak-profile component classes.
Defines classes that add Gaussian/Lorentz broadening, mixing, and
Ikeda–Carpenter asymmetry parameters used by TOF peak shapes. This
@@ -18,12 +19,12 @@
class TofBroadeningMixin:
"""TOF Gaussian/Lorentz broadening and mixing parameters."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._broad_gauss_sigma_0 = Parameter(
name='gauss_sigma_0',
- description='Gaussian broadening coefficient (instrumental resolution)',
+ description='Gaussian broadening (instrumental resolution)',
units='µs²',
value_spec=AttributeSpec(
default=0.0,
@@ -33,7 +34,7 @@ def __init__(self):
)
self._broad_gauss_sigma_1 = Parameter(
name='gauss_sigma_1',
- description='Gaussian broadening coefficient (dependent on d-spacing)',
+ description='Gaussian broadening (dependent on d-spacing)',
units='µs/Å',
value_spec=AttributeSpec(
default=0.0,
@@ -43,7 +44,7 @@ def __init__(self):
)
self._broad_gauss_sigma_2 = Parameter(
name='gauss_sigma_2',
- description='Gaussian broadening coefficient (instrument-dependent term)',
+ description='Gaussian broadening (instrument-dependent term)',
units='µs²/Ų',
value_spec=AttributeSpec(
default=0.0,
@@ -53,7 +54,7 @@ def __init__(self):
)
self._broad_lorentz_gamma_0 = Parameter(
name='lorentz_gamma_0',
- description='Lorentzian broadening coefficient (dependent on microstrain effects)',
+ description='Lorentzian broadening (microstrain effects)',
units='µs',
value_spec=AttributeSpec(
default=0.0,
@@ -63,7 +64,7 @@ def __init__(self):
)
self._broad_lorentz_gamma_1 = Parameter(
name='lorentz_gamma_1',
- description='Lorentzian broadening coefficient (dependent on d-spacing)',
+ description='Lorentzian broadening (dependent on d-spacing)',
units='µs/Å',
value_spec=AttributeSpec(
default=0.0,
@@ -73,7 +74,7 @@ def __init__(self):
)
self._broad_lorentz_gamma_2 = Parameter(
name='lorentz_gamma_2',
- description='Lorentzian broadening coefficient (instrument-dependent term)',
+ description='Lorentzian broadening (instrument-dependent term)',
units='µs²/Ų',
value_spec=AttributeSpec(
default=0.0,
@@ -83,8 +84,7 @@ def __init__(self):
)
self._broad_mix_beta_0 = Parameter(
name='mix_beta_0',
- description='Mixing parameter. Defines the ratio of Gaussian '
- 'to Lorentzian contributions in TOF profiles',
+ description='Ratio of Gaussian to Lorentzian contributions',
units='deg',
value_spec=AttributeSpec(
default=0.0,
@@ -94,8 +94,7 @@ def __init__(self):
)
self._broad_mix_beta_1 = Parameter(
name='mix_beta_1',
- description='Mixing parameter. Defines the ratio of Gaussian '
- 'to Lorentzian contributions in TOF profiles',
+ description='Ratio of Gaussian to Lorentzian contributions',
units='deg',
value_spec=AttributeSpec(
default=0.0,
@@ -109,75 +108,122 @@ def __init__(self):
# ------------------------------------------------------------------
@property
- def broad_gauss_sigma_0(self):
+ def broad_gauss_sigma_0(self) -> Parameter:
+ """
+ Gaussian broadening (instrumental resolution) (µs²).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_gauss_sigma_0
@broad_gauss_sigma_0.setter
- def broad_gauss_sigma_0(self, value):
+ def broad_gauss_sigma_0(self, value: float) -> None:
self._broad_gauss_sigma_0.value = value
@property
- def broad_gauss_sigma_1(self):
+ def broad_gauss_sigma_1(self) -> Parameter:
+ """
+ Gaussian broadening (dependent on d-spacing) (µs/Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_gauss_sigma_1
@broad_gauss_sigma_1.setter
- def broad_gauss_sigma_1(self, value):
+ def broad_gauss_sigma_1(self, value: float) -> None:
self._broad_gauss_sigma_1.value = value
@property
- def broad_gauss_sigma_2(self):
+ def broad_gauss_sigma_2(self) -> Parameter:
+ """
+ Gaussian broadening (instrument-dependent term) (µs²/Ų).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_gauss_sigma_2
@broad_gauss_sigma_2.setter
- def broad_gauss_sigma_2(self, value):
- """Set Gaussian sigma_2 parameter."""
+ def broad_gauss_sigma_2(self, value: float) -> None:
self._broad_gauss_sigma_2.value = value
@property
- def broad_lorentz_gamma_0(self):
+ def broad_lorentz_gamma_0(self) -> Parameter:
+ """
+ Lorentzian broadening (microstrain effects) (µs).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_lorentz_gamma_0
@broad_lorentz_gamma_0.setter
- def broad_lorentz_gamma_0(self, value):
+ def broad_lorentz_gamma_0(self, value: float) -> None:
self._broad_lorentz_gamma_0.value = value
@property
- def broad_lorentz_gamma_1(self):
+ def broad_lorentz_gamma_1(self) -> Parameter:
+ """
+ Lorentzian broadening (dependent on d-spacing) (µs/Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_lorentz_gamma_1
@broad_lorentz_gamma_1.setter
- def broad_lorentz_gamma_1(self, value):
+ def broad_lorentz_gamma_1(self, value: float) -> None:
self._broad_lorentz_gamma_1.value = value
@property
- def broad_lorentz_gamma_2(self):
+ def broad_lorentz_gamma_2(self) -> Parameter:
+ """
+ Lorentzian broadening (instrument-dependent term) (µs²/Ų).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_lorentz_gamma_2
@broad_lorentz_gamma_2.setter
- def broad_lorentz_gamma_2(self, value):
+ def broad_lorentz_gamma_2(self, value: float) -> None:
self._broad_lorentz_gamma_2.value = value
@property
- def broad_mix_beta_0(self):
+ def broad_mix_beta_0(self) -> Parameter:
+ """
+ Ratio of Gaussian to Lorentzian contributions (deg).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_mix_beta_0
@broad_mix_beta_0.setter
- def broad_mix_beta_0(self, value):
+ def broad_mix_beta_0(self, value: float) -> None:
self._broad_mix_beta_0.value = value
@property
- def broad_mix_beta_1(self):
+ def broad_mix_beta_1(self) -> Parameter:
+ """
+ Ratio of Gaussian to Lorentzian contributions (deg).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_mix_beta_1
@broad_mix_beta_1.setter
- def broad_mix_beta_1(self, value):
+ def broad_mix_beta_1(self, value: float) -> None:
self._broad_mix_beta_1.value = value
class IkedaCarpenterAsymmetryMixin:
"""Ikeda–Carpenter asymmetry parameters."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._asym_alpha_0 = Parameter(
@@ -202,17 +248,29 @@ def __init__(self):
)
@property
- def asym_alpha_0(self):
+ def asym_alpha_0(self) -> Parameter:
+ """
+ Ikeda-Carpenter asymmetry parameter α₀.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_alpha_0
@asym_alpha_0.setter
- def asym_alpha_0(self, value):
+ def asym_alpha_0(self, value: float) -> None:
self._asym_alpha_0.value = value
@property
- def asym_alpha_1(self):
+ def asym_alpha_1(self) -> Parameter:
+ """
+ Ikeda-Carpenter asymmetry parameter α₁.
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._asym_alpha_1
@asym_alpha_1.setter
- def asym_alpha_1(self, value):
+ def asym_alpha_1(self, value: float) -> None:
self._asym_alpha_1.value = value
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/total.py b/src/easydiffraction/datablocks/experiment/categories/peak/total.py
index a1166c1a..61d5e6fd 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/total.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/total.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Total-scattering (PDF) peak profile classes."""
diff --git a/src/easydiffraction/datablocks/experiment/categories/peak/total_mixins.py b/src/easydiffraction/datablocks/experiment/categories/peak/total_mixins.py
index 139e37dd..bae2c974 100644
--- a/src/easydiffraction/datablocks/experiment/categories/peak/total_mixins.py
+++ b/src/easydiffraction/datablocks/experiment/categories/peak/total_mixins.py
@@ -1,7 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Total scattering / pair distribution function (PDF) peak-profile
-component classes.
+"""
+Total scattering / PDF peak-profile component classes.
This module provides classes that add broadening and asymmetry
parameters. They are composed into concrete peak classes elsewhere via
@@ -17,13 +17,12 @@
class TotalBroadeningMixin:
"""PDF broadening/damping/sharpening parameters."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._damp_q = Parameter(
name='damp_q',
- description='Instrumental Q-resolution damping factor '
- '(affects high-r PDF peak amplitude)',
+ description='Q-resolution damping for high-r PDF peak amplitude',
units='Å⁻¹',
value_spec=AttributeSpec(
default=0.05,
@@ -33,8 +32,7 @@ def __init__(self):
)
self._broad_q = Parameter(
name='broad_q',
- description='Quadratic PDF peak broadening coefficient '
- '(thermal and model uncertainty contribution)',
+ description='Quadratic peak broadening from thermal uncertainty',
units='Å⁻²',
value_spec=AttributeSpec(
default=0.0,
@@ -44,8 +42,7 @@ def __init__(self):
)
self._cutoff_q = Parameter(
name='cutoff_q',
- description='Q-value cutoff applied to model PDF for Fourier '
- 'transform (controls real-space resolution)',
+ description='Q-value cutoff for Fourier transform',
units='Å⁻¹',
value_spec=AttributeSpec(
default=25.0,
@@ -55,7 +52,7 @@ def __init__(self):
)
self._sharp_delta_1 = Parameter(
name='sharp_delta_1',
- description='PDF peak sharpening coefficient (1/r dependence)',
+ description='Peak sharpening coefficient (1/r dependence)',
units='Å',
value_spec=AttributeSpec(
default=0.0,
@@ -65,7 +62,7 @@ def __init__(self):
)
self._sharp_delta_2 = Parameter(
name='sharp_delta_2',
- description='PDF peak sharpening coefficient (1/r² dependence)',
+ description='Peak sharpening coefficient (1/r² dependence)',
units='Ų',
value_spec=AttributeSpec(
default=0.0,
@@ -75,7 +72,7 @@ def __init__(self):
)
self._damp_particle_diameter = Parameter(
name='damp_particle_diameter',
- description='Particle diameter for spherical envelope damping correction in PDF',
+ description='Particle diameter for spherical envelope damping correction',
units='Å',
value_spec=AttributeSpec(
default=0.0,
@@ -89,49 +86,85 @@ def __init__(self):
# ------------------------------------------------------------------
@property
- def damp_q(self):
+ def damp_q(self) -> Parameter:
+ """
+ Q-resolution damping for high-r PDF peak amplitude (Å⁻¹).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._damp_q
@damp_q.setter
- def damp_q(self, value):
+ def damp_q(self, value: float) -> None:
self._damp_q.value = value
@property
- def broad_q(self):
+ def broad_q(self) -> Parameter:
+ """
+ Quadratic peak broadening from thermal uncertainty (Å⁻²).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._broad_q
@broad_q.setter
- def broad_q(self, value):
+ def broad_q(self, value: float) -> None:
self._broad_q.value = value
@property
def cutoff_q(self) -> Parameter:
+ """
+ Q-value cutoff for Fourier transform (Å⁻¹).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._cutoff_q
@cutoff_q.setter
- def cutoff_q(self, value):
+ def cutoff_q(self, value: float) -> None:
self._cutoff_q.value = value
@property
def sharp_delta_1(self) -> Parameter:
+ """
+ PDF peak sharpening coefficient (1/r dependence) (Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._sharp_delta_1
@sharp_delta_1.setter
- def sharp_delta_1(self, value):
+ def sharp_delta_1(self, value: float) -> None:
self._sharp_delta_1.value = value
@property
- def sharp_delta_2(self):
+ def sharp_delta_2(self) -> Parameter:
+ """
+ PDF peak sharpening coefficient (1/r² dependence) (Ų).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._sharp_delta_2
@sharp_delta_2.setter
- def sharp_delta_2(self, value):
+ def sharp_delta_2(self, value: float) -> None:
self._sharp_delta_2.value = value
@property
- def damp_particle_diameter(self):
+ def damp_particle_diameter(self) -> Parameter:
+ """
+ Particle diameter for spherical envelope damping correction (Å).
+
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
+ """
return self._damp_particle_diameter
@damp_particle_diameter.setter
- def damp_particle_diameter(self, value):
+ def damp_particle_diameter(self, value: float) -> None:
self._damp_particle_diameter.value = value
diff --git a/src/easydiffraction/datablocks/experiment/collection.py b/src/easydiffraction/datablocks/experiment/collection.py
index 854b77ad..5cdf3f6b 100644
--- a/src/easydiffraction/datablocks/experiment/collection.py
+++ b/src/easydiffraction/datablocks/experiment/collection.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Collection of experiment data blocks."""
@@ -11,7 +11,8 @@
class Experiments(DatablockCollection):
- """Collection of Experiment data blocks.
+ """
+ Collection of Experiment data blocks.
Provides convenience constructors for common creation patterns and
helper methods for simple presentation of collection contents.
@@ -35,14 +36,21 @@ def create(
radiation_probe: str | None = None,
scattering_type: str | None = None,
) -> None:
- """Add an experiment without associating a data file.
-
- Args:
- name: Experiment identifier.
- sample_form: Sample form (e.g. ``'powder'``).
- beam_mode: Beam mode (e.g. ``'constant wavelength'``).
- radiation_probe: Radiation probe (e.g. ``'neutron'``).
- scattering_type: Scattering type (e.g. ``'bragg'``).
+ """
+ Add an experiment without associating a data file.
+
+ Parameters
+ ----------
+ name : str
+ Experiment identifier.
+ sample_form : str | None, default=None
+ Sample form (e.g. ``'powder'``).
+ beam_mode : str | None, default=None
+ Beam mode (e.g. ``'constant wavelength'``).
+ radiation_probe : str | None, default=None
+ Radiation probe (e.g. ``'neutron'``).
+ scattering_type : str | None, default=None
+ Scattering type (e.g. ``'bragg'``).
"""
experiment = ExperimentFactory.from_scratch(
name=name,
@@ -59,10 +67,13 @@ def add_from_cif_str(
self,
cif_str: str,
) -> None:
- """Add an experiment from a CIF string.
+ """
+ Add an experiment from a CIF string.
- Args:
- cif_str: Full CIF document as a string.
+ Parameters
+ ----------
+ cif_str : str
+ Full CIF document as a string.
"""
experiment = ExperimentFactory.from_cif_str(cif_str)
self.add(experiment)
@@ -73,10 +84,13 @@ def add_from_cif_path(
self,
cif_path: str,
) -> None:
- """Add an experiment from a CIF file path.
+ """
+ Add an experiment from a CIF file path.
- Args:
- cif_path(str): Path to a CIF document.
+ Parameters
+ ----------
+ cif_path : str
+ Path to a CIF document.
"""
experiment = ExperimentFactory.from_cif_path(cif_path)
self.add(experiment)
@@ -92,15 +106,23 @@ def add_from_data_path(
radiation_probe: str | None = None,
scattering_type: str | None = None,
) -> None:
- """Add an experiment from a data file path.
-
- Args:
- name: Experiment identifier.
- data_path: Path to the measured data file.
- sample_form: Sample form (e.g. ``'powder'``).
- beam_mode: Beam mode (e.g. ``'constant wavelength'``).
- radiation_probe: Radiation probe (e.g. ``'neutron'``).
- scattering_type: Scattering type (e.g. ``'bragg'``).
+ """
+ Add an experiment from a data file path.
+
+ Parameters
+ ----------
+ name : str
+ Experiment identifier.
+ data_path : str
+ Path to the measured data file.
+ sample_form : str | None, default=None
+ Sample form (e.g. ``'powder'``).
+ beam_mode : str | None, default=None
+ Beam mode (e.g. ``'constant wavelength'``).
+ radiation_probe : str | None, default=None
+ Radiation probe (e.g. ``'neutron'``).
+ scattering_type : str | None, default=None
+ Scattering type (e.g. ``'bragg'``).
"""
experiment = ExperimentFactory.from_data_path(
name=name,
diff --git a/src/easydiffraction/datablocks/experiment/item/__init__.py b/src/easydiffraction/datablocks/experiment/item/__init__.py
index ffe5775d..35a64fb1 100644
--- a/src/easydiffraction/datablocks/experiment/item/__init__.py
+++ b/src/easydiffraction/datablocks/experiment/item/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.experiment.item.base import ExperimentBase
diff --git a/src/easydiffraction/datablocks/experiment/item/base.py b/src/easydiffraction/datablocks/experiment/item/base.py
index 24c6ee6e..2dddee44 100644
--- a/src/easydiffraction/datablocks/experiment/item/base.py
+++ b/src/easydiffraction/datablocks/experiment/item/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Base classes for experiment datablock items."""
@@ -34,16 +34,14 @@
class ExperimentBase(DatablockItem):
- """Base class for all experiment datablock items with only core
- attributes.
- """
+ """Base class for all experiment datablock items."""
def __init__(
self,
*,
name: str,
type: ExperimentType,
- ):
+ ) -> None:
super().__init__()
self._name = name
self._type = type
@@ -58,18 +56,19 @@ def name(self) -> str:
@name.setter
def name(self, new: str) -> None:
- """Rename the experiment.
+ """
+ Rename the experiment.
- Args:
- new: New name for this experiment.
+ Parameters
+ ----------
+ new : str
+ New name for this experiment.
"""
self._name = new
@property
- def type(self): # TODO: Consider another name
- """Experiment type descriptor (sample form, probe, beam
- mode).
- """
+ def type(self) -> object: # TODO: Consider another name
+ """Experiment type: sample form, probe, beam mode."""
return self._type
@property
@@ -86,10 +85,18 @@ def show_as_cif(self) -> None:
@abstractmethod
def _load_ascii_data_to_experiment(self, data_path: str) -> None:
- """Load ASCII data from file into the experiment data category.
+ """
+ Load ASCII data from file into the experiment data category.
+
+ Parameters
+ ----------
+ data_path : str
+ Path to the ASCII file to load.
- Args:
- data_path: Path to the ASCII file to load.
+ Raises
+ ------
+ NotImplementedError
+ Subclasses must implement this method.
"""
raise NotImplementedError()
@@ -98,8 +105,9 @@ def _load_ascii_data_to_experiment(self, data_path: str) -> None:
# ------------------------------------------------------------------
@property
- def calculator(self):
- """The active calculator instance for this experiment.
+ def calculator(self) -> object:
+ """
+ The active calculator instance for this experiment.
Auto-resolved on first access from the experiment's data
category ``calculator_support`` and
@@ -118,11 +126,14 @@ def calculator_type(self) -> str:
@calculator_type.setter
def calculator_type(self, tag: str) -> None:
- """Switch to a different calculator backend.
+ """
+ Switch to a different calculator backend.
- Args:
- tag: Calculator tag (e.g. ``'cryspy'``, ``'crysfml'``,
- ``'pdffit'``).
+ Parameters
+ ----------
+ tag : str
+ Calculator tag (e.g. ``'cryspy'``, ``'crysfml'``,
+ ``'pdffit'``).
"""
from easydiffraction.analysis.calculators.factory import CalculatorFactory
@@ -140,9 +151,7 @@ def calculator_type(self, tag: str) -> None:
console.print(tag)
def show_supported_calculator_types(self) -> None:
- """Print a table of calculator backends supported by this
- experiment.
- """
+ """Print a table of supported calculator backends."""
from easydiffraction.analysis.calculators.factory import CalculatorFactory
supported_tags = self._supported_calculator_tags()
@@ -169,10 +178,7 @@ def show_current_calculator_type(self) -> None:
console.print(self.calculator_type)
def _resolve_calculator(self) -> None:
- """Auto-resolve the default calculator from the data category's
- ``calculator_support`` and
- ``CalculatorFactory._default_rules``.
- """
+ """Auto-resolve the default calculator from data category."""
from easydiffraction.analysis.calculators.factory import CalculatorFactory
tag = CalculatorFactory.default_tag(
@@ -185,7 +191,8 @@ def _resolve_calculator(self) -> None:
self._calculator_type = tag
def _supported_calculator_tags(self) -> list[str]:
- """Return calculator tags supported by this experiment.
+ """
+ Return calculator tags supported by this experiment.
Intersects the data category's ``calculator_support`` with
calculators whose engines are importable.
@@ -231,11 +238,14 @@ def __init__(
@abstractmethod
def _load_ascii_data_to_experiment(self, data_path: str) -> None:
- """Load single crystal data from an ASCII file.
+ """
+ Load single crystal data from an ASCII file.
- Args:
- data_path: Path to data file with columns compatible with
- the beam mode.
+ Parameters
+ ----------
+ data_path : str
+ Path to data file with columns compatible with the beam
+ mode.
"""
pass
@@ -244,7 +254,7 @@ def _load_ascii_data_to_experiment(self, data_path: str) -> None:
# ------------------------------------------------------------------
@property
- def extinction(self):
+ def extinction(self) -> object:
"""Active extinction correction model."""
return self._extinction
@@ -255,10 +265,13 @@ def extinction_type(self) -> str:
@extinction_type.setter
def extinction_type(self, new_type: str) -> None:
- """Switch to a different extinction correction model.
+ """
+ Switch to a different extinction correction model.
- Args:
- new_type: Extinction tag (e.g. ``'shelx'``).
+ Parameters
+ ----------
+ new_type : str
+ Extinction tag (e.g. ``'shelx'``).
"""
supported_tags = ExtinctionFactory.supported_tags()
if new_type not in supported_tags:
@@ -288,7 +301,7 @@ def show_current_extinction_type(self) -> None:
# ------------------------------------------------------------------
@property
- def linked_crystal(self):
+ def linked_crystal(self) -> object:
"""Linked crystal model for this experiment."""
return self._linked_crystal
@@ -299,10 +312,13 @@ def linked_crystal_type(self) -> str:
@linked_crystal_type.setter
def linked_crystal_type(self, new_type: str) -> None:
- """Switch to a different linked-crystal reference type.
+ """
+ Switch to a different linked-crystal reference type.
- Args:
- new_type: Linked-crystal tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Linked-crystal tag (e.g. ``'default'``).
"""
supported_tags = LinkedCrystalFactory.supported_tags()
if new_type not in supported_tags:
@@ -332,7 +348,7 @@ def show_current_linked_crystal_type(self) -> None:
# ------------------------------------------------------------------
@property
- def instrument(self):
+ def instrument(self) -> object:
"""Active instrument model for this experiment."""
return self._instrument
@@ -343,10 +359,13 @@ def instrument_type(self) -> str:
@instrument_type.setter
def instrument_type(self, new_type: str) -> None:
- """Switch to a different instrument type.
+ """
+ Switch to a different instrument type.
- Args:
- new_type: Instrument tag (e.g. ``'cwl-sc'``).
+ Parameters
+ ----------
+ new_type : str
+ Instrument tag (e.g. ``'cwl-sc'``).
"""
supported = InstrumentFactory.supported_for(
scattering_type=self.type.scattering_type.value,
@@ -384,7 +403,7 @@ def show_current_instrument_type(self) -> None:
# ------------------------------------------------------------------
@property
- def data(self):
+ def data(self) -> object:
"""Data collection for this experiment."""
return self._data
@@ -395,10 +414,13 @@ def data_type(self) -> str:
@data_type.setter
def data_type(self, new_type: str) -> None:
- """Switch to a different data collection type.
+ """
+ Switch to a different data collection type.
- Args:
- new_type: Data tag (e.g. ``'bragg-sc'``).
+ Parameters
+ ----------
+ new_type : str
+ Data tag (e.g. ``'bragg-sc'``).
"""
supported_tags = DataFactory.supported_tags()
if new_type not in supported_tags:
@@ -454,12 +476,17 @@ def _get_valid_linked_phases(
self,
structures: Structures,
) -> List[Any]:
- """Get valid linked phases for this experiment.
+ """
+ Get valid linked phases for this experiment.
- Args:
- structures: Collection of structures.
+ Parameters
+ ----------
+ structures : Structures
+ Collection of structures.
- Returns:
+ Returns
+ -------
+ List[Any]
A list of valid linked phases.
"""
if not self.linked_phases:
@@ -485,16 +512,19 @@ def _get_valid_linked_phases(
@abstractmethod
def _load_ascii_data_to_experiment(self, data_path: str) -> None:
- """Load powder diffraction data from an ASCII file.
+ """
+ Load powder diffraction data from an ASCII file.
- Args:
- data_path: Path to data file with columns compatible with
- the beam mode (e.g. 2θ/I/σ for CWL, TOF/I/σ for TOF).
+ Parameters
+ ----------
+ data_path : str
+ Path to data file with columns compatible with the beam mode
+ (e.g. 2θ/I/σ for CWL, TOF/I/σ for TOF).
"""
pass
@property
- def linked_phases(self):
+ def linked_phases(self) -> object:
"""Collection of phases linked to this experiment."""
return self._linked_phases
@@ -505,10 +535,13 @@ def linked_phases_type(self) -> str:
@linked_phases_type.setter
def linked_phases_type(self, new_type: str) -> None:
- """Switch to a different linked-phases collection type.
+ """
+ Switch to a different linked-phases collection type.
- Args:
- new_type: Linked-phases tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Linked-phases tag (e.g. ``'default'``).
"""
supported_tags = LinkedPhasesFactory.supported_tags()
if new_type not in supported_tags:
@@ -534,7 +567,7 @@ def show_current_linked_phases_type(self) -> None:
console.print(self.linked_phases_type)
@property
- def excluded_regions(self):
+ def excluded_regions(self) -> object:
"""Collection of excluded regions for the x-grid."""
return self._excluded_regions
@@ -545,10 +578,13 @@ def excluded_regions_type(self) -> str:
@excluded_regions_type.setter
def excluded_regions_type(self, new_type: str) -> None:
- """Switch to a different excluded-regions collection type.
+ """
+ Switch to a different excluded-regions collection type.
- Args:
- new_type: Excluded-regions tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Excluded-regions tag (e.g. ``'default'``).
"""
supported_tags = ExcludedRegionsFactory.supported_tags()
if new_type not in supported_tags:
@@ -565,9 +601,7 @@ def excluded_regions_type(self, new_type: str) -> None:
console.print(new_type)
def show_supported_excluded_regions_types(self) -> None:
- """Print a table of supported excluded-regions collection
- types.
- """
+ """Print a table of supported excluded-regions types."""
ExcludedRegionsFactory.show_supported()
def show_current_excluded_regions_type(self) -> None:
@@ -580,7 +614,7 @@ def show_current_excluded_regions_type(self) -> None:
# ------------------------------------------------------------------
@property
- def data(self):
+ def data(self) -> object:
"""Data collection for this experiment."""
return self._data
@@ -591,10 +625,13 @@ def data_type(self) -> str:
@data_type.setter
def data_type(self, new_type: str) -> None:
- """Switch to a different data collection type.
+ """
+ Switch to a different data collection type.
- Args:
- new_type: Data tag (e.g. ``'bragg-pd-cwl'``).
+ Parameters
+ ----------
+ new_type : str
+ Data tag (e.g. ``'bragg-pd-cwl'``).
"""
supported_tags = DataFactory.supported_tags()
if new_type not in supported_tags:
@@ -619,21 +656,24 @@ def show_current_data_type(self) -> None:
console.print(self.data_type)
@property
- def peak(self):
+ def peak(self) -> object:
"""Peak category object with profile parameters and mixins."""
return self._peak
@property
- def peak_profile_type(self):
+ def peak_profile_type(self) -> object:
"""Currently selected peak profile type enum."""
return self._peak_profile_type
@peak_profile_type.setter
- def peak_profile_type(self, new_type: str):
- """Change the active peak profile type, if supported.
+ def peak_profile_type(self, new_type: str) -> None:
+ """
+ Change the active peak profile type, if supported.
- Args:
- new_type: New profile type as tag string.
+ Parameters
+ ----------
+ new_type : str
+ New profile type as tag string.
"""
supported = PeakFactory.supported_for(
scattering_type=self.type.scattering_type.value,
@@ -659,14 +699,14 @@ def peak_profile_type(self, new_type: str):
console.paragraph(f"Peak profile type for experiment '{self.name}' changed to")
console.print(new_type)
- def show_supported_peak_profile_types(self):
+ def show_supported_peak_profile_types(self) -> None:
"""Print available peak profile types for this experiment."""
PeakFactory.show_supported(
scattering_type=self.type.scattering_type.value,
beam_mode=self.type.beam_mode.value,
)
- def show_current_peak_profile_type(self):
+ def show_current_peak_profile_type(self) -> None:
"""Print the currently selected peak profile type."""
console.paragraph('Current peak profile type')
console.print(self.peak_profile_type)
diff --git a/src/easydiffraction/datablocks/experiment/item/bragg_pd.py b/src/easydiffraction/datablocks/experiment/item/bragg_pd.py
index 258085c5..d5b469cf 100644
--- a/src/easydiffraction/datablocks/experiment/item/bragg_pd.py
+++ b/src/easydiffraction/datablocks/experiment/item/bragg_pd.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -25,9 +25,7 @@
@ExperimentFactory.register
class BraggPdExperiment(PdExperimentBase):
- """Standard (Bragg) Powder Diffraction experiment class with
- specific attributes.
- """
+ """Standard Bragg powder diffraction experiment."""
type_info = TypeInfo(
tag='bragg-pd',
@@ -57,8 +55,8 @@ def __init__(
self._background = BackgroundFactory.create(self._background_type)
def _load_ascii_data_to_experiment(self, data_path: str) -> None:
- """Load (x, y, sy) data from an ASCII file into the data
- category.
+ """
+ Load (x, y, sy) data from an ASCII file into the data category.
The file format is space/column separated with 2 or 3 columns:
``x y [sy]``. If ``sy`` is missing, it is approximated as
@@ -105,7 +103,7 @@ def _load_ascii_data_to_experiment(self, data_path: str) -> None:
# ------------------------------------------------------------------
@property
- def instrument(self):
+ def instrument(self) -> object:
"""Active instrument model for this experiment."""
return self._instrument
@@ -116,10 +114,13 @@ def instrument_type(self) -> str:
@instrument_type.setter
def instrument_type(self, new_type: str) -> None:
- """Switch to a different instrument type.
+ """
+ Switch to a different instrument type.
- Args:
- new_type: Instrument tag (e.g. ``'cwl-pd'``).
+ Parameters
+ ----------
+ new_type : str
+ Instrument tag (e.g. ``'cwl-pd'``).
"""
supported = InstrumentFactory.supported_for(
scattering_type=self.type.scattering_type.value,
@@ -157,12 +158,12 @@ def show_current_instrument_type(self) -> None:
# ------------------------------------------------------------------
@property
- def background_type(self):
+ def background_type(self) -> object:
"""Current background type enum value."""
return self._background_type
@background_type.setter
- def background_type(self, new_type):
+ def background_type(self, new_type: str) -> None:
"""Set a new background type and recreate background object."""
if self._background_type == new_type:
console.paragraph(f"Background type for experiment '{self.name}' already set to")
@@ -190,14 +191,15 @@ def background_type(self, new_type):
console.print(new_type)
@property
- def background(self):
+ def background(self) -> object:
+ """Active background model for this experiment."""
return self._background
- def show_supported_background_types(self):
+ def show_supported_background_types(self) -> None:
"""Print a table of supported background types."""
BackgroundFactory.show_supported()
- def show_current_background_type(self):
+ def show_current_background_type(self) -> None:
"""Print the currently used background type."""
console.paragraph('Current background type')
console.print(self.background_type)
diff --git a/src/easydiffraction/datablocks/experiment/item/bragg_sc.py b/src/easydiffraction/datablocks/experiment/item/bragg_sc.py
index e8142e0e..3cb3f8a1 100644
--- a/src/easydiffraction/datablocks/experiment/item/bragg_sc.py
+++ b/src/easydiffraction/datablocks/experiment/item/bragg_sc.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -23,9 +23,7 @@
@ExperimentFactory.register
class CwlScExperiment(ScExperimentBase):
- """Standard (Bragg) constant wavelength single srystal experiment
- class with specific attributes.
- """
+ """Bragg constant-wavelength single-crystal experiment."""
type_info = TypeInfo(
tag='bragg-sc-cwl',
@@ -46,10 +44,11 @@ def __init__(
super().__init__(name=name, type=type)
def _load_ascii_data_to_experiment(self, data_path: str) -> None:
- """Load measured data from an ASCII file into the data category.
+ """
+ Load measured data from an ASCII file into the data category.
- The file format is space/column separated with 5 columns:
- ``h k l Iobs sIobs``.
+ The file format is space/column separated with 5 columns: ``h k
+ l Iobs sIobs``.
"""
try:
data = np.loadtxt(data_path)
@@ -87,9 +86,7 @@ def _load_ascii_data_to_experiment(self, data_path: str) -> None:
@ExperimentFactory.register
class TofScExperiment(ScExperimentBase):
- """Standard (Bragg) time-of-flight single srystal experiment class
- with specific attributes.
- """
+ """Bragg time-of-flight single-crystal experiment."""
type_info = TypeInfo(
tag='bragg-sc-tof',
@@ -110,10 +107,11 @@ def __init__(
super().__init__(name=name, type=type)
def _load_ascii_data_to_experiment(self, data_path: str) -> None:
- """Load measured data from an ASCII file into the data category.
+ """
+ Load measured data from an ASCII file into the data category.
- The file format is space/column separated with 6 columns:
- ``h k l Iobs sIobs wavelength``.
+ The file format is space/column separated with 6 columns: ``h k
+ l Iobs sIobs wavelength``.
"""
try:
data = np.loadtxt(data_path)
diff --git a/src/easydiffraction/datablocks/experiment/item/enums.py b/src/easydiffraction/datablocks/experiment/item/enums.py
index 8d0f153e..2375c38e 100644
--- a/src/easydiffraction/datablocks/experiment/item/enums.py
+++ b/src/easydiffraction/datablocks/experiment/item/enums.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Enumerations for experiment configuration (forms, modes, types)."""
@@ -13,9 +13,25 @@ class SampleFormEnum(str, Enum):
@classmethod
def default(cls) -> 'SampleFormEnum':
+ """
+ Return the default sample form (POWDER).
+
+ Returns
+ -------
+ 'SampleFormEnum'
+ The default enum member.
+ """
return cls.POWDER
def description(self) -> str:
+ """
+ Return a human-readable description of this sample form.
+
+ Returns
+ -------
+ str
+ Description string for the current enum member.
+ """
if self is SampleFormEnum.POWDER:
return 'Powdered or polycrystalline sample.'
elif self is SampleFormEnum.SINGLE_CRYSTAL:
@@ -30,9 +46,25 @@ class ScatteringTypeEnum(str, Enum):
@classmethod
def default(cls) -> 'ScatteringTypeEnum':
+ """
+ Return the default scattering type (BRAGG).
+
+ Returns
+ -------
+ 'ScatteringTypeEnum'
+ The default enum member.
+ """
return cls.BRAGG
def description(self) -> str:
+ """
+ Return a human-readable description of this scattering type.
+
+ Returns
+ -------
+ str
+ Description string for the current enum member.
+ """
if self is ScatteringTypeEnum.BRAGG:
return 'Bragg diffraction for conventional structure refinement.'
elif self is ScatteringTypeEnum.TOTAL:
@@ -47,9 +79,25 @@ class RadiationProbeEnum(str, Enum):
@classmethod
def default(cls) -> 'RadiationProbeEnum':
+ """
+ Return the default radiation probe (NEUTRON).
+
+ Returns
+ -------
+ 'RadiationProbeEnum'
+ The default enum member.
+ """
return cls.NEUTRON
def description(self) -> str:
+ """
+ Return a human-readable description of this radiation probe.
+
+ Returns
+ -------
+ str
+ Description string for the current enum member.
+ """
if self is RadiationProbeEnum.NEUTRON:
return 'Neutron diffraction.'
elif self is RadiationProbeEnum.XRAY:
@@ -65,9 +113,25 @@ class BeamModeEnum(str, Enum):
@classmethod
def default(cls) -> 'BeamModeEnum':
+ """
+ Return the default beam mode (CONSTANT_WAVELENGTH).
+
+ Returns
+ -------
+ 'BeamModeEnum'
+ The default enum member.
+ """
return cls.CONSTANT_WAVELENGTH
def description(self) -> str:
+ """
+ Return a human-readable description of this beam mode.
+
+ Returns
+ -------
+ str
+ Description string for the current enum member.
+ """
if self is BeamModeEnum.CONSTANT_WAVELENGTH:
return 'Constant wavelength (CW) diffraction.'
elif self is BeamModeEnum.TIME_OF_FLIGHT:
@@ -104,6 +168,23 @@ def default(
scattering_type: ScatteringTypeEnum | None = None,
beam_mode: BeamModeEnum | None = None,
) -> 'PeakProfileTypeEnum':
+ """
+ Return the default peak profile type for a given mode.
+
+ Parameters
+ ----------
+ scattering_type : ScatteringTypeEnum | None, default=None
+ Scattering type; defaults to
+ ``ScatteringTypeEnum.default()`` when ``None``.
+ beam_mode : BeamModeEnum | None, default=None
+ Beam mode; defaults to ``BeamModeEnum.default()`` when
+ ``None``.
+
+ Returns
+ -------
+ 'PeakProfileTypeEnum'
+ The default profile type for the given combination.
+ """
if scattering_type is None:
scattering_type = ScatteringTypeEnum.default()
if beam_mode is None:
@@ -119,6 +200,14 @@ def default(
}[(scattering_type, beam_mode)]
def description(self) -> str:
+ """
+ Return a human-readable description of this peak profile type.
+
+ Returns
+ -------
+ str
+ Description string for the current enum member.
+ """
if self is PeakProfileTypeEnum.PSEUDO_VOIGT:
return 'Pseudo-Voigt profile'
elif self is PeakProfileTypeEnum.SPLIT_PSEUDO_VOIGT:
diff --git a/src/easydiffraction/datablocks/experiment/item/factory.py b/src/easydiffraction/datablocks/experiment/item/factory.py
index 3e5aebb5..6406ed30 100644
--- a/src/easydiffraction/datablocks/experiment/item/factory.py
+++ b/src/easydiffraction/datablocks/experiment/item/factory.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Factory for creating experiment instances from various inputs.
+"""
+Factory for creating experiment instances from various inputs.
Provides individual class methods for each creation pathway:
``from_cif_path``, ``from_cif_str``, ``from_data_path``, and
@@ -55,7 +56,7 @@ class ExperimentFactory(FactoryBase):
}
# TODO: Add to core/factory.py?
- def __init__(self):
+ def __init__(self) -> None:
log.error(
'Experiment objects must be created using class methods such as '
'`ExperimentFactory.from_cif_str(...)`, etc.'
@@ -74,9 +75,7 @@ def _create_experiment_type(
radiation_probe: str | None = None,
scattering_type: str | None = None,
) -> ExperimentType:
- """Construct an ExperimentType, using defaults for omitted
- values.
- """
+ """Construct ExperimentType with defaults for omitted values."""
# Note: validation of input values is done via Descriptor setter
# methods
@@ -95,7 +94,7 @@ def _create_experiment_type(
@classmethod
@typechecked
- def _resolve_class(cls, expt_type: ExperimentType):
+ def _resolve_class(cls, expt_type: ExperimentType) -> type:
"""Look up the experiment class from the type enums."""
tag = cls.default_tag(
scattering_type=expt_type.scattering_type.value,
@@ -140,16 +139,25 @@ def from_scratch(
radiation_probe: str | None = None,
scattering_type: str | None = None,
) -> ExperimentBase:
- """Create an experiment without measured data.
-
- Args:
- name: Experiment identifier.
- sample_form: Sample form (e.g. ``'powder'``).
- beam_mode: Beam mode (e.g. ``'constant wavelength'``).
- radiation_probe: Radiation probe (e.g. ``'neutron'``).
- scattering_type: Scattering type (e.g. ``'bragg'``).
-
- Returns:
+ """
+ Create an experiment without measured data.
+
+ Parameters
+ ----------
+ name : str
+ Experiment identifier.
+ sample_form : str | None, default=None
+ Sample form (e.g. ``'powder'``).
+ beam_mode : str | None, default=None
+ Beam mode (e.g. ``'constant wavelength'``).
+ radiation_probe : str | None, default=None
+ Radiation probe (e.g. ``'neutron'``).
+ scattering_type : str | None, default=None
+ Scattering type (e.g. ``'bragg'``).
+
+ Returns
+ -------
+ ExperimentBase
An experiment instance with only metadata.
"""
expt_type = cls._create_experiment_type(
@@ -169,12 +177,17 @@ def from_cif_str(
cls,
cif_str: str,
) -> ExperimentBase:
- """Create an experiment from a CIF string.
+ """
+ Create an experiment from a CIF string.
- Args:
- cif_str: Full CIF document as a string.
+ Parameters
+ ----------
+ cif_str : str
+ Full CIF document as a string.
- Returns:
+ Returns
+ -------
+ ExperimentBase
A populated experiment instance.
"""
doc = document_from_string(cif_str)
@@ -188,12 +201,17 @@ def from_cif_path(
cls,
cif_path: str,
) -> ExperimentBase:
- """Create an experiment from a CIF file path.
+ """
+ Create an experiment from a CIF file path.
- Args:
- cif_path: Path to a CIF file.
+ Parameters
+ ----------
+ cif_path : str
+ Path to a CIF file.
- Returns:
+ Returns
+ -------
+ ExperimentBase
A populated experiment instance.
"""
doc = document_from_path(cif_path)
@@ -212,17 +230,27 @@ def from_data_path(
radiation_probe: str | None = None,
scattering_type: str | None = None,
) -> ExperimentBase:
- """Create an experiment from a raw data ASCII file.
-
- Args:
- name: Experiment identifier.
- data_path: Path to the measured data file.
- sample_form: Sample form (e.g. ``'powder'``).
- beam_mode: Beam mode (e.g. ``'constant wavelength'``).
- radiation_probe: Radiation probe (e.g. ``'neutron'``).
- scattering_type: Scattering type (e.g. ``'bragg'``).
-
- Returns:
+ """
+ Create an experiment from a raw data ASCII file.
+
+ Parameters
+ ----------
+ name : str
+ Experiment identifier.
+ data_path : str
+ Path to the measured data file.
+ sample_form : str | None, default=None
+ Sample form (e.g. ``'powder'``).
+ beam_mode : str | None, default=None
+ Beam mode (e.g. ``'constant wavelength'``).
+ radiation_probe : str | None, default=None
+ Radiation probe (e.g. ``'neutron'``).
+ scattering_type : str | None, default=None
+ Scattering type (e.g. ``'bragg'``).
+
+ Returns
+ -------
+ ExperimentBase
An experiment instance with measured data attached.
"""
expt_obj = cls.from_scratch(
diff --git a/src/easydiffraction/datablocks/experiment/item/total_pd.py b/src/easydiffraction/datablocks/experiment/item/total_pd.py
index 881dd0ce..ade11e6f 100644
--- a/src/easydiffraction/datablocks/experiment/item/total_pd.py
+++ b/src/easydiffraction/datablocks/experiment/item/total_pd.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
@@ -38,15 +38,14 @@ def __init__(
self,
name: str,
type: ExperimentType,
- ):
+ ) -> None:
super().__init__(name=name, type=type)
- def _load_ascii_data_to_experiment(self, data_path):
- """Loads x, y, sy values from an ASCII data file into the
- experiment.
+ def _load_ascii_data_to_experiment(self, data_path: str) -> None:
+ """
+ Load x, y, sy values from an ASCII file into the experiment.
- The file must be structured as:
- x y sy
+ The file must be structured as: x y sy
"""
try:
from diffpy.utils.parsers.loaddata import loadData
diff --git a/src/easydiffraction/datablocks/structure/__init__.py b/src/easydiffraction/datablocks/structure/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/datablocks/structure/__init__.py
+++ b/src/easydiffraction/datablocks/structure/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/datablocks/structure/categories/__init__.py b/src/easydiffraction/datablocks/structure/categories/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/datablocks/structure/categories/__init__.py
+++ b/src/easydiffraction/datablocks/structure/categories/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/datablocks/structure/categories/atom_sites/__init__.py b/src/easydiffraction/datablocks/structure/categories/atom_sites/__init__.py
index cb4c1750..7bd7b9ad 100644
--- a/src/easydiffraction/datablocks/structure/categories/atom_sites/__init__.py
+++ b/src/easydiffraction/datablocks/structure/categories/atom_sites/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.structure.categories.atom_sites.default import AtomSite
diff --git a/src/easydiffraction/datablocks/structure/categories/atom_sites/default.py b/src/easydiffraction/datablocks/structure/categories/atom_sites/default.py
index 76d890d5..265c3c62 100644
--- a/src/easydiffraction/datablocks/structure/categories/atom_sites/default.py
+++ b/src/easydiffraction/datablocks/structure/categories/atom_sites/default.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Atom site category.
+"""
+Atom site category.
Defines :class:`AtomSite` items and :class:`AtomSites` collection used
in crystallographic structures.
@@ -25,7 +26,8 @@
class AtomSite(CategoryItem):
- """Single atom site with fractional coordinates and ADP.
+ """
+ Single atom site with fractional coordinates and ADP.
Attributes are represented by descriptors to support validation and
CIF serialization.
@@ -138,19 +140,25 @@ def __init__(self) -> None:
@property
def _type_symbol_allowed_values(self) -> list[str]:
- """Return chemical symbols accepted by *cryspy*.
+ """
+ Return chemical symbols accepted by *cryspy*.
- Returns:
- list[str]: Unique element/isotope symbols from the database.
+ Returns
+ -------
+ list[str]
+ Unique element/isotope symbols from the database.
"""
return list({key[1] for key in DATABASE['Isotopes']})
@property
def _wyckoff_letter_allowed_values(self) -> list[str]:
- """Return allowed Wyckoff-letter symbols.
+ """
+ Return allowed Wyckoff-letter symbols.
- Returns:
- list[str]: Currently a hard-coded placeholder list.
+ Returns
+ -------
+ list[str]
+ Currently a hard-coded placeholder list.
"""
# TODO: Need to now current space group. How to access it? Via
# parent Cell? Then letters =
@@ -160,10 +168,13 @@ def _wyckoff_letter_allowed_values(self) -> list[str]:
@property
def _wyckoff_letter_default_value(self) -> str:
- """Return the default Wyckoff letter.
+ """
+ Return the default Wyckoff letter.
- Returns:
- str: First element of the allowed values list.
+ Returns
+ -------
+ str
+ First element of the allowed values list.
"""
# TODO: What to pass as default?
return self._wyckoff_letter_allowed_values[0]
@@ -174,165 +185,132 @@ def _wyckoff_letter_default_value(self) -> str:
@property
def label(self) -> StringDescriptor:
- """Unique label for this atom site.
+ """
+ Unique identifier for the atom site.
- Returns:
- StringDescriptor: Descriptor holding the site label.
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
"""
return self._label
@label.setter
def label(self, value: str) -> None:
- """Set the atom-site label.
-
- Args:
- value (str): New label string.
- """
self._label.value = value
@property
def type_symbol(self) -> StringDescriptor:
- """Chemical element or isotope symbol.
+ """
+ Chemical symbol of the atom at this site.
- Returns:
- StringDescriptor: Descriptor holding the type symbol.
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
"""
return self._type_symbol
@type_symbol.setter
def type_symbol(self, value: str) -> None:
- """Set the chemical element or isotope symbol.
-
- Args:
- value (str): New type symbol (must be in the *cryspy*
- database).
- """
self._type_symbol.value = value
@property
def adp_type(self) -> StringDescriptor:
- """Type of atomic displacement parameter (e.g. ``'Biso'``).
+ """
+ ADP type used (e.g., Biso, Uiso, Uani, Bani).
- Returns:
- StringDescriptor: Descriptor holding the ADP type.
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
"""
return self._adp_type
@adp_type.setter
def adp_type(self, value: str) -> None:
- """Set the ADP type.
-
- Args:
- value (str): New ADP type string.
- """
self._adp_type.value = value
@property
def wyckoff_letter(self) -> StringDescriptor:
- """Wyckoff letter for the symmetry site.
+ """
+ Wyckoff letter for the atom site symmetry position.
- Returns:
- StringDescriptor: Descriptor holding the Wyckoff letter.
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
"""
return self._wyckoff_letter
@wyckoff_letter.setter
def wyckoff_letter(self, value: str) -> None:
- """Set the Wyckoff letter.
-
- Args:
- value (str): New Wyckoff letter.
- """
self._wyckoff_letter.value = value
@property
def fract_x(self) -> Parameter:
- """Fractional *x*-coordinate within the unit cell.
+ """
+ Fractional x-coordinate of the atom site within the unit cell.
- Returns:
- Parameter: Descriptor for the *x* coordinate.
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._fract_x
@fract_x.setter
def fract_x(self, value: float) -> None:
- """Set the fractional *x*-coordinate.
-
- Args:
- value (float): New *x* coordinate.
- """
self._fract_x.value = value
@property
def fract_y(self) -> Parameter:
- """Fractional *y*-coordinate within the unit cell.
+ """
+ Fractional y-coordinate of the atom site within the unit cell.
- Returns:
- Parameter: Descriptor for the *y* coordinate.
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._fract_y
@fract_y.setter
def fract_y(self, value: float) -> None:
- """Set the fractional *y*-coordinate.
-
- Args:
- value (float): New *y* coordinate.
- """
self._fract_y.value = value
@property
def fract_z(self) -> Parameter:
- """Fractional *z*-coordinate within the unit cell.
+ """
+ Fractional z-coordinate of the atom site within the unit cell.
- Returns:
- Parameter: Descriptor for the *z* coordinate.
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._fract_z
@fract_z.setter
def fract_z(self, value: float) -> None:
- """Set the fractional *z*-coordinate.
-
- Args:
- value (float): New *z* coordinate.
- """
self._fract_z.value = value
@property
def occupancy(self) -> Parameter:
- """Site occupancy fraction.
+ """
+ Occupancy fraction of the atom type at this site.
- Returns:
- Parameter: Descriptor for the occupancy (0–1).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._occupancy
@occupancy.setter
def occupancy(self, value: float) -> None:
- """Set the site occupancy.
-
- Args:
- value (float): New occupancy fraction.
- """
self._occupancy.value = value
@property
def b_iso(self) -> Parameter:
- r"""Isotropic atomic displacement parameter (*B*-factor).
+ """
+ Isotropic ADP for the atom site (Ų).
- Returns:
- Parameter: Descriptor for *B*\_iso (Ų).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._b_iso
@b_iso.setter
def b_iso(self, value: float) -> None:
- r"""Set the isotropic displacement parameter.
-
- Args:
- value (float): New *B*\_iso value in Ų.
- """
self._b_iso.value = value
@@ -354,7 +332,8 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
def _apply_atomic_coordinates_symmetry_constraints(self) -> None:
- """Apply symmetry rules to fractional coordinates of every site.
+ """
+ Apply symmetry rules to fractional coordinates of every site.
Uses the parent structure's space-group symbol, IT coordinate
system code and each atom's Wyckoff letter. Atoms without a
@@ -387,11 +366,14 @@ def _update(
self,
called_by_minimizer: bool = False,
) -> None:
- """Recalculate atom sites after a change.
+ """
+ Recalculate atom sites after a change.
- Args:
- called_by_minimizer (bool): Whether the update was triggered
- by the fitting minimizer. Currently unused.
+ Parameters
+ ----------
+ called_by_minimizer : bool, default=False
+ Whether the update was triggered by the fitting minimizer.
+ Currently unused.
"""
del called_by_minimizer
diff --git a/src/easydiffraction/datablocks/structure/categories/atom_sites/factory.py b/src/easydiffraction/datablocks/structure/categories/atom_sites/factory.py
index e233d0bd..c91b3dda 100644
--- a/src/easydiffraction/datablocks/structure/categories/atom_sites/factory.py
+++ b/src/easydiffraction/datablocks/structure/categories/atom_sites/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Atom-sites factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/structure/categories/cell/__init__.py b/src/easydiffraction/datablocks/structure/categories/cell/__init__.py
index 08773b3e..16f6cab2 100644
--- a/src/easydiffraction/datablocks/structure/categories/cell/__init__.py
+++ b/src/easydiffraction/datablocks/structure/categories/cell/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.structure.categories.cell.default import Cell
diff --git a/src/easydiffraction/datablocks/structure/categories/cell/default.py b/src/easydiffraction/datablocks/structure/categories/cell/default.py
index e07e20e0..53cc98ee 100644
--- a/src/easydiffraction/datablocks/structure/categories/cell/default.py
+++ b/src/easydiffraction/datablocks/structure/categories/cell/default.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Unit cell parameters category for structures."""
@@ -16,8 +16,8 @@
@CellFactory.register
class Cell(CategoryItem):
- """Unit cell with lengths *a*, *b*, *c* and angles *alpha*, *beta*,
- *gamma*.
+ """
+ Unit cell with lengths a, b, c and angles alpha, beta, gamma.
All six lattice parameters are exposed as :class:`Parameter`
descriptors supporting validation, fitting and CIF serialization.
@@ -34,7 +34,7 @@ def __init__(self) -> None:
self._length_a = Parameter(
name='length_a',
- description='Length of the a axis of the unit cell.',
+ description='Length of the a axis of the unit cell',
units='Å',
value_spec=AttributeSpec(
default=10.0,
@@ -44,7 +44,7 @@ def __init__(self) -> None:
)
self._length_b = Parameter(
name='length_b',
- description='Length of the b axis of the unit cell.',
+ description='Length of the b axis of the unit cell',
units='Å',
value_spec=AttributeSpec(
default=10.0,
@@ -54,7 +54,7 @@ def __init__(self) -> None:
)
self._length_c = Parameter(
name='length_c',
- description='Length of the c axis of the unit cell.',
+ description='Length of the c axis of the unit cell',
units='Å',
value_spec=AttributeSpec(
default=10.0,
@@ -64,7 +64,7 @@ def __init__(self) -> None:
)
self._angle_alpha = Parameter(
name='angle_alpha',
- description='Angle between edges b and c.',
+ description='Angle between edges b and c',
units='deg',
value_spec=AttributeSpec(
default=90.0,
@@ -74,7 +74,7 @@ def __init__(self) -> None:
)
self._angle_beta = Parameter(
name='angle_beta',
- description='Angle between edges a and c.',
+ description='Angle between edges a and c',
units='deg',
value_spec=AttributeSpec(
default=90.0,
@@ -84,7 +84,7 @@ def __init__(self) -> None:
)
self._angle_gamma = Parameter(
name='angle_gamma',
- description='Angle between edges a and b.',
+ description='Angle between edges a and b',
units='deg',
value_spec=AttributeSpec(
default=90.0,
@@ -100,7 +100,8 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
def _apply_cell_symmetry_constraints(self) -> None:
- """Apply symmetry constraints to cell parameters in place.
+ """
+ Apply symmetry constraints to cell parameters in place.
Uses the parent structure's space-group symbol to determine
which lattice parameters are dependent and sets them
@@ -132,11 +133,14 @@ def _update(
self,
called_by_minimizer: bool = False,
) -> None:
- """Recalculate cell parameters after a change.
+ """
+ Recalculate cell parameters after a change.
- Args:
- called_by_minimizer (bool): Whether the update was triggered
- by the fitting minimizer. Currently unused.
+ Parameters
+ ----------
+ called_by_minimizer : bool, default=False
+ Whether the update was triggered by the fitting minimizer.
+ Currently unused.
"""
del called_by_minimizer # TODO: ???
@@ -148,108 +152,84 @@ def _update(
@property
def length_a(self) -> Parameter:
- """Length of the *a* axis.
+ """
+ Length of the a axis of the unit cell (Å).
- Returns:
- Parameter: Descriptor for lattice parameter *a* (Å).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._length_a
@length_a.setter
def length_a(self, value: float) -> None:
- """Set the length of the *a* axis.
-
- Args:
- value (float): New length in ångströms.
- """
self._length_a.value = value
@property
def length_b(self) -> Parameter:
- """Length of the *b* axis.
+ """
+ Length of the b axis of the unit cell (Å).
- Returns:
- Parameter: Descriptor for lattice parameter *b* (Å).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._length_b
@length_b.setter
def length_b(self, value: float) -> None:
- """Set the length of the *b* axis.
-
- Args:
- value (float): New length in ångströms.
- """
self._length_b.value = value
@property
def length_c(self) -> Parameter:
- """Length of the *c* axis.
+ """
+ Length of the c axis of the unit cell (Å).
- Returns:
- Parameter: Descriptor for lattice parameter *c* (Å).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._length_c
@length_c.setter
def length_c(self, value: float) -> None:
- """Set the length of the *c* axis.
-
- Args:
- value (float): New length in ångströms.
- """
self._length_c.value = value
@property
def angle_alpha(self) -> Parameter:
- """Angle between edges *b* and *c*.
+ """
+ Angle between edges b and c (deg).
- Returns:
- Parameter: Descriptor for angle *α* (degrees).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._angle_alpha
@angle_alpha.setter
def angle_alpha(self, value: float) -> None:
- """Set the angle between edges *b* and *c*.
-
- Args:
- value (float): New angle in degrees.
- """
self._angle_alpha.value = value
@property
def angle_beta(self) -> Parameter:
- """Angle between edges *a* and *c*.
+ """
+ Angle between edges a and c (deg).
- Returns:
- Parameter: Descriptor for angle *β* (degrees).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._angle_beta
@angle_beta.setter
def angle_beta(self, value: float) -> None:
- """Set the angle between edges *a* and *c*.
-
- Args:
- value (float): New angle in degrees.
- """
self._angle_beta.value = value
@property
def angle_gamma(self) -> Parameter:
- """Angle between edges *a* and *b*.
+ """
+ Angle between edges a and b (deg).
- Returns:
- Parameter: Descriptor for angle *γ* (degrees).
+ Reading this property returns the underlying ``Parameter``
+ object. Assigning to it updates the parameter value.
"""
return self._angle_gamma
@angle_gamma.setter
def angle_gamma(self, value: float) -> None:
- """Set the angle between edges *a* and *b*.
-
- Args:
- value (float): New angle in degrees.
- """
self._angle_gamma.value = value
diff --git a/src/easydiffraction/datablocks/structure/categories/cell/factory.py b/src/easydiffraction/datablocks/structure/categories/cell/factory.py
index c5fde941..6817b2d7 100644
--- a/src/easydiffraction/datablocks/structure/categories/cell/factory.py
+++ b/src/easydiffraction/datablocks/structure/categories/cell/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Cell factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/structure/categories/space_group/__init__.py b/src/easydiffraction/datablocks/structure/categories/space_group/__init__.py
index daf02947..a8b33e62 100644
--- a/src/easydiffraction/datablocks/structure/categories/space_group/__init__.py
+++ b/src/easydiffraction/datablocks/structure/categories/space_group/__init__.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
from easydiffraction.datablocks.structure.categories.space_group.default import SpaceGroup
diff --git a/src/easydiffraction/datablocks/structure/categories/space_group/default.py b/src/easydiffraction/datablocks/structure/categories/space_group/default.py
index 7076d272..a91cc554 100644
--- a/src/easydiffraction/datablocks/structure/categories/space_group/default.py
+++ b/src/easydiffraction/datablocks/structure/categories/space_group/default.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Space group category for crystallographic structures."""
@@ -21,8 +21,8 @@
@SpaceGroupFactory.register
class SpaceGroup(CategoryItem):
- """Space group with Hermann–Mauguin symbol and IT coordinate system
- code.
+ """
+ Space group with H-M symbol and IT coordinate system code.
Holds the space-group symbol (``name_h_m``) and the International
Tables coordinate-system qualifier (``it_coordinate_system_code``).
@@ -84,28 +84,30 @@ def __init__(self) -> None:
# ------------------------------------------------------------------
def _reset_it_coordinate_system_code(self) -> None:
- """Reset the IT coordinate system code to the default for the
- current group.
- """
+ """Reset IT coordinate system code to default for this group."""
self._it_coordinate_system_code.value = self._it_coordinate_system_code_default_value
@property
def _name_h_m_allowed_values(self) -> list[str]:
- """Return the list of recognised Hermann–Mauguin short symbols.
+ """
+ Return the list of recognised Hermann–Mauguin short symbols.
- Returns:
- list[str]: All short H-M symbols known to *cryspy*.
+ Returns
+ -------
+ list[str]
+ All short H-M symbols known to *cryspy*.
"""
return ACCESIBLE_NAME_HM_SHORT
@property
def _it_coordinate_system_code_allowed_values(self) -> list[str]:
- """Return allowed IT coordinate system codes for the current
- group.
+ """
+ Return allowed IT coordinate system codes for the current group.
- Returns:
- list[str]: Coordinate-system codes, or ``['']`` when none
- are defined.
+ Returns
+ -------
+ list[str]
+ Coordinate-system codes, or ``['']`` when none are defined.
"""
name = self.name_h_m.value
it_number = get_it_number_by_name_hm_short(name)
@@ -115,10 +117,13 @@ def _it_coordinate_system_code_allowed_values(self) -> list[str]:
@property
def _it_coordinate_system_code_default_value(self) -> str:
- """Return the default IT coordinate system code.
+ """
+ Return the default IT coordinate system code.
- Returns:
- str: First element of the allowed codes list.
+ Returns
+ -------
+ str
+ First element of the allowed codes list.
"""
return self._it_coordinate_system_code_allowed_values[0]
@@ -128,40 +133,31 @@ def _it_coordinate_system_code_default_value(self) -> str:
@property
def name_h_m(self) -> StringDescriptor:
- """Hermann–Mauguin symbol of the space group.
+ """
+ Hermann-Mauguin symbol of the space group.
- Returns:
- StringDescriptor: Descriptor holding the H-M symbol.
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
"""
return self._name_h_m
@name_h_m.setter
def name_h_m(self, value: str) -> None:
- """Set the Hermann–Mauguin symbol and reset the coordinate-
- system code.
-
- Args:
- value (str): New H-M symbol (must be a recognised short
- symbol).
- """
self._name_h_m.value = value
self._reset_it_coordinate_system_code()
@property
def it_coordinate_system_code(self) -> StringDescriptor:
- """International Tables coordinate-system code.
+ """
+ A qualifier identifying which setting in IT is used.
- Returns:
- StringDescriptor: Descriptor holding the IT code.
+ Reading this property returns the underlying
+ ``StringDescriptor`` object. Assigning to it updates the
+ parameter value.
"""
return self._it_coordinate_system_code
@it_coordinate_system_code.setter
def it_coordinate_system_code(self, value: str) -> None:
- """Set the IT coordinate-system code.
-
- Args:
- value (str): New coordinate-system code (must be allowed for
- the current space group).
- """
self._it_coordinate_system_code.value = value
diff --git a/src/easydiffraction/datablocks/structure/categories/space_group/factory.py b/src/easydiffraction/datablocks/structure/categories/space_group/factory.py
index 87807cef..9ef8611d 100644
--- a/src/easydiffraction/datablocks/structure/categories/space_group/factory.py
+++ b/src/easydiffraction/datablocks/structure/categories/space_group/factory.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Space-group factory — delegates entirely to ``FactoryBase``."""
diff --git a/src/easydiffraction/datablocks/structure/collection.py b/src/easydiffraction/datablocks/structure/collection.py
index ecc8f26e..801b416a 100644
--- a/src/easydiffraction/datablocks/structure/collection.py
+++ b/src/easydiffraction/datablocks/structure/collection.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Collection of structure data blocks."""
@@ -11,7 +11,8 @@
class Structures(DatablockCollection):
- """Ordered collection of :class:`Structure` instances.
+ """
+ Ordered collection of :class:`Structure` instances.
Provides convenience ``add_from_*`` methods that mirror the
:class:`StructureFactory` classmethods plus a bare :meth:`add` for
@@ -33,10 +34,13 @@ def create(
*,
name: str,
) -> None:
- """Create a minimal structure and add it to the collection.
+ """
+ Create a minimal structure and add it to the collection.
- Args:
- name (str): Identifier for the new structure.
+ Parameters
+ ----------
+ name : str
+ Identifier for the new structure.
"""
structure = StructureFactory.from_scratch(name=name)
self.add(structure)
@@ -47,10 +51,13 @@ def add_from_cif_str(
self,
cif_str: str,
) -> None:
- """Create a structure from CIF content and add it.
+ """
+ Create a structure from CIF content and add it.
- Args:
- cif_str (str): CIF file content as a string.
+ Parameters
+ ----------
+ cif_str : str
+ CIF file content as a string.
"""
structure = StructureFactory.from_cif_str(cif_str)
self.add(structure)
@@ -61,10 +68,13 @@ def add_from_cif_path(
self,
cif_path: str,
) -> None:
- """Create a structure from a CIF file and add it.
+ """
+ Create a structure from a CIF file and add it.
- Args:
- cif_path (str): Filesystem path to a CIF file.
+ Parameters
+ ----------
+ cif_path : str
+ Filesystem path to a CIF file.
"""
structure = StructureFactory.from_cif_path(cif_path)
self.add(structure)
diff --git a/src/easydiffraction/datablocks/structure/item/__init__.py b/src/easydiffraction/datablocks/structure/item/__init__.py
index 429f2648..4e798e20 100644
--- a/src/easydiffraction/datablocks/structure/item/__init__.py
+++ b/src/easydiffraction/datablocks/structure/item/__init__.py
@@ -1,2 +1,2 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
diff --git a/src/easydiffraction/datablocks/structure/item/base.py b/src/easydiffraction/datablocks/structure/item/base.py
index cd517785..80d8f76a 100644
--- a/src/easydiffraction/datablocks/structure/item/base.py
+++ b/src/easydiffraction/datablocks/structure/item/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Structure datablock item."""
@@ -40,20 +40,26 @@ def __init__(
@property
def name(self) -> str:
- """Name identifier for this structure.
+ """
+ Name identifier for this structure.
- Returns:
- str: The structure's name.
+ Returns
+ -------
+ str
+ The structure's name.
"""
return self._name
@name.setter
@typechecked
def name(self, new: str) -> None:
- """Set the name identifier for this structure.
+ """
+ Set the name identifier for this structure.
- Args:
- new (str): New name string.
+ Parameters
+ ----------
+ new : str
+ New name string.
"""
self._name = new
@@ -69,10 +75,13 @@ def cell(self) -> Cell:
@cell.setter
@typechecked
def cell(self, new: Cell) -> None:
- """Replace the unit-cell category for this structure.
+ """
+ Replace the unit-cell category for this structure.
- Args:
- new (Cell): New unit-cell instance.
+ Parameters
+ ----------
+ new : Cell
+ New unit-cell instance.
"""
self._cell = new
@@ -83,10 +92,13 @@ def cell_type(self) -> str:
@cell_type.setter
def cell_type(self, new_type: str) -> None:
- """Switch to a different unit-cell type.
+ """
+ Switch to a different unit-cell type.
- Args:
- new_type: Cell tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Cell tag (e.g. ``'default'``).
"""
supported_tags = CellFactory.supported_tags()
if new_type not in supported_tags:
@@ -122,10 +134,13 @@ def space_group(self) -> SpaceGroup:
@space_group.setter
@typechecked
def space_group(self, new: SpaceGroup) -> None:
- """Replace the space-group category for this structure.
+ """
+ Replace the space-group category for this structure.
- Args:
- new (SpaceGroup): New space-group instance.
+ Parameters
+ ----------
+ new : SpaceGroup
+ New space-group instance.
"""
self._space_group = new
@@ -136,10 +151,13 @@ def space_group_type(self) -> str:
@space_group_type.setter
def space_group_type(self, new_type: str) -> None:
- """Switch to a different space-group type.
+ """
+ Switch to a different space-group type.
- Args:
- new_type: Space-group tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Space-group tag (e.g. ``'default'``).
"""
supported_tags = SpaceGroupFactory.supported_tags()
if new_type not in supported_tags:
@@ -175,10 +193,13 @@ def atom_sites(self) -> AtomSites:
@atom_sites.setter
@typechecked
def atom_sites(self, new: AtomSites) -> None:
- """Replace the atom-sites collection for this structure.
+ """
+ Replace the atom-sites collection for this structure.
- Args:
- new (AtomSites): New atom-sites collection.
+ Parameters
+ ----------
+ new : AtomSites
+ New atom-sites collection.
"""
self._atom_sites = new
@@ -189,10 +210,13 @@ def atom_sites_type(self) -> str:
@atom_sites_type.setter
def atom_sites_type(self, new_type: str) -> None:
- """Switch to a different atom-sites collection type.
+ """
+ Switch to a different atom-sites collection type.
- Args:
- new_type: Atom-sites tag (e.g. ``'default'``).
+ Parameters
+ ----------
+ new_type : str
+ Atom-sites tag (e.g. ``'default'``).
"""
supported_tags = AtomSitesFactory.supported_tags()
if new_type not in supported_tags:
@@ -221,9 +245,7 @@ def show_current_atom_sites_type(self) -> None:
# ------------------------------------------------------------------
def show(self) -> None:
- """Display an ASCII projection of the structure on a 2D
- plane.
- """
+ """Display an ASCII projection of the structure in 2D."""
console.paragraph(f"Structure 🧩 '{self.name}'")
console.print('Not implemented yet.')
diff --git a/src/easydiffraction/datablocks/structure/item/factory.py b/src/easydiffraction/datablocks/structure/item/factory.py
index a2067dff..567d26dc 100644
--- a/src/easydiffraction/datablocks/structure/item/factory.py
+++ b/src/easydiffraction/datablocks/structure/item/factory.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Factory for creating structure instances from various inputs.
+"""
+Factory for creating structure instances from various inputs.
Provides individual class methods for each creation pathway:
``from_scratch``, ``from_cif_path``, or ``from_cif_str``.
@@ -26,7 +27,7 @@
class StructureFactory:
"""Create :class:`Structure` instances from supported inputs."""
- def __init__(self):
+ def __init__(self) -> None:
log.error(
'Structure objects must be created using class methods such as '
'`StructureFactory.from_cif_str(...)`, etc.'
@@ -42,13 +43,18 @@ def _from_gemmi_block(
cls,
block: gemmi.cif.Block,
) -> Structure:
- """Build a structure from a single *gemmi* CIF block.
+ """
+ Build a structure from a single *gemmi* CIF block.
- Args:
- block (gemmi.cif.Block): Parsed CIF data block.
+ Parameters
+ ----------
+ block : gemmi.cif.Block
+ Parsed CIF data block.
- Returns:
- Structure: A fully populated structure instance.
+ Returns
+ -------
+ Structure
+ A fully populated structure instance.
"""
name = name_from_block(block)
structure = Structure(name=name)
@@ -67,13 +73,18 @@ def from_scratch(
*,
name: str,
) -> Structure:
- """Create a minimal default structure.
+ """
+ Create a minimal default structure.
- Args:
- name (str): Identifier for the new structure.
+ Parameters
+ ----------
+ name : str
+ Identifier for the new structure.
- Returns:
- Structure: An empty structure with default categories.
+ Returns
+ -------
+ Structure
+ An empty structure with default categories.
"""
return Structure(name=name)
@@ -84,13 +95,18 @@ def from_cif_str(
cls,
cif_str: str,
) -> Structure:
- """Create a structure by parsing a CIF string.
+ """
+ Create a structure by parsing a CIF string.
- Args:
- cif_str (str): Raw CIF content.
+ Parameters
+ ----------
+ cif_str : str
+ Raw CIF content.
- Returns:
- Structure: A populated structure instance.
+ Returns
+ -------
+ Structure
+ A populated structure instance.
"""
doc = document_from_string(cif_str)
block = pick_sole_block(doc)
@@ -103,13 +119,18 @@ def from_cif_path(
cls,
cif_path: str,
) -> Structure:
- """Create a structure by reading and parsing a CIF file.
+ """
+ Create a structure by reading and parsing a CIF file.
- Args:
- cif_path (str): Filesystem path to a CIF file.
+ Parameters
+ ----------
+ cif_path : str
+ Filesystem path to a CIF file.
- Returns:
- Structure: A populated structure instance.
+ Returns
+ -------
+ Structure
+ A populated structure instance.
"""
doc = document_from_path(cif_path)
block = pick_sole_block(doc)
diff --git a/src/easydiffraction/display/__init__.py b/src/easydiffraction/display/__init__.py
index 265560b2..25bccda4 100644
--- a/src/easydiffraction/display/__init__.py
+++ b/src/easydiffraction/display/__init__.py
@@ -1,14 +1,15 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Display subsystem for tables and plots.
+"""
+Display subsystem for tables and plots.
-This package contains user-facing facades and backend implementations
-to render tabular data and plots in different environments.
+This package contains user-facing facades and backend implementations to
+render tabular data and plots in different environments.
- Tables: see :mod:`easydiffraction.display.tables` and the engines in
- :mod:`easydiffraction.display.tablers`.
-- Plots: see :mod:`easydiffraction.display.plotting` and the engines in
- :mod:`easydiffraction.display.plotters`.
+:mod:`easydiffraction.display.tablers`. - Plots: see
+:mod:`easydiffraction.display.plotting` and the engines in
+:mod:`easydiffraction.display.plotters`.
"""
# TODO: The following works in Jupyter, but breaks MkDocs builds.
diff --git a/src/easydiffraction/display/base.py b/src/easydiffraction/display/base.py
index d97f7be9..6ffc0698 100644
--- a/src/easydiffraction/display/base.py
+++ b/src/easydiffraction/display/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Common base classes for display components and their factories."""
@@ -6,7 +6,6 @@
from abc import ABC
from abc import abstractmethod
-from typing import Any
from typing import List
from typing import Tuple
@@ -18,14 +17,15 @@
class RendererBase(SingletonBase, ABC):
- """Base class for display components with pluggable engines.
+ """
+ Base class for display components with pluggable engines.
Subclasses provide a factory and a default engine. This class
manages the active backend instance and exposes helpers to inspect
supported engines in a table-friendly format.
"""
- def __init__(self):
+ def __init__(self) -> None:
self._engine = self._default_engine()
self._backend = self._factory().create(self._engine)
@@ -43,10 +43,27 @@ def _default_engine(cls) -> str:
@property
def engine(self) -> str:
+ """
+ Return the name of the currently active rendering engine.
+
+ Returns
+ -------
+ str
+ Identifier of the active engine.
+ """
return self._engine
@engine.setter
def engine(self, new_engine: str) -> None:
+ """
+ Switch to a different rendering engine.
+
+ Parameters
+ ----------
+ new_engine : str
+ Identifier of the engine to activate. Must be a key
+ returned by ``_factory()._registry()``.
+ """
if new_engine == self._engine:
log.info(f"Engine is already set to '{new_engine}'. No change made.")
return
@@ -90,18 +107,25 @@ class RendererFactoryBase(ABC):
"""Base factory that manages discovery and creation of backends."""
@classmethod
- def create(cls, engine_name: str) -> Any:
- """Create a backend instance for the given engine.
+ def create(cls, engine_name: str) -> object:
+ """
+ Create a backend instance for the given engine.
- Args:
- engine_name: Identifier of the engine to instantiate as
- listed in ``_registry()``.
+ Parameters
+ ----------
+ engine_name : str
+ Identifier of the engine to instantiate as listed in
+ ``_registry()``.
- Returns:
+ Returns
+ -------
+ object
A new backend instance corresponding to ``engine_name``.
- Raises:
- ValueError: If the engine name is not supported.
+ Raises
+ ------
+ ValueError
+ If the engine name is not supported.
"""
registry = cls._registry()
if engine_name not in registry:
@@ -117,16 +141,15 @@ def supported_engines(cls) -> List[str]:
@classmethod
def descriptions(cls) -> List[Tuple[str, str]]:
- """Return pairs of engine name and human-friendly
- description.
- """
+ """Return (name, description) pairs for each engine."""
items = cls._registry().items()
return [(name, config.get('description')) for name, config in items]
@classmethod
@abstractmethod
def _registry(cls) -> dict:
- """Return engine registry. Implementations must provide this.
+ """
+ Return engine registry. Implementations must provide this.
The returned mapping should have keys as engine names and values
as a config dict with 'description' and 'class'. Lazy imports
diff --git a/src/easydiffraction/display/plotters/__init__.py b/src/easydiffraction/display/plotters/__init__.py
index 14dae26a..09931ae8 100644
--- a/src/easydiffraction/display/plotters/__init__.py
+++ b/src/easydiffraction/display/plotters/__init__.py
@@ -1,10 +1,11 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Plotting backends.
+"""
+Plotting backends.
This subpackage implements plotting engines used by the high-level
plotting facade:
-- :mod:`.ascii` for terminal-friendly ASCII plots.
-- :mod:`.plotly` for interactive plots in notebooks or browsers.
+- :mod:`.ascii` for terminal-friendly ASCII plots. - :mod:`.plotly` for
+interactive plots in notebooks or browsers.
"""
diff --git a/src/easydiffraction/display/plotters/ascii.py b/src/easydiffraction/display/plotters/ascii.py
index 7b5ff6a8..8735a8a0 100644
--- a/src/easydiffraction/display/plotters/ascii.py
+++ b/src/easydiffraction/display/plotters/ascii.py
@@ -1,10 +1,11 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""ASCII plotting backend.
+"""
+ASCII plotting backend.
-Renders compact line charts in the terminal using
-``asciichartpy``. This backend is well suited for quick feedback in
-CLI environments and keeps a consistent API with other plotters.
+Renders compact line charts in the terminal using ``asciichartpy``. This
+backend is well suited for quick feedback in CLI environments and keeps
+a consistent API with other plotters.
"""
import asciichartpy
@@ -25,16 +26,21 @@
class AsciiPlotter(PlotterBase):
"""Terminal-based plotter using ASCII art."""
- def _get_legend_item(self, label):
- """Return a colored legend entry for a given series label.
+ def _get_legend_item(self, label: str) -> str:
+ """
+ Return a colored legend entry for a given series label.
- The legend uses a colored line matching the series color and
- the human-readable name from :data:`SERIES_CONFIG`.
+ The legend uses a colored line matching the series color and the
+ human-readable name from :data:`SERIES_CONFIG`.
- Args:
- label: Series identifier (e.g., ``'meas'``).
+ Parameters
+ ----------
+ label : str
+ Series identifier (e.g., ``'meas'``).
- Returns:
+ Returns
+ -------
+ str
A formatted legend string with color escapes.
"""
color_start = DEFAULT_COLORS[label]
@@ -46,27 +52,34 @@ def _get_legend_item(self, label):
def plot_powder(
self,
- x,
- y_series,
- labels,
- axes_labels,
- title,
- height=None,
- ):
- """Render a line plot for powder diffraction data.
+ x: object,
+ y_series: object,
+ labels: object,
+ axes_labels: object,
+ title: str,
+ height: int | None = None,
+ ) -> None:
+ """
+ Render a line plot for powder diffraction data.
Suitable for powder diffraction data where intensity is plotted
against an x-axis variable (2θ, TOF, d-spacing). Uses ASCII
characters for terminal display.
- Args:
- x: 1D array-like of x values (only used for range
- display).
- y_series: Sequence of y arrays to plot.
- labels: Series identifiers corresponding to y_series.
- axes_labels: Ignored; kept for API compatibility.
- title: Figure title printed above the chart.
- height: Number of text rows to allocate for the chart.
+ Parameters
+ ----------
+ x : object
+ 1D array-like of x values (only used for range display).
+ y_series : object
+ Sequence of y arrays to plot.
+ labels : object
+ Series identifiers corresponding to y_series.
+ axes_labels : object
+ Ignored; kept for API compatibility.
+ title : str
+ Figure title printed above the chart.
+ height : int | None, default=None
+ Number of text rows to allocate for the chart.
"""
# Intentionally unused; kept for a consistent display API
del axes_labels
@@ -92,26 +105,34 @@ def plot_powder(
def plot_single_crystal(
self,
- x_calc,
- y_meas,
- y_meas_su,
- axes_labels,
- title,
- height=None,
- ):
- """Render a scatter plot for single crystal diffraction data.
+ x_calc: object,
+ y_meas: object,
+ y_meas_su: object,
+ axes_labels: object,
+ title: str,
+ height: int | None = None,
+ ) -> None:
+ """
+ Render a scatter plot for single crystal diffraction data.
Creates an ASCII scatter plot showing measured vs calculated
values with a diagonal reference line.
- Args:
- x_calc: 1D array-like of calculated values (x-axis).
- y_meas: 1D array-like of measured values (y-axis).
- y_meas_su: 1D array-like of measurement uncertainties
- (ignored in ASCII mode).
- axes_labels: Pair of strings for the x and y titles.
- title: Figure title.
- height: Number of text rows for the chart (default: 15).
+ Parameters
+ ----------
+ x_calc : object
+ 1D array-like of calculated values (x-axis).
+ y_meas : object
+ 1D array-like of measured values (y-axis).
+ y_meas_su : object
+ 1D array-like of measurement uncertainties (ignored in ASCII
+ mode).
+ axes_labels : object
+ Pair of strings for the x and y titles.
+ title : str
+ Figure title.
+ height : int | None, default=None
+ Number of text rows for the chart (default: 15).
"""
# Intentionally unused; ASCII scatter doesn't show error bars
del y_meas_su
diff --git a/src/easydiffraction/display/plotters/base.py b/src/easydiffraction/display/plotters/base.py
index 7220dfeb..d7ca594c 100644
--- a/src/easydiffraction/display/plotters/base.py
+++ b/src/easydiffraction/display/plotters/base.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
"""Abstract base and shared constants for plotting backends."""
@@ -18,10 +18,11 @@
class XAxisType(str, Enum):
- """X-axis types for diffraction plots.
+ """
+ X-axis types for diffraction plots.
- Values match attribute names in data models for direct use
- with ``getattr(pattern, x_axis)``.
+ Values match attribute names in data models for direct use with
+ ``getattr(pattern, x_axis)``.
"""
TWO_THETA = 'two_theta'
@@ -151,64 +152,80 @@ class XAxisType(str, Enum):
class PlotterBase(ABC):
- """Abstract base for plotting backends.
+ """
+ Abstract base for plotting backends.
Implementations accept x values, multiple y-series, optional labels
and render a plot to the chosen medium.
- Two main plot types are supported:
- - ``plot_powder``: Line plots for powder diffraction patterns
- (intensity vs. 2θ/TOF/d-spacing).
- - ``plot_single_crystal``: Scatter plots comparing measured vs.
- calculated values (e.g., F²meas vs F²calc for single crystal).
+ Two main plot types are supported: - ``plot_powder``: Line plots for
+ powder diffraction patterns (intensity vs. 2θ/TOF/d-spacing). -
+ ``plot_single_crystal``: Scatter plots comparing measured vs.
+ calculated values (e.g., F²meas vs F²calc for single crystal).
"""
@abstractmethod
def plot_powder(
self,
- x,
- y_series,
- labels,
- axes_labels,
- title,
- height,
- ):
- """Render a line plot for powder diffraction data.
+ x: object,
+ y_series: object,
+ labels: object,
+ axes_labels: object,
+ title: str,
+ height: int | None,
+ ) -> None:
+ """
+ Render a line plot for powder diffraction data.
Suitable for powder diffraction data where intensity is plotted
against an x-axis variable (2θ, TOF, d-spacing).
- Args:
- x: 1D array of x-axis values.
- y_series: Sequence of y arrays to plot.
- labels: Identifiers corresponding to y_series.
- axes_labels: Pair of strings for the x and y titles.
- title: Figure title.
- height: Backend-specific height (text rows or pixels).
+ Parameters
+ ----------
+ x : object
+ 1D array of x-axis values.
+ y_series : object
+ Sequence of y arrays to plot.
+ labels : object
+ Identifiers corresponding to y_series.
+ axes_labels : object
+ Pair of strings for the x and y titles.
+ title : str
+ Figure title.
+ height : int | None
+ Backend-specific height (text rows or pixels).
"""
pass
@abstractmethod
def plot_single_crystal(
self,
- x_calc,
- y_meas,
- y_meas_su,
- axes_labels,
- title,
- height,
- ):
- """Render a scatter plot for single crystal diffraction data.
+ x_calc: object,
+ y_meas: object,
+ y_meas_su: object,
+ axes_labels: object,
+ title: str,
+ height: int | None,
+ ) -> None:
+ """
+ Render a scatter plot for single crystal diffraction data.
Suitable for single crystal diffraction data where measured
values are plotted against calculated values with error bars.
- Args:
- x_calc: 1D array of calculated values (x-axis).
- y_meas: 1D array of measured values (y-axis).
- y_meas_su: 1D array of measurement uncertainties.
- axes_labels: Pair of strings for the x and y titles.
- title: Figure title.
- height: Backend-specific height (text rows or pixels).
+ Parameters
+ ----------
+ x_calc : object
+ 1D array of calculated values (x-axis).
+ y_meas : object
+ 1D array of measured values (y-axis).
+ y_meas_su : object
+ 1D array of measurement uncertainties.
+ axes_labels : object
+ Pair of strings for the x and y titles.
+ title : str
+ Figure title.
+ height : int | None
+ Backend-specific height (text rows or pixels).
"""
pass
diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py
index bf2b4907..4df79cf0 100644
--- a/src/easydiffraction/display/plotters/plotly.py
+++ b/src/easydiffraction/display/plotters/plotly.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2026 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Plotly plotting backend.
+"""
+Plotly plotting backend.
Provides an interactive plotting implementation using Plotly. In
notebooks, figures are displayed inline; in other environments a browser
@@ -38,19 +39,25 @@ class PlotlyPlotter(PlotterBase):
def _get_powder_trace(
self,
- x,
- y,
- label,
- ):
- """Create a Plotly trace for powder diffraction data.
-
- Args:
- x: 1D array-like of x-axis values.
- y: 1D array-like of y-axis values.
- label: Series identifier (``'meas'``, ``'calc'``, or
- ``'resid'``).
-
- Returns:
+ x: object,
+ y: object,
+ label: str,
+ ) -> object:
+ """
+ Create a Plotly trace for powder diffraction data.
+
+ Parameters
+ ----------
+ x : object
+ 1D array-like of x-axis values.
+ y : object
+ 1D array- like of y-axis values.
+ label : str
+ Series identifier (``'meas'``, ``'calc'``, or ``'resid'``).
+
+ Returns
+ -------
+ object
A configured :class:`plotly.graph_objects.Scatter` trace.
"""
mode = SERIES_CONFIG[label]['mode']
@@ -70,18 +77,25 @@ def _get_powder_trace(
def _get_single_crystal_trace(
self,
- x_calc,
- y_meas,
- y_meas_su,
- ):
- """Create a Plotly trace for single crystal diffraction data.
-
- Args:
- x_calc: 1D array-like of calculated values (x-axis).
- y_meas: 1D array-like of measured values (y-axis).
- y_meas_su: 1D array-like of measurement uncertainties.
-
- Returns:
+ x_calc: object,
+ y_meas: object,
+ y_meas_su: object,
+ ) -> object:
+ """
+ Create a Plotly trace for single crystal diffraction data.
+
+ Parameters
+ ----------
+ x_calc : object
+ 1D array-like of calculated values (x-axis).
+ y_meas : object
+ 1D array-like of measured values (y-axis).
+ y_meas_su : object
+ 1D array-like of measurement uncertainties.
+
+ Returns
+ -------
+ object
A configured :class:`plotly.graph_objects.Scatter` trace
with markers and error bars.
"""
@@ -105,13 +119,16 @@ def _get_single_crystal_trace(
return trace
- def _get_diagonal_shape(self):
- """Create a diagonal reference line shape.
+ def _get_diagonal_shape(self) -> dict:
+ """
+ Create a diagonal reference line shape.
Returns a y=x diagonal line spanning the plot area using paper
coordinates (0,0) to (1,1).
- Returns:
+ Returns
+ -------
+ dict
A dict configuring a diagonal line shape.
"""
return dict(
@@ -126,10 +143,13 @@ def _get_diagonal_shape(self):
line=dict(width=0.5),
)
- def _get_config(self):
- """Return the Plotly figure configuration.
+ def _get_config(self) -> dict:
+ """
+ Return the Plotly figure configuration.
- Returns:
+ Returns
+ -------
+ dict
A dict with display and mode bar settings.
"""
return dict(
@@ -145,16 +165,22 @@ def _get_config(self):
def _get_figure(
self,
- data,
- layout,
- ):
- """Create and configure a Plotly figure.
-
- Args:
- data: List of traces to include in the figure.
- layout: Layout configuration dict.
-
- Returns:
+ data: object,
+ layout: object,
+ ) -> object:
+ """
+ Create and configure a Plotly figure.
+
+ Parameters
+ ----------
+ data : object
+ List of traces to include in the figure.
+ layout : object
+ Layout configuration dict.
+
+ Returns
+ -------
+ object
A configured :class:`plotly.graph_objects.Figure`.
"""
fig = go.Figure(data=data, layout=layout)
@@ -166,15 +192,18 @@ def _get_figure(
def _show_figure(
self,
- fig,
- ):
- """Display a Plotly figure.
+ fig: object,
+ ) -> None:
+ """
+ Display a Plotly figure.
Renders the figure using the appropriate method for the current
environment (browser for PyCharm, inline HTML for Jupyter).
- Args:
- fig: A :class:`plotly.graph_objects.Figure` to display.
+ Parameters
+ ----------
+ fig : object
+ A :class:`plotly.graph_objects.Figure` to display.
"""
config = self._get_config()
@@ -191,18 +220,25 @@ def _show_figure(
def _get_layout(
self,
- title,
- axes_labels,
- **kwargs,
- ):
- """Create a Plotly layout configuration.
-
- Args:
- title: Figure title.
- axes_labels: Pair of strings for the x and y titles.
- **kwargs: Additional layout parameters (e.g., shapes).
-
- Returns:
+ title: str,
+ axes_labels: object,
+ **kwargs: object,
+ ) -> object:
+ """
+ Create a Plotly layout configuration.
+
+ Parameters
+ ----------
+ title : str
+ Figure title.
+ axes_labels : object
+ Pair of strings for the x and y titles.
+ **kwargs : object
+ Additional layout parameters (e.g., shapes).
+
+ Returns
+ -------
+ object
A configured :class:`plotly.graph_objects.Layout`.
"""
return go.Layout(
@@ -238,25 +274,33 @@ def _get_layout(
def plot_powder(
self,
- x,
- y_series,
- labels,
- axes_labels,
- title,
- height=None,
- ):
- """Render a line plot for powder diffraction data.
+ x: object,
+ y_series: object,
+ labels: object,
+ axes_labels: object,
+ title: str,
+ height: int | None = None,
+ ) -> None:
+ """
+ Render a line plot for powder diffraction data.
Suitable for powder diffraction data where intensity is plotted
against an x-axis variable (2θ, TOF, d-spacing).
- Args:
- x: 1D array-like of x-axis values.
- y_series: Sequence of y arrays to plot.
- labels: Series identifiers corresponding to y_series.
- axes_labels: Pair of strings for the x and y titles.
- title: Figure title.
- height: Ignored; Plotly auto-sizes based on renderer.
+ Parameters
+ ----------
+ x : object
+ 1D array-like of x-axis values.
+ y_series : object
+ Sequence of y arrays to plot.
+ labels : object
+ Series identifiers corresponding to y_series.
+ axes_labels : object
+ Pair of strings for the x and y titles.
+ title : str
+ Figure title.
+ height : int | None, default=None
+ Ignored; Plotly auto-sizes based on renderer.
"""
# Intentionally unused; accepted for API compatibility
del height
@@ -277,26 +321,34 @@ def plot_powder(
def plot_single_crystal(
self,
- x_calc,
- y_meas,
- y_meas_su,
- axes_labels,
- title,
- height=None,
- ):
- """Render a scatter plot for single crystal diffraction data.
+ x_calc: object,
+ y_meas: object,
+ y_meas_su: object,
+ axes_labels: object,
+ title: str,
+ height: int | None = None,
+ ) -> None:
+ """
+ Render a scatter plot for single crystal diffraction data.
Suitable for single crystal diffraction data where measured
- values are plotted against calculated values with error bars
- and a diagonal reference line.
-
- Args:
- x_calc: 1D array-like of calculated values (x-axis).
- y_meas: 1D array-like of measured values (y-axis).
- y_meas_su: 1D array-like of measurement uncertainties.
- axes_labels: Pair of strings for the x and y titles.
- title: Figure title.
- height: Ignored; Plotly auto-sizes based on renderer.
+ values are plotted against calculated values with error bars and
+ a diagonal reference line.
+
+ Parameters
+ ----------
+ x_calc : object
+ 1D array-like of calculated values (x-axis).
+ y_meas : object
+ 1D array-like of measured values (y-axis).
+ y_meas_su : object
+ 1D array-like of measurement uncertainties.
+ axes_labels : object
+ Pair of strings for the x and y titles.
+ title : str
+ Figure title.
+ height : int | None, default=None
+ Ignored; Plotly auto-sizes based on renderer.
"""
# Intentionally unused; accepted for API compatibility
del height
diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py
index 90d54261..ec8e1d5c 100644
--- a/src/easydiffraction/display/plotting.py
+++ b/src/easydiffraction/display/plotting.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Plotting facade for measured and calculated patterns.
+"""
+Plotting facade for measured and calculated patterns.
Uses the common :class:`RendererBase` so plotters and tablers share a
consistent configuration surface and engine handling.
@@ -28,6 +29,8 @@
class PlotterEngineEnum(str, Enum):
+ """Available plotting engine backends."""
+
ASCII = 'asciichartpy'
PLOTLY = 'plotly'
@@ -56,7 +59,7 @@ class Plotter(RendererBase):
# Private special methods
# ------------------------------------------------------------------
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
# X-axis limits
self._x_min = DEFAULT_MIN
@@ -80,17 +83,30 @@ def _default_engine(cls) -> str:
# Private helper methods
# ------------------------------------------------------------------
- def _auto_x_range_for_ascii(self, pattern, x_array, x_min, x_max):
- """For the ASCII engine, narrow the range around the tallest
- peak.
-
- Args:
- pattern: Data pattern object (needs ``intensity_meas``).
- x_array: Full x-axis array.
- x_min: Current minimum (may be ``None``).
- x_max: Current maximum (may be ``None``).
-
- Returns:
+ def _auto_x_range_for_ascii(
+ self,
+ pattern: object,
+ x_array: object,
+ x_min: object,
+ x_max: object,
+ ) -> tuple:
+ """
+ For the ASCII engine, narrow the range around the tallest peak.
+
+ Parameters
+ ----------
+ pattern : object
+ Data pattern object (needs ``intensity_meas``).
+ x_array : object
+ Full x-axis array.
+ x_min : object
+ Current minimum (may be ``None``).
+ x_max : object
+ Current maximum (may be ``None``).
+
+ Returns
+ -------
+ tuple
Tuple of ``(x_min, x_max)``, possibly narrowed.
"""
if self._engine == 'asciichartpy' and (x_min is None or x_max is None):
@@ -104,21 +120,28 @@ def _auto_x_range_for_ascii(self, pattern, x_array, x_min, x_max):
def _filtered_y_array(
self,
- y_array,
- x_array,
- x_min,
- x_max,
- ):
- """Filter an array by the inclusive x-range limits.
-
- Args:
- y_array: 1D array-like of y values.
- x_array: 1D array-like of x values (same length as
- ``y_array``).
- x_min: Minimum x limit (or ``None`` to use default).
- x_max: Maximum x limit (or ``None`` to use default).
-
- Returns:
+ y_array: object,
+ x_array: object,
+ x_min: object,
+ x_max: object,
+ ) -> object:
+ """
+ Filter an array by the inclusive x-range limits.
+
+ Parameters
+ ----------
+ y_array : object
+ 1D array-like of y values.
+ x_array : object
+ 1D array-like of x values (same length as ``y_array``).
+ x_min : object
+ Minimum x limit (or ``None`` to use default).
+ x_max : object
+ Maximum x limit (or ``None`` to use default).
+
+ Returns
+ -------
+ object
Filtered ``y_array`` values where ``x_array`` lies within
``[x_min, x_max]``.
"""
@@ -132,39 +155,55 @@ def _filtered_y_array(
return filtered_y_array
- def _get_axes_labels(self, sample_form, scattering_type, x_axis):
- """Look up axis labels for the given experiment / x-axis
- combination.
- """
+ def _get_axes_labels(
+ self,
+ sample_form: object,
+ scattering_type: object,
+ x_axis: object,
+ ) -> list:
+ """Look up axis labels for the experiment / x-axis."""
return DEFAULT_AXES_LABELS[(sample_form, scattering_type, x_axis)]
def _prepare_powder_data(
self,
- pattern,
- expt_name,
- expt_type,
- x_min,
- x_max,
- x,
- need_meas=False,
- need_calc=False,
- show_residual=False,
- ):
- """Validate, resolve axes, auto-range, and filter arrays.
-
- Args:
- pattern: Data pattern object with intensity arrays.
- expt_name: Experiment name for error messages.
- expt_type: Experiment type with sample_form, scattering,
- and beam enums.
- x_min: Optional minimum x-axis limit.
- x_max: Optional maximum x-axis limit.
- x: Explicit x-axis type or ``None``.
- need_meas: Whether ``intensity_meas`` is required.
- need_calc: Whether ``intensity_calc`` is required.
- show_residual: If ``True``, compute meas − calc residual.
-
- Returns:
+ pattern: object,
+ expt_name: str,
+ expt_type: object,
+ x_min: object,
+ x_max: object,
+ x: object,
+ need_meas: bool = False,
+ need_calc: bool = False,
+ show_residual: bool = False,
+ ) -> dict | None:
+ """
+ Validate, resolve axes, auto-range, and filter arrays.
+
+ Parameters
+ ----------
+ pattern : object
+ Data pattern object with intensity arrays.
+ expt_name : str
+ Experiment name for error messages.
+ expt_type : object
+ Experiment type with sample_form, scattering, and beam
+ enums.
+ x_min : object
+ Optional minimum x-axis limit.
+ x_max : object
+ Optional maximum x-axis limit.
+ x : object
+ Explicit x-axis type or ``None``.
+ need_meas : bool, default=False
+ Whether ``intensity_meas`` is required.
+ need_calc : bool, default=False
+ Whether ``intensity_calc`` is required.
+ show_residual : bool, default=False
+ If ``True``, compute meas − calc residual.
+
+ Returns
+ -------
+ dict | None
A dict with keys ``x_filtered``, ``y_series``, ``y_labels``,
``axes_labels``, and ``x_axis``; or ``None`` when a required
array is missing.
@@ -222,15 +261,21 @@ def _prepare_powder_data(
'x_axis': x_axis,
}
- def _resolve_x_axis(self, expt_type, x):
- """Determine the x-axis type from experiment metadata.
-
- Args:
- expt_type: Experiment type with sample_form,
- scattering_type, and beam_mode enums.
- x: Explicit x-axis type or ``None`` to auto-detect.
-
- Returns:
+ def _resolve_x_axis(self, expt_type: object, x: object) -> tuple:
+ """
+ Determine the x-axis type from experiment metadata.
+
+ Parameters
+ ----------
+ expt_type : object
+ Experiment type with sample_form, scattering_type, and
+ beam_mode enums.
+ x : object
+ Explicit x-axis type or ``None`` to auto-detect.
+
+ Returns
+ -------
+ tuple
Tuple of ``(x_axis, x_name, sample_form, scattering_type,
beam_mode)``.
"""
@@ -246,16 +291,19 @@ def _resolve_x_axis(self, expt_type, x):
# ------------------------------------------------------------------
@property
- def x_min(self):
+ def x_min(self) -> float:
"""Minimum x-axis limit."""
return self._x_min
@x_min.setter
- def x_min(self, value):
- """Set the minimum x-axis limit.
+ def x_min(self, value: object) -> None:
+ """
+ Set the minimum x-axis limit.
- Args:
- value: Minimum limit or ``None`` to reset to default.
+ Parameters
+ ----------
+ value : object
+ Minimum limit or ``None`` to reset to default.
"""
if value is not None:
self._x_min = value
@@ -263,16 +311,19 @@ def x_min(self, value):
self._x_min = DEFAULT_MIN
@property
- def x_max(self):
+ def x_max(self) -> float:
"""Maximum x-axis limit."""
return self._x_max
@x_max.setter
- def x_max(self, value):
- """Set the maximum x-axis limit.
+ def x_max(self, value: object) -> None:
+ """
+ Set the maximum x-axis limit.
- Args:
- value: Maximum limit or ``None`` to reset to default.
+ Parameters
+ ----------
+ value : object
+ Maximum limit or ``None`` to reset to default.
"""
if value is not None:
self._x_max = value
@@ -280,16 +331,19 @@ def x_max(self, value):
self._x_max = DEFAULT_MAX
@property
- def height(self):
+ def height(self) -> int:
"""Plot height (rows for ASCII, pixels for Plotly)."""
return self._height
@height.setter
- def height(self, value):
- """Set plot height.
+ def height(self, value: object) -> None:
+ """
+ Set plot height.
- Args:
- value: Height value or ``None`` to reset to default.
+ Parameters
+ ----------
+ value : object
+ Height value or ``None`` to reset to default.
"""
if value is not None:
self._height = value
@@ -300,7 +354,7 @@ def height(self, value):
# Public methods
# ------------------------------------------------------------------
- def show_config(self):
+ def show_config(self) -> None:
"""Display the current plotting configuration."""
headers = [
('Parameter', 'left'),
@@ -317,25 +371,32 @@ def show_config(self):
def plot_meas(
self,
- pattern,
- expt_name,
- expt_type,
- x_min=None,
- x_max=None,
- x=None,
- ):
- """Plot measured pattern using the current engine.
-
- Args:
- pattern: Object with x-axis arrays (``two_theta``,
- ``time_of_flight``, ``d_spacing``) and ``meas`` array.
- expt_name: Experiment name for the title.
- expt_type: Experiment type with scattering/beam enums.
- x_min: Optional minimum x-axis limit.
- x_max: Optional maximum x-axis limit.
- x: X-axis type (``'two_theta'``, ``'time_of_flight'``, or
- ``'d_spacing'``). If ``None``, auto-detected from
- beam mode.
+ pattern: object,
+ expt_name: str,
+ expt_type: object,
+ x_min: object = None,
+ x_max: object = None,
+ x: object = None,
+ ) -> None:
+ """
+ Plot measured pattern using the current engine.
+
+ Parameters
+ ----------
+ pattern : object
+ Object with x-axis arrays (``two_theta``,
+ ``time_of_flight``, ``d_spacing``) and ``meas`` array.
+ expt_name : str
+ Experiment name for the title.
+ expt_type : object
+ Experiment type with scattering/beam enums.
+ x_min : object, default=None
+ Optional minimum x-axis limit.
+ x_max : object, default=None
+ Optional maximum x-axis limit.
+ x : object, default=None
+ X-axis type (``'two_theta'``, ``'time_of_flight'``, or
+ ``'d_spacing'``). If ``None``, auto-detected from beam mode.
"""
ctx = self._prepare_powder_data(
pattern,
@@ -360,25 +421,32 @@ def plot_meas(
def plot_calc(
self,
- pattern,
- expt_name,
- expt_type,
- x_min=None,
- x_max=None,
- x=None,
- ):
- """Plot calculated pattern using the current engine.
-
- Args:
- pattern: Object with x-axis arrays (``two_theta``,
- ``time_of_flight``, ``d_spacing``) and ``calc`` array.
- expt_name: Experiment name for the title.
- expt_type: Experiment type with scattering/beam enums.
- x_min: Optional minimum x-axis limit.
- x_max: Optional maximum x-axis limit.
- x: X-axis type (``'two_theta'``, ``'time_of_flight'``, or
- ``'d_spacing'``). If ``None``, auto-detected from
- beam mode.
+ pattern: object,
+ expt_name: str,
+ expt_type: object,
+ x_min: object = None,
+ x_max: object = None,
+ x: object = None,
+ ) -> None:
+ """
+ Plot calculated pattern using the current engine.
+
+ Parameters
+ ----------
+ pattern : object
+ Object with x-axis arrays (``two_theta``,
+ ``time_of_flight``, ``d_spacing``) and ``calc`` array.
+ expt_name : str
+ Experiment name for the title.
+ expt_type : object
+ Experiment type with scattering/beam enums.
+ x_min : object, default=None
+ Optional minimum x-axis limit.
+ x_max : object, default=None
+ Optional maximum x-axis limit.
+ x : object, default=None
+ X-axis type (``'two_theta'``, ``'time_of_flight'``, or
+ ``'d_spacing'``). If ``None``, auto-detected from beam mode.
"""
ctx = self._prepare_powder_data(
pattern,
@@ -403,37 +471,44 @@ def plot_calc(
def plot_meas_vs_calc(
self,
- pattern,
- expt_name,
- expt_type,
- x_min=None,
- x_max=None,
- show_residual=False,
- x=None,
- ):
- """Plot measured and calculated series and optional residual.
+ pattern: object,
+ expt_name: str,
+ expt_type: object,
+ x_min: object = None,
+ x_max: object = None,
+ show_residual: bool = False,
+ x: object = None,
+ ) -> None:
+ """
+ Plot measured and calculated series and optional residual.
Supports both powder and single crystal data with a unified API.
- For powder diffraction:
- - x='two_theta', 'time_of_flight', or 'd_spacing'
- - Auto-detected from beam mode if not specified
-
- For single crystal diffraction:
- - x='intensity_calc' (default): scatter plot
- - x='d_spacing' or 'sin_theta_over_lambda': line plot
-
- Args:
- pattern: Data pattern object with meas/calc arrays.
- expt_name: Experiment name for the title.
- expt_type: Experiment type with sample_form,
- scattering, and beam enums.
- x_min: Optional minimum x-axis limit.
- x_max: Optional maximum x-axis limit.
- show_residual: If ``True``, add residual series
- (powder only).
- x: X-axis type. If ``None``, auto-detected from sample form
- and beam mode.
+ For powder diffraction: - x='two_theta', 'time_of_flight', or
+ 'd_spacing' - Auto-detected from beam mode if not specified
+
+ For single crystal diffraction: - x='intensity_calc' (default):
+ scatter plot - x='d_spacing' or 'sin_theta_over_lambda': line
+ plot
+
+ Parameters
+ ----------
+ pattern : object
+ Data pattern object with meas/calc arrays.
+ expt_name : str
+ Experiment name for the title.
+ expt_type : object
+ Experiment type with sample_form, scattering, and beam
+ enums.
+ x_min : object, default=None
+ Optional minimum x-axis limit.
+ x_max : object, default=None
+ Optional maximum x-axis limit.
+ show_residual : bool, default=False
+ If ``True``, add residual series (powder only).
+ x : object, default=None
+ X-axis type. If ``None``, auto-detected from sample form and
+ beam mode.
"""
x_axis, _, sample_form, scattering_type, _ = self._resolve_x_axis(expt_type, x)
diff --git a/src/easydiffraction/display/tablers/__init__.py b/src/easydiffraction/display/tablers/__init__.py
index 93d84417..6471fbff 100644
--- a/src/easydiffraction/display/tablers/__init__.py
+++ b/src/easydiffraction/display/tablers/__init__.py
@@ -1,10 +1,11 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Tabular rendering backends.
+"""
+Tabular rendering backends.
-This subpackage provides concrete implementations for rendering
-tables in different environments:
+This subpackage provides concrete implementations for rendering tables
+in different environments:
-- :mod:`.rich` for terminal and notebooks using the Rich library.
-- :mod:`.pandas` for notebooks using DataFrame Styler.
+- :mod:`.rich` for terminal and notebooks using the Rich library. -
+:mod:`.pandas` for notebooks using DataFrame Styler.
"""
diff --git a/src/easydiffraction/display/tablers/base.py b/src/easydiffraction/display/tablers/base.py
index 2b710d8f..869c5a17 100644
--- a/src/easydiffraction/display/tablers/base.py
+++ b/src/easydiffraction/display/tablers/base.py
@@ -1,6 +1,7 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors
+# SPDX-FileCopyrightText: 2025 EasyScience contributors
# SPDX-License-Identifier: BSD-3-Clause
-"""Low-level backends for rendering tables.
+"""
+Low-level backends for rendering tables.
This module defines the abstract base for tabular renderers and small
helpers for consistent styling across terminal and notebook outputs.
@@ -10,7 +11,6 @@
from abc import ABC
from abc import abstractmethod
-from typing import Any
from IPython import get_ipython
from rich.color import Color
@@ -19,11 +19,11 @@
class TableBackendBase(ABC):
- """Abstract base class for concrete table backends.
+ """
+ Abstract base class for concrete table backends.
- Subclasses implement the ``render`` method which receives an
- index-aware pandas DataFrame and the alignment for each column
- header.
+ Subclasses implement the ``render`` method which receives an index-
+ aware pandas DataFrame and the alignment for each column header.
"""
FLOAT_PRECISION = 5
@@ -34,20 +34,26 @@ def __init__(self) -> None:
super().__init__()
self._float_fmt = f'{{:.{self.FLOAT_PRECISION}f}}'.format
- def _format_value(self, value: Any) -> Any:
- """Format floats with fixed precision and others as strings.
+ def _format_value(self, value: object) -> object:
+ """
+ Format floats with fixed precision and others as strings.
- Args:
- value: Cell value to format.
+ Parameters
+ ----------
+ value : object
+ Cell value to format.
- Returns:
+ Returns
+ -------
+ object
A string representation with fixed precision for floats or
``str(value)`` for other types.
"""
return self._float_fmt(value) if isinstance(value, float) else str(value)
def _is_dark_theme(self) -> bool:
- """Return True when a dark theme is detected in Jupyter.
+ """
+ Return True when a dark theme is detected in Jupyter.
If not running inside Jupyter, return a sane default (True).
"""
@@ -62,14 +68,18 @@ def _is_dark_theme(self) -> bool:
return is_dark()
- def _rich_to_hex(self, color):
- """Convert a Rich color name to a CSS-style hex string.
+ def _rich_to_hex(self, color: str) -> str:
+ """
+ Convert a Rich color name to a CSS-style hex string.
- Args:
- color: Rich color name or specification parsable by
- :mod:`rich`.
+ Parameters
+ ----------
+ color : str
+ Rich color name or specification parsable by :mod:`rich`.
- Returns:
+ Returns
+ -------
+ str
Hex color string in the form ``#RRGGBB``.
"""
c = Color.parse(color)
@@ -90,21 +100,27 @@ def _pandas_border_color(self) -> str:
@abstractmethod
def render(
self,
- alignments,
- df,
- display_handle: Any | None = None,
- ) -> Any:
- """Render the provided DataFrame with backend-specific styling.
-
- Args:
- alignments: Iterable of column justifications (e.g.,
- ``'left'`` or ``'center'``) corresponding to the data
- columns.
- df: Index-aware DataFrame with data to render.
- display_handle: Optional environment-specific handle to
- enable in-place updates.
-
- Returns:
+ alignments: object,
+ df: object,
+ display_handle: object | None = None,
+ ) -> object:
+ """
+ Render the provided DataFrame with backend-specific styling.
+
+ Parameters
+ ----------
+ alignments : object
+ Iterable of column justifications (e.g., ``'left'`` or
+ ``'center'``) corresponding to the data columns.
+ df : object
+ Index-aware DataFrame with data to render.
+ display_handle : object | None, default=None
+ Optional environment-specific handle to enable in-place
+ updates.
+
+ Returns
+ -------
+ object
Backend-defined return value (commonly ``None``).
"""
pass
diff --git a/src/easydiffraction/display/tablers/pandas.py b/src/easydiffraction/display/tablers/pandas.py
index da05b5e8..4efef148 100644
--- a/src/easydiffraction/display/tablers/pandas.py
+++ b/src/easydiffraction/display/tablers/pandas.py
@@ -1,11 +1,9 @@
-# SPDX-FileCopyrightText: 2021-2026 EasyDiffraction contributors