From ecb51e423599e0ef6fc711680f4577899487a8fb Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 21:25:50 +0200 Subject: [PATCH 001/106] Add Bayesian analysis design note --- docs/dev/bayesian-analysis-design.md | 410 +++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 docs/dev/bayesian-analysis-design.md diff --git a/docs/dev/bayesian-analysis-design.md b/docs/dev/bayesian-analysis-design.md new file mode 100644 index 00000000..d3097e46 --- /dev/null +++ b/docs/dev/bayesian-analysis-design.md @@ -0,0 +1,410 @@ +# Bayesian Analysis Design + +**Status:** Draft +**Date:** 2026-05-07 + +## Goal + +Add Bayesian analysis to the existing fitting workflow with the smallest +user-facing API change possible, reusing the current `Analysis`, +`Fit`, `Fitter`, minimizer factory, result reporting, and plotting +surfaces. + +The primary first target is BUMPS DREAM sampling for diffraction +refinement with parameter bounds taken from each parameter's +`fit_min` and `fit_max` attributes. + +## User-Facing API + +The intended workflow stays aligned with the current fitting API: + +```python +project.analysis.fit.minimizer_type = 'bumps (lm)' +project.analysis.fit() + +project.analysis.fit.minimizer_type = 'bumps (dream)' +project.analysis.fit() + +project.analysis.display.fit_results() +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') +project.display.plotter.plot_param_correlations() +``` + +Additional Bayesian-only plotting methods should be added rather than +overloading every existing method with different semantics: + +```python +project.display.plotter.plot_posterior_pairs() +project.display.plotter.plot_param_distribution(param) +``` + +For the first implementation, these Bayesian plotting methods may use +ArviZ with the Plotly backend internally. + +### Explicit Two-Step Workflow + +`'bumps (dream)'` should **not** implicitly run a deterministic +Levenberg-Marquardt pre-fit. Users should call `'bumps (lm)'` first when +they want a better starting point. + +Reasons: + +- It keeps `fit()` behavior explicit and predictable. +- It avoids hidden extra runtime. +- It keeps deterministic fit failures separate from sampling failures. +- It matches the current minimizer-selection model. + +## Core Architectural Decision + +### Keep Full Results in `analysis.fit_results` + +Bayesian results should be stored in a new runtime result object, +**not** in a new heavy `Analysis` category. + +Recommended model: + +- `FitResults` remains the base deterministic result container. +- `BayesianFitResults` extends `FitResults` for posterior-specific data. +- `analysis.fit_results` stores either `FitResults` or + `BayesianFitResults`. + +This keeps the existing public access pattern unchanged: + +```python +project.analysis.fit_results +``` + +### Why Not a New Results Category Under `Analysis` + +Current `Analysis` categories are lightweight, structured, +project-owned configuration or control objects: + +- `fit` +- `aliases` +- `constraints` +- `joint_fit_experiments` + +These are serialized with the project. Full Bayesian results are a poor +fit for this category model because they are: + +- runtime products rather than project configuration +- potentially large arrays +- not natural CIF content +- often disposable or recomputable + +Posterior chains, posterior predictive draws, and pair-plot input data +should therefore remain runtime-only objects attached to +`BayesianFitResults`. + +## Optional Future Category + +A **small** `Analysis` category may still be useful later, but only for +Bayesian configuration, not for heavy result storage. + +Possible future category name: + +- `analysis.sampling` +- or `analysis.bayesian` + +Possible responsibilities: + +- sampler type +- point estimate policy +- default HDI levels +- exposed DREAM hyperparameters if they become public later + +This category should stay lightweight and serializable. It should not +store raw chains. + +## Proposed New Runtime Types + +### `BumpsDreamMinimizer` + +Add a new minimizer implementation registered through +`MinimizerFactory` with tag: + +```python +'bumps (dream)' +``` + +Responsibilities: + +- build bounded BUMPS parameters from EasyDiffraction parameters +- require finite `fit_min` and `fit_max` for every sampled parameter +- run DREAM with internal default settings +- collect posterior samples and sampler state +- compute posterior summaries +- set project parameters to the chosen point estimate after sampling + +### `BayesianFitResults` + +Subclass `FitResults` and add Bayesian-specific fields. + +Recommended fields: + +- `sampler_name` +- `point_estimate_name` +- `posterior_samples` +- `posterior_parameter_summaries` +- `posterior_predictive` +- `credible_interval_levels` +- `engine_result` + +### Supporting Value Objects + +Recommended helper containers: + +- `PosteriorSamples` +- `PosteriorParameterSummary` +- `PosteriorPredictiveSummary` + +These keep `BayesianFitResults` structured and reduce pressure to hide +plotting-specific arrays inside experiment data categories. + +## Point Estimate Policy + +After a DREAM run, project parameters should be updated to the **MAP** +or best posterior sample, not to independent marginal medians. + +Reason: + +- per-parameter medians can produce a parameter vector that was never + sampled jointly +- MAP corresponds to a coherent sampled state +- the calculated profile shown after Bayesian fitting should correspond + to one actual parameter set + +Posterior tables can still report median, standard deviation, and HDIs. + +## Parameter Bounds + +DREAM should require finite bounds for every sampled free parameter. + +Behavior: + +- use `fit_min` and `fit_max` +- if any sampled parameter is unbounded, stop with a clear error +- the error should list the offending parameter names + +This is stricter than some deterministic minimizers, but appropriate for +bounded posterior sampling. + +## Hidden DREAM Defaults + +For the first implementation, sampling parameters should stay internal +and use library defaults. + +Examples: + +- `n_steps` +- `n_burn` +- `thin` +- `pop` +- `alpha` + +These can become user-configurable later through a small sampling +configuration category or explicit keyword API. + +## Display Behavior + +### `project.analysis.display.fit_results()` + +Keep the existing entry point and dispatch by result type. + +Deterministic fit: + +- keep the current summary +- keep the current fitted-parameter table + +Bayesian fit: + +- show a sampling summary section +- show posterior parameter summaries instead of only fitted values and + covariance-derived uncertainties + +Recommended Bayesian table columns: + +- datablock +- category +- entry +- parameter +- start +- MAP +- median +- posterior std +- 68% interval +- 95% interval +- units + +## Plotting Behavior + +### `plot_meas_vs_calc(expt_name=...)` + +Keep the existing method name. + +Deterministic fit: + +- current measured vs calculated behavior unchanged + +Bayesian fit: + +- measured pattern +- MAP calculated line +- shaded credible band around prediction + +Recommended default: + +- one shaded 95% credible interval band + +This is the clearest default for diffraction patterns. A full posterior +predictive distribution at every x value is useful but visually denser, +so it should not be the default first view. + +### `plot_param_correlations()` + +Keep the current method name and purpose. + +Deterministic fit: + +- covariance- or engine-derived correlation matrix + +Bayesian fit: + +- posterior-sample correlation matrix + +This preserves the meaning of the method. + +### New `plot_posterior_pairs()` + +Add a new Bayesian-specific method for pairwise posterior exploration. + +Intended behavior: + +- ArviZ-backed implementation first +- Plotly backend +- pairwise scatter or density panels +- marginal distributions on the diagonal +- optional parameter subset support later + +This method should serve the role of an interactive corner or pair plot. + +### New `plot_param_distribution(param)` + +Add a one-dimensional marginal posterior plot for a selected parameter. + +Intended behavior: + +- ArviZ-backed implementation first +- posterior histogram or density +- MAP marker +- median marker +- HDI overlay + +This is more natural than starting with a model-comparison distribution +plot because the current library stores one active fit result, not a set +of compared Bayesian models. + +### Possible Later Addition: `plot_posterior_predictive(...)` + +A dedicated method can be added later for richer predictive views. + +Possible API: + +```python +project.display.plotter.plot_posterior_predictive( + expt_name='hrpt', + style='band', +) +``` + +Possible styles: + +- `band` +- `dist` + +For the first implementation, these views may also be delegated to +ArviZ where practical. + +## Data Ownership + +Experiment `data` categories should remain responsible for: + +- measured pattern +- current calculated pattern +- current background pattern + +Posterior-specific data should remain analysis-owned through +`BayesianFitResults`, because it is: + +- fit-result scoped +- potentially joint across experiments +- used mainly for reporting and plotting + +## Persistence and Serialization + +For the first implementation: + +- do not serialize full posterior chains to CIF +- do not force posterior arrays into project save files + +Possible future export surfaces: + +- explicit posterior export methods +- CSV summaries +- NumPy or NetCDF export if needed later + +## Dependency Direction + +For the first implementation, add ArviZ as a runtime dependency and use +it for Bayesian plotting and summary-oriented data transformations where +that reduces implementation cost. + +Recommended direction: + +- keep Plotly as the interactive rendering backend +- use ArviZ-backed plotting internally for Bayesian views where it fits +- keep the public EasyDiffraction plotting API independent of ArviZ + +Future note: + +- once Bayesian functionality stabilizes, EasyDiffraction may replace + some or all ArviZ-backed plots with project-native implementations to + improve control over styling, interactivity, and domain-specific + diffraction presentation + +## Recommended First Implementation Scope + +### Phase 1 + +- add `MinimizerTypeEnum.BUMPS_DREAM` +- add `BumpsDreamMinimizer` +- add `BayesianFitResults` +- keep `analysis.fit_results` as the single public result slot +- make `analysis.display.fit_results()` dispatch by result type + +### Phase 2 + +- extend `plot_meas_vs_calc()` with Bayesian credible bands +- extend `plot_param_correlations()` to use posterior samples when + available +- add `plot_posterior_pairs()` +- add `plot_param_distribution(param)` + +### Phase 3 + +- consider adding a lightweight `analysis.sampling` category for saved + Bayesian configuration +- consider explicit posterior export APIs +- consider richer predictive plotting modes + +## Summary + +The recommended design is: + +- add `'bumps (dream)'` as a normal minimizer type +- keep Bayesian analysis inside the existing `fit()` workflow +- store heavy posterior results in `BayesianFitResults` +- keep `analysis.fit_results` as the main public result entry point +- avoid a new heavy `Analysis` category for results +- only add a small new `Analysis` category later if Bayesian settings + need to become persistent and user-configurable From b3a5462669b4c007b36c6c881ec4d754156211ab Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 21:26:05 +0200 Subject: [PATCH 002/106] Add arviz for Bayesian analysis --- pixi.lock | 254 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 253 insertions(+), 2 deletions(-) diff --git a/pixi.lock b/pixi.lock index 4ff7fdb6..3ac082e7 100644 --- a/pixi.lock +++ b/pixi.lock @@ -175,6 +175,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -343,6 +347,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: ./ @@ -511,6 +517,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -678,6 +688,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: ./ @@ -840,6 +852,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -1007,6 +1023,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl - pypi: ./ @@ -1186,6 +1204,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -1354,6 +1376,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/3e/868e5c3364b6cee19ff3e1a122194fa4ce51def02c61023970442162859e/yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: ./ @@ -1521,6 +1545,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -1688,6 +1716,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/19/2a/725ecc166d53438bc88f76822ed4b1e3b10756e790bafd7b523fe97c322d/yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl - pypi: ./ @@ -1849,6 +1879,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -2016,6 +2050,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f5/be/25216a49daeeb7af2bec0db22d5e7df08ed1d7c9f65d78b14f3b74fd72fc/yarl-1.23.0-cp312-cp312-win_amd64.whl - pypi: ./ @@ -2194,6 +2230,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -2362,6 +2402,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: ./ @@ -2530,6 +2572,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -2697,6 +2743,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: ./ @@ -2859,6 +2907,10 @@ 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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 @@ -3026,6 +3078,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl - pypi: ./ @@ -4089,6 +4143,125 @@ packages: - pkg:pypi/arrow?source=hash-mapping size: 113854 timestamp: 1760831179410 +- pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + name: arviz + version: 1.1.0 + sha256: 87ebd21ce052f30d21f932b4166fc31b91c0bc7443f8da7fed3518b342267010 + requires_dist: + - arviz-base>=1.1.0,<1.2.0 + - arviz-stats[xarray]>=1.1.0,<1.2.0 + - arviz-plots>=1.1.0,<1.2.0 + - arviz-plots[bokeh] ; extra == 'bokeh' + - build ; extra == 'check' + - pre-commit ; extra == 'check' + - h5netcdf ; extra == 'doc' + - h5py ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - matplotlib ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - pydata-sphinx-theme>=0.13 ; extra == 'doc' + - sphinx>=5 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - sphinx-notfound-page ; extra == 'doc' + - sphinxcontrib-youtube ; extra == 'doc' + - sphinx-togglebutton ; extra == 'doc' + - sphobjinv ; extra == 'doc' + - arviz-base[h5netcdf] ; extra == 'h5netcdf' + - arviz-plots[matplotlib] ; extra == 'matplotlib' + - arviz-base[netcdf4] ; extra == 'netcdf4' + - arviz-plots[plotly] ; extra == 'plotly' + - pytest ; extra == 'test' + - arviz-base[zarr] ; extra == 'zarr' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + name: arviz-base + version: 1.1.0 + sha256: 4f97016f697751038f45d144331a1830c921f0ebc2739d5df343120fba453e83 + requires_dist: + - numpy>=2 + - xarray>=2024.11.0 + - typing-extensions>=3.10 + - lazy-loader>=0.4 + - build ; extra == 'check' + - pre-commit ; extra == 'check' + - docstub==0.4 ; extra == 'check' + - mypy ; extra == 'check' + - pre-commit ; extra == 'ci' + - cloudpickle ; extra == 'ci' + - sphinx-book-theme ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx>=5 ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'h5netcdf' + - netcdf4 ; extra == 'netcdf4' + - xarray!=2025.8.0 ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - scipy ; extra == 'test' + - zarr ; extra == 'zarr' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + name: arviz-plots + version: 1.1.0 + sha256: 5c7ab5b0c7c29cda6ddb5e04c699c70285fe68a76d2b1b42302c69a85742adde + requires_dist: + - arviz-base>=1.1,<1.2 + - arviz-stats[xarray]>=1.1,<1.2 + - bokeh>=3.4 ; extra == 'bokeh' + - sphinx-book-theme ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx>=6 ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'doc' + - plotly<6 ; extra == 'doc' + - matplotlib>=3.9 ; extra == 'matplotlib' + - plotly>=5.19 ; extra == 'plotly' + - webcolors ; extra == 'plotly' + - hypothesis ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - h5netcdf[h5py] ; extra == 'test' + - kaleido ; extra == 'test' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + name: arviz-stats + version: 1.1.0 + sha256: ed47334ccff8670a0b90a50e1a37e7257268084eb3436e6b7b15e623f1001947 + requires_dist: + - numpy>=2 + - scipy>=1.13 + - sphinx-book-theme ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx<9 ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'doc' + - sphinx-autosummary-accessors ; extra == 'doc' + - numba ; extra == 'numba' + - xarray-einstats[einops,numba] ; extra == 'numba' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest ; extra == 'test-xarray' + - pytest-cov ; extra == 'test-xarray' + - h5netcdf[h5py] ; extra == 'test-xarray' + - arviz-base>=1.1,<1.2 ; extra == 'xarray' + - xarray-einstats ; extra == 'xarray' + - xarray>=2024.11.0 ; extra == 'xarray' + requires_python: '>=3.12' - pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl name: asciichartpy version: 1.5.25 @@ -5388,9 +5561,10 @@ packages: requires_python: '>=3.12' - pypi: ./ name: easydiffraction - version: 0.16.0+devdirty3 - sha256: f7b222922aa1bbe773d6384ee96acc456820490c46139a8f2598129cb6c4717e + version: 0.16.0+devdirty7 + sha256: 0b4085f9386dbebf4b7c5a85d5f98b35d8cf1fc69f791bd0759d20995c534a33 requires_dist: + - arviz - asciichartpy - asteval - bumps @@ -12697,6 +12871,82 @@ packages: requires_dist: - h11>=0.16.0,<1 requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + name: xarray + version: 2026.4.0 + sha256: d43751d9fb4a90f9249c30431684f00c41bc874f1edccd862631a40cbc0edf08 + requires_dist: + - numpy>=1.26 + - packaging>=24.2 + - pandas>=2.2 + - scipy>=1.15 ; extra == 'accel' + - bottleneck ; extra == 'accel' + - numbagg>=0.9 ; extra == 'accel' + - numba>=0.62 ; extra == 'accel' + - flox>=0.10 ; extra == 'accel' + - opt-einsum ; extra == 'accel' + - xarray[accel,etc,io,parallel,viz] ; extra == 'complete' + - netcdf4>=1.6.0 ; extra == 'io' + - h5netcdf[h5py]>=1.5.0 ; extra == 'io' + - pydap ; extra == 'io' + - scipy>=1.15 ; extra == 'io' + - zarr>=3.0 ; extra == 'io' + - fsspec ; extra == 'io' + - cftime ; extra == 'io' + - pooch ; extra == 'io' + - sparse>=0.15 ; extra == 'etc' + - dask[complete] ; extra == 'parallel' + - cartopy>=0.24 ; extra == 'viz' + - matplotlib>=3.10 ; extra == 'viz' + - nc-time-axis ; extra == 'viz' + - seaborn ; extra == 'viz' + - pandas-stubs ; extra == 'types' + - scipy-stubs ; extra == 'types' + - types-colorama ; extra == 'types' + - types-decorator ; extra == 'types' + - types-defusedxml ; extra == 'types' + - types-docutils ; extra == 'types' + - types-networkx ; extra == 'types' + - types-openpyxl ; extra == 'types' + - types-pexpect ; extra == 'types' + - types-psutil ; extra == 'types' + - types-pycurl ; extra == 'types' + - types-pygments ; extra == 'types' + - types-python-dateutil ; extra == 'types' + - types-pytz ; extra == 'types' + - types-pyyaml ; extra == 'types' + - types-requests ; extra == 'types' + - types-setuptools ; extra == 'types' + - types-xlrd ; extra == 'types' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + name: xarray-einstats + version: 0.10.0 + sha256: fa3169b46cee29092db820d8bbc203148bada4fc970ee75e62cbf3dd7c5a8945 + requires_dist: + - numpy>=2.0 + - scipy>=1.13 + - xarray>=2024.2.0 + - furo ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx>=5 ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - watermark ; extra == 'doc' + - matplotlib ; extra == 'doc' + - sphinx-togglebutton ; extra == 'doc' + - einops ; extra == 'einops' + - numba>=0.55 ; extra == 'numba' + - hypothesis ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - packaging ; extra == 'test' + - scipy>=1.15 ; extra == 'test' + - preliz>=0.19 ; extra == 'test' + requires_python: '>=3.12' - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl name: xraydb version: 4.5.8 diff --git a/pyproject.toml b/pyproject.toml index 5faffe6b..3bab31f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,7 @@ dependencies = [ 'darkdetect', # Detecting dark mode (system-level) 'pandas', # Displaying tables in Jupyter notebooks 'plotly', # Interactive plots + 'arviz', # Bayesian analysis summaries and posterior plotting 'py3Dmol', # Visualisation of crystal structures ] From 252ee56acfc217c4563f92f6700679d74870f2b7 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 23:46:22 +0200 Subject: [PATCH 003/106] Remove old package structure documentation --- .github/copilot-instructions.md | 6 +- docs/architecture/package-structure-full.md | 425 ------------------- docs/architecture/package-structure-short.md | 224 ---------- tools/generate_package_docs.py | 4 +- 4 files changed, 5 insertions(+), 654 deletions(-) delete mode 100644 docs/architecture/package-structure-full.md delete mode 100644 docs/architecture/package-structure-short.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 18b01c47..5613d742 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -77,7 +77,7 @@ ## Testing - Every new module, class, or bug fix ships with tests. See - `docs/architecture/architecture.md` Β§10 for the full strategy. + `docs/dev/architecture.md` Β§10 for the full strategy. - Unit tests mirror the source tree: `src/easydiffraction//.py` β†’ `tests/unit/easydiffraction//test_.py`. Verify with @@ -102,8 +102,8 @@ - Before any structural/design change (new categories, factories, switchable-category wiring, datablocks, CIF serialisation), read - `docs/architecture/architecture.md` and follow documented patterns. - Localised bug fixes or test updates need only this file. + `docs/dev/architecture.md` and follow documented patterns. Localised + bug fixes or test updates need only this file. - Project is in beta: no legacy shims, no deprecation warnings β€” update tests and tutorials to the current API. - Minimal diffs; don't reformat working code. Fix only what's asked; diff --git a/docs/architecture/package-structure-full.md b/docs/architecture/package-structure-full.md deleted file mode 100644 index be35bb07..00000000 --- a/docs/architecture/package-structure-full.md +++ /dev/null @@ -1,425 +0,0 @@ -# Package Structure (full) - -``` -πŸ“¦ easydiffraction -β”œβ”€β”€ πŸ“ analysis -β”‚ β”œβ”€β”€ πŸ“ calculators -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderReflnRecord -β”‚ β”‚ β”‚ └── 🏷️ class CalculatorBase -β”‚ β”‚ β”œβ”€β”€ πŸ“„ crysfml.py -β”‚ β”‚ β”‚ └── 🏷️ class CrysfmlCalculator -β”‚ β”‚ β”œβ”€β”€ πŸ“„ cryspy.py -β”‚ β”‚ β”‚ └── 🏷️ class CryspyCalculator -β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class CalculatorFactory -β”‚ β”‚ └── πŸ“„ pdffit.py -β”‚ β”‚ └── 🏷️ class PdffitCalculator -β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”œβ”€β”€ πŸ“ aliases -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class Alias -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class Aliases -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class AliasesFactory -β”‚ β”‚ β”œβ”€β”€ πŸ“ constraints -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class Constraint -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class Constraints -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class ConstraintsFactory -β”‚ β”‚ β”œβ”€β”€ πŸ“ fit -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class Fit -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class FitModeEnum -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class FitFactory -β”‚ β”‚ β”œβ”€β”€ πŸ“ joint_fit_experiments -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class JointFitExperiment -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class JointFitExperiments -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class JointFitExperimentsFactory -β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“ fit_helpers -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ metrics.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ reporting.py -β”‚ β”‚ β”‚ └── 🏷️ class FitResults -β”‚ β”‚ └── πŸ“„ tracking.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class _TerminalLiveHandle -β”‚ β”‚ └── 🏷️ class FitProgressTracker -β”‚ β”œβ”€β”€ πŸ“ minimizers -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ └── 🏷️ class MinimizerBase -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps.py -β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class _EasyDiffractionFitness -β”‚ β”‚ β”‚ └── 🏷️ class BumpsMinimizer -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_amoeba.py -β”‚ β”‚ β”‚ └── 🏷️ class BumpsAmoebaMinimizer -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_de.py -β”‚ β”‚ β”‚ └── 🏷️ class BumpsDEMinimizer -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_lm.py -β”‚ β”‚ β”‚ └── 🏷️ class BumpsLmMinimizer -β”‚ β”‚ β”œβ”€β”€ πŸ“„ dfols.py -β”‚ β”‚ β”‚ └── 🏷️ class DfolsMinimizer -β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ └── 🏷️ class MinimizerTypeEnum -β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class MinimizerFactory -β”‚ β”‚ β”œβ”€β”€ πŸ“„ lmfit.py -β”‚ β”‚ β”‚ └── 🏷️ class LmfitMinimizer -β”‚ β”‚ β”œβ”€β”€ πŸ“„ lmfit_least_squares.py -β”‚ β”‚ β”‚ └── 🏷️ class LmfitLeastSquaresMinimizer -β”‚ β”‚ └── πŸ“„ lmfit_leastsq.py -β”‚ β”‚ └── 🏷️ class LmfitLeastsqMinimizer -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ analysis.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class AnalysisDisplay -β”‚ β”‚ └── 🏷️ class Analysis -β”‚ β”œβ”€β”€ πŸ“„ fitting.py -β”‚ β”‚ └── 🏷️ class Fitter -β”‚ └── πŸ“„ sequential.py -β”‚ └── 🏷️ class SequentialFitTemplate -β”œβ”€β”€ πŸ“ core -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ category.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class CategoryItem -β”‚ β”‚ └── 🏷️ class CategoryCollection -β”‚ β”œβ”€β”€ πŸ“„ collection.py -β”‚ β”‚ └── 🏷️ class CollectionBase -β”‚ β”œβ”€β”€ πŸ“„ datablock.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class DatablockItem -β”‚ β”‚ └── 🏷️ class DatablockCollection -β”‚ β”œβ”€β”€ πŸ“„ diagnostic.py -β”‚ β”‚ └── 🏷️ class Diagnostics -β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ └── 🏷️ class FactoryBase -β”‚ β”œβ”€β”€ πŸ“„ guard.py -β”‚ β”‚ └── 🏷️ class GuardedBase -β”‚ β”œβ”€β”€ πŸ“„ identity.py -β”‚ β”‚ └── 🏷️ class Identity -β”‚ β”œβ”€β”€ πŸ“„ metadata.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class TypeInfo -β”‚ β”‚ β”œβ”€β”€ 🏷️ class Compatibility -β”‚ β”‚ └── 🏷️ class CalculatorSupport -β”‚ β”œβ”€β”€ πŸ“„ singleton.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class SingletonBase -β”‚ β”‚ └── 🏷️ class ConstraintsHandler -β”‚ β”œβ”€β”€ πŸ“„ validation.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class DataTypeHints -β”‚ β”‚ β”œβ”€β”€ 🏷️ class DataTypes -β”‚ β”‚ β”œβ”€β”€ 🏷️ class ValidationStage -β”‚ β”‚ β”œβ”€β”€ 🏷️ class ValidatorBase -β”‚ β”‚ β”œβ”€β”€ 🏷️ class TypeValidator -β”‚ β”‚ β”œβ”€β”€ 🏷️ class RangeValidator -β”‚ β”‚ β”œβ”€β”€ 🏷️ class MembershipValidator -β”‚ β”‚ β”œβ”€β”€ 🏷️ class RegexValidator -β”‚ β”‚ └── 🏷️ class AttributeSpec -β”‚ └── πŸ“„ variable.py -β”‚ β”œβ”€β”€ 🏷️ class GenericDescriptorBase -β”‚ β”œβ”€β”€ 🏷️ class GenericStringDescriptor -β”‚ β”œβ”€β”€ 🏷️ class GenericNumericDescriptor -β”‚ β”œβ”€β”€ 🏷️ class GenericParameter -β”‚ β”œβ”€β”€ 🏷️ class StringDescriptor -β”‚ β”œβ”€β”€ 🏷️ class NumericDescriptor -β”‚ └── 🏷️ class Parameter -β”œβ”€β”€ πŸ“ crystallography -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ crystallography.py -β”‚ └── πŸ“„ space_groups.py -β”‚ └── 🏷️ class _RestrictedUnpickler -β”œβ”€β”€ πŸ“ datablocks -β”‚ β”œβ”€β”€ πŸ“ experiment -β”‚ β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ background -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class BackgroundBase -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ chebyshev.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PolynomialTerm -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ChebyshevPolynomialBackground -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class BackgroundTypeEnum -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class BackgroundFactory -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ line_segment.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class LineSegment -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class LineSegmentBackground -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ calculation -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class Calculation -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class CalculationFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ data -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdDataPointBaseMixin -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdCwlDataPointMixin -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdTofDataPointMixin -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdCwlDataPoint -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdTofDataPoint -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdDataBase -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdCwlData -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class PdTofData -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class DataFactory -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_pd.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TotalDataPoint -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TotalDataBase -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TotalData -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ diffrn -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class DefaultDiffrn -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class DiffrnFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ excluded_regions -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class ExcludedRegion -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ExcludedRegions -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ExcludedRegionsFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ experiment_type -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ExperimentType -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ExperimentTypeFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ extinction -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ becker_coppens.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class BeckerCoppensExtinction -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ExtinctionFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ instrument -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class InstrumentBase -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ cwl.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class CwlInstrumentBase -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class CwlScInstrument -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class CwlPdInstrument -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class InstrumentFactory -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ tof.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TofScInstrument -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TofPdInstrument -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ linked_crystal -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class LinkedCrystal -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class LinkedCrystalFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ linked_phases -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class LinkedPhase -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class LinkedPhases -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class LinkedPhasesFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ peak -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class PeakBase -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ cwl.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class CwlPseudoVoigt -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class CwlPseudoVoigtEmpiricalAsymmetry -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class CwlThompsonCoxHastings -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ cwl_mixins.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class CwlBroadeningMixin -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class EmpiricalAsymmetryMixin -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class FcjAsymmetryMixin -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class PeakFactory -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ tof.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TofPseudoVoigt -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TofJorgensen -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TofJorgensenVonDreele -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TofDoubleJorgensenVonDreele -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ tof_mixins.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TofGaussianBroadeningMixin -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TofLorentzianBroadeningMixin -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class TofBackToBackExponentialMixin -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TofDoubleExponentialMixin -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ total.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TotalGaussianDampedSinc -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_mixins.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TotalBroadeningMixin -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ refln -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderReflnBase -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderCwlRefln -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderTofRefln -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderReflnDataBase -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderCwlReflnData -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class PowderTofReflnData -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class Refln -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ReflnData -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ReflnFactory -β”‚ β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“ item -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class ExperimentBase -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class ScExperimentBase -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class PdExperimentBase -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class BraggPdExperiment -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class CwlScExperiment -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TofScExperiment -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class SampleFormEnum -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class ScatteringTypeEnum -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class RadiationProbeEnum -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class BeamModeEnum -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class CalculatorEnum -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PeakProfileTypeEnum -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ExtinctionModelEnum -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ExperimentFactory -β”‚ β”‚ β”‚ └── πŸ“„ total_pd.py -β”‚ β”‚ β”‚ └── 🏷️ class TotalPdExperiment -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ └── πŸ“„ collection.py -β”‚ β”‚ └── 🏷️ class Experiments -β”‚ β”œβ”€β”€ πŸ“ structure -β”‚ β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ atom_site_aniso -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class AtomSiteAniso -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class AtomSiteAnisoCollection -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class AtomSiteAnisoFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ atom_sites -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class AtomSite -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class AtomSites -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class AdpTypeEnum -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class AtomSitesFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ cell -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class Cell -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class CellFactory -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ space_group -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class SpaceGroup -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class SpaceGroupFactory -β”‚ β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“ item -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class Structure -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class StructureFactory -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ └── πŸ“„ collection.py -β”‚ β”‚ └── 🏷️ class Structures -β”‚ └── πŸ“„ __init__.py -β”œβ”€β”€ πŸ“ display -β”‚ β”œβ”€β”€ πŸ“ plotters -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ ascii.py -β”‚ β”‚ β”‚ └── 🏷️ class AsciiPlotter -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class BraggTickSet -β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderMeasVsCalcSpec -β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class XAxisType -β”‚ β”‚ β”‚ └── 🏷️ class PlotterBase -β”‚ β”‚ └── πŸ“„ plotly.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderCompositeRows -β”‚ β”‚ └── 🏷️ class PlotlyPlotter -β”‚ β”œβ”€β”€ πŸ“ tablers -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ └── 🏷️ class TableBackendBase -β”‚ β”‚ β”œβ”€β”€ πŸ“„ pandas.py -β”‚ β”‚ β”‚ └── 🏷️ class PandasTableBackend -β”‚ β”‚ └── πŸ“„ rich.py -β”‚ β”‚ └── 🏷️ class RichTableBackend -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class RendererBase -β”‚ β”‚ └── 🏷️ class RendererFactoryBase -β”‚ β”œβ”€β”€ πŸ“„ plotting.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class PlotterEngineEnum -β”‚ β”‚ β”œβ”€β”€ 🏷️ class _MeasVsCalcPlotOptions -β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PowderMeasVsCalcSeries -β”‚ β”‚ β”œβ”€β”€ 🏷️ class Plotter -β”‚ β”‚ └── 🏷️ class PlotterFactory -β”‚ β”œβ”€β”€ πŸ“„ tables.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class TableEngineEnum -β”‚ β”‚ β”œβ”€β”€ 🏷️ class TableRenderer -β”‚ β”‚ └── 🏷️ class TableRendererFactory -β”‚ └── πŸ“„ utils.py -β”‚ └── 🏷️ class JupyterScrollManager -β”œβ”€β”€ πŸ“ io -β”‚ β”œβ”€β”€ πŸ“ cif -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ handler.py -β”‚ β”‚ β”‚ └── 🏷️ class CifHandler -β”‚ β”‚ β”œβ”€β”€ πŸ“„ parse.py -β”‚ β”‚ └── πŸ“„ serialize.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ └── πŸ“„ ascii.py -β”œβ”€β”€ πŸ“ project -β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”œβ”€β”€ πŸ“ display -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── 🏷️ class Display -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── 🏷️ class DisplayFactory -β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ project.py -β”‚ β”‚ └── 🏷️ class Project -β”‚ └── πŸ“„ project_info.py -β”‚ └── 🏷️ class ProjectInfo -β”œβ”€β”€ πŸ“ summary -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ └── πŸ“„ summary.py -β”‚ └── 🏷️ class Summary -β”œβ”€β”€ πŸ“ utils -β”‚ β”œβ”€β”€ πŸ“ _vendored -β”‚ β”‚ β”œβ”€β”€ πŸ“ jupyter_dark_detect -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ └── πŸ“„ detector.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ └── πŸ“„ theme_detect.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ └── 🏷️ class VerbosityEnum -β”‚ β”œβ”€β”€ πŸ“„ environment.py -β”‚ β”œβ”€β”€ πŸ“„ logging.py -β”‚ β”‚ β”œβ”€β”€ 🏷️ class IconifiedRichHandler -β”‚ β”‚ β”œβ”€β”€ 🏷️ class ConsoleManager -β”‚ β”‚ β”œβ”€β”€ 🏷️ class LoggerConfig -β”‚ β”‚ β”œβ”€β”€ 🏷️ class ExceptionHookManager -β”‚ β”‚ β”œβ”€β”€ 🏷️ class Logger -β”‚ β”‚ └── 🏷️ class ConsolePrinter -β”‚ └── πŸ“„ utils.py -β”œβ”€β”€ πŸ“„ __init__.py -└── πŸ“„ __main__.py -``` diff --git a/docs/architecture/package-structure-short.md b/docs/architecture/package-structure-short.md deleted file mode 100644 index ba2a0b33..00000000 --- a/docs/architecture/package-structure-short.md +++ /dev/null @@ -1,224 +0,0 @@ -# Package Structure (short) - -``` -πŸ“¦ easydiffraction -β”œβ”€β”€ πŸ“ analysis -β”‚ β”œβ”€β”€ πŸ“ calculators -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ crysfml.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ cryspy.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ └── πŸ“„ pdffit.py -β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”œβ”€β”€ πŸ“ aliases -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”œβ”€β”€ πŸ“ constraints -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”œβ”€β”€ πŸ“ fit -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”œβ”€β”€ πŸ“ joint_fit_experiments -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“ fit_helpers -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ metrics.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ reporting.py -β”‚ β”‚ └── πŸ“„ tracking.py -β”‚ β”œβ”€β”€ πŸ“ minimizers -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_amoeba.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_de.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_lm.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ dfols.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ lmfit.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ lmfit_least_squares.py -β”‚ β”‚ └── πŸ“„ lmfit_leastsq.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ analysis.py -β”‚ β”œβ”€β”€ πŸ“„ fitting.py -β”‚ └── πŸ“„ sequential.py -β”œβ”€β”€ πŸ“ core -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ category.py -β”‚ β”œβ”€β”€ πŸ“„ collection.py -β”‚ β”œβ”€β”€ πŸ“„ datablock.py -β”‚ β”œβ”€β”€ πŸ“„ diagnostic.py -β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”œβ”€β”€ πŸ“„ guard.py -β”‚ β”œβ”€β”€ πŸ“„ identity.py -β”‚ β”œβ”€β”€ πŸ“„ metadata.py -β”‚ β”œβ”€β”€ πŸ“„ singleton.py -β”‚ β”œβ”€β”€ πŸ“„ validation.py -β”‚ └── πŸ“„ variable.py -β”œβ”€β”€ πŸ“ crystallography -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ crystallography.py -β”‚ └── πŸ“„ space_groups.py -β”œβ”€β”€ πŸ“ datablocks -β”‚ β”œβ”€β”€ πŸ“ experiment -β”‚ β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ background -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ chebyshev.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ line_segment.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ calculation -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ data -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_pd.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ diffrn -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ excluded_regions -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ experiment_type -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ extinction -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ becker_coppens.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ instrument -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ cwl.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ tof.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ linked_crystal -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ linked_phases -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ peak -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ cwl.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ cwl_mixins.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ tof.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ tof_mixins.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ total.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_mixins.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ refln -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“ item -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py -β”‚ β”‚ β”‚ └── πŸ“„ total_pd.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ └── πŸ“„ collection.py -β”‚ β”œβ”€β”€ πŸ“ structure -β”‚ β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ atom_site_aniso -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ atom_sites -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ cell -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ space_group -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“ item -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ └── πŸ“„ collection.py -β”‚ └── πŸ“„ __init__.py -β”œβ”€β”€ πŸ“ display -β”‚ β”œβ”€β”€ πŸ“ plotters -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ ascii.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ └── πŸ“„ plotly.py -β”‚ β”œβ”€β”€ πŸ“ tablers -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ pandas.py -β”‚ β”‚ └── πŸ“„ rich.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ base.py -β”‚ β”œβ”€β”€ πŸ“„ plotting.py -β”‚ β”œβ”€β”€ πŸ“„ tables.py -β”‚ └── πŸ“„ utils.py -β”œβ”€β”€ πŸ“ io -β”‚ β”œβ”€β”€ πŸ“ cif -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ handler.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ parse.py -β”‚ β”‚ └── πŸ“„ serialize.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ └── πŸ“„ ascii.py -β”œβ”€β”€ πŸ“ project -β”‚ β”œβ”€β”€ πŸ“ categories -β”‚ β”‚ β”œβ”€β”€ πŸ“ display -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ default.py -β”‚ β”‚ β”‚ └── πŸ“„ factory.py -β”‚ β”‚ └── πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ project.py -β”‚ └── πŸ“„ project_info.py -β”œβ”€β”€ πŸ“ summary -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ └── πŸ“„ summary.py -β”œβ”€β”€ πŸ“ utils -β”‚ β”œβ”€β”€ πŸ“ _vendored -β”‚ β”‚ β”œβ”€β”€ πŸ“ jupyter_dark_detect -β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ β”‚ └── πŸ“„ detector.py -β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”‚ └── πŸ“„ theme_detect.py -β”‚ β”œβ”€β”€ πŸ“„ __init__.py -β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”œβ”€β”€ πŸ“„ environment.py -β”‚ β”œβ”€β”€ πŸ“„ logging.py -β”‚ └── πŸ“„ utils.py -β”œβ”€β”€ πŸ“„ __init__.py -└── πŸ“„ __main__.py -``` diff --git a/tools/generate_package_docs.py b/tools/generate_package_docs.py index 671a4f0e..1d860557 100644 --- a/tools/generate_package_docs.py +++ b/tools/generate_package_docs.py @@ -3,7 +3,7 @@ """Generate project package structure markdown files. -Outputs two docs under docs/architecture/: +Outputs two docs under docs/dev/: - package-structure-short.md (folders/files only) - package-structure-full.md (folders/files and classes) @@ -21,7 +21,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1] SRC_ROOT = REPO_ROOT / 'src' / 'easydiffraction' -DOCS_OUT_DIR = REPO_ROOT / 'docs' / 'architecture' +DOCS_OUT_DIR = REPO_ROOT / 'docs' / 'dev' IGNORE_DIRS = { From 7849de32de0dd83b5767ba92a0c1ca8b2939cf2a Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 23:48:03 +0200 Subject: [PATCH 004/106] Update package structure docs with refln reorganization --- docs/dev/package-structure-full.md | 19 ++++++++++++++++--- docs/dev/package-structure-short.md | 6 +++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/dev/package-structure-full.md b/docs/dev/package-structure-full.md index ae233b21..be35bb07 100644 --- a/docs/dev/package-structure-full.md +++ b/docs/dev/package-structure-full.md @@ -6,6 +6,7 @@ β”‚ β”œβ”€β”€ πŸ“ calculators β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ base.py +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderReflnRecord β”‚ β”‚ β”‚ └── 🏷️ class CalculatorBase β”‚ β”‚ β”œβ”€β”€ πŸ“„ crysfml.py β”‚ β”‚ β”‚ └── 🏷️ class CrysfmlCalculator @@ -169,9 +170,6 @@ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdDataBase β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PdCwlData β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class PdTofData -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py -β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class Refln -β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ReflnData β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class DataFactory β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_pd.py @@ -257,6 +255,20 @@ β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TotalGaussianDampedSinc β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_mixins.py β”‚ β”‚ β”‚ β”‚ └── 🏷️ class TotalBroadeningMixin +β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ refln +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderReflnBase +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderCwlRefln +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderTofRefln +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderReflnDataBase +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PowderCwlReflnData +β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class PowderTofReflnData +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class Refln +β”‚ β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ReflnData +β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py +β”‚ β”‚ β”‚ β”‚ └── 🏷️ class ReflnFactory β”‚ β”‚ β”‚ └── πŸ“„ __init__.py β”‚ β”‚ β”œβ”€β”€ πŸ“ item β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py @@ -353,6 +365,7 @@ β”‚ β”œβ”€β”€ πŸ“„ plotting.py β”‚ β”‚ β”œβ”€β”€ 🏷️ class PlotterEngineEnum β”‚ β”‚ β”œβ”€β”€ 🏷️ class _MeasVsCalcPlotOptions +β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PowderMeasVsCalcSeries β”‚ β”‚ β”œβ”€β”€ 🏷️ class Plotter β”‚ β”‚ └── 🏷️ class PlotterFactory β”‚ β”œβ”€β”€ πŸ“„ tables.py diff --git a/docs/dev/package-structure-short.md b/docs/dev/package-structure-short.md index 30b4daf7..ba2a0b33 100644 --- a/docs/dev/package-structure-short.md +++ b/docs/dev/package-structure-short.md @@ -85,7 +85,6 @@ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ data β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py -β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_pd.py β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ diffrn @@ -128,6 +127,11 @@ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ tof_mixins.py β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ total.py β”‚ β”‚ β”‚ β”‚ └── πŸ“„ total_mixins.py +β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ refln +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_pd.py +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bragg_sc.py +β”‚ β”‚ β”‚ β”‚ └── πŸ“„ factory.py β”‚ β”‚ β”‚ └── πŸ“„ __init__.py β”‚ β”‚ β”œβ”€β”€ πŸ“ item β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py From 9a880810c0054b2438842c02b415c9175b098296 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 23:48:15 +0200 Subject: [PATCH 005/106] Plan Bayesian DREAM implementation --- docs/dev/bayesian-analysis-design.md | 616 ++++++++++++++++++++------- docs/dev/plan_bayesian-analysis.md | 334 +++++++++++++++ 2 files changed, 806 insertions(+), 144 deletions(-) create mode 100644 docs/dev/plan_bayesian-analysis.md diff --git a/docs/dev/bayesian-analysis-design.md b/docs/dev/bayesian-analysis-design.md index d3097e46..1ca66fdb 100644 --- a/docs/dev/bayesian-analysis-design.md +++ b/docs/dev/bayesian-analysis-design.md @@ -1,18 +1,49 @@ # Bayesian Analysis Design -**Status:** Draft -**Date:** 2026-05-07 +**Status:** Design proposal **Date:** 2026-05-07 ## Goal Add Bayesian analysis to the existing fitting workflow with the smallest -user-facing API change possible, reusing the current `Analysis`, -`Fit`, `Fitter`, minimizer factory, result reporting, and plotting -surfaces. - -The primary first target is BUMPS DREAM sampling for diffraction -refinement with parameter bounds taken from each parameter's -`fit_min` and `fit_max` attributes. +user-facing API change possible. The first implementation target is the +BUMPS DREAM sampler for diffraction refinement, with sampled parameters +bounded by each parameter's `fit_min` and `fit_max` attributes. + +The word `DREAM` in this document means the BUMPS Markov-chain Monte +Carlo sampler. It does not refer to the ESS DREAM instrument. + +## Design Principles + +- Keep `project.analysis.fit()` as the single execution entry point. +- Add `'bumps (dream)'` as a normal minimizer tag. +- Store large posterior outputs in runtime result objects, not in CIF + categories. +- Commit one coherent sampled parameter vector back to the project after + sampling. +- Keep deterministic fitting and Bayesian sampling behavior explicit. +- Add Bayesian display and plotting behavior without changing existing + deterministic semantics. + +## Current Code Anchors + +The design should extend the existing seams instead of adding a parallel +analysis stack: + +- `src/easydiffraction/analysis/categories/fit/default.py` owns + `fit.minimizer_type` and `fit.mode`. +- `src/easydiffraction/analysis/fitting.py` collects free parameters, + builds the residual objective, and calls `MinimizerBase.fit()`. +- `src/easydiffraction/analysis/minimizers/base.py` defines the + minimizer lifecycle and returns a `FitResults` instance. +- `src/easydiffraction/analysis/minimizers/bumps.py` already adapts an + EasyDiffraction residual function into BUMPS through + `_EasyDiffractionFitness`. +- `src/easydiffraction/analysis/fit_helpers/reporting.py` owns + `FitResults` display behavior. +- `src/easydiffraction/display/plotting.py` currently builds parameter + correlations from `analysis.fit_results.engine_result`. +- `pyproject.toml` already declares `arviz`, so Bayesian plotting does + not need a new dependency decision. ## User-Facing API @@ -30,36 +61,104 @@ project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') project.display.plotter.plot_param_correlations() ``` -Additional Bayesian-only plotting methods should be added rather than -overloading every existing method with different semantics: +Additional Bayesian-specific plotting methods should be added rather +than forcing every existing plotting method to accept Bayesian-specific +options: ```python project.display.plotter.plot_posterior_pairs() project.display.plotter.plot_param_distribution(param) +project.display.plotter.plot_posterior_predictive(expt_name='hrpt') ``` -For the first implementation, these Bayesian plotting methods may use -ArviZ with the Plotly backend internally. - ### Explicit Two-Step Workflow -`'bumps (dream)'` should **not** implicitly run a deterministic +`'bumps (dream)'` must not implicitly run a deterministic Levenberg-Marquardt pre-fit. Users should call `'bumps (lm)'` first when they want a better starting point. Reasons: -- It keeps `fit()` behavior explicit and predictable. -- It avoids hidden extra runtime. -- It keeps deterministic fit failures separate from sampling failures. -- It matches the current minimizer-selection model. +- `fit()` stays explicit and predictable. +- Hidden pre-fitting can add significant runtime. +- Deterministic failures stay separate from sampling failures. +- The behavior matches the existing minimizer-selection model. + +## Scope + +### In Scope For The First Implementation + +- Register `MinimizerTypeEnum.BUMPS_DREAM` with tag `'bumps (dream)'`. +- Add `BumpsDreamMinimizer`. +- Add `BayesianFitResults` and small posterior value objects. +- Require finite bounds for every sampled free parameter. +- Use bounded uniform priors implied by `fit_min` and `fit_max`. +- Use the existing residual objective and BUMPS likelihood convention. +- Store posterior chains runtime-only in `analysis.fit_results`. +- Display posterior summaries from `analysis.display.fit_results()`. +- Add posterior correlation support to `plot_param_correlations()`. +- Add posterior marginal and posterior pair plots. +- Add posterior predictive plotting with capped draw evaluation. + +### Out Of Scope Initially + +- Automatic deterministic pre-fitting. +- Persistent Bayesian configuration categories. +- CIF serialization of posterior chains. +- Export of posterior chains. +- Model comparison across multiple Bayesian fits. +- User-facing DREAM hyperparameter controls. +- Unbounded posterior predictive storage for every draw and every + experiment. +- Sequential Bayesian fitting. + +## Resolved Design Decisions + +- `plot_posterior_predictive(...)` is required for the first useful + Bayesian implementation. +- Posterior chains remain runtime-only and do not need an export API in + phase 1. +- `project.analysis.fit(random_seed=...)` should be supported for + `'bumps (dream)'` because stochastic scientific workflows need + reproducibility. If omitted, the minimizer should generate a seed and + record it in `BayesianFitResults.sampler_settings`. +- Deterministic minimizers should reject a non-`None` `random_seed` with + a clear error rather than silently ignoring it. +- `BayesianFitResults.success` should mean that DREAM completed and + produced usable posterior samples. Convergence quality should be + stored separately in diagnostics, displayed prominently, and warned on + when poor. It should set `success=False` only when there are no usable + samples or the sampler itself fails. +- Posterior predictive plots should evaluate a capped subset of + posterior draws. Start with an internal default cap of 200 draws, + record the effective draw count in the result, and expose the cap only + later if users need control. + +## Statistical Semantics + +The existing residual objective returns the residual vector consumed by +deterministic minimizers. The first Bayesian implementation should treat +the BUMPS negative log likelihood as: + +```python +nllf = 0.5 * sum(residuals**2) +``` + +This assumes residuals are already scaled consistently with the +experimental uncertainty model. If an experiment does not provide valid +uncertainties, the posterior is only as meaningful as the residual +weighting currently used by deterministic fitting. + +Initial priors are uniform inside finite `fit_min` and `fit_max` bounds +and zero outside those bounds. No Gaussian, log-normal, or +domain-specific priors are part of the first implementation. ## Core Architectural Decision -### Keep Full Results in `analysis.fit_results` +### Keep Full Results In `analysis.fit_results` -Bayesian results should be stored in a new runtime result object, -**not** in a new heavy `Analysis` category. +Bayesian results should be stored in a new runtime result object, not in +a new heavy `Analysis` category. Recommended model: @@ -74,10 +173,10 @@ This keeps the existing public access pattern unchanged: project.analysis.fit_results ``` -### Why Not a New Results Category Under `Analysis` +### Why Not A New Results Category Under `Analysis` -Current `Analysis` categories are lightweight, structured, -project-owned configuration or control objects: +Current `Analysis` categories are lightweight, structured, project-owned +configuration or control objects: - `fit` - `aliases` @@ -92,36 +191,39 @@ fit for this category model because they are: - not natural CIF content - often disposable or recomputable -Posterior chains, posterior predictive draws, and pair-plot input data +Posterior chains, posterior predictive draws, and pair-plot inputs should therefore remain runtime-only objects attached to `BayesianFitResults`. ## Optional Future Category -A **small** `Analysis` category may still be useful later, but only for +A small `Analysis` category may still be useful later, but only for Bayesian configuration, not for heavy result storage. Possible future category name: - `analysis.sampling` -- or `analysis.bayesian` +- `analysis.bayesian` Possible responsibilities: - sampler type - point estimate policy -- default HDI levels -- exposed DREAM hyperparameters if they become public later +- default highest-density interval levels +- default posterior predictive draw cap +- public DREAM hyperparameters +- persistent default random seed policy, if users need saved sampling + preferences later -This category should stay lightweight and serializable. It should not +This category should stay lightweight and serializable. It must not store raw chains. -## Proposed New Runtime Types +## Runtime Type Contracts ### `BumpsDreamMinimizer` -Add a new minimizer implementation registered through -`MinimizerFactory` with tag: +Add a new minimizer implementation registered through `MinimizerFactory` +with tag: ```python 'bumps (dream)' @@ -129,18 +231,37 @@ Add a new minimizer implementation registered through Responsibilities: -- build bounded BUMPS parameters from EasyDiffraction parameters -- require finite `fit_min` and `fit_max` for every sampled parameter -- run DREAM with internal default settings -- collect posterior samples and sampler state -- compute posterior summaries -- set project parameters to the chosen point estimate after sampling +- Reuse `_EasyDiffractionFitness` or a small subclass of it. +- Build bounded BUMPS parameters from EasyDiffraction parameters. +- Preserve parameter order from `Fitter.fit()` through all arrays. +- Validate finite bounds before starting the sampler. +- Run DREAM with internal defaults. +- Collect posterior samples, log likelihood values, and sampler + diagnostics where BUMPS exposes them. +- Choose and commit the MAP or best posterior sample after sampling. +- Build `BayesianFitResults`. + +The existing `BumpsMinimizer` handles BUMPS parameter ordering carefully +because `FitProblem` can sort parameters internally. DREAM must preserve +the same guarantee: result arrays and summaries must be mapped back to +the original EasyDiffraction parameter order. ### `BayesianFitResults` -Subclass `FitResults` and add Bayesian-specific fields. +Subclass `FitResults` and add Bayesian-specific fields. Inherited fields +should keep deterministic-compatible meanings: -Recommended fields: +- `success`: sampler completed and produced usable posterior samples +- `parameters`: EasyDiffraction parameters updated to the committed MAP + vector +- `starting_parameters`: an immutable snapshot of starting values, not + the same mutable parameter objects after fitting +- `reduced_chi_square`: reduced chi-square at the committed MAP vector, + when available +- `engine_result`: raw or lightly wrapped BUMPS DREAM result +- `fitting_time`: elapsed sampling time + +Recommended Bayesian fields: - `sampler_name` - `point_estimate_name` @@ -148,51 +269,154 @@ Recommended fields: - `posterior_parameter_summaries` - `posterior_predictive` - `credible_interval_levels` -- `engine_result` +- `diagnostics` +- `sampler_settings` + +`sampler_settings` should record the internal defaults actually used. +That keeps a runtime audit trail even before the settings are public +configuration. + +For DREAM, `sampler_settings` must include `random_seed`, whether the +seed was user-provided or generated, and the posterior predictive draw +cap used for summaries. + +### `PosteriorSamples` + +Recommended fields: + +- `parameter_names`: minimizer-safe names, matching sampled array order +- `parameter_labels`: user-facing labels for tables and plots +- `values`: NumPy array shaped `(chain, draw, parameter)` +- `flat_values`: optional cached array shaped `(sample, parameter)` +- `log_likelihood`: optional NumPy array shaped `(chain, draw)` +- `log_posterior`: optional NumPy array shaped `(chain, draw)` +- `bounds`: mapping from parameter name to `(fit_min, fit_max)` +- `start_values`: starting values in parameter order +- `map_values`: committed MAP values in parameter order +- `map_chain`: chain index of the MAP sample, if known +- `map_draw`: draw index of the MAP sample, if known + +The object should provide one conversion helper: + +```python +posterior_samples.to_arviz() +``` -### Supporting Value Objects +This keeps public EasyDiffraction methods independent of ArviZ while +letting plotting and summaries use ArviZ internally. -Recommended helper containers: +### `PosteriorParameterSummary` -- `PosteriorSamples` -- `PosteriorParameterSummary` -- `PosteriorPredictiveSummary` +Recommended fields: -These keep `BayesianFitResults` structured and reduce pressure to hide -plotting-specific arrays inside experiment data categories. +- `parameter_name` +- `parameter_label` +- `datablock` +- `category` +- `entry` +- `parameter` +- `start` +- `map` +- `mean` +- `median` +- `std` +- `hdi` +- `fit_min` +- `fit_max` +- `units` + +`hdi` should be a mapping keyed by interval probability, for example: + +```python +{ + 0.68: (lower_68, upper_68), + 0.95: (lower_95, upper_95), +} +``` + +### `PosteriorPredictiveSummary` + +Posterior predictive data can be expensive for diffraction patterns, so +the first implementation should store summaries rather than every draw. + +Recommended fields: + +- `experiment_name` +- `x` +- `y_observed` +- `y_map` +- `intervals` +- `draw_count` + +`intervals` should be keyed by interval probability: + +```python +{ + 0.95: (lower_y, upper_y), +} +``` + +Posterior predictive summaries are required for +`plot_posterior_predictive(...)`, but they should be based on a capped +subset of posterior draws. The default cap is an internal implementation +constant, initially 200 draws. ## Point Estimate Policy -After a DREAM run, project parameters should be updated to the **MAP** -or best posterior sample, not to independent marginal medians. +After a DREAM run, project parameters should be updated to the MAP or +best posterior sample, not to independent marginal medians. -Reason: +Reasons: -- per-parameter medians can produce a parameter vector that was never - sampled jointly -- MAP corresponds to a coherent sampled state -- the calculated profile shown after Bayesian fitting should correspond - to one actual parameter set +- Per-parameter medians can produce a parameter vector that was never + sampled jointly. +- MAP corresponds to one coherent sampled state. +- The calculated profile shown after Bayesian fitting should correspond + to one actual parameter set. -Posterior tables can still report median, standard deviation, and HDIs. +Posterior tables should still report mean, median, standard deviation, +and HDIs. + +If the sampler fails before producing usable samples, the minimizer +should restore starting parameter values instead of leaving the project +at an arbitrary last sampled state. ## Parameter Bounds DREAM should require finite bounds for every sampled free parameter. -Behavior: +Validation rules: + +- Use `fit_min` and `fit_max`. +- Bounds must be finite. +- `fit_min` must be strictly less than `fit_max`. +- The starting value must be inside the bounds. +- Validate only sampled parameters: free, unconstrained parameters + collected by `Fitter.fit()`. + +Failure behavior: -- use `fit_min` and `fit_max` -- if any sampled parameter is unbounded, stop with a clear error -- the error should list the offending parameter names +- Stop before running BUMPS. +- Raise a clear `ValueError`. +- List every offending parameter and the specific problem. This is stricter than some deterministic minimizers, but appropriate for bounded posterior sampling. -## Hidden DREAM Defaults +### Interaction With Physical Limits + +`Analysis.fit(use_physical_limits=True)` currently allows deterministic +minimizers to fill unbounded `fit_min` and `fit_max` from parameter +value spec physical limits. DREAM should use the same pre-processing +path. + +If `use_physical_limits=True` still leaves any sampled parameter +unbounded, DREAM must fail with the same finite-bound error. + +## DREAM Defaults And Reproducibility For the first implementation, sampling parameters should stay internal -and use library defaults. +and use library defaults or small wrapper constants in `bumps_dream.py`. Examples: @@ -202,8 +426,17 @@ Examples: - `pop` - `alpha` -These can become user-configurable later through a small sampling -configuration category or explicit keyword API. +These should not be user-facing API initially. They should be recorded +in `BayesianFitResults.sampler_settings` so users can inspect how a +runtime result was produced. + +The exception is `random_seed`, which should be accepted as an optional +keyword by `project.analysis.fit(...)` when the active minimizer is +`'bumps (dream)'`. This keeps stochastic results reproducible without +creating a persistent sampling category in phase 1. + +Tests may monkeypatch the internal defaults to keep unit and integration +tests fast. That test hook should not become public API. ## Display Behavior @@ -219,6 +452,8 @@ Deterministic fit: Bayesian fit: - show a sampling summary section +- show sampler settings that materially affect the result +- show diagnostics when available - show posterior parameter summaries instead of only fitted values and covariance-derived uncertainties @@ -230,12 +465,16 @@ Recommended Bayesian table columns: - parameter - start - MAP +- mean - median - posterior std -- 68% interval -- 95% interval +- 68% HDI +- 95% HDI - units +Display code should not require ArviZ at render time if summaries were +already computed by the minimizer. + ## Plotting Behavior ### `plot_meas_vs_calc(expt_name=...)` @@ -250,11 +489,12 @@ Bayesian fit: - measured pattern - MAP calculated line -- shaded credible band around prediction - -Recommended default: +- one shaded 95% credible interval band when `posterior_predictive` is + available -- one shaded 95% credible interval band +If predictive intervals are unavailable, the method should plot the MAP +calculated line and warn that posterior predictive intervals were not +computed. This is the clearest default for diffraction patterns. A full posterior predictive distribution at every x value is useful but visually denser, @@ -270,23 +510,33 @@ Deterministic fit: Bayesian fit: -- posterior-sample correlation matrix +- posterior-sample correlation matrix computed from flattened posterior + samples + +Implementation detail: + +- Check for `BayesianFitResults.posterior_samples` first. +- Fall back to the existing covariance path for deterministic results. +- Keep the current thresholding and lower-triangle display behavior. -This preserves the meaning of the method. +This preserves the meaning of the method while making it work for +posterior samples. ### New `plot_posterior_pairs()` -Add a new Bayesian-specific method for pairwise posterior exploration. +Add a Bayesian-specific method for pairwise posterior exploration. Intended behavior: - ArviZ-backed implementation first -- Plotly backend +- Plotly backend where practical - pairwise scatter or density panels - marginal distributions on the diagonal -- optional parameter subset support later +- optional parameter subset support This method should serve the role of an interactive corner or pair plot. +When the active result is deterministic, it should log a clear warning +instead of trying to infer a posterior from covariance. ### New `plot_param_distribution(param)` @@ -300,15 +550,23 @@ Intended behavior: - median marker - HDI overlay -This is more natural than starting with a model-comparison distribution -plot because the current library stores one active fit result, not a set -of compared Bayesian models. +Parameter selection should accept the same identifiers users see in +fit-result tables where possible: -### Possible Later Addition: `plot_posterior_predictive(...)` +- parameter object +- unique parameter name +- user-facing label -A dedicated method can be added later for richer predictive views. +Ambiguous string matches should fail with a clear error listing matching +parameters. -Possible API: +### New `plot_posterior_predictive(...)` + +Add a dedicated method for posterior predictive views. This is required +for phase 1 because `plot_meas_vs_calc(...)` should stay a concise +measured-versus-current-calculation view. + +Initial API: ```python project.display.plotter.plot_posterior_predictive( @@ -320,10 +578,21 @@ project.display.plotter.plot_posterior_predictive( Possible styles: - `band` -- `dist` +- `draws` +- `distribution` + +Initial behavior: + +- default to `style='band'` +- show measured pattern +- show MAP calculated line +- show a 95% posterior predictive band by default +- support capped individual posterior predictive draws with + `style='draws'` -For the first implementation, these views may also be delegated to -ArviZ where practical. +For the first implementation, richer views may be delegated to ArviZ +where practical, but diffraction-specific x/y plotting should remain +clear and domain-oriented. ## Data Ownership @@ -340,71 +609,130 @@ Posterior-specific data should remain analysis-owned through - potentially joint across experiments - used mainly for reporting and plotting -## Persistence and Serialization +When the MAP vector is committed, normal category update behavior should +make the current calculated pattern correspond to the MAP values. +Posterior predictive summaries should not mutate experiment data +categories for every posterior draw. + +## Persistence And Serialization For the first implementation: -- do not serialize full posterior chains to CIF -- do not force posterior arrays into project save files +- Do not serialize full posterior chains to CIF. +- Do not force posterior arrays into project save files. +- Let project auto-save persist the current MAP parameter values and + `fit.minimizer_type`, as it already does for deterministic fitting. +- Treat `analysis.fit_results` as runtime-only. Possible future export surfaces: - explicit posterior export methods - CSV summaries -- NumPy or NetCDF export if needed later - -## Dependency Direction - -For the first implementation, add ArviZ as a runtime dependency and use -it for Bayesian plotting and summary-oriented data transformations where -that reduces implementation cost. - -Recommended direction: - -- keep Plotly as the interactive rendering backend -- use ArviZ-backed plotting internally for Bayesian views where it fits -- keep the public EasyDiffraction plotting API independent of ArviZ - -Future note: - -- once Bayesian functionality stabilizes, EasyDiffraction may replace - some or all ArviZ-backed plots with project-native implementations to - improve control over styling, interactivity, and domain-specific - diffraction presentation - -## Recommended First Implementation Scope - -### Phase 1 - -- add `MinimizerTypeEnum.BUMPS_DREAM` -- add `BumpsDreamMinimizer` -- add `BayesianFitResults` -- keep `analysis.fit_results` as the single public result slot -- make `analysis.display.fit_results()` dispatch by result type - -### Phase 2 - -- extend `plot_meas_vs_calc()` with Bayesian credible bands -- extend `plot_param_correlations()` to use posterior samples when - available -- add `plot_posterior_pairs()` -- add `plot_param_distribution(param)` - -### Phase 3 - -- consider adding a lightweight `analysis.sampling` category for saved - Bayesian configuration -- consider explicit posterior export APIs -- consider richer predictive plotting modes +- ArviZ NetCDF export +- NumPy archive export + +## Failure And Warning Policy + +Hard failures should stop before expensive sampling when possible: + +- missing finite bounds +- invalid bound order +- start value outside bounds +- no sampled parameters +- BUMPS DREAM backend unavailable + +Soft warnings should allow a result to be returned: + +- convergence diagnostics unavailable +- convergence diagnostics outside recommended thresholds +- posterior predictive intervals not computed +- MAP value close to a fit bound + +`success` should mean that the sampler completed and usable posterior +samples were produced. Convergence diagnostics should be shown and +stored separately. Poor convergence should set a diagnostic flag and log +a warning, but it should not turn the result into a hard failure unless +there are no usable samples. + +## Testing Requirements + +Unit tests should cover: + +- `MinimizerTypeEnum.BUMPS_DREAM` and factory registration. +- Finite-bound validation with all offending parameters reported. +- Start-value-inside-bounds validation. +- `random_seed` threading and recording for DREAM. +- Non-`None` `random_seed` rejection for deterministic minimizers. +- Preservation of parameter order between EasyDiffraction parameters, + BUMPS parameters, posterior arrays, and summaries. +- MAP commit behavior. +- Restore-start-values behavior on sampler failure. +- `BayesianFitResults.display_results()` table content. +- Posterior correlation calculation from flattened posterior samples. +- Posterior predictive summary generation with capped draw evaluation. +- Deterministic correlation behavior remaining unchanged. +- Project serialization not including posterior arrays. + +Integration tests should cover: + +- A small bounded synthetic refinement with `'bumps (dream)'`. +- Optional deterministic pre-fit followed by DREAM as two explicit + `fit()` calls. +- `analysis.display.fit_results()` after DREAM. +- `plot_posterior_predictive(...)` after DREAM. +- Bayesian plotting smoke tests using a small posterior fixture. + +## Implementation Plan + +The detailed implementation plan is +`docs/dev/plan_bayesian-analysis.md`. It follows +`.github/copilot-instructions.md`: phase 1 is implementation only, phase +2 is verification, and every completed phase 1 implementation step must +be staged with explicit paths and committed locally before the next step +starts. + +High-level implementation order: + +- register the DREAM minimizer +- add Bayesian result models +- thread optional `random_seed` through fitting +- implement DREAM sampling and MAP commit behavior +- add Bayesian result display +- add posterior correlations +- add posterior distribution plots +- add posterior predictive summaries and plots + +## Acceptance Criteria + +The first useful implementation is complete when: + +- `project.analysis.fit.show_minimizer_types()` lists `'bumps (dream)'`. +- `project.analysis.fit.minimizer_type = 'bumps (dream)'` runs through + the same `project.analysis.fit()` path as other minimizers. +- Missing finite bounds fail before sampling with a clear parameter + list. +- Successful sampling stores `BayesianFitResults` in + `project.analysis.fit_results`. +- Project parameters are left at the MAP sample after a successful run. +- `project.analysis.display.fit_results()` renders posterior summaries. +- `plot_param_correlations()` works from posterior samples. +- `plot_posterior_predictive(expt_name=...)` shows measured data, MAP + calculation, and a posterior predictive band. +- Saving a project does not serialize posterior chains. + +## Implementation Discovery + +During implementation, inspect which BUMPS DREAM result object fields +are stable enough to store directly in `engine_result`. Normalize +posterior samples, log-likelihood values, diagnostics, and summaries +into EasyDiffraction-owned value objects first; keep `engine_result` as +an opaque backend escape hatch. ## Summary -The recommended design is: - -- add `'bumps (dream)'` as a normal minimizer type -- keep Bayesian analysis inside the existing `fit()` workflow -- store heavy posterior results in `BayesianFitResults` -- keep `analysis.fit_results` as the main public result entry point -- avoid a new heavy `Analysis` category for results -- only add a small new `Analysis` category later if Bayesian settings - need to become persistent and user-configurable +The recommended design is to add `'bumps (dream)'` as a normal minimizer +type, keep Bayesian analysis inside the existing `fit()` workflow, store +heavy posterior data in `BayesianFitResults`, and keep +`analysis.fit_results` as the main public result entry point. A +lightweight serialized `Analysis` category can be added later if +Bayesian settings need to become persistent and user-configurable. diff --git a/docs/dev/plan_bayesian-analysis.md b/docs/dev/plan_bayesian-analysis.md new file mode 100644 index 00000000..76be62c3 --- /dev/null +++ b/docs/dev/plan_bayesian-analysis.md @@ -0,0 +1,334 @@ +# Bayesian Analysis Implementation Plan + +**Status:** Planned **Feature name:** `bayesian-analysis` **Suggested +branch:** `feature/bayesian-analysis` **Design doc:** +`docs/dev/bayesian-analysis-design.md` + +## Context + +This plan follows `.github/copilot-instructions.md`. The instructions +refer to `docs/architecture/architecture.md`, but this checkout does not +contain that file. The matching living architecture document used for +this plan is `docs/dev/architecture.md`. + +Relevant current seams: + +- `src/easydiffraction/analysis/categories/fit/default.py` +- `src/easydiffraction/analysis/analysis.py` +- `src/easydiffraction/analysis/fitting.py` +- `src/easydiffraction/analysis/minimizers/base.py` +- `src/easydiffraction/analysis/minimizers/bumps.py` +- `src/easydiffraction/analysis/minimizers/enums.py` +- `src/easydiffraction/analysis/minimizers/factory.py` +- `src/easydiffraction/analysis/minimizers/__init__.py` +- `src/easydiffraction/analysis/fit_helpers/reporting.py` +- `src/easydiffraction/display/plotting.py` + +## Decisions + +- Add Bayesian sampling as a normal minimizer tag: `'bumps (dream)'`. +- Keep `project.analysis.fit()` as the execution entry point. +- Keep posterior chains runtime-only in `BayesianFitResults`. +- Do not add posterior chain export in phase 1. +- Add `plot_posterior_predictive(...)` in phase 1. +- Add optional `random_seed` support for `'bumps (dream)'`. +- Generate and record a seed when the user does not provide one. +- Reject non-`None` `random_seed` for deterministic minimizers. +- Treat sampler completion and convergence quality separately. +- Use `success=False` only when DREAM fails or no usable posterior + samples exist. +- Store and display convergence diagnostics; warn on poor convergence. +- Start with an internal posterior predictive draw cap of 200. + +## Scope + +Phase 1 delivers implementation only. Do not add or run tests in phase 1 +unless the user explicitly asks. Stop after phase 1 and request review. + +Phase 2 delivers verification only. Add/update tests, then run the +commands listed in this plan. + +## Agent Execution Rule + +When an AI agent follows this plan, every completed phase 1 +implementation step must be staged with explicit paths and committed +locally before moving to the next implementation step or the phase 1 +review gate. Commits must be atomic, single-purpose, and aligned with +the step just completed. + +If implementation uncovers a serious requirement, risk, design issue, or +scope change not covered by this plan, stop and ask for clarification or +approval before proceeding. + +## Status Checklist + +- [x] Repository context gathered. +- [x] Design decisions recorded. +- [ ] Phase 1 implementation complete. +- [ ] Phase 1 review approved. +- [ ] Phase 2 tests added. +- [ ] Phase 2 verification commands completed. + +## Phase 1: Implementation + +### Step 1: Register The DREAM Minimizer + +- [ ] Add `BUMPS_DREAM = 'bumps (dream)'` to `MinimizerTypeEnum`. +- [ ] Add a human-readable enum description. +- [ ] Add `src/easydiffraction/analysis/minimizers/bumps_dream.py`. +- [ ] Register `BumpsDreamMinimizer` with `MinimizerFactory`. +- [ ] Import `BumpsDreamMinimizer` from + `src/easydiffraction/analysis/minimizers/__init__.py`. +- [ ] Update `docs/dev/architecture.md` minimizer tag tables if the + implementation changes the documented supported tags. + +Likely files: + +- `src/easydiffraction/analysis/minimizers/enums.py` +- `src/easydiffraction/analysis/minimizers/bumps_dream.py` +- `src/easydiffraction/analysis/minimizers/__init__.py` +- `docs/dev/architecture.md` + +Suggested commit message: + +```text +Register BUMPS DREAM minimizer +``` + +### Step 2: Add Bayesian Result Models + +- [ ] Add `BayesianFitResults`. +- [ ] Add `PosteriorSamples`. +- [ ] Add `PosteriorParameterSummary`. +- [ ] Add `PosteriorPredictiveSummary`. +- [ ] Keep public constructors explicit; do not use `**kwargs`. +- [ ] Add NumPy-style docstrings for public classes and methods. +- [ ] Provide `PosteriorSamples.to_arviz()` for plotting integration. + +Likely files: + +- `src/easydiffraction/analysis/fit_helpers/bayesian.py` +- `src/easydiffraction/analysis/fit_helpers/reporting.py` +- `src/easydiffraction/analysis/fit_helpers/__init__.py` + +Suggested commit message: + +```text +Add Bayesian fit result models +``` + +### Step 3: Thread Random Seed Through Fit Execution + +- [ ] Add optional `random_seed: int | None = None` to `Fit.run(...)` + and `Fit.__call__(...)`. +- [ ] Thread `random_seed` through `Analysis._run_fit(...)`, + `_fit_single(...)`, `_fit_joint(...)`, and `Fitter.fit(...)`. +- [ ] Thread `random_seed` through `MinimizerBase.fit(...)`. +- [ ] Reject non-`None` `random_seed` in deterministic minimizers with a + clear `ValueError`. +- [ ] Let `BumpsDreamMinimizer` generate a seed when `random_seed` is + `None`. +- [ ] Record the user-provided or generated seed in + `BayesianFitResults.sampler_settings`. + +Likely files: + +- `src/easydiffraction/analysis/categories/fit/default.py` +- `src/easydiffraction/analysis/analysis.py` +- `src/easydiffraction/analysis/fitting.py` +- `src/easydiffraction/analysis/minimizers/base.py` +- `src/easydiffraction/analysis/minimizers/bumps_dream.py` + +Suggested commit message: + +```text +Thread random seed through fitting +``` + +### Step 4: Implement DREAM Sampling + +- [ ] Reuse `_EasyDiffractionFitness` or extract a shared BUMPS helper + only if needed. +- [ ] Build BUMPS parameters from sampled EasyDiffraction parameters. +- [ ] Validate finite bounds, bound ordering, and start values before + sampling. +- [ ] Preserve parameter order across BUMPS parameters, posterior + arrays, summaries, and MAP commit. +- [ ] Run BUMPS DREAM with internal defaults. +- [ ] Commit the MAP or best posterior sample to project parameters. +- [ ] Restore starting values if the sampler fails before producing + usable samples. +- [ ] Store raw BUMPS output as `engine_result` only after stable fields + have been normalized into EasyDiffraction-owned result objects. + +Likely files: + +- `src/easydiffraction/analysis/minimizers/bumps.py` +- `src/easydiffraction/analysis/minimizers/bumps_dream.py` +- `src/easydiffraction/analysis/fit_helpers/bayesian.py` + +Suggested commit message: + +```text +Implement BUMPS DREAM sampling +``` + +### Step 5: Add Bayesian Display + +- [ ] Make `BayesianFitResults.display_results(...)` render sampler + status, diagnostics, settings, and posterior parameter summaries. +- [ ] Keep deterministic `FitResults.display_results(...)` unchanged. +- [ ] Ensure `analysis.display.fit_results()` continues to dispatch + through the active result object. +- [ ] Display poor convergence prominently without hiding usable + posterior summaries. + +Likely files: + +- `src/easydiffraction/analysis/fit_helpers/bayesian.py` +- `src/easydiffraction/analysis/fit_helpers/reporting.py` + +Suggested commit message: + +```text +Display Bayesian fit summaries +``` + +### Step 6: Add Posterior Correlations + +- [ ] Extend `plot_param_correlations()` to detect + `BayesianFitResults.posterior_samples`. +- [ ] Compute the correlation matrix from flattened posterior samples. +- [ ] Preserve deterministic covariance and engine-derived behavior. +- [ ] Preserve current thresholding and lower-triangle display behavior. + +Likely files: + +- `src/easydiffraction/display/plotting.py` +- `src/easydiffraction/analysis/fit_helpers/bayesian.py` + +Suggested commit message: + +```text +Plot posterior parameter correlations +``` + +### Step 7: Add Bayesian Posterior Plots + +- [ ] Add `plot_posterior_pairs(...)`. +- [ ] Add `plot_param_distribution(param, ...)`. +- [ ] Use `PosteriorSamples.to_arviz()` internally where practical. +- [ ] Accept parameter objects, unique names, and user-facing labels for + one-parameter selection. +- [ ] Fail ambiguous string matches with a clear list of matches. +- [ ] Warn clearly when Bayesian-only plots are called on deterministic + results. + +Likely files: + +- `src/easydiffraction/display/plotting.py` +- `src/easydiffraction/analysis/fit_helpers/bayesian.py` + +Suggested commit message: + +```text +Add posterior distribution plots +``` + +### Step 8: Add Posterior Predictive Plots + +- [ ] Generate posterior predictive summaries from a capped subset of + posterior draws. +- [ ] Store summaries in `BayesianFitResults.posterior_predictive`. +- [ ] Add `plot_posterior_predictive(expt_name, style='band', ...)`. +- [ ] Support `style='band'` and `style='draws'` initially. +- [ ] Extend `plot_meas_vs_calc(...)` to show a 95% credible band when + posterior predictive summaries are available. +- [ ] Keep experiment data categories responsible only for measured, + current calculated, and current background patterns. + +Likely files: + +- `src/easydiffraction/display/plotting.py` +- `src/easydiffraction/analysis/minimizers/bumps_dream.py` +- `src/easydiffraction/analysis/fit_helpers/bayesian.py` + +Suggested commit message: + +```text +Add posterior predictive plotting +``` + +## Phase 1 Review Gate + +- [ ] Inspect `git status --short`. +- [ ] Inspect the diff for unrelated changes. +- [ ] Confirm every phase 1 step has an atomic local commit. +- [ ] Present the implementation summary for review. +- [ ] Do not start phase 2 until the user approves verification work. + +## Phase 2: Verification + +### Test Additions + +- [ ] Add unit tests for enum and factory registration. +- [ ] Add unit tests for finite-bound validation. +- [ ] Add unit tests for start-value-inside-bounds validation. +- [ ] Add unit tests for `random_seed` behavior. +- [ ] Add unit tests for deterministic minimizer seed rejection. +- [ ] Add unit tests for parameter order preservation. +- [ ] Add unit tests for MAP commit and restore-on-failure behavior. +- [ ] Add unit tests for Bayesian display output. +- [ ] Add unit tests for posterior sample correlation calculation. +- [ ] Add unit tests for posterior predictive summary generation. +- [ ] Add plotting smoke tests using small posterior fixtures. +- [ ] Add integration coverage for a small bounded DREAM refinement. +- [ ] Add integration coverage for explicit LM pre-fit followed by + DREAM. +- [ ] Add serialization coverage proving posterior chains are not saved. + +Likely test files: + +- `tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py` +- `tests/unit/easydiffraction/analysis/minimizers/test_enums.py` +- `tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py` +- `tests/unit/easydiffraction/display/test_plotting.py` +- `tests/integration/fitting/test_bayesian_dream.py` +- `tests/integration/fitting/test_project_load.py` + +Suggested commit message: + +```text +Test Bayesian DREAM workflow +``` + +### Verification Commands + +- [ ] `pixi run test-structure-check` +- [ ] `pixi run fix` +- [ ] `pixi run check` +- [ ] `pixi run unit-tests` +- [ ] `pixi run integration-tests` +- [ ] `pixi run script-tests` + +If `pixi run fix` regenerates package-structure docs, accept the +generated changes and include them only in the verification commit where +they were produced. + +## Non-Blocking Implementation Discovery + +The BUMPS DREAM return object must be inspected during implementation. +If the stable public fields are insufficient for posterior samples, +log-likelihood values, or diagnostics, normalize the available fields +into EasyDiffraction-owned value objects and keep `engine_result` +opaque. If this prevents a required feature, stop and ask before +changing scope. + +## Suggested Pull Request + +**Title:** Add Bayesian DREAM sampling and posterior plots + +**Description:** Adds Bayesian refinement through the BUMPS DREAM +sampler, including reproducible runs, posterior parameter summaries, and +posterior predictive plots so users can inspect uncertainty in fitted +diffraction models. From e34c278a56e50c7815a8a2e7608072ed7a4b543e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 23:54:00 +0200 Subject: [PATCH 006/106] Register BUMPS DREAM minimizer --- docs/dev/architecture.md | 45 ++++++++++--------- .../analysis/minimizers/__init__.py | 1 + .../analysis/minimizers/bumps_dream.py | 35 +++++++++++++++ .../analysis/minimizers/enums.py | 2 + 4 files changed, 61 insertions(+), 22 deletions(-) create mode 100644 src/easydiffraction/analysis/minimizers/bumps_dream.py diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index 390aa77b..dbfe59c8 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md @@ -527,28 +527,28 @@ from .line_segment import LineSegmentBackground ### 5.5 All Factories -| Factory | Domain | Tags resolve to | -| ---------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `BackgroundFactory` | Background categories | `LineSegmentBackground`, `ChebyshevPolynomialBackground` | -| `PeakFactory` | Peak profiles | `CwlPseudoVoigt`, `TofJorgensen`, `TofJorgensenVonDreele`, … | -| `InstrumentFactory` | Instruments | `CwlPdInstrument`, `TofPdInstrument`, … | -| `DataFactory` | Data collections | `PdCwlData`, `PdTofData`, `TotalData` | -| `ReflnFactory` | Reflection collections | `ReflnData`, `PowderCwlReflnData`, `PowderTofReflnData` | -| `ExtinctionFactory` | Extinction models | `BeckerCoppensExtinction` | -| `LinkedCrystalFactory` | Linked-crystal refs | `LinkedCrystal` | -| `ExcludedRegionsFactory` | Excluded regions | `ExcludedRegions` | -| `LinkedPhasesFactory` | Linked phases | `LinkedPhases` | -| `ExperimentTypeFactory` | Experiment descriptors | `ExperimentType` | -| `CellFactory` | Unit cells | `Cell` | -| `SpaceGroupFactory` | Space groups | `SpaceGroup` | -| `AtomSitesFactory` | Atom sites | `AtomSites` | -| `AtomSiteAnisoFactory` | Anisotropic ADPs | `AtomSiteAnisoCollection` | -| `AliasesFactory` | Parameter aliases | `Aliases` | -| `ConstraintsFactory` | Parameter constraints | `Constraints` | -| `FitModeFactory` | Fit-mode category | `FitMode` | -| `JointFitExperimentsFactory` | Joint-fit weights | `JointFitExperiments` | -| `CalculatorFactory` | Calculation engines | `CryspyCalculator`, `CrysfmlCalculator`, `PdffitCalculator` | -| `MinimizerFactory` | Minimisers | `LmfitMinimizer`, `LmfitLeastsqMinimizer`, `LmfitLeastSquaresMinimizer`, `DfolsMinimizer`, `BumpsMinimizer`, `BumpsLmMinimizer`, `BumpsAmoebaMinimizer`, `BumpsDEMinimizer` | +| Factory | Domain | Tags resolve to | +| --- | --- | --- | +| `BackgroundFactory` | Background categories | `LineSegmentBackground`, `ChebyshevPolynomialBackground` | +| `PeakFactory` | Peak profiles | `CwlPseudoVoigt`, `TofJorgensen`, `TofJorgensenVonDreele`, … | +| `InstrumentFactory` | Instruments | `CwlPdInstrument`, `TofPdInstrument`, … | +| `DataFactory` | Data collections | `PdCwlData`, `PdTofData`, `TotalData` | +| `ReflnFactory` | Reflection collections | `ReflnData`, `PowderCwlReflnData`, `PowderTofReflnData` | +| `ExtinctionFactory` | Extinction models | `BeckerCoppensExtinction` | +| `LinkedCrystalFactory` | Linked-crystal refs | `LinkedCrystal` | +| `ExcludedRegionsFactory` | Excluded regions | `ExcludedRegions` | +| `LinkedPhasesFactory` | Linked phases | `LinkedPhases` | +| `ExperimentTypeFactory` | Experiment descriptors | `ExperimentType` | +| `CellFactory` | Unit cells | `Cell` | +| `SpaceGroupFactory` | Space groups | `SpaceGroup` | +| `AtomSitesFactory` | Atom sites | `AtomSites` | +| `AtomSiteAnisoFactory` | Anisotropic ADPs | `AtomSiteAnisoCollection` | +| `AliasesFactory` | Parameter aliases | `Aliases` | +| `ConstraintsFactory` | Parameter constraints | `Constraints` | +| `FitModeFactory` | Fit-mode category | `FitMode` | +| `JointFitExperimentsFactory` | Joint-fit weights | `JointFitExperiments` | +| `CalculatorFactory` | Calculation engines | `CryspyCalculator`, `CrysfmlCalculator`, `PdffitCalculator` | +| `MinimizerFactory` | Minimisers | `LmfitMinimizer`, `LmfitLeastsqMinimizer`, `LmfitLeastSquaresMinimizer`, `DfolsMinimizer`, `BumpsMinimizer`, `BumpsLmMinimizer`, `BumpsDreamMinimizer`, `BumpsAmoebaMinimizer`, `BumpsDEMinimizer` | > **Note:** `ExperimentFactory` and `StructureFactory` are _builder_ > factories with `from_cif_path`, `from_cif_str`, `from_data_path`, and @@ -675,6 +675,7 @@ the choice. | `dfols` | `DfolsMinimizer` | | `bumps` | `BumpsMinimizer` | | `bumps (lm)` | `BumpsLmMinimizer` | +| `bumps (dream)` | `BumpsDreamMinimizer` | | `bumps (amoeba)` | `BumpsAmoebaMinimizer` | | `bumps (de)` | `BumpsDEMinimizer` | diff --git a/src/easydiffraction/analysis/minimizers/__init__.py b/src/easydiffraction/analysis/minimizers/__init__.py index 7dddb75e..7639dd8a 100644 --- a/src/easydiffraction/analysis/minimizers/__init__.py +++ b/src/easydiffraction/analysis/minimizers/__init__.py @@ -4,6 +4,7 @@ from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer from easydiffraction.analysis.minimizers.bumps_amoeba import BumpsAmoebaMinimizer from easydiffraction.analysis.minimizers.bumps_de import BumpsDEMinimizer +from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer from easydiffraction.analysis.minimizers.bumps_lm import BumpsLmMinimizer from easydiffraction.analysis.minimizers.dfols import DfolsMinimizer from easydiffraction.analysis.minimizers.lmfit import LmfitMinimizer diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py new file mode 100644 index 00000000..7a951d81 --- /dev/null +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause +"""Bumps minimizer variant using the DREAM sampler.""" + +from __future__ import annotations + +from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer +from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum +from easydiffraction.analysis.minimizers.factory import MinimizerFactory +from easydiffraction.core.metadata import TypeInfo + +DEFAULT_METHOD = 'dream' +DEFAULT_MAX_ITERATIONS = 1000 + + +@MinimizerFactory.register +class BumpsDreamMinimizer(BumpsMinimizer): + """Bumps minimizer using the DREAM Bayesian sampler.""" + + type_info = TypeInfo( + tag=MinimizerTypeEnum.BUMPS_DREAM, + description='Bumps library with DREAM Bayesian sampling', + ) + + def __init__( + self, + name: str = MinimizerTypeEnum.BUMPS_DREAM, + method: str = DEFAULT_METHOD, + max_iterations: int = DEFAULT_MAX_ITERATIONS, + ) -> None: + super().__init__( + name=name, + method=method, + max_iterations=max_iterations, + ) \ No newline at end of file diff --git a/src/easydiffraction/analysis/minimizers/enums.py b/src/easydiffraction/analysis/minimizers/enums.py index cdfe4ecb..5d8ad218 100644 --- a/src/easydiffraction/analysis/minimizers/enums.py +++ b/src/easydiffraction/analysis/minimizers/enums.py @@ -16,6 +16,7 @@ class MinimizerTypeEnum(StrEnum): DFOLS = 'dfols' BUMPS = 'bumps' BUMPS_LM = 'bumps (lm)' + BUMPS_DREAM = 'bumps (dream)' BUMPS_AMOEBA = 'bumps (amoeba)' BUMPS_DE = 'bumps (de)' @@ -45,6 +46,7 @@ def description(self) -> str: 'BUMPS library using the default Levenberg-Marquardt method' ), MinimizerTypeEnum.BUMPS_LM: ('BUMPS library with Levenberg-Marquardt method'), + MinimizerTypeEnum.BUMPS_DREAM: ('BUMPS library with DREAM Bayesian sampling'), MinimizerTypeEnum.BUMPS_AMOEBA: ('BUMPS library with Nelder-Mead simplex method'), MinimizerTypeEnum.BUMPS_DE: ('BUMPS library with differential evolution method'), } From 303dc2708df22491105dfa032a641b09a5202260 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 23:55:42 +0200 Subject: [PATCH 007/106] Add Bayesian fit result models --- .../analysis/fit_helpers/__init__.py | 6 + .../analysis/fit_helpers/bayesian.py | 234 ++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 src/easydiffraction/analysis/fit_helpers/bayesian.py diff --git a/src/easydiffraction/analysis/fit_helpers/__init__.py b/src/easydiffraction/analysis/fit_helpers/__init__.py index 4e798e20..c7c53862 100644 --- a/src/easydiffraction/analysis/fit_helpers/__init__.py +++ b/src/easydiffraction/analysis/fit_helpers/__init__.py @@ -1,2 +1,8 @@ # SPDX-FileCopyrightText: 2026 EasyScience contributors # SPDX-License-Identifier: BSD-3-Clause + +from easydiffraction.analysis.fit_helpers.bayesian import BayesianFitResults +from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary +from easydiffraction.analysis.fit_helpers.bayesian import PosteriorPredictiveSummary +from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples +from easydiffraction.analysis.fit_helpers.reporting import FitResults diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py new file mode 100644 index 00000000..811b8ecb --- /dev/null +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -0,0 +1,234 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause +"""Bayesian fit result models and posterior data containers.""" + +from __future__ import annotations + +from dataclasses import dataclass + +import numpy as np + +from easydiffraction.analysis.fit_helpers.reporting import FitResults + + +@dataclass(slots=True) +class PosteriorParameterSummary: + """Posterior summary statistics for one fitted parameter. + + Parameters + ---------- + unique_name : str + Unique parameter name used across EasyDiffraction. + display_name : str + Human-readable label used in plots and tables. + map_value : float + Maximum-a-posteriori or best-sampled parameter value. + median : float + Posterior median value. + standard_deviation : float + Posterior standard deviation. + interval_68 : tuple[float, float] + Central 68% interval. + interval_95 : tuple[float, float] + Central 95% interval. + ess_bulk : float | None, default=None + Bulk effective sample size when available. + r_hat : float | None, default=None + Rank-normalized split-$\hat{R}$ when available. + """ + + unique_name: str + display_name: str + map_value: float + median: float + standard_deviation: float + interval_68: tuple[float, float] + interval_95: tuple[float, float] + ess_bulk: float | None = None + r_hat: float | None = None + + +@dataclass(slots=True) +class PosteriorPredictiveSummary: + """Posterior predictive summaries for one experiment. + + Parameters + ---------- + experiment_name : str + Experiment identifier. + x : np.ndarray + X-axis values for the predictive curves. + map_prediction : np.ndarray + Prediction corresponding to the committed point estimate. + lower_95 : np.ndarray | None, default=None + Lower bound of the 95% credible interval. + upper_95 : np.ndarray | None, default=None + Upper bound of the 95% credible interval. + lower_68 : np.ndarray | None, default=None + Lower bound of the 68% credible interval. + upper_68 : np.ndarray | None, default=None + Upper bound of the 68% credible interval. + draws : np.ndarray | None, default=None + Optional capped predictive draws with shape ``(n_draws, n_x)``. + """ + + experiment_name: str + x: np.ndarray + map_prediction: np.ndarray + lower_95: np.ndarray | None = None + upper_95: np.ndarray | None = None + lower_68: np.ndarray | None = None + upper_68: np.ndarray | None = None + draws: np.ndarray | None = None + + +@dataclass(slots=True) +class PosteriorSamples: + """Posterior samples and sample statistics from a Bayesian fit. + + Parameters + ---------- + parameter_names : list[str] + Parameter names in the preserved EasyDiffraction order. + parameter_samples : np.ndarray + Sample array with shape ``(n_draws, n_chains, n_parameters)``. + log_posterior : np.ndarray | None, default=None + Log-posterior values with shape ``(n_draws, n_chains)`` when + available. + draw_index : np.ndarray | None, default=None + Optional draw or generation indices associated with the first + axis of ``parameter_samples``. + """ + + parameter_names: list[str] + parameter_samples: np.ndarray + log_posterior: np.ndarray | None = None + draw_index: np.ndarray | None = None + + def flattened(self) -> np.ndarray: + """Return flattened posterior samples by parameter. + + Returns + ------- + np.ndarray + Array with shape ``(n_draws * n_chains, n_parameters)``. + """ + return np.asarray(self.parameter_samples).reshape(-1, len(self.parameter_names)) + + def to_arviz(self) -> object: + """Convert posterior samples to an ArviZ ``InferenceData`` object. + + Returns + ------- + object + ArviZ ``InferenceData`` instance built from the stored + posterior samples. + + Raises + ------ + ValueError + If the stored arrays do not have the expected shapes. + """ + import arviz as az + + posterior_array = np.asarray(self.parameter_samples, dtype=float) + if posterior_array.ndim != 3: + msg = 'Posterior sample array must have shape (n_draws, n_chains, n_parameters).' + raise ValueError(msg) + + n_draws, n_chains, n_parameters = posterior_array.shape + if n_parameters != len(self.parameter_names): + msg = 'Posterior sample array does not match the parameter name list length.' + raise ValueError(msg) + + posterior_dict = { + name: np.transpose(posterior_array[:, :, index], (1, 0)) + for index, name in enumerate(self.parameter_names) + } + + sample_stats: dict[str, np.ndarray] | None = None + if self.log_posterior is not None: + log_posterior = np.asarray(self.log_posterior, dtype=float) + if log_posterior.shape != (n_draws, n_chains): + msg = 'Log-posterior array must match the first two posterior sample axes.' + raise ValueError(msg) + sample_stats = {'lp': np.transpose(log_posterior, (1, 0))} + + return az.from_dict(posterior=posterior_dict, sample_stats=sample_stats) + + +class BayesianFitResults(FitResults): + """Container for Bayesian fit results and posterior summaries. + + Parameters + ---------- + success : bool, default=False + Whether the Bayesian fit produced usable posterior results. + parameters : list[object] | None, default=None + Final committed parameter objects. + reduced_chi_square : float | None, default=None + Reduced chi-square evaluated at the committed point estimate. + engine_result : object | None, default=None + Opaque backend result object. + starting_parameters : list[object] | None, default=None + Starting parameter objects or snapshots. + fitting_time : float | None, default=None + Total fitting time in seconds. + sampler_name : str, default='dream' + Sampler identifier. + point_estimate_name : str, default='map' + Name of the point estimate committed back to the project. + posterior_samples : PosteriorSamples | None, default=None + Stored posterior samples. + posterior_parameter_summaries : list[PosteriorParameterSummary] | None, default=None + Posterior summaries for each sampled parameter. + posterior_predictive : dict[str, PosteriorPredictiveSummary] | None, default=None + Posterior predictive summaries keyed by experiment name. + credible_interval_levels : tuple[float, ...], default=(0.68, 0.95) + Interval levels available in the summaries. + sampler_settings : dict[str, object] | None, default=None + Sampler settings recorded for reproducibility. + convergence_diagnostics : dict[str, object] | None, default=None + Convergence diagnostics and status metadata. + """ + + def __init__( + self, + *, + success: bool = False, + parameters: list[object] | None = None, + reduced_chi_square: float | None = None, + engine_result: object | None = None, + starting_parameters: list[object] | None = None, + fitting_time: float | None = None, + sampler_name: str = 'dream', + point_estimate_name: str = 'map', + posterior_samples: PosteriorSamples | None = None, + posterior_parameter_summaries: list[PosteriorParameterSummary] | None = None, + posterior_predictive: dict[str, PosteriorPredictiveSummary] | None = None, + credible_interval_levels: tuple[float, ...] = (0.68, 0.95), + sampler_settings: dict[str, object] | None = None, + convergence_diagnostics: dict[str, object] | None = None, + ) -> None: + super().__init__( + success=success, + parameters=parameters, + reduced_chi_square=reduced_chi_square, + engine_result=engine_result, + starting_parameters=starting_parameters, + fitting_time=fitting_time, + ) + self.sampler_name = sampler_name + self.point_estimate_name = point_estimate_name + self.posterior_samples = posterior_samples + self.posterior_parameter_summaries = ( + posterior_parameter_summaries if posterior_parameter_summaries is not None else [] + ) + self.posterior_predictive = ( + posterior_predictive if posterior_predictive is not None else {} + ) + self.credible_interval_levels = credible_interval_levels + self.sampler_settings = sampler_settings if sampler_settings is not None else {} + self.convergence_diagnostics = ( + convergence_diagnostics if convergence_diagnostics is not None else {} + ) \ No newline at end of file From cd8d233ed0e8351ab946b369435c00d9a77ea02b Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Thu, 7 May 2026 23:57:13 +0200 Subject: [PATCH 008/106] Thread random seed through fitting --- src/easydiffraction/analysis/analysis.py | 32 +++++++++++++++-- .../analysis/categories/fit/default.py | 16 +++++++-- src/easydiffraction/analysis/fitting.py | 4 +++ .../analysis/minimizers/base.py | 34 +++++++++++++++++++ .../analysis/minimizers/bumps_dream.py | 24 ++++++++++++- 5 files changed, 104 insertions(+), 6 deletions(-) diff --git a/src/easydiffraction/analysis/analysis.py b/src/easydiffraction/analysis/analysis.py index c132e409..dd4de8c0 100644 --- a/src/easydiffraction/analysis/analysis.py +++ b/src/easydiffraction/analysis/analysis.py @@ -513,7 +513,13 @@ def joint_fit_experiments(self) -> object: """Per-experiment weight collection for joint fitting.""" return self._joint_fit_experiments - def _run_fit(self, verbosity: str | None = None, *, use_physical_limits: bool = False) -> None: + def _run_fit( + self, + verbosity: str | None = None, + *, + use_physical_limits: bool = False, + random_seed: int | None = None, + ) -> None: """ Execute fitting for all experiments. @@ -542,6 +548,8 @@ def _run_fit(self, verbosity: str | None = None, *, use_physical_limits: bool = When ``True``, fall back to physical limits from the value spec for parameters whose ``fit_min``/``fit_max`` are unbounded. + random_seed : int | None, default=None + Optional random seed passed to stochastic minimizers. """ verb = VerbosityEnum(verbosity if verbosity is not None else self.project.verbosity) @@ -563,10 +571,20 @@ def _run_fit(self, verbosity: str | None = None, *, use_physical_limits: bool = # Run the fitting process mode = FitModeEnum(self._fit.mode.value) if mode is FitModeEnum.JOINT: - self._fit_joint(verb, structures, experiments, use_physical_limits=use_physical_limits) + self._fit_joint( + verb, + structures, + experiments, + use_physical_limits=use_physical_limits, + random_seed=random_seed, + ) elif mode is FitModeEnum.SINGLE: self._fit_single( - verb, structures, experiments, use_physical_limits=use_physical_limits + verb, + structures, + experiments, + use_physical_limits=use_physical_limits, + random_seed=random_seed, ) elif mode is FitModeEnum.SEQUENTIAL: log.error( @@ -585,6 +603,7 @@ def _fit_joint( experiments: object, *, use_physical_limits: bool, + random_seed: int | None, ) -> None: """ Run joint fitting across all experiments with weights. @@ -599,6 +618,8 @@ def _fit_joint( Project experiments collection. use_physical_limits : bool Whether to use physical limits as fit bounds. + random_seed : int | None + Optional random seed passed to stochastic minimizers. """ mode = FitModeEnum.JOINT # Auto-populate joint_fit_experiments if empty @@ -622,6 +643,7 @@ def _fit_joint( analysis=self, verbosity=verb, use_physical_limits=use_physical_limits, + random_seed=random_seed, ) # After fitting, get the results @@ -634,6 +656,7 @@ def _fit_single( experiments: object, *, use_physical_limits: bool, + random_seed: int | None, ) -> None: """ Run single-mode fitting for each experiment independently. @@ -648,6 +671,8 @@ def _fit_single( Project experiments collection. use_physical_limits : bool Whether to use physical limits as fit bounds. + random_seed : int | None + Optional random seed passed to stochastic minimizers. """ mode = FitModeEnum.SINGLE expt_names = experiments.names @@ -666,6 +691,7 @@ def _fit_single( analysis=self, verbosity=verb, use_physical_limits=use_physical_limits, + random_seed=random_seed, ) # After fitting, snapshot parameter values before diff --git a/src/easydiffraction/analysis/categories/fit/default.py b/src/easydiffraction/analysis/categories/fit/default.py index c002fe39..7a9ebcb1 100644 --- a/src/easydiffraction/analysis/categories/fit/default.py +++ b/src/easydiffraction/analysis/categories/fit/default.py @@ -148,6 +148,7 @@ def run( verbosity: str | None = None, *, use_physical_limits: bool = False, + random_seed: int | None = None, ) -> None: """ Execute fitting for the owning analysis. @@ -158,6 +159,8 @@ def run( Console output verbosity override. use_physical_limits : bool, default=False Whether to fall back to physical limits as fit bounds. + random_seed : int | None, default=None + Optional random seed passed to stochastic minimizers. Raises ------ @@ -168,16 +171,25 @@ def run( if parent is None: msg = 'Fit category is not attached to an Analysis object.' raise RuntimeError(msg) - parent._run_fit(verbosity=verbosity, use_physical_limits=use_physical_limits) + parent._run_fit( + verbosity=verbosity, + use_physical_limits=use_physical_limits, + random_seed=random_seed, + ) def __call__( self, verbosity: str | None = None, *, use_physical_limits: bool = False, + random_seed: int | None = None, ) -> None: """Execute :meth:`run` for convenience.""" - self.run(verbosity=verbosity, use_physical_limits=use_physical_limits) + self.run( + verbosity=verbosity, + use_physical_limits=use_physical_limits, + random_seed=random_seed, + ) def from_cif(self, block: object, idx: int = 0) -> None: """ diff --git a/src/easydiffraction/analysis/fitting.py b/src/easydiffraction/analysis/fitting.py index 9b036014..db5590e1 100644 --- a/src/easydiffraction/analysis/fitting.py +++ b/src/easydiffraction/analysis/fitting.py @@ -39,6 +39,7 @@ def fit( verbosity: VerbosityEnum = VerbosityEnum.FULL, *, use_physical_limits: bool = False, + random_seed: int | None = None, ) -> None: """ Run the fitting process. @@ -65,6 +66,8 @@ def fit( When ``True``, fall back to physical limits from the value spec for parameters whose ``fit_min``/``fit_max`` are unbounded. + random_seed : int | None, default=None + Optional random seed passed to stochastic minimizers. """ # Enforce symmetry constraints (e.g. ADP) before collecting # free parameters so that components fixed by site symmetry are @@ -118,6 +121,7 @@ def objective_function(engine_params: dict[str, Any]) -> np.ndarray: objective_function, verbosity=verbosity, use_physical_limits=use_physical_limits, + random_seed=random_seed, ) def _process_fit_results( diff --git a/src/easydiffraction/analysis/minimizers/base.py b/src/easydiffraction/analysis/minimizers/base.py index c0b39eb3..93b811ae 100644 --- a/src/easydiffraction/analysis/minimizers/base.py +++ b/src/easydiffraction/analysis/minimizers/base.py @@ -41,6 +41,7 @@ def __init__( self._best_chi2: float | None = None self._best_iteration: int | None = None self._fitting_time: float | None = None + self._resolved_random_seed: int | None = None self.tracker: FitProgressTracker = FitProgressTracker() def _start_tracking( @@ -231,6 +232,32 @@ def _warn_physical_limit_violations(parameters: list[object]) -> None: def _check_success(self, raw_result: object) -> bool: """Determine whether the fit was successful.""" + def _resolve_random_seed(self, random_seed: int | None) -> int | None: + """Validate or normalize the random seed for this minimizer. + + Parameters + ---------- + random_seed : int | None + User-provided random seed. + + Returns + ------- + int | None + Seed accepted by the minimizer, or ``None`` when not used. + + Raises + ------ + ValueError + If this minimizer does not support ``random_seed``. + """ + if random_seed is None: + self._resolved_random_seed = None + return None + + minimizer_name = self.name or self.__class__.__name__ + msg = f"Minimizer '{minimizer_name}' does not support random_seed." + raise ValueError(msg) + def fit( self, parameters: list[object], @@ -238,6 +265,7 @@ def fit( verbosity: VerbosityEnum = VerbosityEnum.FULL, *, use_physical_limits: bool = False, + random_seed: int | None = None, ) -> FitResults: """ Run the full minimization workflow. @@ -255,6 +283,8 @@ def fit( When ``True``, fall back to physical limits from the value spec for parameters whose ``fit_min``/``fit_max`` are unbounded. + random_seed : int | None, default=None + Optional random seed passed to stochastic minimizers. Returns ------- @@ -264,6 +294,8 @@ def fit( if use_physical_limits: self._apply_physical_limits(parameters) + resolved_random_seed = self._resolve_random_seed(random_seed) + minimizer_name = self.name or 'Unnamed Minimizer' if self.method is not None and f'({self.method})' not in minimizer_name: minimizer_name += f' ({self.method})' @@ -271,6 +303,8 @@ def fit( self._start_tracking(minimizer_name, verbosity=verbosity) solver_args = self._prepare_solver_args(parameters) + if resolved_random_seed is not None: + solver_args['random_seed'] = resolved_random_seed raw_result = self._run_solver(objective_function, **solver_args) self._stop_tracking() diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 7a951d81..c989ffcc 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -4,6 +4,8 @@ from __future__ import annotations +import numpy as np + from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum from easydiffraction.analysis.minimizers.factory import MinimizerFactory @@ -32,4 +34,24 @@ def __init__( name=name, method=method, max_iterations=max_iterations, - ) \ No newline at end of file + ) + + def _resolve_random_seed(self, random_seed: int | None) -> int: + """Return a user-provided or generated random seed. + + Parameters + ---------- + random_seed : int | None + User-provided random seed. + + Returns + ------- + int + Seed to use for the DREAM run. + """ + if random_seed is None: + generator = np.random.default_rng() + random_seed = int(generator.integers(0, np.iinfo(np.int32).max)) + + self._resolved_random_seed = int(random_seed) + return self._resolved_random_seed \ No newline at end of file From 3e4d09e9f38fac93e07e79e7c6a6e954c606d7dd Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 00:09:36 +0200 Subject: [PATCH 009/106] Implement DREAM sampling --- .../analysis/fit_helpers/bayesian.py | 157 ++++++++- .../analysis/minimizers/base.py | 33 +- .../analysis/minimizers/bumps_dream.py | 308 +++++++++++++++++- 3 files changed, 492 insertions(+), 6 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 811b8ecb..516a1cb9 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -6,10 +6,14 @@ from dataclasses import dataclass +import arviz as az import numpy as np from easydiffraction.analysis.fit_helpers.reporting import FitResults +R_HAT_CONVERGENCE_THRESHOLD = 1.01 +ESS_BULK_CONVERGENCE_THRESHOLD = 400.0 + @dataclass(slots=True) class PosteriorParameterSummary: @@ -34,7 +38,7 @@ class PosteriorParameterSummary: ess_bulk : float | None, default=None Bulk effective sample size when available. r_hat : float | None, default=None - Rank-normalized split-$\hat{R}$ when available. + Rank-normalized split-$\\hat{R}$ when available. """ unique_name: str @@ -154,7 +158,11 @@ def to_arviz(self) -> object: raise ValueError(msg) sample_stats = {'lp': np.transpose(log_posterior, (1, 0))} - return az.from_dict(posterior=posterior_dict, sample_stats=sample_stats) + data = {'posterior': posterior_dict} + if sample_stats is not None: + data['sample_stats'] = sample_stats + + return az.from_dict(data) class BayesianFitResults(FitResults): @@ -190,6 +198,10 @@ class BayesianFitResults(FitResults): Sampler settings recorded for reproducibility. convergence_diagnostics : dict[str, object] | None, default=None Convergence diagnostics and status metadata. + sampler_completed : bool, default=False + Whether the sampler completed a run and returned posterior data. + best_log_posterior : float | None, default=None + Best log-posterior value reported by the sampler. """ def __init__( @@ -209,6 +221,8 @@ def __init__( credible_interval_levels: tuple[float, ...] = (0.68, 0.95), sampler_settings: dict[str, object] | None = None, convergence_diagnostics: dict[str, object] | None = None, + sampler_completed: bool = False, + best_log_posterior: float | None = None, ) -> None: super().__init__( success=success, @@ -231,4 +245,141 @@ def __init__( self.sampler_settings = sampler_settings if sampler_settings is not None else {} self.convergence_diagnostics = ( convergence_diagnostics if convergence_diagnostics is not None else {} - ) \ No newline at end of file + ) + self.sampler_completed = sampler_completed + self.best_log_posterior = best_log_posterior + + +def compute_convergence_diagnostics(posterior_samples: PosteriorSamples) -> dict[str, object]: + """Compute convergence diagnostics from posterior samples. + + Parameters + ---------- + posterior_samples : PosteriorSamples + Posterior samples container. + + Returns + ------- + dict[str, object] + Convergence metrics keyed by diagnostic name. + """ + inference_data = posterior_samples.to_arviz() + rhat_dataset = az.rhat(inference_data) + ess_dataset = az.ess(inference_data, method='bulk') + + r_hat_by_parameter = _dataset_to_scalar_dict(rhat_dataset) + ess_bulk_by_parameter = _dataset_to_scalar_dict(ess_dataset) + + max_r_hat = max(r_hat_by_parameter.values(), default=None) + min_ess_bulk = min(ess_bulk_by_parameter.values(), default=None) + + converged = True + if max_r_hat is not None and max_r_hat > R_HAT_CONVERGENCE_THRESHOLD: + converged = False + if min_ess_bulk is not None and min_ess_bulk < ESS_BULK_CONVERGENCE_THRESHOLD: + converged = False + + return { + 'converged': converged, + 'r_hat_by_parameter': r_hat_by_parameter, + 'ess_bulk_by_parameter': ess_bulk_by_parameter, + 'max_r_hat': max_r_hat, + 'min_ess_bulk': min_ess_bulk, + 'n_draws': int(posterior_samples.parameter_samples.shape[0]), + 'n_chains': int(posterior_samples.parameter_samples.shape[1]), + 'n_parameters': len(posterior_samples.parameter_names), + } + + +def summarize_posterior_parameters( + parameter_names: list[str], + posterior_samples: PosteriorSamples, + map_values: np.ndarray, + convergence_diagnostics: dict[str, object] | None = None, +) -> list[PosteriorParameterSummary]: + """Build posterior parameter summaries in EasyDiffraction order. + + Parameters + ---------- + parameter_names : list[str] + Sampled parameter names in EasyDiffraction order. + posterior_samples : PosteriorSamples + Posterior sample container. + map_values : np.ndarray + MAP or best-sampled parameter values in the same order. + convergence_diagnostics : dict[str, object] | None, default=None + Optional convergence diagnostics keyed by parameter name. + + Returns + ------- + list[PosteriorParameterSummary] + Summary rows matching the input parameter order. + + Raises + ------ + ValueError + If the posterior sample array is incompatible with the + parameter name list. + """ + flattened = posterior_samples.flattened() + if flattened.shape[1] != len(parameter_names): + msg = 'Posterior samples do not match the sampled parameter name list length.' + raise ValueError(msg) + + r_hat_by_parameter = {} + ess_bulk_by_parameter = {} + if convergence_diagnostics is not None: + r_hat_by_parameter = convergence_diagnostics.get('r_hat_by_parameter', {}) + ess_bulk_by_parameter = convergence_diagnostics.get('ess_bulk_by_parameter', {}) + + summaries: list[PosteriorParameterSummary] = [] + for index, parameter_name in enumerate(parameter_names): + values = flattened[:, index] + interval_68 = tuple(np.quantile(values, [0.16, 0.84]).tolist()) + interval_95 = tuple(np.quantile(values, [0.025, 0.975]).tolist()) + summaries.append( + PosteriorParameterSummary( + unique_name=parameter_name, + display_name=parameter_name, + map_value=float(map_values[index]), + median=float(np.median(values)), + standard_deviation=float(np.std(values, ddof=1)), + interval_68=(float(interval_68[0]), float(interval_68[1])), + interval_95=(float(interval_95[0]), float(interval_95[1])), + ess_bulk=_maybe_scalar(ess_bulk_by_parameter.get(parameter_name)), + r_hat=_maybe_scalar(r_hat_by_parameter.get(parameter_name)), + ) + ) + + return summaries + + +def standard_deviations_from_summaries( + summaries: list[PosteriorParameterSummary], +) -> np.ndarray: + """Return posterior standard deviations in summary order. + + Parameters + ---------- + summaries : list[PosteriorParameterSummary] + Posterior summaries in parameter order. + + Returns + ------- + np.ndarray + Standard deviations in the same order. + """ + return np.array([summary.standard_deviation for summary in summaries], dtype=float) + + +def _dataset_to_scalar_dict(dataset: object) -> dict[str, float]: + values: dict[str, float] = {} + for name, data_array in dataset.data_vars.items(): + values[name] = float(np.asarray(data_array).reshape(-1)[0]) + return values + + +def _maybe_scalar(value: object) -> float | None: + if value is None: + return None + return float(value) \ No newline at end of file diff --git a/src/easydiffraction/analysis/minimizers/base.py b/src/easydiffraction/analysis/minimizers/base.py index 93b811ae..46da77c5 100644 --- a/src/easydiffraction/analysis/minimizers/base.py +++ b/src/easydiffraction/analysis/minimizers/base.py @@ -125,7 +125,37 @@ def _finalize_fit( self._warn_boundary_parameters(parameters) self._warn_physical_limit_violations(parameters) success = self._check_success(raw_result) - self.result = FitResults( + self.result = self._build_fit_results( + parameters=parameters, + raw_result=raw_result, + success=success, + ) + return self.result + + def _build_fit_results( + self, + *, + parameters: list[object], + raw_result: object, + success: bool, + ) -> FitResults: + """Build the final fit-result object for this minimizer. + + Parameters + ---------- + parameters : list[object] + Parameters after the solver finished. + raw_result : object + Backend-specific solver output object. + success : bool + Whether the minimizer considers the run successful. + + Returns + ------- + FitResults + Aggregated outcome of the fit. + """ + return FitResults( success=success, parameters=parameters, reduced_chi_square=self.tracker.best_chi2, @@ -133,7 +163,6 @@ def _finalize_fit( starting_parameters=parameters, fitting_time=self.tracker.fitting_time, ) - return self.result @staticmethod def _warn_boundary_parameters(parameters: list[object]) -> None: diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index c989ffcc..28a2f4de 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -4,15 +4,35 @@ from __future__ import annotations +import random + import numpy as np +from bumps.fitproblem import FitProblem +from bumps.fitters import FITTERS +from bumps.fitters import FitDriver +from scipy.optimize import OptimizeResult +from easydiffraction.analysis.fit_helpers.bayesian import BayesianFitResults +from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples +from easydiffraction.analysis.fit_helpers.bayesian import compute_convergence_diagnostics +from easydiffraction.analysis.fit_helpers.bayesian import standard_deviations_from_summaries +from easydiffraction.analysis.fit_helpers.bayesian import summarize_posterior_parameters +from easydiffraction.analysis.minimizers.bumps import _EasyDiffractionFitness from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum from easydiffraction.analysis.minimizers.factory import MinimizerFactory from easydiffraction.core.metadata import TypeInfo +from easydiffraction.utils.logging import log DEFAULT_METHOD = 'dream' DEFAULT_MAX_ITERATIONS = 1000 +DEFAULT_BURN_FRACTION = 0.2 +DEFAULT_MIN_BURN = 50 +DEFAULT_THIN = 1 +DEFAULT_POP = 4 +DEFAULT_ALPHA = 0.0 +DEFAULT_OUTLIER_TEST = 'none' +DEFAULT_TRIM = False @MinimizerFactory.register @@ -54,4 +74,290 @@ def _resolve_random_seed(self, random_seed: int | None) -> int: random_seed = int(generator.integers(0, np.iinfo(np.int32).max)) self._resolved_random_seed = int(random_seed) - return self._resolved_random_seed \ No newline at end of file + return self._resolved_random_seed + + def _prepare_solver_args( + self, + parameters: list[object], + ) -> dict[str, object]: + """Prepare DREAM solver arguments in EasyDiffraction order. + + Parameters + ---------- + parameters : list[object] + List of parameters to be sampled. + + Returns + ------- + dict[str, object] + BUMPS parameters plus EasyDiffraction parameter metadata. + """ + solver_args = super()._prepare_solver_args(parameters) + solver_args['parameter_names'] = [parameter.unique_name for parameter in parameters] + solver_args['parameter_uids'] = [parameter._minimizer_uid for parameter in parameters] + solver_args['starting_uncertainties'] = [parameter.uncertainty for parameter in parameters] + return solver_args + + def _run_solver( + self, + objective_function: object, + **kwargs: object, + ) -> object: + """Run the DREAM sampler and normalize its posterior outputs. + + Parameters + ---------- + objective_function : object + Objective function returning residuals. + **kwargs : object + Solver arguments including BUMPS parameters and random seed. + + Returns + ------- + object + Normalized DREAM result stored in an ``OptimizeResult``. + """ + bumps_params = kwargs.get('bumps_params') + parameter_names = kwargs.get('parameter_names') + parameter_uids = kwargs.get('parameter_uids') + random_seed = kwargs.get('random_seed') + starting_uncertainties = kwargs.get('starting_uncertainties') + fitness = _EasyDiffractionFitness(bumps_params, objective_function) + fitness.nllf() + problem = FitProblem(fitness) + + fitclass = next(cls for cls in FITTERS if cls.id == self.method) + proposed_burn = max(DEFAULT_MIN_BURN, int(self.max_iterations * DEFAULT_BURN_FRACTION)) + burn = min(proposed_burn, max(self.max_iterations - 1, 0)) + samples = self.max_iterations * DEFAULT_POP * len(bumps_params) + driver = FitDriver( + fitclass=fitclass, + problem=problem, + monitors=[], + steps=self.max_iterations, + burn=burn, + thin=DEFAULT_THIN, + pop=DEFAULT_POP, + samples=samples, + alpha=DEFAULT_ALPHA, + outliers=DEFAULT_OUTLIER_TEST, + trim=DEFAULT_TRIM, + ) + driver.clip() + + starting_values = np.array([parameter.value for parameter in bumps_params], dtype=float) + if starting_uncertainties is None: + starting_uncertainties = [None] * len(bumps_params) + + numpy_state = np.random.get_state() + python_state = random.getstate() + np.random.seed(random_seed) + random.seed(random_seed) + try: + best_values, best_nllf = driver.fit() + except Exception as error: # pragma: no cover - defensive runtime path + return OptimizeResult( + x=starting_values, + dx=None, + fun=None, + success=False, + status=-1, + message=f'DREAM sampling failed: {error}', + var_names=parameter_names, + posterior_samples=None, + posterior_parameter_summaries=[], + convergence_diagnostics={}, + sampler_settings={'random_seed': int(random_seed)}, + sampler_completed=False, + raw_state=None, + best_log_posterior=None, + starting_values=starting_values, + starting_uncertainties=starting_uncertainties, + ) + finally: + np.random.set_state(numpy_state) + random.setstate(python_state) + + state = getattr(driver.fitter, 'state', None) + if best_values is None or state is None: + return OptimizeResult( + x=starting_values, + dx=None, + fun=None, + success=False, + status=-1, + message='DREAM sampling did not produce usable posterior samples.', + var_names=parameter_names, + posterior_samples=None, + posterior_parameter_summaries=[], + convergence_diagnostics={}, + sampler_settings={'random_seed': int(random_seed)}, + sampler_completed=False, + raw_state=state, + best_log_posterior=None, + starting_values=starting_values, + starting_uncertainties=starting_uncertainties, + ) + + draw_index, parameter_samples_array, log_posterior = state.chains() + if parameter_samples_array.ndim != 3 or parameter_samples_array.size == 0: + return OptimizeResult( + x=starting_values, + dx=None, + fun=None, + success=False, + status=-1, + message='DREAM sampling did not return a usable posterior sample array.', + var_names=parameter_names, + posterior_samples=None, + posterior_parameter_summaries=[], + convergence_diagnostics={}, + sampler_settings={'random_seed': int(random_seed)}, + sampler_completed=True, + raw_state=state, + best_log_posterior=None, + starting_values=starting_values, + starting_uncertainties=starting_uncertainties, + ) + + state_best_values, best_log_posterior = state.best() + best_by_name = dict(zip(state.labels, state_best_values, strict=True)) + label_to_index = {label: index for index, label in enumerate(state.labels)} + ordered_indices = [label_to_index[uid] for uid in parameter_uids] + ordered_samples = np.asarray(parameter_samples_array, dtype=float)[:, :, ordered_indices] + map_values = np.array([best_by_name[uid] for uid in parameter_uids], dtype=float) + + posterior_samples = PosteriorSamples( + parameter_names=parameter_names, + parameter_samples=ordered_samples, + log_posterior=np.asarray(log_posterior, dtype=float), + draw_index=np.asarray(draw_index, dtype=float), + ) + convergence_diagnostics = compute_convergence_diagnostics(posterior_samples) + posterior_parameter_summaries = summarize_posterior_parameters( + parameter_names=parameter_names, + posterior_samples=posterior_samples, + map_values=map_values, + convergence_diagnostics=convergence_diagnostics, + ) + posterior_standard_deviations = standard_deviations_from_summaries( + posterior_parameter_summaries + ) + + sampler_settings = { + 'random_seed': int(random_seed), + 'steps': int(self.max_iterations), + 'burn': int(burn), + 'thin': int(DEFAULT_THIN), + 'pop': int(DEFAULT_POP), + 'samples': int(samples), + 'alpha': float(DEFAULT_ALPHA), + 'outliers': DEFAULT_OUTLIER_TEST, + 'trim': DEFAULT_TRIM, + } + + if not convergence_diagnostics.get('converged', True): + log.warning( + 'DREAM sampling completed, but convergence diagnostics indicate ' + 'the posterior may be poorly mixed.' + ) + + return OptimizeResult( + x=map_values, + dx=posterior_standard_deviations, + fun=float(best_nllf), + success=True, + status=0, + message='DREAM sampling completed', + var_names=parameter_names, + posterior_samples=posterior_samples, + posterior_parameter_summaries=posterior_parameter_summaries, + convergence_diagnostics=convergence_diagnostics, + sampler_settings=sampler_settings, + sampler_completed=True, + raw_state=state, + best_log_posterior=float(best_log_posterior), + starting_values=starting_values, + starting_uncertainties=starting_uncertainties, + ) + + def _sync_result_to_parameters( + self, + parameters: list[object], + raw_result: object, + ) -> None: + """Commit MAP values on success and restore starts on failure. + + Parameters + ---------- + parameters : list[object] + Parameters being optimized. + raw_result : object + DREAM result object. + """ + if getattr(raw_result, 'success', False): + values = raw_result.x + uncertainties = getattr(raw_result, 'dx', None) + else: + values = getattr(raw_result, 'starting_values', None) + uncertainties = getattr(raw_result, 'starting_uncertainties', None) + + if values is None: + return + + for index, parameter in enumerate(parameters): + parameter._set_value_from_minimizer(float(values[index])) + if uncertainties is None: + parameter.uncertainty = None + continue + + uncertainty = uncertainties[index] + parameter.uncertainty = None if uncertainty is None else float(uncertainty) + + def _build_fit_results( + self, + *, + parameters: list[object], + raw_result: object, + success: bool, + ) -> BayesianFitResults: + """Build the Bayesian fit result container. + + Parameters + ---------- + parameters : list[object] + Parameters after the solver finished. + raw_result : object + Normalized DREAM solver output. + success : bool + Whether DREAM produced usable posterior samples. + + Returns + ------- + BayesianFitResults + Bayesian result object for the finished run. + """ + fit_results = BayesianFitResults( + success=success, + parameters=parameters, + reduced_chi_square=self.tracker.best_chi2, + engine_result=getattr(raw_result, 'raw_state', raw_result), + starting_parameters=parameters, + fitting_time=self.tracker.fitting_time, + sampler_name='dream', + point_estimate_name='map', + posterior_samples=getattr(raw_result, 'posterior_samples', None), + posterior_parameter_summaries=getattr( + raw_result, 'posterior_parameter_summaries', [] + ), + posterior_predictive={}, + credible_interval_levels=(0.68, 0.95), + sampler_settings=getattr(raw_result, 'sampler_settings', {}), + convergence_diagnostics=getattr(raw_result, 'convergence_diagnostics', {}), + sampler_completed=getattr(raw_result, 'sampler_completed', False), + best_log_posterior=getattr(raw_result, 'best_log_posterior', None), + ) + fit_results.message = getattr(raw_result, 'message', '') + fit_results.iterations = int(self.max_iterations) + fit_results.result = raw_result + return fit_results \ No newline at end of file From 448887b51c37d6978dd89331dd6079b589b8cf48 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 00:12:55 +0200 Subject: [PATCH 010/106] Add Bayesian fit result display --- .../analysis/fit_helpers/bayesian.py | 249 +++++++++++++++++- .../analysis/fit_helpers/reporting.py | 32 ++- 2 files changed, 278 insertions(+), 3 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 516a1cb9..e5e85fbf 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -9,7 +9,15 @@ import arviz as az import numpy as np +from easydiffraction.analysis.fit_helpers.metrics import calculate_r_factor +from easydiffraction.analysis.fit_helpers.metrics import calculate_r_factor_squared +from easydiffraction.analysis.fit_helpers.metrics import calculate_rb_factor +from easydiffraction.analysis.fit_helpers.metrics import calculate_weighted_r_factor +from easydiffraction.analysis.fit_helpers.reporting import _build_parameter_row +from easydiffraction.analysis.fit_helpers.reporting import _format_optional_float from easydiffraction.analysis.fit_helpers.reporting import FitResults +from easydiffraction.utils.logging import console +from easydiffraction.utils.utils import render_table R_HAT_CONVERGENCE_THRESHOLD = 1.01 ESS_BULK_CONVERGENCE_THRESHOLD = 400.0 @@ -249,6 +257,82 @@ def __init__( self.sampler_completed = sampler_completed self.best_log_posterior = best_log_posterior + def display_results( + self, + y_obs: list[float] | None = None, + y_calc: list[float] | None = None, + y_err: list[float] | None = None, + f_obs: list[float] | None = None, + f_calc: list[float] | None = None, + ) -> None: + """Render a Bayesian fit summary with posterior diagnostics. + + Parameters + ---------- + y_obs : list[float] | None, default=None + Observed intensities for pattern R-factor metrics. + y_calc : list[float] | None, default=None + Calculated intensities for pattern R-factor metrics. + y_err : list[float] | None, default=None + Standard deviations of observed intensities for wR. + f_obs : list[float] | None, default=None + Observed structure-factor magnitudes for Bragg R. + f_calc : list[float] | None, default=None + Calculated structure-factor magnitudes for Bragg R. + """ + status_icon = 'βœ…' if self.success else '❌' + rf = rf2 = wr = br = None + if y_obs is not None and y_calc is not None: + rf = calculate_r_factor(y_obs, y_calc) * 100 + rf2 = calculate_r_factor_squared(y_obs, y_calc) * 100 + if y_obs is not None and y_calc is not None and y_err is not None: + wr = calculate_weighted_r_factor(y_obs, y_calc, y_err) * 100 + if f_obs is not None and f_calc is not None: + br = calculate_rb_factor(f_obs, f_calc) * 100 + + console.paragraph('Bayesian fit results') + console.print(f'{status_icon} Success: {self.success}') + if self.message: + console.print(f'ℹ️ Status: {self.message}') + console.print(f'πŸ§ͺ Sampler: {self.sampler_name}') + console.print(f'🎯 Committed point estimate: {self.point_estimate_name}') + console.print(f'πŸ” Sampler completed: {self.sampler_completed}') + console.print(f'⏱️ Fitting time: {_format_optional_float(self.fitting_time, suffix=" seconds")}') + console.print( + 'πŸ“ Goodness-of-fit (reduced χ²): ' + f'{_format_optional_float(self.reduced_chi_square)}' + ) + if self.best_log_posterior is not None: + console.print(f'πŸ“‰ Best log-posterior: {self.best_log_posterior:.2f}') + + sampler_settings = _format_sampler_settings(self.sampler_settings) + if sampler_settings is not None: + console.print(f'βš™οΈ Sampler settings: {sampler_settings}') + + convergence_summary = _format_convergence_summary(self.convergence_diagnostics) + if convergence_summary is not None: + console.print(f'πŸ“Š Convergence: {convergence_summary}') + + if rf is not None: + console.print(f'πŸ“ R-factor (Rf): {rf:.2f}%') + if rf2 is not None: + console.print(f'πŸ“ R-factor squared (RfΒ²): {rf2:.2f}%') + if wr is not None: + console.print(f'πŸ“ Weighted R-factor (wR): {wr:.2f}%') + if br is not None: + console.print(f'πŸ“ Bragg R-factor (BR): {br:.2f}%') + + console.print('πŸ“ˆ Committed parameters:') + _render_committed_parameter_table(self.parameters) + + console.print('πŸ“Š Posterior parameter summaries:') + _render_posterior_summary_table( + parameters=self.parameters, + posterior_parameter_summaries=self.posterior_parameter_summaries, + ) + + self._print_table_notes() + def compute_convergence_diagnostics(posterior_samples: PosteriorSamples) -> dict[str, object]: """Compute convergence diagnostics from posterior samples. @@ -382,4 +466,167 @@ def _dataset_to_scalar_dict(dataset: object) -> dict[str, float]: def _maybe_scalar(value: object) -> float | None: if value is None: return None - return float(value) \ No newline at end of file + return float(value) + + +def _format_sampler_settings(sampler_settings: dict[str, object]) -> str | None: + if not sampler_settings: + return None + + parts: list[str] = [] + for key in ('random_seed', 'steps', 'burn', 'thin', 'pop', 'samples'): + if key in sampler_settings: + parts.append(f'{key}={sampler_settings[key]}') + return ', '.join(parts) if parts else None + + +def _format_convergence_summary(convergence_diagnostics: dict[str, object]) -> str | None: + if not convergence_diagnostics: + return None + + parts: list[str] = [] + converged = convergence_diagnostics.get('converged') + if converged is not None: + status = 'yes' if converged else '[yellow]check diagnostics[/yellow]' + parts.append(f'converged={status}') + + max_r_hat = _maybe_scalar(convergence_diagnostics.get('max_r_hat')) + if max_r_hat is not None: + parts.append(f'max_r_hat={_format_r_hat(max_r_hat)}') + + min_ess_bulk = _maybe_scalar(convergence_diagnostics.get('min_ess_bulk')) + if min_ess_bulk is not None: + parts.append(f'min_ess_bulk={_format_ess_bulk(min_ess_bulk)}') + + n_draws = convergence_diagnostics.get('n_draws') + n_chains = convergence_diagnostics.get('n_chains') + if n_draws is not None and n_chains is not None: + parts.append(f'draws={n_draws}, chains={n_chains}') + + return ', '.join(parts) if parts else None + + +def _render_committed_parameter_table(parameters: list[object]) -> None: + headers = [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'start', + 'map', + 'uncertainty', + 'units', + 'change', + ] + alignments = [ + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'left', + 'right', + ] + rows = [_build_parameter_row(parameter) for parameter in parameters] + render_table( + columns_headers=headers, + columns_alignment=alignments, + columns_data=rows, + ) + + +def _render_posterior_summary_table( + *, + parameters: list[object], + posterior_parameter_summaries: list[PosteriorParameterSummary], +) -> None: + if not posterior_parameter_summaries: + console.print('No posterior parameter summaries available.') + return + + parameters_by_name = {parameter.unique_name: parameter for parameter in parameters} + headers = [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'median', + 'std', + '68% interval', + '95% interval', + 'r_hat', + 'ess_bulk', + 'units', + ] + alignments = [ + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'right', + 'right', + 'right', + 'left', + ] + rows = [ + _build_posterior_summary_row(summary, parameters_by_name) + for summary in posterior_parameter_summaries + ] + render_table( + columns_headers=headers, + columns_alignment=alignments, + columns_data=rows, + ) + + +def _build_posterior_summary_row( + summary: PosteriorParameterSummary, + parameters_by_name: dict[str, object], +) -> list[str]: + parameter = parameters_by_name.get(summary.unique_name) + identity = getattr(parameter, '_identity', None) + datablock = getattr(identity, 'datablock_entry_name', 'N/A') + category = getattr(identity, 'category_code', 'N/A') + entry = getattr(identity, 'category_entry_name', '') or '' + units = getattr(parameter, 'units', 'N/A') + + return [ + datablock, + category, + entry, + summary.display_name, + f'{summary.median:.4f}', + f'{summary.standard_deviation:.4f}', + _format_interval(summary.interval_68), + _format_interval(summary.interval_95), + _format_r_hat(summary.r_hat), + _format_ess_bulk(summary.ess_bulk), + units, + ] + + +def _format_interval(interval: tuple[float, float]) -> str: + return f'[{interval[0]:.4f}, {interval[1]:.4f}]' + + +def _format_r_hat(value: float | None) -> str: + if value is None: + return 'N/A' + formatted = f'{value:.3f}' + if value > R_HAT_CONVERGENCE_THRESHOLD: + return f'[yellow]{formatted}[/yellow]' + return formatted + + +def _format_ess_bulk(value: float | None) -> str: + if value is None: + return 'N/A' + formatted = f'{value:.1f}' + if value < ESS_BULK_CONVERGENCE_THRESHOLD: + return f'[yellow]{formatted}[/yellow]' + return formatted \ No newline at end of file diff --git a/src/easydiffraction/analysis/fit_helpers/reporting.py b/src/easydiffraction/analysis/fit_helpers/reporting.py index a83ad7bf..329f77e6 100644 --- a/src/easydiffraction/analysis/fit_helpers/reporting.py +++ b/src/easydiffraction/analysis/fit_helpers/reporting.py @@ -108,8 +108,11 @@ def display_results( console.paragraph('Fit results') console.print(f'{status_icon} Success: {self.success}') - console.print(f'⏱️ Fitting time: {self.fitting_time:.2f} seconds') - console.print(f'πŸ“ Goodness-of-fit (reduced χ²): {self.reduced_chi_square:.2f}') + console.print(f'⏱️ Fitting time: {_format_optional_float(self.fitting_time, suffix=" seconds")}') + console.print( + 'πŸ“ Goodness-of-fit (reduced χ²): ' + f'{_format_optional_float(self.reduced_chi_square)}' + ) if rf is not None: console.print(f'πŸ“ R-factor (Rf): {rf:.2f}%') if rf2 is not None: @@ -248,3 +251,28 @@ def _compute_relative_change(param: object) -> str: change = ((param.value - param._fit_start_value) / param._fit_start_value) * 100 arrow = '↑' if change > 0 else '↓' return f'{abs(change):.2f} % {arrow}' + + +def _format_optional_float( + value: float | None, + *, + suffix: str = '', +) -> str: + """Format an optional float for console output. + + Parameters + ---------- + value : float | None + Value to format. + suffix : str, default='' + Optional suffix appended to formatted numeric values. + + Returns + ------- + str + ``'N/A'`` when the value is ``None``; otherwise a formatted + string with two decimal places. + """ + if value is None: + return 'N/A' + return f'{value:.2f}{suffix}' From 3d44796be3eb1e1b2ae966e136345c2b18bee6e4 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 00:14:16 +0200 Subject: [PATCH 011/106] Plot Bayesian parameter correlations --- src/easydiffraction/display/plotting.py | 73 +++++++++++++++++++------ 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 61e93f68..09b8d5a8 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -739,10 +739,27 @@ def _get_param_correlation_dataframe(self) -> pd.DataFrame | None: Square correlation matrix labeled by parameter unique names, or ``None`` if unavailable. """ - result = self._get_fit_result_for_correlation() - if result is None: + fit_results = self._get_fit_result_for_correlation() + if fit_results is None: + return None + + posterior_samples = getattr(fit_results, 'posterior_samples', None) + if posterior_samples is not None: + corr_df = self._correlation_from_posterior_samples(posterior_samples) + if corr_df is not None: + return corr_df + + raw_result = getattr(fit_results, 'result', None) + if raw_result is None: + raw_result = getattr(fit_results, 'engine_result', None) + if raw_result is None: + log.warning('No raw fit result available. Correlation matrix cannot be plotted.') + return None + + var_names = getattr(raw_result, 'var_names', None) + if not var_names: + log.warning('Fit result does not expose variable names for a correlation matrix.') return None - raw_result, var_names, fit_results = result covar = getattr(raw_result, 'covar', None) if covar is not None: @@ -757,21 +774,20 @@ def _get_param_correlation_dataframe(self) -> pd.DataFrame | None: log.warning( 'Correlation matrix is unavailable for this fit. ' - 'Use the lmfit minimizer and ensure covariance estimation succeeds.' + 'Use a minimizer that returns covariance information or posterior samples.' ) return None def _get_fit_result_for_correlation( self, - ) -> tuple[object, list[str], object] | None: + ) -> object | None: """ - Validate and return the raw fit result for correlation. + Validate and return the fit result for correlation. Returns ------- - tuple[object, list[str], object] | None - A tuple of ``(raw_result, var_names, fit_results)`` when all - required data is present, or ``None`` otherwise. + object | None + Fit result object when available, or ``None`` otherwise. """ if self._project is None: log.warning('Plotter is not attached to a project.') @@ -781,18 +797,43 @@ def _get_fit_result_for_correlation( if fit_results is None: log.warning('No fit results available. Run fit() first.') return None + return fit_results - raw_result = getattr(fit_results, 'engine_result', None) - if raw_result is None: - log.warning('No raw fit result available. Correlation matrix cannot be plotted.') + @staticmethod + def _correlation_from_posterior_samples( + posterior_samples: object, + ) -> pd.DataFrame | None: + """Convert posterior samples into a correlation DataFrame. + + Parameters + ---------- + posterior_samples : object + Posterior sample container exposing ``flattened()`` and + ``parameter_names``. + + Returns + ------- + pd.DataFrame | None + Correlation matrix labeled by posterior parameter names, or + ``None`` if the sample array is invalid. + """ + parameter_names = getattr(posterior_samples, 'parameter_names', None) + if not parameter_names: + log.warning('Posterior samples do not expose parameter names.') return None - var_names = getattr(raw_result, 'var_names', None) - if not var_names: - log.warning('Fit result does not expose variable names for a correlation matrix.') + flattened = np.asarray(posterior_samples.flattened(), dtype=float) + if flattened.ndim != 2 or flattened.shape[1] != len(parameter_names): + log.warning('Posterior sample array has an invalid shape for correlations.') + return None + if flattened.shape[0] < 2: + log.warning('At least two posterior draws are required for correlations.') return None - return raw_result, var_names, fit_results + corr = np.corrcoef(flattened, rowvar=False) + corr = np.nan_to_num(corr, nan=0.0, posinf=0.0, neginf=0.0) + np.fill_diagonal(corr, 1.0) + return pd.DataFrame(corr, index=parameter_names, columns=parameter_names) @staticmethod def _correlation_from_covariance( From 391699df62f7d736a01f836a9a02993819baaa2e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 00:16:32 +0200 Subject: [PATCH 012/106] Add posterior ArviZ plots --- src/easydiffraction/display/plotting.py | 182 ++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 09b8d5a8..1c9e0afb 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -623,6 +623,40 @@ def plot_param_correlations( ) ) + def plot_posterior_pairs( + self, + parameters: list[object] | None = None, + ) -> None: + """Plot posterior pair relationships for sampled parameters. + + Parameters + ---------- + parameters : list[object] | None, default=None + Optional subset of sampled parameters to include. When + ``None``, all sampled parameters are shown. + """ + plot = self._build_posterior_pairs_plot(parameters=parameters) + if plot is None: + return + plot.show() + + def plot_param_distribution( + self, + param: object, + ) -> None: + """Plot the posterior distribution for one sampled parameter. + + Parameters + ---------- + param : object + Parameter descriptor whose posterior distribution should be + plotted. + """ + plot = self._build_param_distribution_plot(param) + if plot is None: + return + plot.show() + @staticmethod def _filter_correlation_dataframe( corr_df: pd.DataFrame, @@ -778,6 +812,154 @@ def _get_param_correlation_dataframe(self) -> pd.DataFrame | None: ) return None + def _build_posterior_pairs_plot( + self, + *, + parameters: list[object] | None, + ) -> object | None: + """Build an ArviZ posterior pair-plot object. + + Parameters + ---------- + parameters : list[object] | None + Optional subset of sampled parameters to include. + + Returns + ------- + object | None + ArviZ plot object, or ``None`` when posterior plotting is + unavailable. + """ + inference_data, fit_results = self._get_posterior_inference_data() + if inference_data is None or fit_results is None: + return None + + parameter_names = self._resolve_posterior_parameter_names( + fit_results=fit_results, + parameters=parameters, + ) + if parameter_names is None: + return None + if len(parameter_names) < 2: + log.warning('Posterior pair plots require at least two sampled parameters.') + return None + + import arviz as az + + plot = az.plot_pair( + inference_data, + var_names=parameter_names, + backend='plotly', + marginal=True, + ) + if hasattr(plot, 'add_title'): + plot.add_title('Posterior pair plot') + return plot + + def _build_param_distribution_plot( + self, + param: object, + ) -> object | None: + """Build an ArviZ posterior distribution plot for one parameter. + + Parameters + ---------- + param : object + Parameter descriptor to plot. + + Returns + ------- + object | None + ArviZ plot object, or ``None`` when posterior plotting is + unavailable. + """ + inference_data, fit_results = self._get_posterior_inference_data() + if inference_data is None or fit_results is None: + return None + + parameter_names = self._resolve_posterior_parameter_names( + fit_results=fit_results, + parameters=[param], + ) + if parameter_names is None: + return None + + import arviz as az + + plot = az.plot_dist( + inference_data, + var_names=parameter_names, + backend='plotly', + point_estimate='median', + ) + if hasattr(plot, 'add_title'): + plot.add_title(f'Posterior distribution: {parameter_names[0]}') + return plot + + def _get_posterior_inference_data( + self, + ) -> tuple[object | None, object | None]: + """Return posterior inference data for the current Bayesian fit. + + Returns + ------- + tuple[object | None, object | None] + ``(inference_data, fit_results)`` when posterior samples are + available, otherwise ``(None, None)``. + """ + if self.engine != PlotterEngineEnum.PLOTLY.value: + log.warning('Posterior plots currently require the Plotly plotting backend.') + return None, None + + fit_results = self._get_fit_result_for_correlation() + if fit_results is None: + return None, None + + posterior_samples = getattr(fit_results, 'posterior_samples', None) + if posterior_samples is None: + log.warning('Posterior samples are unavailable. Run a Bayesian fit first.') + return None, None + + return posterior_samples.to_arviz(), fit_results + + @staticmethod + def _resolve_posterior_parameter_names( + *, + fit_results: object, + parameters: list[object] | None, + ) -> list[str] | None: + """Resolve posterior parameter names from descriptors. + + Parameters + ---------- + fit_results : object + Bayesian fit result exposing posterior samples. + parameters : list[object] | None + Optional parameter subset. + + Returns + ------- + list[str] | None + Posterior parameter names in plotting order, or ``None`` if + the selection cannot be resolved. + """ + posterior_samples = getattr(fit_results, 'posterior_samples', None) + available_names = getattr(posterior_samples, 'parameter_names', None) + if not available_names: + log.warning('Posterior samples do not expose parameter names.') + return None + + if parameters is None: + return list(available_names) + + requested_names = [getattr(parameter, 'unique_name', None) for parameter in parameters] + missing_names = [name for name in requested_names if name not in available_names] + if missing_names: + missing = ', '.join(str(name) for name in missing_names) + log.warning(f'Posterior samples do not contain the selected parameters: {missing}') + return None + return [str(name) for name in requested_names if name is not None] + def _get_fit_result_for_correlation( self, ) -> object | None: From 8add02835fc59453eed40ba41261909dfcd6d8a3 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 00:20:26 +0200 Subject: [PATCH 013/106] Add posterior predictive plots --- .../analysis/fit_helpers/bayesian.py | 3 + src/easydiffraction/display/plotters/ascii.py | 2 + src/easydiffraction/display/plotters/base.py | 2 + .../display/plotters/plotly.py | 40 ++ src/easydiffraction/display/plotting.py | 381 ++++++++++++++++++ 5 files changed, 428 insertions(+) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index e5e85fbf..3615a0ed 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -68,6 +68,8 @@ class PosteriorPredictiveSummary: ---------- experiment_name : str Experiment identifier. + x_axis_name : str + Name of the x-axis used for the predictive arrays. x : np.ndarray X-axis values for the predictive curves. map_prediction : np.ndarray @@ -85,6 +87,7 @@ class PosteriorPredictiveSummary: """ experiment_name: str + x_axis_name: str x: np.ndarray map_prediction: np.ndarray lower_95: np.ndarray | None = None diff --git a/src/easydiffraction/display/plotters/ascii.py b/src/easydiffraction/display/plotters/ascii.py index a0c95fe1..4aeb5577 100644 --- a/src/easydiffraction/display/plotters/ascii.py +++ b/src/easydiffraction/display/plotters/ascii.py @@ -131,6 +131,8 @@ def plot_powder_meas_vs_calc( title=plot_spec.title, height=plot_spec.height, ) + if plot_spec.predictive_lower_95 is not None and plot_spec.predictive_upper_95 is not None: + console.print('Posterior predictive bands are available with the Plotly engine only.') if plot_spec.bragg_tick_sets: console.print('Bragg peak subplot rows are available with the Plotly engine only.') diff --git a/src/easydiffraction/display/plotters/base.py b/src/easydiffraction/display/plotters/base.py index b1a19a27..85d09434 100644 --- a/src/easydiffraction/display/plotters/base.py +++ b/src/easydiffraction/display/plotters/base.py @@ -60,6 +60,8 @@ class PowderMeasVsCalcSpec: bragg_peaks_height_fraction: float height: int | None = None y_bkg: np.ndarray | None = None + predictive_lower_95: np.ndarray | None = None + predictive_upper_95: np.ndarray | None = None class XAxisType(StrEnum): diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 887879dd..e219ffa9 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -65,6 +65,7 @@ COMPOSITE_MARGIN_RIGHT = 30 COMPOSITE_MARGIN_TOP = 40 COMPOSITE_MARGIN_BOTTOM = 45 +PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.18)' @dataclass(frozen=True) @@ -1233,6 +1234,15 @@ def plot_powder_meas_vs_calc( row_heights=layout.row_heights, ) + if plot_spec.predictive_lower_95 is not None and plot_spec.predictive_upper_95 is not None: + lower_trace, upper_trace = self._get_predictive_band_traces( + x=plot_spec.x, + lower=plot_spec.predictive_lower_95, + upper=plot_spec.predictive_upper_95, + ) + fig.add_trace(lower_trace, row=1, col=1) + fig.add_trace(upper_trace, row=1, col=1) + main_traces = ( ( ('meas', plot_spec.y_meas), @@ -1370,6 +1380,36 @@ def plot_powder_meas_vs_calc( self._show_figure(fig) + @staticmethod + def _get_predictive_band_traces( + *, + x: np.ndarray, + lower: np.ndarray, + upper: np.ndarray, + ) -> tuple[go.Scatter, go.Scatter]: + """Return Plotly traces for a filled predictive interval band.""" + lower_trace = go.Scatter( + x=x, + y=lower, + mode='lines', + line={'color': 'rgba(0, 0, 0, 0)'}, + hoverinfo='skip', + showlegend=False, + legendgroup='predictive_band', + ) + upper_trace = go.Scatter( + x=x, + y=upper, + mode='lines', + line={'color': 'rgba(0, 0, 0, 0)'}, + fill='tonexty', + fillcolor=PREDICTIVE_BAND_COLOR, + name='Posterior predictive 95% CI', + hoverinfo='skip', + legendgroup='predictive_band', + ) + return lower_trace, upper_trace + def plot_single_crystal( self, x_calc: object, diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 1c9e0afb..9a5fc56e 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -69,6 +69,8 @@ def description(self) -> str: DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION = 0.10 DEFAULT_RESID_HEIGHT = DEFAULT_RESIDUAL_HEIGHT_FRACTION DEFAULT_BRAGG_ROW = DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION +DEFAULT_POSTERIOR_PREDICTIVE_DRAWS = 200 +DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP = 50 @dataclass(frozen=True) @@ -657,6 +659,70 @@ def plot_param_distribution( return plot.show() + def plot_posterior_predictive( + self, + expt_name: str, + style: str = 'band', + ) -> None: + """Plot posterior predictive curves for a powder experiment. + + Parameters + ---------- + expt_name : str + Experiment name to plot. + style : str, default='band' + Either ``'band'`` for a 95% credible interval or + ``'draws'`` for sampled predictive curves. + """ + if style not in {'band', 'draws'}: + msg = "style must be either 'band' or 'draws'." + raise ValueError(msg) + + if self._project is None: + log.warning('Plotter is not attached to a project.') + return + + if self.engine != PlotterEngineEnum.PLOTLY.value: + log.warning('Posterior predictive plots currently require the Plotly backend.') + return + + experiment = self._project.experiments[expt_name] + x_axis, _, sample_form, scattering_type, _ = self._resolve_x_axis(experiment.type, None) + if sample_form != SampleFormEnum.POWDER: + log.warning('Posterior predictive plots currently support powder experiments only.') + return + + summary = self._get_or_build_posterior_predictive_summary( + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + ) + if summary is None: + return + + pattern = intensity_category_for(experiment) + y_meas = getattr(pattern, 'intensity_meas', None) + if y_meas is None: + log.warning(f'No measured data available for experiment {expt_name}.') + return + + axes_labels = self._get_axes_labels(sample_form, scattering_type, x_axis) + if style == 'band': + self._plot_posterior_predictive_band( + expt_name=expt_name, + summary=summary, + y_meas=np.asarray(y_meas, dtype=float), + axes_labels=axes_labels, + ) + return + + self._plot_posterior_predictive_draws( + expt_name=expt_name, + summary=summary, + y_meas=np.asarray(y_meas, dtype=float), + axes_labels=axes_labels, + ) + @staticmethod def _filter_correlation_dataframe( corr_df: pd.DataFrame, @@ -896,6 +962,183 @@ def _build_param_distribution_plot( plot.add_title(f'Posterior distribution: {parameter_names[0]}') return plot + def _get_or_build_posterior_predictive_summary( + self, + *, + experiment: object, + expt_name: str, + x_axis: object, + ) -> object | None: + """Return a cached or newly built posterior predictive summary.""" + fit_results = self._get_fit_result_for_correlation() + if fit_results is None: + return None + + posterior_predictive = getattr(fit_results, 'posterior_predictive', None) + posterior_samples = getattr(fit_results, 'posterior_samples', None) + if posterior_predictive is None or posterior_samples is None: + return None + + x_axis_name = getattr(x_axis, 'value', x_axis) + cache_key = self._posterior_predictive_key(expt_name, str(x_axis_name)) + summary = posterior_predictive.get(cache_key) + if summary is not None: + return summary + + summary = self._build_posterior_predictive_summary( + fit_results=fit_results, + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + ) + if summary is None: + return None + + posterior_predictive[cache_key] = summary + return summary + + def _build_posterior_predictive_summary( + self, + *, + fit_results: object, + experiment: object, + expt_name: str, + x_axis: object, + ) -> object | None: + """Build posterior predictive summaries from posterior draws.""" + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorPredictiveSummary + + posterior_samples = getattr(fit_results, 'posterior_samples', None) + if posterior_samples is None: + return None + + flattened_samples = np.asarray(posterior_samples.flattened(), dtype=float) + parameter_names = getattr(posterior_samples, 'parameter_names', None) + if flattened_samples.ndim != 2 or not parameter_names: + log.warning('Posterior samples are unavailable for predictive summaries.') + return None + + parameters_by_name = { + getattr(parameter, 'unique_name', ''): parameter for parameter in fit_results.parameters + } + sampled_parameters = [] + for name in parameter_names: + parameter = parameters_by_name.get(name) + if parameter is None: + log.warning( + 'Posterior predictive summaries require matching fitted parameters for ' + f"'{name}'." + ) + return None + sampled_parameters.append(parameter) + + original_values = np.array([parameter.value for parameter in sampled_parameters], dtype=float) + original_uncertainties = [parameter.uncertainty for parameter in sampled_parameters] + + map_prediction = None + x_values = None + predictive_draws: list[np.ndarray] = [] + draw_indices = self._posterior_predictive_draw_indices(flattened_samples.shape[0]) + try: + map_prediction, x_values = self._evaluate_posterior_predictive_state( + sampled_parameters=sampled_parameters, + values=original_values, + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + ) + if map_prediction is None or x_values is None: + return None + + for index in draw_indices: + prediction, current_x = self._evaluate_posterior_predictive_state( + sampled_parameters=sampled_parameters, + values=flattened_samples[index], + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + ) + if prediction is None or current_x is None: + return None + if prediction.shape != map_prediction.shape or current_x.shape != x_values.shape: + log.warning('Posterior predictive draws returned inconsistent array shapes.') + return None + predictive_draws.append(prediction) + finally: + for parameter, value, uncertainty in zip( + sampled_parameters, + original_values, + original_uncertainties, + strict=True, + ): + parameter._set_value_from_minimizer(float(value)) + parameter.uncertainty = uncertainty + self._update_project_categories(expt_name) + + predictive_draw_array = np.asarray(predictive_draws, dtype=float) + lower_68, upper_68 = np.quantile(predictive_draw_array, [0.16, 0.84], axis=0) + lower_95, upper_95 = np.quantile(predictive_draw_array, [0.025, 0.975], axis=0) + x_axis_name = getattr(x_axis, 'value', x_axis) + + return PosteriorPredictiveSummary( + experiment_name=expt_name, + x_axis_name=str(x_axis_name), + x=np.asarray(x_values, dtype=float), + map_prediction=np.asarray(map_prediction, dtype=float), + lower_95=np.asarray(lower_95, dtype=float), + upper_95=np.asarray(upper_95, dtype=float), + lower_68=np.asarray(lower_68, dtype=float), + upper_68=np.asarray(upper_68, dtype=float), + draws=predictive_draw_array, + ) + + def _evaluate_posterior_predictive_state( + self, + *, + sampled_parameters: list[object], + values: np.ndarray, + experiment: object, + expt_name: str, + x_axis: object, + ) -> tuple[np.ndarray | None, np.ndarray | None]: + """Evaluate one posterior predictive state for an experiment.""" + for parameter, value in zip(sampled_parameters, values, strict=True): + parameter._set_value_from_minimizer(float(value)) + + self._update_project_categories(expt_name) + pattern = intensity_category_for(experiment) + x_name = getattr(x_axis, 'value', x_axis) + x_values = getattr(pattern, x_name, None) + y_calc = getattr(pattern, 'intensity_calc', None) + if x_values is None or y_calc is None: + log.warning( + f'Posterior predictive data is unavailable for experiment {expt_name}. ' + 'Ensure calculated intensities and the selected x axis are available.' + ) + return None, None + + return np.asarray(y_calc, dtype=float), np.asarray(x_values, dtype=float) + + @staticmethod + def _posterior_predictive_draw_indices(n_draws: int) -> np.ndarray: + """Select evenly spaced posterior draws for predictive summaries.""" + if n_draws <= DEFAULT_POSTERIOR_PREDICTIVE_DRAWS: + return np.arange(n_draws, dtype=int) + + return np.unique( + np.linspace( + 0, + n_draws - 1, + num=DEFAULT_POSTERIOR_PREDICTIVE_DRAWS, + dtype=int, + ) + ) + + @staticmethod + def _posterior_predictive_key(expt_name: str, x_axis_name: str) -> str: + """Return the cache key for a posterior predictive summary.""" + return f'{expt_name}:{x_axis_name}' + def _get_posterior_inference_data( self, ) -> tuple[object | None, object | None]: @@ -922,6 +1165,120 @@ def _get_posterior_inference_data( return posterior_samples.to_arviz(), fit_results + def _plot_posterior_predictive_band( + self, + *, + expt_name: str, + summary: object, + y_meas: np.ndarray, + axes_labels: list[str], + ) -> None: + """Render a posterior predictive band plot using Plotly.""" + import plotly.graph_objects as go + + fig = go.Figure() + fig.add_trace( + go.Scatter( + x=summary.x, + y=summary.lower_95, + mode='lines', + line={'color': 'rgba(0, 0, 0, 0)'}, + hoverinfo='skip', + showlegend=False, + ) + ) + fig.add_trace( + go.Scatter( + x=summary.x, + y=summary.upper_95, + mode='lines', + line={'color': 'rgba(0, 0, 0, 0)'}, + fill='tonexty', + fillcolor='rgba(214, 39, 40, 0.18)', + name='Posterior predictive 95% CI', + hoverinfo='skip', + ) + ) + fig.add_trace( + go.Scatter( + x=summary.x, + y=summary.map_prediction, + mode='lines', + line={'color': 'rgb(214, 39, 40)', 'width': 2}, + name='MAP prediction', + ) + ) + fig.add_trace( + go.Scatter( + x=summary.x, + y=y_meas, + mode='lines+markers', + line={'color': 'rgb(31, 119, 180)', 'width': 1.5}, + name='Measured', + ) + ) + fig.update_layout( + title=f"Posterior predictive for experiment πŸ”¬ '{expt_name}'", + xaxis_title=axes_labels[0], + yaxis_title=axes_labels[1], + ) + fig.show() + + def _plot_posterior_predictive_draws( + self, + *, + expt_name: str, + summary: object, + y_meas: np.ndarray, + axes_labels: list[str], + ) -> None: + """Render posterior predictive draws using Plotly.""" + import plotly.graph_objects as go + + fig = go.Figure() + draws = getattr(summary, 'draws', None) + if draws is None: + log.warning('Posterior predictive draws are unavailable for plotting.') + return + + draw_cap = min(len(draws), DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP) + for index in range(draw_cap): + fig.add_trace( + go.Scatter( + x=summary.x, + y=draws[index], + mode='lines', + line={'color': 'rgba(120, 120, 120, 0.18)', 'width': 1}, + name='Posterior draw' if index == 0 else None, + showlegend=index == 0, + ) + ) + + fig.add_trace( + go.Scatter( + x=summary.x, + y=summary.map_prediction, + mode='lines', + line={'color': 'rgb(214, 39, 40)', 'width': 2}, + name='MAP prediction', + ) + ) + fig.add_trace( + go.Scatter( + x=summary.x, + y=y_meas, + mode='lines+markers', + line={'color': 'rgb(31, 119, 180)', 'width': 1.5}, + name='Measured', + ) + ) + fig.update_layout( + title=f"Posterior predictive draws for experiment πŸ”¬ '{expt_name}'", + xaxis_title=axes_labels[0], + yaxis_title=axes_labels[1], + ) + fig.show() + @staticmethod def _resolve_posterior_parameter_names( *, @@ -1506,6 +1863,28 @@ def _plot_powder_bragg_meas_vs_calc( x_min=ctx['x_min'], x_max=ctx['x_max'], ) + + predictive_summary = self._get_or_build_posterior_predictive_summary( + experiment=experiment, + expt_name=expt_name, + x_axis=ctx['x_axis'], + ) + predictive_lower_95 = None + predictive_upper_95 = None + if predictive_summary is not None: + predictive_lower_95 = self._filtered_y_array( + predictive_summary.lower_95, + predictive_summary.x, + ctx['x_min'], + ctx['x_max'], + ) + predictive_upper_95 = self._filtered_y_array( + predictive_summary.upper_95, + predictive_summary.x, + ctx['x_min'], + ctx['x_max'], + ) + plot_spec = PowderMeasVsCalcSpec( x=ctx['x_filtered'], y_meas=series.y_meas, @@ -1518,6 +1897,8 @@ def _plot_powder_bragg_meas_vs_calc( bragg_peaks_height_fraction=DEFAULT_BRAGG_ROW, height=self._composite_plot_height(), y_bkg=series.y_bkg, + predictive_lower_95=predictive_lower_95, + predictive_upper_95=predictive_upper_95, ) self._backend.plot_powder_meas_vs_calc(plot_spec=plot_spec) From 100678ed501c0c090b355ac816bc3f6bdc053fca Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 00:55:20 +0200 Subject: [PATCH 014/106] Refine Bayesian fit UX --- .../analysis/fit_helpers/bayesian.py | 13 +- .../analysis/fit_helpers/tracking.py | 88 +++++- .../analysis/minimizers/bumps_dream.py | 69 ++++- .../display/plotters/plotly.py | 7 +- src/easydiffraction/display/plotting.py | 252 ++++++++++++++++-- 5 files changed, 389 insertions(+), 40 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 3615a0ed..62d6cab3 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -382,6 +382,7 @@ def summarize_posterior_parameters( parameter_names: list[str], posterior_samples: PosteriorSamples, map_values: np.ndarray, + parameter_display_names: list[str] | None = None, convergence_diagnostics: dict[str, object] | None = None, ) -> list[PosteriorParameterSummary]: """Build posterior parameter summaries in EasyDiffraction order. @@ -394,6 +395,8 @@ def summarize_posterior_parameters( Posterior sample container. map_values : np.ndarray MAP or best-sampled parameter values in the same order. + parameter_display_names : list[str] | None, default=None + Human-readable parameter names in the same order. convergence_diagnostics : dict[str, object] | None, default=None Optional convergence diagnostics keyed by parameter name. @@ -412,6 +415,9 @@ def summarize_posterior_parameters( if flattened.shape[1] != len(parameter_names): msg = 'Posterior samples do not match the sampled parameter name list length.' raise ValueError(msg) + if parameter_display_names is not None and len(parameter_display_names) != len(parameter_names): + msg = 'Posterior display-name list must match the sampled parameter name list length.' + raise ValueError(msg) r_hat_by_parameter = {} ess_bulk_by_parameter = {} @@ -424,10 +430,15 @@ def summarize_posterior_parameters( values = flattened[:, index] interval_68 = tuple(np.quantile(values, [0.16, 0.84]).tolist()) interval_95 = tuple(np.quantile(values, [0.025, 0.975]).tolist()) + display_name = ( + parameter_display_names[index] + if parameter_display_names is not None + else parameter_name + ) summaries.append( PosteriorParameterSummary( unique_name=parameter_name, - display_name=parameter_name, + display_name=display_name, map_value=float(map_values[index]), median=float(np.median(values)), standard_deviation=float(np.std(values, ddof=1)), diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py index 99f9c8b6..97aeeec9 100644 --- a/src/easydiffraction/analysis/fit_helpers/tracking.py +++ b/src/easydiffraction/analysis/fit_helpers/tracking.py @@ -29,6 +29,8 @@ from easydiffraction.utils.logging import ConsoleManager SIGNIFICANT_CHANGE_THRESHOLD = 0.01 # 1% threshold +SAMPLER_PROGRESS_UPDATE_SECONDS = 5.0 +SAMPLER_PROGRESS_STATUS = 'sampling...' DEFAULT_HEADERS = ['iteration', 'χ²', 'improvement [%]'] DEFAULT_ALIGNMENTS = ['center', 'center', 'center'] @@ -101,6 +103,7 @@ def __init__(self) -> None: self._best_iteration: int | None = None self._fitting_time: float | None = None self._verbosity: VerbosityEnum = VerbosityEnum.FULL + self._last_progress_time: float | None = None self._df_rows: list[list[str]] = [] self._display_handle: object | None = None @@ -115,6 +118,7 @@ def reset(self) -> None: self._best_chi2 = None self._best_iteration = None self._fitting_time = None + self._last_progress_time = None def track( self, @@ -185,6 +189,75 @@ def track( return residuals + def track_sampler_progress( + self, + *, + iteration: int, + reduced_chi2: float, + elapsed_time: float, + status: str = SAMPLER_PROGRESS_STATUS, + ) -> None: + """Update progress from a sampler monitor. + + Parameters + ---------- + iteration : int + Sampler iteration or generation index. + reduced_chi2 : float + Best reduced chi-square implied by the current best sample. + elapsed_time : float + Elapsed wall time in seconds. + status : str, default='sampling...' + Text shown for periodic progress rows without a chi-square + improvement. + """ + self._iteration = iteration + + row: list[str] = [] + if self._previous_chi2 is None or self._best_chi2 is None: + self._previous_chi2 = reduced_chi2 + self._best_chi2 = reduced_chi2 + self._best_iteration = iteration + self._last_progress_time = elapsed_time + row = [ + str(iteration), + f'{reduced_chi2:.2f}', + '', + ] + else: + if reduced_chi2 < self._best_chi2: + self._best_chi2 = reduced_chi2 + self._best_iteration = iteration + + change = 0.0 + if self._previous_chi2 > 0: + change = (self._previous_chi2 - reduced_chi2) / self._previous_chi2 + + if change > SIGNIFICANT_CHANGE_THRESHOLD: + row = [ + str(iteration), + f'{reduced_chi2:.2f}', + f'{change * 100:.1f}% ↓', + ] + self._previous_chi2 = reduced_chi2 + self._last_progress_time = elapsed_time + elif ( + self._last_progress_time is None + or elapsed_time - self._last_progress_time >= SAMPLER_PROGRESS_UPDATE_SECONDS + ): + row = [ + str(iteration), + f'{self._best_chi2:.2f}', + status, + ] + self._last_progress_time = elapsed_time + + if row: + self.add_tracking_info(row) + + self._last_chi2 = reduced_chi2 + self._last_iteration = iteration + @property def best_chi2(self) -> float | None: """Best recorded reduced chi-square value or None.""" @@ -266,13 +339,14 @@ def add_tracking_info(self, row: list[str]) -> None: def finish_tracking(self) -> None: """Finalize progress display and print best result summary.""" - # Add last iteration as last row - row: list[str] = [ - str(self._last_iteration), - f'{self._last_chi2:.2f}' if self._last_chi2 is not None else '', - '', - ] - self.add_tracking_info(row) + if self._last_iteration is not None: + row: list[str] = [ + str(self._last_iteration), + f'{self._last_chi2:.2f}' if self._last_chi2 is not None else '', + '', + ] + if not self._df_rows or self._df_rows[-1][:2] != row[:2]: + self.add_tracking_info(row) if self._verbosity is not VerbosityEnum.FULL: return diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 28a2f4de..9f2ade75 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -10,6 +10,7 @@ from bumps.fitproblem import FitProblem from bumps.fitters import FITTERS from bumps.fitters import FitDriver +from bumps.fitters import monitor as bumps_monitor from scipy.optimize import OptimizeResult from easydiffraction.analysis.fit_helpers.bayesian import BayesianFitResults @@ -35,6 +36,60 @@ DEFAULT_TRIM = False +class _DreamProgressMonitor(bumps_monitor.Monitor): + """Progress monitor translating DREAM updates into chi-square rows.""" + + def __init__( + self, + *, + tracker: object, + n_points: int, + n_parameters: int, + n_chains: int, + ) -> None: + self._tracker = tracker + self._n_points = n_points + self._n_parameters = n_parameters + self._n_chains = max(1, n_chains) + + def config_history(self, history: object) -> None: + """Declare the history fields needed for progress updates.""" + history.requires(time=1, step=1, value=1) + + def __call__(self, history: object) -> None: + """Forward sampler progress to the shared fit tracker.""" + step = int(history.step[0]) if history.step else 0 + generation = max(1, step // self._n_chains) + reduced_chi2 = self._reduced_chi_square_from_nllf(float(history.value[0])) + self._tracker.track_sampler_progress( + iteration=generation, + reduced_chi2=reduced_chi2, + elapsed_time=float(history.time[0]), + ) + + def final(self, history: object, best: dict[str, object]) -> None: + """Record the final DREAM state in the shared fit tracker.""" + if not history.time or best.get('value') is None: + return + step = int(history.step[0]) if history.step else 0 + generation = max(1, step // self._n_chains) + reduced_chi2 = self._reduced_chi_square_from_nllf(float(best['value'])) + self._tracker.track_sampler_progress( + iteration=generation, + reduced_chi2=reduced_chi2, + elapsed_time=float(history.time[0]), + status='', + ) + + def _reduced_chi_square_from_nllf(self, nllf: float) -> float: + """Convert DREAM's negative log-likelihood to reduced chi-square.""" + dof = self._n_points - self._n_parameters + chi_square = 2.0 * nllf + if dof <= 0: + return chi_square + return chi_square / dof + + @MinimizerFactory.register class BumpsDreamMinimizer(BumpsMinimizer): """Bumps minimizer using the DREAM Bayesian sampler.""" @@ -94,6 +149,9 @@ def _prepare_solver_args( """ solver_args = super()._prepare_solver_args(parameters) solver_args['parameter_names'] = [parameter.unique_name for parameter in parameters] + solver_args['parameter_display_names'] = [ + getattr(parameter, 'name', parameter.unique_name) for parameter in parameters + ] solver_args['parameter_uids'] = [parameter._minimizer_uid for parameter in parameters] solver_args['starting_uncertainties'] = [parameter.uncertainty for parameter in parameters] return solver_args @@ -119,6 +177,7 @@ def _run_solver( """ bumps_params = kwargs.get('bumps_params') parameter_names = kwargs.get('parameter_names') + parameter_display_names = kwargs.get('parameter_display_names') parameter_uids = kwargs.get('parameter_uids') random_seed = kwargs.get('random_seed') starting_uncertainties = kwargs.get('starting_uncertainties') @@ -130,10 +189,17 @@ def _run_solver( proposed_burn = max(DEFAULT_MIN_BURN, int(self.max_iterations * DEFAULT_BURN_FRACTION)) burn = min(proposed_burn, max(self.max_iterations - 1, 0)) samples = self.max_iterations * DEFAULT_POP * len(bumps_params) + n_chains = DEFAULT_POP * len(bumps_params) + progress_monitor = _DreamProgressMonitor( + tracker=self.tracker, + n_points=fitness.numpoints(), + n_parameters=len(bumps_params), + n_chains=n_chains, + ) driver = FitDriver( fitclass=fitclass, problem=problem, - monitors=[], + monitors=[progress_monitor], steps=self.max_iterations, burn=burn, thin=DEFAULT_THIN, @@ -238,6 +304,7 @@ def _run_solver( parameter_names=parameter_names, posterior_samples=posterior_samples, map_values=map_values, + parameter_display_names=parameter_display_names, convergence_diagnostics=convergence_diagnostics, ) posterior_standard_deviations = standard_deviations_from_summaries( diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index e219ffa9..59bab8db 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -65,7 +65,8 @@ COMPOSITE_MARGIN_RIGHT = 30 COMPOSITE_MARGIN_TOP = 40 COMPOSITE_MARGIN_BOTTOM = 45 -PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.18)' +PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.26)' +PREDICTIVE_BAND_EDGE_COLOR = 'rgba(214, 39, 40, 0.45)' @dataclass(frozen=True) @@ -1392,7 +1393,7 @@ def _get_predictive_band_traces( x=x, y=lower, mode='lines', - line={'color': 'rgba(0, 0, 0, 0)'}, + line={'color': PREDICTIVE_BAND_EDGE_COLOR, 'width': 1}, hoverinfo='skip', showlegend=False, legendgroup='predictive_band', @@ -1401,7 +1402,7 @@ def _get_predictive_band_traces( x=x, y=upper, mode='lines', - line={'color': 'rgba(0, 0, 0, 0)'}, + line={'color': PREDICTIVE_BAND_EDGE_COLOR, 'width': 1}, fill='tonexty', fillcolor=PREDICTIVE_BAND_COLOR, name='Posterior predictive 95% CI', diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 9a5fc56e..bb0ecb4b 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -883,7 +883,7 @@ def _build_posterior_pairs_plot( *, parameters: list[object] | None, ) -> object | None: - """Build an ArviZ posterior pair-plot object. + """Build a Plotly posterior pair plot. Parameters ---------- @@ -893,11 +893,11 @@ def _build_posterior_pairs_plot( Returns ------- object | None - ArviZ plot object, or ``None`` when posterior plotting is + Plotly figure, or ``None`` when posterior plotting is unavailable. """ - inference_data, fit_results = self._get_posterior_inference_data() - if inference_data is None or fit_results is None: + posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() + if posterior_samples is None or fit_results is None: return None parameter_names = self._resolve_posterior_parameter_names( @@ -910,23 +910,87 @@ def _build_posterior_pairs_plot( log.warning('Posterior pair plots require at least two sampled parameters.') return None - import arviz as az + go = __import__('plotly.graph_objects', fromlist=['Figure', 'Histogram', 'Scattergl']) + make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots - plot = az.plot_pair( - inference_data, - var_names=parameter_names, - backend='plotly', - marginal=True, + samples = self._selected_posterior_samples(posterior_samples, parameter_names) + if samples is None: + return None + samples = self._thin_posterior_samples(samples) + labels = self._posterior_plot_labels(fit_results, parameter_names) + + n_parameters = len(parameter_names) + fig = make_subplots( + rows=n_parameters, + cols=n_parameters, + shared_xaxes='columns', + shared_yaxes='rows', + horizontal_spacing=0.03, + vertical_spacing=0.03, ) - if hasattr(plot, 'add_title'): - plot.add_title('Posterior pair plot') - return plot + + for row_index in range(n_parameters): + for col_index in range(n_parameters): + row = row_index + 1 + col = col_index + 1 + if col_index > row_index: + fig.update_xaxes(visible=False, row=row, col=col) + fig.update_yaxes(visible=False, row=row, col=col) + continue + + x_values = samples[:, col_index] + y_values = samples[:, row_index] + if row_index == col_index: + fig.add_trace( + go.Histogram( + x=x_values, + nbinsx=40, + histnorm='probability density', + marker={'color': 'rgb(99, 110, 250)'}, + showlegend=False, + hovertemplate='%{x:.4f}
density=%{y:.4f}', + ), + row=row, + col=col, + ) + else: + fig.add_trace( + go.Scattergl( + x=x_values, + y=y_values, + mode='markers', + marker={ + 'color': 'rgba(99, 110, 250, 0.18)', + 'size': 4, + }, + showlegend=False, + hovertemplate=( + f'{labels[col_index]}: %{{x:.4f}}
' + f'{labels[row_index]}: %{{y:.4f}}' + ), + ), + row=row, + col=col, + ) + + fig.update_xaxes(showticklabels=(row_index == n_parameters - 1), row=row, col=col) + fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) + if row_index == n_parameters - 1: + fig.update_xaxes(title_text=labels[col_index], row=row, col=col) + if col_index == 0 and row_index > 0: + fig.update_yaxes(title_text=labels[row_index], row=row, col=col) + + fig.update_layout( + title='Posterior pair plot', + bargap=0.05, + ) + return fig def _build_param_distribution_plot( self, param: object, ) -> object | None: - """Build an ArviZ posterior distribution plot for one parameter. + """Build a Plotly posterior distribution plot for one parameter. Parameters ---------- @@ -936,11 +1000,11 @@ def _build_param_distribution_plot( Returns ------- object | None - ArviZ plot object, or ``None`` when posterior plotting is + Plotly figure, or ``None`` when posterior plotting is unavailable. """ - inference_data, fit_results = self._get_posterior_inference_data() - if inference_data is None or fit_results is None: + posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() + if posterior_samples is None or fit_results is None: return None parameter_names = self._resolve_posterior_parameter_names( @@ -950,17 +1014,64 @@ def _build_param_distribution_plot( if parameter_names is None: return None - import arviz as az + go = __import__('plotly.graph_objects', fromlist=['Figure', 'Histogram']) + + parameter_name = parameter_names[0] + samples = self._selected_posterior_samples(posterior_samples, [parameter_name]) + if samples is None: + return None + values = samples[:, 0] + label = self._posterior_plot_labels(fit_results, [parameter_name])[0] + summary = self._posterior_summary_by_name(fit_results).get(parameter_name) + + fig = go.Figure() + if summary is not None: + fig.add_vrect( + x0=summary.interval_95[0], + x1=summary.interval_95[1], + fillcolor='rgba(99, 110, 250, 0.08)', + line_width=0, + ) + fig.add_vrect( + x0=summary.interval_68[0], + x1=summary.interval_68[1], + fillcolor='rgba(99, 110, 250, 0.18)', + line_width=0, + ) + + fig.add_trace( + go.Histogram( + x=values, + nbinsx=50, + histnorm='probability density', + marker={'color': 'rgb(99, 110, 250)'}, + opacity=0.85, + name='Posterior samples', + ) + ) + + median = float(np.median(values)) + fig.add_vline( + x=median, + line={'color': 'rgb(99, 110, 250)', 'width': 2}, + annotation_text='median', + annotation_position='top', + ) + if summary is not None: + fig.add_vline( + x=summary.map_value, + line={'color': 'rgb(214, 39, 40)', 'width': 2, 'dash': 'dash'}, + annotation_text='MAP', + annotation_position='top right', + ) - plot = az.plot_dist( - inference_data, - var_names=parameter_names, - backend='plotly', - point_estimate='median', + fig.update_layout( + title=f'Posterior distribution: {label}', + xaxis_title=label, + yaxis_title='Probability density', + bargap=0.05, ) - if hasattr(plot, 'add_title'): - plot.add_title(f'Posterior distribution: {parameter_names[0]}') - return plot + return fig def _get_or_build_posterior_predictive_summary( self, @@ -1165,6 +1276,25 @@ def _get_posterior_inference_data( return posterior_samples.to_arviz(), fit_results + def _get_posterior_samples_and_fit_results( + self, + ) -> tuple[object | None, object | None]: + """Return posterior samples and fit results for plotting.""" + if self.engine != PlotterEngineEnum.PLOTLY.value: + log.warning('Posterior plots currently require the Plotly plotting backend.') + return None, None + + fit_results = self._get_fit_result_for_correlation() + if fit_results is None: + return None, None + + posterior_samples = getattr(fit_results, 'posterior_samples', None) + if posterior_samples is None: + log.warning('Posterior samples are unavailable. Run a Bayesian fit first.') + return None, None + + return posterior_samples, fit_results + def _plot_posterior_predictive_band( self, *, @@ -1174,7 +1304,7 @@ def _plot_posterior_predictive_band( axes_labels: list[str], ) -> None: """Render a posterior predictive band plot using Plotly.""" - import plotly.graph_objects as go + go = __import__('plotly.graph_objects', fromlist=['Figure', 'Scatter']) fig = go.Figure() fig.add_trace( @@ -1233,7 +1363,7 @@ def _plot_posterior_predictive_draws( axes_labels: list[str], ) -> None: """Render posterior predictive draws using Plotly.""" - import plotly.graph_objects as go + go = __import__('plotly.graph_objects', fromlist=['Figure', 'Scatter']) fig = go.Figure() draws = getattr(summary, 'draws', None) @@ -1317,6 +1447,72 @@ def _resolve_posterior_parameter_names( return None return [str(name) for name in requested_names if name is not None] + @staticmethod + def _selected_posterior_samples( + posterior_samples: object, + parameter_names: list[str], + ) -> np.ndarray | None: + """Return flattened posterior samples in the selected order.""" + available_names = getattr(posterior_samples, 'parameter_names', None) + if not available_names: + return None + + name_to_index = {name: index for index, name in enumerate(available_names)} + try: + indices = [name_to_index[name] for name in parameter_names] + except KeyError: + return None + + flattened = np.asarray(posterior_samples.flattened(), dtype=float) + if flattened.ndim != 2: + return None + return flattened[:, indices] + + @staticmethod + def _thin_posterior_samples( + samples: np.ndarray, + *, + max_points: int = 4000, + ) -> np.ndarray: + """Downsample posterior samples for interactive plotting.""" + if samples.shape[0] <= max_points: + return samples + + indices = np.linspace(0, samples.shape[0] - 1, num=max_points, dtype=int) + return samples[indices] + + @staticmethod + def _posterior_plot_labels( + fit_results: object, + parameter_names: list[str], + ) -> list[str]: + """Return readable posterior plot labels for selected parameters.""" + parameters_by_name = { + getattr(parameter, 'unique_name', ''): parameter for parameter in fit_results.parameters + } + labels: list[str] = [] + for parameter_name in parameter_names: + parameter = parameters_by_name.get(parameter_name) + if parameter is None: + labels.append(parameter_name) + continue + + entry_name = getattr(getattr(parameter, '_identity', None), 'category_entry_name', '') + short_name = getattr(parameter, 'name', parameter_name) + if entry_name: + labels.append(f'{entry_name} {short_name}') + else: + labels.append(short_name) + return labels + + @staticmethod + def _posterior_summary_by_name( + fit_results: object, + ) -> dict[str, object]: + """Return posterior summaries keyed by unique parameter name.""" + summaries = getattr(fit_results, 'posterior_parameter_summaries', []) + return {summary.unique_name: summary for summary in summaries} + def _get_fit_result_for_correlation( self, ) -> object | None: From d17fc0d632ca2432b83f2a6406216d572a639928 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 01:16:00 +0200 Subject: [PATCH 015/106] Fix DREAM sampler progress reporting --- .../analysis/fit_helpers/tracking.py | 9 +++++++- .../analysis/minimizers/bumps_dream.py | 23 ++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py index 97aeeec9..f9789b88 100644 --- a/src/easydiffraction/analysis/fit_helpers/tracking.py +++ b/src/easydiffraction/analysis/fit_helpers/tracking.py @@ -31,7 +31,7 @@ SIGNIFICANT_CHANGE_THRESHOLD = 0.01 # 1% threshold SAMPLER_PROGRESS_UPDATE_SECONDS = 5.0 SAMPLER_PROGRESS_STATUS = 'sampling...' -DEFAULT_HEADERS = ['iteration', 'χ²', 'improvement [%]'] +DEFAULT_HEADERS = ['iteration', 'χ²', 'change / status'] DEFAULT_ALIGNMENTS = ['center', 'center', 'center'] @@ -99,6 +99,7 @@ def __init__(self) -> None: self._previous_chi2: float | None = None self._last_chi2: float | None = None self._last_iteration: int | None = None + self._last_reported_iteration: int | None = None self._best_chi2: float | None = None self._best_iteration: int | None = None self._fitting_time: float | None = None @@ -115,6 +116,7 @@ def reset(self) -> None: self._previous_chi2 = None self._last_chi2 = None self._last_iteration = None + self._last_reported_iteration = None self._best_chi2 = None self._best_iteration = None self._fitting_time = None @@ -242,8 +244,11 @@ def track_sampler_progress( self._previous_chi2 = reduced_chi2 self._last_progress_time = elapsed_time elif ( + iteration != self._last_reported_iteration + and ( self._last_progress_time is None or elapsed_time - self._last_progress_time >= SAMPLER_PROGRESS_UPDATE_SECONDS + ) ): row = [ str(iteration), @@ -325,6 +330,8 @@ def add_tracking_info(self, row: list[str]) -> None: row : list[str] Columns corresponding to DEFAULT_HEADERS. """ + if row and row[0].isdigit(): + self._last_reported_iteration = int(row[0]) self._df_rows.append(row) if self._verbosity is not VerbosityEnum.FULL: return diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 9f2ade75..0f1cf08c 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -45,12 +45,14 @@ def __init__( tracker: object, n_points: int, n_parameters: int, - n_chains: int, + total_generations: int, + burn_steps: int, ) -> None: self._tracker = tracker self._n_points = n_points self._n_parameters = n_parameters - self._n_chains = max(1, n_chains) + self._total_generations = max(1, total_generations) + self._burn_steps = max(0, burn_steps) def config_history(self, history: object) -> None: """Declare the history fields needed for progress updates.""" @@ -59,12 +61,13 @@ def config_history(self, history: object) -> None: def __call__(self, history: object) -> None: """Forward sampler progress to the shared fit tracker.""" step = int(history.step[0]) if history.step else 0 - generation = max(1, step // self._n_chains) + generation = max(1, step) reduced_chi2 = self._reduced_chi_square_from_nllf(float(history.value[0])) self._tracker.track_sampler_progress( iteration=generation, reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), + status=self._status_text(generation), ) def final(self, history: object, best: dict[str, object]) -> None: @@ -72,7 +75,7 @@ def final(self, history: object, best: dict[str, object]) -> None: if not history.time or best.get('value') is None: return step = int(history.step[0]) if history.step else 0 - generation = max(1, step // self._n_chains) + generation = max(1, step) reduced_chi2 = self._reduced_chi_square_from_nllf(float(best['value'])) self._tracker.track_sampler_progress( iteration=generation, @@ -81,6 +84,13 @@ def final(self, history: object, best: dict[str, object]) -> None: status='', ) + def _status_text(self, generation: int) -> str: + """Return a human-readable DREAM progress string.""" + clamped_generation = min(generation, self._total_generations) + progress = 100.0 * clamped_generation / self._total_generations + phase = 'burn-in' if clamped_generation <= self._burn_steps else 'sampling' + return f'{phase} {progress:.1f}% ({clamped_generation}/{self._total_generations})' + def _reduced_chi_square_from_nllf(self, nllf: float) -> float: """Convert DREAM's negative log-likelihood to reduced chi-square.""" dof = self._n_points - self._n_parameters @@ -189,12 +199,13 @@ def _run_solver( proposed_burn = max(DEFAULT_MIN_BURN, int(self.max_iterations * DEFAULT_BURN_FRACTION)) burn = min(proposed_burn, max(self.max_iterations - 1, 0)) samples = self.max_iterations * DEFAULT_POP * len(bumps_params) - n_chains = DEFAULT_POP * len(bumps_params) + total_generations = int(self.max_iterations + burn + 1) progress_monitor = _DreamProgressMonitor( tracker=self.tracker, n_points=fitness.numpoints(), n_parameters=len(bumps_params), - n_chains=n_chains, + total_generations=total_generations, + burn_steps=int(burn), ) driver = FitDriver( fitclass=fitclass, From a33f65750d4f731b9767d7aa9382aa46e8507f2b Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 01:29:24 +0200 Subject: [PATCH 016/106] Fix posterior pair plot axis sharing --- src/easydiffraction/display/plotting.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index bb0ecb4b..3c4567b2 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -924,7 +924,6 @@ def _build_posterior_pairs_plot( rows=n_parameters, cols=n_parameters, shared_xaxes='columns', - shared_yaxes='rows', horizontal_spacing=0.03, vertical_spacing=0.03, ) From 55adea8846d047381b1db5d73ab76b8c7232ff3d Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 01:45:07 +0200 Subject: [PATCH 017/106] Improve Bayesian demo parameter choices --- tmp/bumps_dream/ed-2-bayesian-new-API.py | 207 +++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 tmp/bumps_dream/ed-2-bayesian-new-API.py diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py new file mode 100644 index 00000000..680a2302 --- /dev/null +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -0,0 +1,207 @@ +# %% [markdown] +# # Structure Refinement: LBCO, HRPT +# +# This minimalistic example is designed to show how Rietveld refinement +# can be performed when both the crystal structure and experiment are +# defined directly in code. Only the experimentally measured data is +# loaded from an external file. It also shows how to switch calculation +# engine. +# +# For this example, constant-wavelength neutron powder diffraction data +# for La0.5Ba0.5CoO3 from HRPT at PSI is used. +# +# It does not contain any advanced features or options, and includes no +# comments or explanations β€” these can be found in the other tutorials. +# Default values are used for all parameters if not specified. Only +# essential and self-explanatory code is provided. +# +# The example is intended for users who are already familiar with the +# EasyDiffraction library and want to quickly get started with a simple +# refinement. It is also useful for those who want to see what a +# refinement might look like in code. For a more detailed explanation of +# the code, please refer to the other tutorials. + +# %% [markdown] +# ## Import Library + +# %% +import easydiffraction as ed + +# %% [markdown] +# ## Step 1: Define Project + +# %% +project = ed.Project() + +# %% [markdown] +# ## Step 2: Define Structure + +# %% +project.structures.create(name='lbco') + +# %% +structure = project.structures['lbco'] + +# %% +structure.space_group.name_h_m = 'P m -3 m' +structure.space_group.it_coordinate_system_code = '1' + +# %% +structure.cell.length_a = 3.8909 + +# %% +structure.atom_sites.create( + label='La', + type_symbol='La', + fract_x=0, + fract_y=0, + fract_z=0, + wyckoff_letter='a', + adp_type='Biso', + adp_iso=0.5, + occupancy=0.5, +) +structure.atom_sites.create( + label='Ba', + type_symbol='Ba', + fract_x=0, + fract_y=0, + fract_z=0, + wyckoff_letter='a', + adp_type='Biso', + adp_iso=0.5, + occupancy=0.5, +) +structure.atom_sites.create( + label='Co', + type_symbol='Co', + fract_x=0.5, + fract_y=0.5, + fract_z=0.5, + wyckoff_letter='b', + adp_type='Biso', + adp_iso=0.5, +) +structure.atom_sites.create( + label='O', + type_symbol='O', + fract_x=0, + fract_y=0.5, + fract_z=0.5, + wyckoff_letter='c', + adp_type='Biso', + adp_iso=0.5, +) + +# %% [markdown] +# ## Step 3: Define Experiment + +# %% +data_path = ed.download_data(id=3, destination='data') + +# %% +project.experiments.add_from_data_path( + name='hrpt', + data_path=data_path, + sample_form='powder', + beam_mode='constant wavelength', + radiation_probe='neutron', +) + +# %% +experiment = project.experiments['hrpt'] + +# %% +experiment.instrument.setup_wavelength = 1.494 +experiment.instrument.calib_twotheta_offset = 0.6226 + +# %% +experiment.peak.broad_gauss_u = 0.0816 +experiment.peak.broad_gauss_v = -0.1159 +experiment.peak.broad_gauss_w = 0.1204 +experiment.peak.broad_lorentz_y = 0.0844 + +# %% +experiment.background.create(id='1', x=10, y=168.5585) +experiment.background.create(id='2', x=30, y=164.3357) +experiment.background.create(id='3', x=50, y=166.8881) +experiment.background.create(id='4', x=110, y=175.4006) +experiment.background.create(id='5', x=165, y=174.2813) + +# %% +experiment.excluded_regions.create(id='1', start=0, end=20) +experiment.excluded_regions.create(id='2', start=160, end=180) + +# %% +experiment.linked_phases.create(id='lbco', scale=9.1351) + +# %% [markdown] +# ## Step 4: Perform Analysis + +# %% +structure.cell.length_a.free = True +experiment.peak.broad_gauss_w.free = True +experiment.linked_phases['lbco'].scale.free = True + +# %% +project.analysis.fit.show_minimizer_types() +project.analysis.fit.minimizer_type = 'bumps (lm)' + +# %% +project.analysis.fit() + +# %% +project.analysis.display.fit_results() + +# %% +project.display.plotter.plot_param_correlations() + +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') + +# %% [markdown] +# ## Step 5: Perform Bayesian Analysis + +# %% +length_a = structure.cell.length_a.value +structure.cell.length_a.fit_min = length_a - 0.01 +structure.cell.length_a.fit_max = length_a + 0.01 + +scale = experiment.linked_phases['lbco'].scale.value +experiment.linked_phases['lbco'].scale.fit_min = scale * 0.8 +experiment.linked_phases['lbco'].scale.fit_max = scale * 1.2 + +broad_gauss_w = experiment.peak.broad_gauss_w.value +experiment.peak.broad_gauss_w.fit_min = max(0.001, broad_gauss_w * 0.5) +experiment.peak.broad_gauss_w.fit_max = broad_gauss_w * 1.5 + +# %% +project.analysis.display.free_params() + +# %% +project.analysis.fit.show_minimizer_types() +project.analysis.fit.minimizer_type = 'bumps (dream)' + +# %% +project.analysis.fit() + +# %% +project.analysis.display.fit_results() + +# %% +project.display.plotter.plot_param_correlations() + +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') + +# %% +project.display.plotter.plot_posterior_pairs() + +# %% +project.display.plotter.plot_param_distribution(structure.cell.length_a) +project.display.plotter.plot_param_distribution(experiment.linked_phases['lbco'].scale) +project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_w) + +# %% +project.display.plotter.plot_posterior_predictive(expt_name='hrpt', style='band') +project.display.plotter.plot_posterior_predictive(expt_name='hrpt', style='draws') From 4c07c18b9b002d4134ba8194302687e1f4c6c095 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 01:47:41 +0200 Subject: [PATCH 018/106] Expose DREAM sampler settings --- .../analysis/minimizers/bumps_dream.py | 149 +++++++++++++++--- tmp/bumps_dream/ed-2-bayesian-new-API.py | 6 + 2 files changed, 131 insertions(+), 24 deletions(-) diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 0f1cf08c..147828fb 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -120,6 +120,48 @@ def __init__( method=method, max_iterations=max_iterations, ) + self._burn: int | None = None + self._thin: int = DEFAULT_THIN + self._pop: int = DEFAULT_POP + + @property + def steps(self) -> int: + """Number of DREAM generations retained after burn-in.""" + return self._validated_positive_integer('steps', self.max_iterations) + + @steps.setter + def steps(self, value: int) -> None: + self.max_iterations = self._validated_positive_integer('steps', value) + + @property + def burn(self) -> int | None: + """Explicit DREAM burn-in generations or ``None`` for auto.""" + return self._burn + + @burn.setter + def burn(self, value: int | None) -> None: + if value is None: + self._burn = None + return + self._burn = self._validated_non_negative_integer('burn', value) + + @property + def thin(self) -> int: + """DREAM thinning interval.""" + return self._thin + + @thin.setter + def thin(self, value: int) -> None: + self._thin = self._validated_positive_integer('thin', value) + + @property + def pop(self) -> int: + """DREAM population multiplier.""" + return self._pop + + @pop.setter + def pop(self, value: int) -> None: + self._pop = self._validated_positive_integer('pop', value) def _resolve_random_seed(self, random_seed: int | None) -> int: """Return a user-provided or generated random seed. @@ -166,6 +208,68 @@ def _prepare_solver_args( solver_args['starting_uncertainties'] = [parameter.uncertainty for parameter in parameters] return solver_args + @staticmethod + def _validated_positive_integer(name: str, value: int | float) -> int: + """Validate a DREAM setting that must be a positive integer.""" + if isinstance(value, bool): + msg = f"DREAM setting '{name}' must be a positive integer." + raise ValueError(msg) + + integer_value = int(value) + if integer_value != value or integer_value < 1: + msg = f"DREAM setting '{name}' must be a positive integer." + raise ValueError(msg) + return integer_value + + @staticmethod + def _validated_non_negative_integer(name: str, value: int | float) -> int: + """Validate a DREAM setting that must be a non-negative integer.""" + if isinstance(value, bool): + msg = f"DREAM setting '{name}' must be a non-negative integer." + raise ValueError(msg) + + integer_value = int(value) + if integer_value != value or integer_value < 0: + msg = f"DREAM setting '{name}' must be a non-negative integer." + raise ValueError(msg) + return integer_value + + def _resolved_burn(self, steps: int) -> int: + """Return the configured or automatic DREAM burn-in length.""" + if self.burn is None: + proposed_burn = max(DEFAULT_MIN_BURN, int(steps * DEFAULT_BURN_FRACTION)) + return min(proposed_burn, max(steps - 1, 0)) + + burn = self.burn + if burn >= steps: + msg = "DREAM setting 'burn' must be smaller than 'steps'." + raise ValueError(msg) + return burn + + def _sampler_settings( + self, + *, + random_seed: int, + steps: int, + burn: int, + thin: int, + pop: int, + n_parameters: int, + ) -> dict[str, object]: + """Build the sampler settings dictionary recorded in results.""" + samples = steps * pop * n_parameters + return { + 'random_seed': int(random_seed), + 'steps': int(steps), + 'burn': int(burn), + 'thin': int(thin), + 'pop': int(pop), + 'samples': int(samples), + 'alpha': float(DEFAULT_ALPHA), + 'outliers': DEFAULT_OUTLIER_TEST, + 'trim': DEFAULT_TRIM, + } + def _run_solver( self, objective_function: object, @@ -196,10 +300,19 @@ def _run_solver( problem = FitProblem(fitness) fitclass = next(cls for cls in FITTERS if cls.id == self.method) - proposed_burn = max(DEFAULT_MIN_BURN, int(self.max_iterations * DEFAULT_BURN_FRACTION)) - burn = min(proposed_burn, max(self.max_iterations - 1, 0)) - samples = self.max_iterations * DEFAULT_POP * len(bumps_params) - total_generations = int(self.max_iterations + burn + 1) + steps = self.steps + burn = self._resolved_burn(steps) + thin = self.thin + pop = self.pop + sampler_settings = self._sampler_settings( + random_seed=int(random_seed), + steps=steps, + burn=burn, + thin=thin, + pop=pop, + n_parameters=len(bumps_params), + ) + total_generations = int(steps + burn + 1) progress_monitor = _DreamProgressMonitor( tracker=self.tracker, n_points=fitness.numpoints(), @@ -211,11 +324,11 @@ def _run_solver( fitclass=fitclass, problem=problem, monitors=[progress_monitor], - steps=self.max_iterations, + steps=steps, burn=burn, - thin=DEFAULT_THIN, - pop=DEFAULT_POP, - samples=samples, + thin=thin, + pop=pop, + samples=sampler_settings['samples'], alpha=DEFAULT_ALPHA, outliers=DEFAULT_OUTLIER_TEST, trim=DEFAULT_TRIM, @@ -244,7 +357,7 @@ def _run_solver( posterior_samples=None, posterior_parameter_summaries=[], convergence_diagnostics={}, - sampler_settings={'random_seed': int(random_seed)}, + sampler_settings=sampler_settings, sampler_completed=False, raw_state=None, best_log_posterior=None, @@ -268,7 +381,7 @@ def _run_solver( posterior_samples=None, posterior_parameter_summaries=[], convergence_diagnostics={}, - sampler_settings={'random_seed': int(random_seed)}, + sampler_settings=sampler_settings, sampler_completed=False, raw_state=state, best_log_posterior=None, @@ -289,7 +402,7 @@ def _run_solver( posterior_samples=None, posterior_parameter_summaries=[], convergence_diagnostics={}, - sampler_settings={'random_seed': int(random_seed)}, + sampler_settings=sampler_settings, sampler_completed=True, raw_state=state, best_log_posterior=None, @@ -322,18 +435,6 @@ def _run_solver( posterior_parameter_summaries ) - sampler_settings = { - 'random_seed': int(random_seed), - 'steps': int(self.max_iterations), - 'burn': int(burn), - 'thin': int(DEFAULT_THIN), - 'pop': int(DEFAULT_POP), - 'samples': int(samples), - 'alpha': float(DEFAULT_ALPHA), - 'outliers': DEFAULT_OUTLIER_TEST, - 'trim': DEFAULT_TRIM, - } - if not convergence_diagnostics.get('converged', True): log.warning( 'DREAM sampling completed, but convergence diagnostics indicate ' @@ -436,6 +537,6 @@ def _build_fit_results( best_log_posterior=getattr(raw_result, 'best_log_posterior', None), ) fit_results.message = getattr(raw_result, 'message', '') - fit_results.iterations = int(self.max_iterations) + fit_results.iterations = int(fit_results.sampler_settings.get('steps', self.steps)) fit_results.result = raw_result return fit_results \ No newline at end of file diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index 680a2302..6c819a6f 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -182,6 +182,12 @@ project.analysis.fit.show_minimizer_types() project.analysis.fit.minimizer_type = 'bumps (dream)' +dream = project.analysis.fit.minimizer +dream.steps = 1000 +dream.burn = 200 +dream.thin = 1 +dream.pop = 4 + # %% project.analysis.fit() From c1d6e8399a3649cf4c44234454a3707c1d317ac8 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 07:23:52 +0200 Subject: [PATCH 019/106] Render posterior marginals as KDE curves --- src/easydiffraction/display/plotting.py | 191 +++++++++++++++++++++--- 1 file changed, 167 insertions(+), 24 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 3c4567b2..f63b5b7a 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -916,7 +916,7 @@ def _build_posterior_pairs_plot( samples = self._selected_posterior_samples(posterior_samples, parameter_names) if samples is None: return None - samples = self._thin_posterior_samples(samples) + samples = self._thin_posterior_samples(samples, max_points=1500) labels = self._posterior_plot_labels(fit_results, parameter_names) n_parameters = len(parameter_names) @@ -940,18 +940,27 @@ def _build_posterior_pairs_plot( x_values = samples[:, col_index] y_values = samples[:, row_index] if row_index == col_index: - fig.add_trace( - go.Histogram( - x=x_values, - nbinsx=40, - histnorm='probability density', - marker={'color': 'rgb(99, 110, 250)'}, - showlegend=False, - hovertemplate='%{x:.4f}
density=%{y:.4f}', - ), - row=row, - col=col, + density_trace = self._posterior_density_trace( + fit_results=fit_results, + parameter_name=parameter_names[col_index], + values=x_values, + trace_name=labels[col_index], ) + if density_trace is None: + fig.add_trace( + go.Histogram( + x=x_values, + nbinsx=40, + histnorm='probability density', + marker={'color': 'rgb(99, 110, 250)'}, + showlegend=False, + hovertemplate='%{x:.4f}
density=%{y:.4f}', + ), + row=row, + col=col, + ) + else: + fig.add_trace(density_trace, row=row, col=col) else: fig.add_trace( go.Scattergl( @@ -959,8 +968,8 @@ def _build_posterior_pairs_plot( y=y_values, mode='markers', marker={ - 'color': 'rgba(99, 110, 250, 0.18)', - 'size': 4, + 'color': 'rgba(99, 110, 250, 0.22)', + 'size': 3, }, showlegend=False, hovertemplate=( @@ -1038,16 +1047,25 @@ def _build_param_distribution_plot( line_width=0, ) - fig.add_trace( - go.Histogram( - x=values, - nbinsx=50, - histnorm='probability density', - marker={'color': 'rgb(99, 110, 250)'}, - opacity=0.85, - name='Posterior samples', - ) + density_trace = self._posterior_density_trace( + fit_results=fit_results, + parameter_name=parameter_name, + values=values, + trace_name='Posterior density', ) + if density_trace is None: + fig.add_trace( + go.Histogram( + x=values, + nbinsx=50, + histnorm='probability density', + marker={'color': 'rgb(99, 110, 250)'}, + opacity=0.85, + name='Posterior samples', + ) + ) + else: + fig.add_trace(density_trace) median = float(np.median(values)) fig.add_vline( @@ -1068,10 +1086,135 @@ def _build_param_distribution_plot( title=f'Posterior distribution: {label}', xaxis_title=label, yaxis_title='Probability density', - bargap=0.05, ) return fig + def _posterior_density_trace( + self, + *, + fit_results: object, + parameter_name: str, + values: np.ndarray, + trace_name: str, + ) -> object | None: + """Return a filled KDE trace for one posterior marginal.""" + go = __import__('plotly.graph_objects', fromlist=['Scatter']) + + lower_bound, upper_bound = self._posterior_parameter_bounds( + fit_results=fit_results, + parameter_name=parameter_name, + ) + density_curve = self._posterior_density_curve( + values, + lower_bound=lower_bound, + upper_bound=upper_bound, + ) + if density_curve is None: + return None + + grid, density = density_curve + return go.Scatter( + x=grid, + y=density, + mode='lines', + line={'color': 'rgb(99, 110, 250)', 'width': 2}, + fill='tozeroy', + fillcolor='rgba(99, 110, 250, 0.22)', + name=trace_name, + showlegend=False, + hovertemplate='%{x:.4f}
density=%{y:.4f}', + ) + + @staticmethod + def _posterior_parameter_bounds( + *, + fit_results: object, + parameter_name: str, + ) -> tuple[float | None, float | None]: + """Return finite fit bounds for a posterior parameter when available.""" + parameters_by_name = { + getattr(parameter, 'unique_name', ''): parameter for parameter in fit_results.parameters + } + parameter = parameters_by_name.get(parameter_name) + if parameter is None: + return None, None + + lower_bound = getattr(parameter, 'fit_min', None) + upper_bound = getattr(parameter, 'fit_max', None) + lower = ( + float(lower_bound) + if lower_bound is not None and np.isfinite(float(lower_bound)) + else None + ) + upper = ( + float(upper_bound) + if upper_bound is not None and np.isfinite(float(upper_bound)) + else None + ) + return lower, upper + + @classmethod + def _posterior_density_curve( + cls, + values: np.ndarray, + *, + lower_bound: float | None, + upper_bound: float | None, + grid_size: int = 256, + ) -> tuple[np.ndarray, np.ndarray] | None: + """Estimate a boundary-aware posterior density curve.""" + gaussian_kde = __import__('scipy.stats', fromlist=['gaussian_kde']).gaussian_kde + + data = np.asarray(values, dtype=float) + data = data[np.isfinite(data)] + if data.size < 2: + return None + + data_min = float(np.min(data)) + data_max = float(np.max(data)) + data_range = data_max - data_min + padding = 0.05 * data_range if data_range > 0 else max(abs(data_min), 1.0) * 0.05 + if padding == 0: + padding = 1e-6 + + grid_lower = lower_bound if lower_bound is not None else data_min - padding + grid_upper = upper_bound if upper_bound is not None else data_max + padding + if grid_upper <= grid_lower: + return None + + grid = np.linspace(grid_lower, grid_upper, num=grid_size) + if np.allclose(data, data[0]): + bandwidth = max(abs(data[0]) * 0.01, 1e-6) + density = np.exp(-0.5 * ((grid - data[0]) / bandwidth) ** 2) + density /= bandwidth * np.sqrt(2.0 * np.pi) + else: + reflected_data = cls._reflected_density_samples( + data, + lower_bound=lower_bound, + upper_bound=upper_bound, + ) + density = np.asarray(gaussian_kde(reflected_data)(grid), dtype=float) + + area = np.trapezoid(density, grid) + if area <= 0: + return None + return grid, density / area + + @staticmethod + def _reflected_density_samples( + values: np.ndarray, + *, + lower_bound: float | None, + upper_bound: float | None, + ) -> np.ndarray: + """Reflect posterior samples across finite bounds for KDE stability.""" + reflected = [values] + if lower_bound is not None: + reflected.append(2.0 * lower_bound - values) + if upper_bound is not None: + reflected.append(2.0 * upper_bound - values) + return np.concatenate(reflected) + def _get_or_build_posterior_predictive_summary( self, *, From 5ec9def96d648bd6a304ba81ac78d0f6af94b07e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 07:35:08 +0200 Subject: [PATCH 020/106] Add posterior pair density contours --- src/easydiffraction/display/plotting.py | 152 +++++++++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index f63b5b7a..c1075107 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -910,7 +910,10 @@ def _build_posterior_pairs_plot( log.warning('Posterior pair plots require at least two sampled parameters.') return None - go = __import__('plotly.graph_objects', fromlist=['Figure', 'Histogram', 'Scattergl']) + go = __import__( + 'plotly.graph_objects', + fromlist=['Figure', 'Histogram', 'Scattergl', 'Contour'], + ) make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots samples = self._selected_posterior_samples(posterior_samples, parameter_names) @@ -962,6 +965,15 @@ def _build_posterior_pairs_plot( else: fig.add_trace(density_trace, row=row, col=col) else: + contour_trace = self._posterior_contour_trace( + fit_results=fit_results, + x_parameter_name=parameter_names[col_index], + y_parameter_name=parameter_names[row_index], + x_values=x_values, + y_values=y_values, + ) + if contour_trace is not None: + fig.add_trace(contour_trace, row=row, col=col) fig.add_trace( go.Scattergl( x=x_values, @@ -994,6 +1006,52 @@ def _build_posterior_pairs_plot( ) return fig + def _posterior_contour_trace( + self, + *, + fit_results: object, + x_parameter_name: str, + y_parameter_name: str, + x_values: np.ndarray, + y_values: np.ndarray, + ) -> object | None: + """Return a 2D KDE contour trace for posterior pair plots.""" + go = __import__('plotly.graph_objects', fromlist=['Contour']) + + bounds = self._posterior_pair_bounds( + fit_results=fit_results, + x_parameter_name=x_parameter_name, + y_parameter_name=y_parameter_name, + x_values=x_values, + y_values=y_values, + ) + density_surface = self._posterior_pair_density_surface( + x_values=x_values, + y_values=y_values, + x_bounds=bounds[0], + y_bounds=bounds[1], + ) + if density_surface is None: + return None + + x_grid, y_grid, density = density_surface + return go.Contour( + x=x_grid, + y=y_grid, + z=density, + contours={ + 'coloring': 'none', + 'showlabels': False, + 'start': float(np.max(density) * 0.15), + 'end': float(np.max(density) * 0.95), + 'size': float(np.max(density) * 0.16), + }, + line={'color': 'rgba(99, 110, 250, 0.55)', 'width': 1.2}, + hoverinfo='skip', + showscale=False, + showlegend=False, + ) + def _build_param_distribution_plot( self, param: object, @@ -1153,6 +1211,51 @@ def _posterior_parameter_bounds( ) return lower, upper + @classmethod + def _posterior_pair_bounds( + cls, + *, + fit_results: object, + x_parameter_name: str, + y_parameter_name: str, + x_values: np.ndarray, + y_values: np.ndarray, + ) -> tuple[tuple[float, float], tuple[float, float]]: + """Return plotting bounds for a posterior pair panel.""" + x_lower, x_upper = cls._posterior_parameter_bounds( + fit_results=fit_results, + parameter_name=x_parameter_name, + ) + y_lower, y_upper = cls._posterior_parameter_bounds( + fit_results=fit_results, + parameter_name=y_parameter_name, + ) + return ( + cls._posterior_axis_bounds(x_values, lower_bound=x_lower, upper_bound=x_upper), + cls._posterior_axis_bounds(y_values, lower_bound=y_lower, upper_bound=y_upper), + ) + + @staticmethod + def _posterior_axis_bounds( + values: np.ndarray, + *, + lower_bound: float | None, + upper_bound: float | None, + ) -> tuple[float, float]: + """Return finite plotting bounds for one posterior axis.""" + data = np.asarray(values, dtype=float) + data = data[np.isfinite(data)] + data_min = float(np.min(data)) + data_max = float(np.max(data)) + data_range = data_max - data_min + padding = 0.05 * data_range if data_range > 0 else max(abs(data_min), 1.0) * 0.05 + if padding == 0: + padding = 1e-6 + + resolved_lower = lower_bound if lower_bound is not None else data_min - padding + resolved_upper = upper_bound if upper_bound is not None else data_max + padding + return float(resolved_lower), float(resolved_upper) + @classmethod def _posterior_density_curve( cls, @@ -1200,6 +1303,53 @@ def _posterior_density_curve( return None return grid, density / area + @classmethod + def _posterior_pair_density_surface( + cls, + *, + x_values: np.ndarray, + y_values: np.ndarray, + x_bounds: tuple[float, float], + y_bounds: tuple[float, float], + grid_size: int = 96, + ) -> tuple[np.ndarray, np.ndarray, np.ndarray] | None: + """Estimate a 2D KDE surface for a posterior pair panel.""" + gaussian_kde = __import__('scipy.stats', fromlist=['gaussian_kde']).gaussian_kde + + x_data = np.asarray(x_values, dtype=float) + y_data = np.asarray(y_values, dtype=float) + mask = np.isfinite(x_data) & np.isfinite(y_data) + x_data = x_data[mask] + y_data = y_data[mask] + if x_data.size < 2 or y_data.size < 2: + return None + + if np.allclose(x_data, x_data[0]) and np.allclose(y_data, y_data[0]): + return None + + reflected_x = cls._reflected_density_samples( + x_data, + lower_bound=x_bounds[0], + upper_bound=x_bounds[1], + ) + reflected_y = cls._reflected_density_samples( + y_data, + lower_bound=y_bounds[0], + upper_bound=y_bounds[1], + ) + if reflected_x.shape != reflected_y.shape: + return None + + x_grid = np.linspace(x_bounds[0], x_bounds[1], num=grid_size) + y_grid = np.linspace(y_bounds[0], y_bounds[1], num=grid_size) + mesh_x, mesh_y = np.meshgrid(x_grid, y_grid) + positions = np.vstack([mesh_x.ravel(), mesh_y.ravel()]) + density = gaussian_kde(np.vstack([reflected_x, reflected_y]))(positions) + density = np.asarray(density, dtype=float).reshape(mesh_x.shape) + if not np.any(np.isfinite(density)): + return None + return x_grid, y_grid, density + @staticmethod def _reflected_density_samples( values: np.ndarray, From 0f2731c1547469fbc9d9e0c0414a38981c85a1f7 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 07:38:17 +0200 Subject: [PATCH 021/106] Switch Bayesian demo to correlated pair --- tmp/bumps_dream/ed-2-bayesian-new-API.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index 6c819a6f..7c8dc20b 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -140,8 +140,7 @@ # %% structure.cell.length_a.free = True -experiment.peak.broad_gauss_w.free = True -experiment.linked_phases['lbco'].scale.free = True +experiment.instrument.calib_twotheta_offset.free = True # %% project.analysis.fit.show_minimizer_types() @@ -164,16 +163,16 @@ # %% length_a = structure.cell.length_a.value -structure.cell.length_a.fit_min = length_a - 0.01 -structure.cell.length_a.fit_max = length_a + 0.01 +length_a_sigma = structure.cell.length_a.uncertainty or 0.001 +length_a_window = max(8.0 * length_a_sigma, 0.001) +structure.cell.length_a.fit_min = length_a - length_a_window +structure.cell.length_a.fit_max = length_a + length_a_window -scale = experiment.linked_phases['lbco'].scale.value -experiment.linked_phases['lbco'].scale.fit_min = scale * 0.8 -experiment.linked_phases['lbco'].scale.fit_max = scale * 1.2 - -broad_gauss_w = experiment.peak.broad_gauss_w.value -experiment.peak.broad_gauss_w.fit_min = max(0.001, broad_gauss_w * 0.5) -experiment.peak.broad_gauss_w.fit_max = broad_gauss_w * 1.5 +twotheta_offset = experiment.instrument.calib_twotheta_offset.value +twotheta_offset_sigma = experiment.instrument.calib_twotheta_offset.uncertainty or 0.01 +twotheta_offset_window = max(8.0 * twotheta_offset_sigma, 0.01) +experiment.instrument.calib_twotheta_offset.fit_min = twotheta_offset - twotheta_offset_window +experiment.instrument.calib_twotheta_offset.fit_max = twotheta_offset + twotheta_offset_window # %% project.analysis.display.free_params() @@ -205,8 +204,7 @@ # %% project.display.plotter.plot_param_distribution(structure.cell.length_a) -project.display.plotter.plot_param_distribution(experiment.linked_phases['lbco'].scale) -project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_w) +project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) # %% project.display.plotter.plot_posterior_predictive(expt_name='hrpt', style='band') From c3ad035aa30026e5dd25e7d8315f290d43e7757e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 08:58:19 +0200 Subject: [PATCH 022/106] Add Bayesian tracking and posterior plot updates --- .../analysis/fit_helpers/tracking.py | 129 +++++--- .../analysis/minimizers/base.py | 6 +- .../analysis/minimizers/bumps_dream.py | 27 +- src/easydiffraction/display/plotting.py | 293 ++++++++++-------- 4 files changed, 275 insertions(+), 180 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py index f9789b88..68ce2543 100644 --- a/src/easydiffraction/analysis/fit_helpers/tracking.py +++ b/src/easydiffraction/analysis/fit_helpers/tracking.py @@ -30,9 +30,12 @@ SIGNIFICANT_CHANGE_THRESHOLD = 0.01 # 1% threshold SAMPLER_PROGRESS_UPDATE_SECONDS = 5.0 -SAMPLER_PROGRESS_STATUS = 'sampling...' +TRACKING_MODE_FIT = 'fit' +TRACKING_MODE_SAMPLER = 'sampling' DEFAULT_HEADERS = ['iteration', 'χ²', 'change / status'] DEFAULT_ALIGNMENTS = ['center', 'center', 'center'] +SAMPLER_HEADERS = ['iteration', 'progress', 'phase'] +SAMPLER_ALIGNMENTS = ['center', 'center', 'center'] class _TerminalLiveHandle: @@ -105,6 +108,10 @@ def __init__(self) -> None: self._fitting_time: float | None = None self._verbosity: VerbosityEnum = VerbosityEnum.FULL self._last_progress_time: float | None = None + self._tracking_mode: str = TRACKING_MODE_FIT + self._sampler_total_iterations: int | None = None + self._last_sampler_phase: str | None = None + self._last_sampler_progress_percent: float | None = None self._df_rows: list[list[str]] = [] self._display_handle: object | None = None @@ -121,6 +128,10 @@ def reset(self) -> None: self._best_iteration = None self._fitting_time = None self._last_progress_time = None + self._tracking_mode = TRACKING_MODE_FIT + self._sampler_total_iterations = None + self._last_sampler_phase = None + self._last_sampler_progress_percent = None def track( self, @@ -195,9 +206,11 @@ def track_sampler_progress( self, *, iteration: int, + total_iterations: int, + phase: str, + progress_percent: float, reduced_chi2: float, elapsed_time: float, - status: str = SAMPLER_PROGRESS_STATUS, ) -> None: """Update progress from a sampler monitor. @@ -205,15 +218,26 @@ def track_sampler_progress( ---------- iteration : int Sampler iteration or generation index. + total_iterations : int + Total sampler generations configured for the run. + phase : str + Current sampler phase, e.g. ``'burn-in'`` or ``'sampling'``. + progress_percent : float + Completed fraction expressed in percent. reduced_chi2 : float Best reduced chi-square implied by the current best sample. elapsed_time : float Elapsed wall time in seconds. - status : str, default='sampling...' - Text shown for periodic progress rows without a chi-square - improvement. """ self._iteration = iteration + self._tracking_mode = TRACKING_MODE_SAMPLER + self._sampler_total_iterations = max(1, total_iterations) + + clamped_iteration = min(max(1, iteration), self._sampler_total_iterations) + clamped_progress = min(max(progress_percent, 0.0), 100.0) + previous_phase = self._last_sampler_phase + self._last_sampler_phase = phase + self._last_sampler_progress_percent = clamped_progress row: list[str] = [] if self._previous_chi2 is None or self._best_chi2 is None: @@ -222,38 +246,28 @@ def track_sampler_progress( self._best_iteration = iteration self._last_progress_time = elapsed_time row = [ - str(iteration), - f'{reduced_chi2:.2f}', - '', + f'{clamped_iteration}/{self._sampler_total_iterations}', + f'{clamped_progress:.1f}%', + phase, ] else: if reduced_chi2 < self._best_chi2: self._best_chi2 = reduced_chi2 self._best_iteration = iteration - change = 0.0 - if self._previous_chi2 > 0: - change = (self._previous_chi2 - reduced_chi2) / self._previous_chi2 - - if change > SIGNIFICANT_CHANGE_THRESHOLD: - row = [ - str(iteration), - f'{reduced_chi2:.2f}', - f'{change * 100:.1f}% ↓', - ] - self._previous_chi2 = reduced_chi2 - self._last_progress_time = elapsed_time - elif ( + if ( iteration != self._last_reported_iteration and ( - self._last_progress_time is None - or elapsed_time - self._last_progress_time >= SAMPLER_PROGRESS_UPDATE_SECONDS + previous_phase != phase + or self._last_progress_time is None + or elapsed_time - self._last_progress_time >= SAMPLER_PROGRESS_UPDATE_SECONDS + or clamped_iteration >= self._sampler_total_iterations ) ): row = [ - str(iteration), - f'{self._best_chi2:.2f}', - status, + f'{clamped_iteration}/{self._sampler_total_iterations}', + f'{clamped_progress:.1f}%', + phase, ] self._last_progress_time = elapsed_time @@ -292,7 +306,7 @@ def stop_timer(self) -> None: self._end_time = time.perf_counter() self._fitting_time = self._end_time - self._start_time - def start_tracking(self, minimizer_name: str) -> None: + def start_tracking(self, minimizer_name: str, *, mode: str = TRACKING_MODE_FIT) -> None: """ Initialize display and headers and announce the minimizer. @@ -300,14 +314,23 @@ def start_tracking(self, minimizer_name: str) -> None: ---------- minimizer_name : str Name of the minimizer used for the run. + mode : str, default='fit' + Tracking mode for the run. """ if self._verbosity is VerbosityEnum.SILENT: return if self._verbosity is VerbosityEnum.SHORT: return + self._tracking_mode = ( + TRACKING_MODE_SAMPLER if mode == TRACKING_MODE_SAMPLER else TRACKING_MODE_FIT + ) + console.print(f"πŸš€ Starting fit process with '{minimizer_name}'...") - console.print('πŸ“ˆ Goodness-of-fit (reduced χ²) change:') + if self._tracking_mode == TRACKING_MODE_SAMPLER: + console.print('πŸ“ˆ Bayesian sampling progress:') + else: + console.print('πŸ“ˆ Fit progress:') # Reset rows and create an environment-appropriate handle self._df_rows = [] @@ -315,8 +338,8 @@ def start_tracking(self, minimizer_name: str) -> None: # Initial empty table; subsequent updates will reuse the handle render_table( - columns_headers=DEFAULT_HEADERS, - columns_alignment=DEFAULT_ALIGNMENTS, + columns_headers=self._headers(), + columns_alignment=self._alignments(), columns_data=self._df_rows, display_handle=self._display_handle, ) @@ -328,25 +351,43 @@ def add_tracking_info(self, row: list[str]) -> None: Parameters ---------- row : list[str] - Columns corresponding to DEFAULT_HEADERS. + Columns corresponding to the active tracking headers. """ - if row and row[0].isdigit(): - self._last_reported_iteration = int(row[0]) + if row: + iteration_cell = row[0].split('/', maxsplit=1)[0] + if iteration_cell.isdigit(): + self._last_reported_iteration = int(iteration_cell) self._df_rows.append(row) if self._verbosity is not VerbosityEnum.FULL: return # Append and update via the active handle (Jupyter or # terminal live) render_table( - columns_headers=DEFAULT_HEADERS, - columns_alignment=DEFAULT_ALIGNMENTS, + columns_headers=self._headers(), + columns_alignment=self._alignments(), columns_data=self._df_rows, display_handle=self._display_handle, ) def finish_tracking(self) -> None: """Finalize progress display and print best result summary.""" - if self._last_iteration is not None: + if self._tracking_mode == TRACKING_MODE_SAMPLER: + if self._last_iteration is not None and self._sampler_total_iterations is not None: + final_progress = self._last_sampler_progress_percent + if final_progress is None: + final_progress = 100.0 * min( + self._last_iteration, + self._sampler_total_iterations, + ) / self._sampler_total_iterations + row = [ + f'{min(self._last_iteration, self._sampler_total_iterations)}/' + f'{self._sampler_total_iterations}', + f'{final_progress:.1f}%', + self._last_sampler_phase or 'sampling', + ] + if not self._df_rows or self._df_rows[-1] != row: + self.add_tracking_info(row) + elif self._last_iteration is not None: row: list[str] = [ str(self._last_iteration), f'{self._last_chi2:.2f}' if self._last_chi2 is not None else '', @@ -363,9 +404,25 @@ def finish_tracking(self) -> None: with suppress(Exception): self._display_handle.close() + if self._tracking_mode == TRACKING_MODE_SAMPLER: + console.print('βœ… Bayesian sampling complete.') + return + # Print best result console.print( f'πŸ† Best goodness-of-fit (reduced χ²) is {self._best_chi2:.2f} ' f'at iteration {self._best_iteration}' ) console.print('βœ… Fitting complete.') + + def _headers(self) -> list[str]: + """Return column headers for the active tracking mode.""" + if self._tracking_mode == TRACKING_MODE_SAMPLER: + return SAMPLER_HEADERS + return DEFAULT_HEADERS + + def _alignments(self) -> list[str]: + """Return column alignments for the active tracking mode.""" + if self._tracking_mode == TRACKING_MODE_SAMPLER: + return SAMPLER_ALIGNMENTS + return DEFAULT_ALIGNMENTS diff --git a/src/easydiffraction/analysis/minimizers/base.py b/src/easydiffraction/analysis/minimizers/base.py index 46da77c5..84d5371d 100644 --- a/src/easydiffraction/analysis/minimizers/base.py +++ b/src/easydiffraction/analysis/minimizers/base.py @@ -61,7 +61,7 @@ def _start_tracking( """ self.tracker.reset() self.tracker._verbosity = verbosity - self.tracker.start_tracking(minimizer_name) + self.tracker.start_tracking(minimizer_name, mode=self._tracking_mode()) self.tracker.start_timer() def _stop_tracking(self) -> None: @@ -69,6 +69,10 @@ def _stop_tracking(self) -> None: self.tracker.stop_timer() self.tracker.finish_tracking() + def _tracking_mode(self) -> str: + """Return the tracker mode for the current minimizer.""" + return 'fit' + @abstractmethod def _prepare_solver_args(self, parameters: list[Any]) -> dict[str, Any]: """ diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 147828fb..801ab385 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -65,9 +65,11 @@ def __call__(self, history: object) -> None: reduced_chi2 = self._reduced_chi_square_from_nllf(float(history.value[0])) self._tracker.track_sampler_progress( iteration=generation, + total_iterations=self._total_generations, + phase=self._phase_name(generation), + progress_percent=self._progress_percent(generation), reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), - status=self._status_text(generation), ) def final(self, history: object, best: dict[str, object]) -> None: @@ -79,17 +81,24 @@ def final(self, history: object, best: dict[str, object]) -> None: reduced_chi2 = self._reduced_chi_square_from_nllf(float(best['value'])) self._tracker.track_sampler_progress( iteration=generation, + total_iterations=self._total_generations, + phase=self._phase_name(generation), + progress_percent=self._progress_percent(generation), reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), - status='', ) - def _status_text(self, generation: int) -> str: - """Return a human-readable DREAM progress string.""" + def _phase_name(self, generation: int) -> str: + """Return the current sampler phase name.""" clamped_generation = min(generation, self._total_generations) - progress = 100.0 * clamped_generation / self._total_generations - phase = 'burn-in' if clamped_generation <= self._burn_steps else 'sampling' - return f'{phase} {progress:.1f}% ({clamped_generation}/{self._total_generations})' + if clamped_generation <= self._burn_steps: + return 'burn-in' + return 'sampling' + + def _progress_percent(self, generation: int) -> float: + """Return DREAM progress as a percentage.""" + clamped_generation = min(generation, self._total_generations) + return 100.0 * clamped_generation / self._total_generations def _reduced_chi_square_from_nllf(self, nllf: float) -> float: """Convert DREAM's negative log-likelihood to reduced chi-square.""" @@ -183,6 +192,10 @@ def _resolve_random_seed(self, random_seed: int | None) -> int: self._resolved_random_seed = int(random_seed) return self._resolved_random_seed + def _tracking_mode(self) -> str: + """Use sampler-style progress reporting for DREAM runs.""" + return 'sampling' + def _prepare_solver_args( self, parameters: list[object], diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index c1075107..4235f0c5 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -71,6 +71,13 @@ def description(self) -> str: DEFAULT_BRAGG_ROW = DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION DEFAULT_POSTERIOR_PREDICTIVE_DRAWS = 200 DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP = 50 +POSTERIOR_DENSITY_LINE_COLOR = 'rgb(99, 110, 250)' +POSTERIOR_DENSITY_FILL_COLOR = 'rgba(99, 110, 250, 0.22)' +POSTERIOR_MEDIAN_LINE_COLOR = 'rgb(140, 140, 140)' +POSTERIOR_POINT_ESTIMATE_LINE_COLOR = 'rgb(214, 39, 40)' +POSTERIOR_DRAW_LINE_COLOR = 'rgba(140, 140, 140, 0.18)' +POSTERIOR_SCATTER_MARKER_COLOR = 'rgba(140, 140, 140, 0.20)' +POSTERIOR_CONTOUR_LINE_COLOR = 'rgba(99, 110, 250, 0.50)' @dataclass(frozen=True) @@ -662,7 +669,7 @@ def plot_param_distribution( def plot_posterior_predictive( self, expt_name: str, - style: str = 'band', + style: str = 'band+draws', ) -> None: """Plot posterior predictive curves for a powder experiment. @@ -670,12 +677,13 @@ def plot_posterior_predictive( ---------- expt_name : str Experiment name to plot. - style : str, default='band' - Either ``'band'`` for a 95% credible interval or - ``'draws'`` for sampled predictive curves. + style : str, default='band+draws' + ``'band'`` shows the 95% credible interval, + ``'draws'`` shows sampled predictive curves, and + ``'band+draws'`` shows both together. """ - if style not in {'band', 'draws'}: - msg = "style must be either 'band' or 'draws'." + if style not in {'band', 'draws', 'band+draws'}: + msg = "style must be 'band', 'draws', or 'band+draws'." raise ValueError(msg) if self._project is None: @@ -707,20 +715,13 @@ def plot_posterior_predictive( return axes_labels = self._get_axes_labels(sample_form, scattering_type, x_axis) - if style == 'band': - self._plot_posterior_predictive_band( - expt_name=expt_name, - summary=summary, - y_meas=np.asarray(y_meas, dtype=float), - axes_labels=axes_labels, - ) - return - - self._plot_posterior_predictive_draws( + self._plot_posterior_predictive_summary( expt_name=expt_name, summary=summary, y_meas=np.asarray(y_meas, dtype=float), axes_labels=axes_labels, + show_band=style in {'band', 'band+draws'}, + show_draws=style in {'draws', 'band+draws'}, ) @staticmethod @@ -949,6 +950,7 @@ def _build_posterior_pairs_plot( values=x_values, trace_name=labels[col_index], ) + diagonal_y_axis_range = None if density_trace is None: fig.add_trace( go.Histogram( @@ -964,6 +966,11 @@ def _build_posterior_pairs_plot( ) else: fig.add_trace(density_trace, row=row, col=col) + diagonal_y_axis_range = self._posterior_density_axis_range( + np.asarray(density_trace.y) + ) + if diagonal_y_axis_range is not None: + fig.update_yaxes(range=list(diagonal_y_axis_range), row=row, col=col) else: contour_trace = self._posterior_contour_trace( fit_results=fit_results, @@ -980,7 +987,7 @@ def _build_posterior_pairs_plot( y=y_values, mode='markers', marker={ - 'color': 'rgba(99, 110, 250, 0.22)', + 'color': POSTERIOR_SCATTER_MARKER_COLOR, 'size': 3, }, showlegend=False, @@ -1040,13 +1047,20 @@ def _posterior_contour_trace( y=y_grid, z=density, contours={ - 'coloring': 'none', + 'coloring': 'fill', 'showlabels': False, 'start': float(np.max(density) * 0.15), 'end': float(np.max(density) * 0.95), 'size': float(np.max(density) * 0.16), }, - line={'color': 'rgba(99, 110, 250, 0.55)', 'width': 1.2}, + colorscale=[ + [0.0, 'rgba(99, 110, 250, 0.00)'], + [0.35, 'rgba(99, 110, 250, 0.00)'], + [0.60, 'rgba(99, 110, 250, 0.10)'], + [0.80, 'rgba(99, 110, 250, 0.18)'], + [1.0, 'rgba(99, 110, 250, 0.30)'], + ], + line={'color': POSTERIOR_CONTOUR_LINE_COLOR, 'width': 1.0}, hoverinfo='skip', showscale=False, showlegend=False, @@ -1111,40 +1125,62 @@ def _build_param_distribution_plot( values=values, trace_name='Posterior density', ) + y_axis_range = None if density_trace is None: + histogram_density, _ = np.histogram(values, bins=50, density=True) + y_axis_range = self._posterior_density_axis_range(histogram_density) fig.add_trace( go.Histogram( x=values, nbinsx=50, histnorm='probability density', - marker={'color': 'rgb(99, 110, 250)'}, + marker={'color': POSTERIOR_DENSITY_LINE_COLOR}, opacity=0.85, - name='Posterior samples', + name='Posterior density', ) ) else: + density_trace.name = 'Posterior density' + density_trace.showlegend = True fig.add_trace(density_trace) + y_axis_range = self._posterior_density_axis_range(np.asarray(density_trace.y)) median = float(np.median(values)) - fig.add_vline( - x=median, - line={'color': 'rgb(99, 110, 250)', 'width': 2}, - annotation_text='median', - annotation_position='top', - ) - if summary is not None: - fig.add_vline( - x=summary.map_value, - line={'color': 'rgb(214, 39, 40)', 'width': 2, 'dash': 'dash'}, - annotation_text='MAP', - annotation_position='top right', + if y_axis_range is not None: + fig.add_trace( + self._posterior_reference_line_trace( + x_value=median, + y_axis_range=y_axis_range, + trace_name='Median', + color=POSTERIOR_MEDIAN_LINE_COLOR, + dash='dash', + ) ) + if summary is not None: + fig.add_trace( + self._posterior_reference_line_trace( + x_value=summary.map_value, + y_axis_range=y_axis_range, + trace_name='Max posterior', + color=POSTERIOR_POINT_ESTIMATE_LINE_COLOR, + dash='dot', + ) + ) fig.update_layout( title=f'Posterior distribution: {label}', xaxis_title=label, yaxis_title='Probability density', + legend={ + 'bgcolor': 'rgba(0, 0, 0, 0)', + 'xanchor': 'right', + 'x': 1.0, + 'yanchor': 'top', + 'y': 1.0, + }, ) + if y_axis_range is not None: + fig.update_yaxes(range=list(y_axis_range)) return fig def _posterior_density_trace( @@ -1175,14 +1211,54 @@ def _posterior_density_trace( x=grid, y=density, mode='lines', - line={'color': 'rgb(99, 110, 250)', 'width': 2}, + line={'color': POSTERIOR_DENSITY_LINE_COLOR, 'width': 2}, fill='tozeroy', - fillcolor='rgba(99, 110, 250, 0.22)', + fillcolor=POSTERIOR_DENSITY_FILL_COLOR, name=trace_name, showlegend=False, hovertemplate='%{x:.4f}
density=%{y:.4f}', ) + @staticmethod + def _posterior_density_axis_range( + density_values: np.ndarray, + ) -> tuple[float, float] | None: + """Return a padded y-axis range for posterior density plots.""" + data = np.asarray(density_values, dtype=float) + data = data[np.isfinite(data)] + if data.size == 0: + return None + + data_min = float(np.min(data)) + data_max = float(np.max(data)) + data_range = data_max - data_min + padding = 0.08 * data_range if data_range > 0 else max(abs(data_max), 1.0) * 0.05 + if padding == 0: + padding = 1e-6 + return data_min - padding, data_max + padding + + @staticmethod + def _posterior_reference_line_trace( + *, + x_value: float, + y_axis_range: tuple[float, float], + trace_name: str, + color: str, + dash: str, + ) -> object: + """Return a named vertical reference line for posterior plots.""" + go = __import__('plotly.graph_objects', fromlist=['Scatter']) + + return go.Scatter( + x=[x_value, x_value], + y=[y_axis_range[0], y_axis_range[1]], + mode='lines', + line={'color': color, 'width': 2, 'dash': dash}, + name=trace_name, + showlegend=True, + hovertemplate=f'{trace_name}: %{{x:.4f}}', + ) + @staticmethod def _posterior_parameter_bounds( *, @@ -1587,104 +1663,77 @@ def _get_posterior_samples_and_fit_results( return posterior_samples, fit_results - def _plot_posterior_predictive_band( + def _plot_posterior_predictive_summary( self, *, expt_name: str, summary: object, y_meas: np.ndarray, axes_labels: list[str], + show_band: bool, + show_draws: bool, ) -> None: - """Render a posterior predictive band plot using Plotly.""" + """Render posterior predictive summaries using Plotly.""" go = __import__('plotly.graph_objects', fromlist=['Figure', 'Scatter']) fig = go.Figure() - fig.add_trace( - go.Scatter( - x=summary.x, - y=summary.lower_95, - mode='lines', - line={'color': 'rgba(0, 0, 0, 0)'}, - hoverinfo='skip', - showlegend=False, - ) - ) - fig.add_trace( - go.Scatter( - x=summary.x, - y=summary.upper_95, - mode='lines', - line={'color': 'rgba(0, 0, 0, 0)'}, - fill='tonexty', - fillcolor='rgba(214, 39, 40, 0.18)', - name='Posterior predictive 95% CI', - hoverinfo='skip', - ) - ) - fig.add_trace( - go.Scatter( - x=summary.x, - y=summary.map_prediction, - mode='lines', - line={'color': 'rgb(214, 39, 40)', 'width': 2}, - name='MAP prediction', - ) - ) - fig.add_trace( - go.Scatter( - x=summary.x, - y=y_meas, - mode='lines+markers', - line={'color': 'rgb(31, 119, 180)', 'width': 1.5}, - name='Measured', + if show_band: + fig.add_trace( + go.Scatter( + x=summary.x, + y=summary.lower_95, + mode='lines', + line={'color': 'rgba(0, 0, 0, 0)'}, + hoverinfo='skip', + showlegend=False, + ) ) - ) - fig.update_layout( - title=f"Posterior predictive for experiment πŸ”¬ '{expt_name}'", - xaxis_title=axes_labels[0], - yaxis_title=axes_labels[1], - ) - fig.show() - - def _plot_posterior_predictive_draws( - self, - *, - expt_name: str, - summary: object, - y_meas: np.ndarray, - axes_labels: list[str], - ) -> None: - """Render posterior predictive draws using Plotly.""" - go = __import__('plotly.graph_objects', fromlist=['Figure', 'Scatter']) - - fig = go.Figure() - draws = getattr(summary, 'draws', None) - if draws is None: - log.warning('Posterior predictive draws are unavailable for plotting.') - return - - draw_cap = min(len(draws), DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP) - for index in range(draw_cap): fig.add_trace( go.Scatter( x=summary.x, - y=draws[index], + y=summary.upper_95, mode='lines', - line={'color': 'rgba(120, 120, 120, 0.18)', 'width': 1}, - name='Posterior draw' if index == 0 else None, - showlegend=index == 0, + line={'color': 'rgba(0, 0, 0, 0)'}, + fill='tonexty', + fillcolor='rgba(214, 39, 40, 0.18)', + name='Posterior predictive 95% CI', + hoverinfo='skip', ) ) + if show_draws: + draws = getattr(summary, 'draws', None) + if draws is None: + log.warning('Posterior predictive draws are unavailable for plotting.') + return + + draw_cap = min(len(draws), DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP) + for index in range(draw_cap): + fig.add_trace( + go.Scatter( + x=summary.x, + y=draws[index], + mode='lines', + line={'color': POSTERIOR_DRAW_LINE_COLOR, 'width': 1}, + name='Posterior draw' if index == 0 else None, + showlegend=index == 0, + ) + ) + fig.add_trace( go.Scatter( x=summary.x, y=summary.map_prediction, mode='lines', - line={'color': 'rgb(214, 39, 40)', 'width': 2}, - name='MAP prediction', + line={'color': POSTERIOR_POINT_ESTIMATE_LINE_COLOR, 'width': 2}, + name='Max posterior prediction', ) ) + fig.update_layout( + title=f"Posterior predictive for experiment πŸ”¬ '{expt_name}'", + xaxis_title=axes_labels[0], + yaxis_title=axes_labels[1], + ) fig.add_trace( go.Scatter( x=summary.x, @@ -1694,11 +1743,6 @@ def _plot_posterior_predictive_draws( name='Measured', ) ) - fig.update_layout( - title=f"Posterior predictive draws for experiment πŸ”¬ '{expt_name}'", - xaxis_title=axes_labels[0], - yaxis_title=axes_labels[1], - ) fig.show() @staticmethod @@ -2352,27 +2396,6 @@ def _plot_powder_bragg_meas_vs_calc( x_max=ctx['x_max'], ) - predictive_summary = self._get_or_build_posterior_predictive_summary( - experiment=experiment, - expt_name=expt_name, - x_axis=ctx['x_axis'], - ) - predictive_lower_95 = None - predictive_upper_95 = None - if predictive_summary is not None: - predictive_lower_95 = self._filtered_y_array( - predictive_summary.lower_95, - predictive_summary.x, - ctx['x_min'], - ctx['x_max'], - ) - predictive_upper_95 = self._filtered_y_array( - predictive_summary.upper_95, - predictive_summary.x, - ctx['x_min'], - ctx['x_max'], - ) - plot_spec = PowderMeasVsCalcSpec( x=ctx['x_filtered'], y_meas=series.y_meas, @@ -2385,8 +2408,6 @@ def _plot_powder_bragg_meas_vs_calc( bragg_peaks_height_fraction=DEFAULT_BRAGG_ROW, height=self._composite_plot_height(), y_bkg=series.y_bkg, - predictive_lower_95=predictive_lower_95, - predictive_upper_95=predictive_upper_95, ) self._backend.plot_powder_meas_vs_calc(plot_spec=plot_spec) From 6eb6725af44a7970f5d061d98c4e23999f8862da Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 09:01:46 +0200 Subject: [PATCH 023/106] Add posterior draws and log-posterior tracking --- .../analysis/fit_helpers/bayesian.py | 14 +- .../analysis/fit_helpers/tracking.py | 37 +++- .../analysis/minimizers/bumps_dream.py | 8 +- src/easydiffraction/display/plotters/base.py | 2 + .../display/plotters/plotly.py | 85 +++++++-- src/easydiffraction/display/plotting.py | 164 ++++++++++++++++-- tmp/bumps_dream/ed-2-bayesian-new-API.py | 19 +- 7 files changed, 282 insertions(+), 47 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 62d6cab3..2da05935 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -298,7 +298,9 @@ def display_results( if self.message: console.print(f'ℹ️ Status: {self.message}') console.print(f'πŸ§ͺ Sampler: {self.sampler_name}') - console.print(f'🎯 Committed point estimate: {self.point_estimate_name}') + console.print( + f'🎯 Committed point estimate: {_format_point_estimate_name(self.point_estimate_name)}' + ) console.print(f'πŸ” Sampler completed: {self.sampler_completed}') console.print(f'⏱️ Fitting time: {_format_optional_float(self.fitting_time, suffix=" seconds")}') console.print( @@ -494,6 +496,14 @@ def _format_sampler_settings(sampler_settings: dict[str, object]) -> str | None: return ', '.join(parts) if parts else None +def _format_point_estimate_name(point_estimate_name: str) -> str: + """Return a user-facing label for the committed point estimate.""" + normalized_name = point_estimate_name.strip().lower().replace('_', ' ') + if normalized_name == 'map': + return 'Max posterior' + return point_estimate_name.replace('_', ' ').title() + + def _format_convergence_summary(convergence_diagnostics: dict[str, object]) -> str | None: if not convergence_diagnostics: return None @@ -527,7 +537,7 @@ def _render_committed_parameter_table(parameters: list[object]) -> None: 'entry', 'parameter', 'start', - 'map', + 'max posterior', 'uncertainty', 'units', 'change', diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py index 68ce2543..24d7ad5d 100644 --- a/src/easydiffraction/analysis/fit_helpers/tracking.py +++ b/src/easydiffraction/analysis/fit_helpers/tracking.py @@ -34,8 +34,8 @@ TRACKING_MODE_SAMPLER = 'sampling' DEFAULT_HEADERS = ['iteration', 'χ²', 'change / status'] DEFAULT_ALIGNMENTS = ['center', 'center', 'center'] -SAMPLER_HEADERS = ['iteration', 'progress', 'phase'] -SAMPLER_ALIGNMENTS = ['center', 'center', 'center'] +SAMPLER_HEADERS = ['iteration', 'progress', 'log posterior', 'phase'] +SAMPLER_ALIGNMENTS = ['center', 'center', 'center', 'center'] class _TerminalLiveHandle: @@ -112,6 +112,7 @@ def __init__(self) -> None: self._sampler_total_iterations: int | None = None self._last_sampler_phase: str | None = None self._last_sampler_progress_percent: float | None = None + self._last_sampler_log_posterior: float | None = None self._df_rows: list[list[str]] = [] self._display_handle: object | None = None @@ -132,6 +133,7 @@ def reset(self) -> None: self._sampler_total_iterations = None self._last_sampler_phase = None self._last_sampler_progress_percent = None + self._last_sampler_log_posterior = None def track( self, @@ -157,6 +159,16 @@ def track( reduced_chi2 = calculate_reduced_chi_square(residuals, len(parameters)) + if self._tracking_mode == TRACKING_MODE_SAMPLER: + if self._previous_chi2 is None: + self._previous_chi2 = reduced_chi2 + self._best_chi2 = reduced_chi2 + elif self._best_chi2 is None or reduced_chi2 < self._best_chi2: + self._best_chi2 = reduced_chi2 + + self._last_chi2 = reduced_chi2 + return residuals + row: list[str] = [] # First iteration, initialize tracking @@ -192,7 +204,7 @@ def track( self.add_tracking_info(row) # Update best chi-square if better - if reduced_chi2 < self._best_chi2: + if self._best_chi2 is None or reduced_chi2 < self._best_chi2: self._best_chi2 = reduced_chi2 self._best_iteration = self._iteration @@ -209,6 +221,7 @@ def track_sampler_progress( total_iterations: int, phase: str, progress_percent: float, + log_posterior: float, reduced_chi2: float, elapsed_time: float, ) -> None: @@ -224,6 +237,8 @@ def track_sampler_progress( Current sampler phase, e.g. ``'burn-in'`` or ``'sampling'``. progress_percent : float Completed fraction expressed in percent. + log_posterior : float + Current best log-posterior implied by the sampler state. reduced_chi2 : float Best reduced chi-square implied by the current best sample. elapsed_time : float @@ -238,6 +253,7 @@ def track_sampler_progress( previous_phase = self._last_sampler_phase self._last_sampler_phase = phase self._last_sampler_progress_percent = clamped_progress + self._last_sampler_log_posterior = log_posterior row: list[str] = [] if self._previous_chi2 is None or self._best_chi2 is None: @@ -248,6 +264,7 @@ def track_sampler_progress( row = [ f'{clamped_iteration}/{self._sampler_total_iterations}', f'{clamped_progress:.1f}%', + f'{log_posterior:.2f}', phase, ] else: @@ -267,6 +284,7 @@ def track_sampler_progress( row = [ f'{clamped_iteration}/{self._sampler_total_iterations}', f'{clamped_progress:.1f}%', + f'{log_posterior:.2f}', phase, ] self._last_progress_time = elapsed_time @@ -317,15 +335,15 @@ def start_tracking(self, minimizer_name: str, *, mode: str = TRACKING_MODE_FIT) mode : str, default='fit' Tracking mode for the run. """ + self._tracking_mode = ( + TRACKING_MODE_SAMPLER if mode == TRACKING_MODE_SAMPLER else TRACKING_MODE_FIT + ) + if self._verbosity is VerbosityEnum.SILENT: return if self._verbosity is VerbosityEnum.SHORT: return - self._tracking_mode = ( - TRACKING_MODE_SAMPLER if mode == TRACKING_MODE_SAMPLER else TRACKING_MODE_FIT - ) - console.print(f"πŸš€ Starting fit process with '{minimizer_name}'...") if self._tracking_mode == TRACKING_MODE_SAMPLER: console.print('πŸ“ˆ Bayesian sampling progress:') @@ -383,6 +401,11 @@ def finish_tracking(self) -> None: f'{min(self._last_iteration, self._sampler_total_iterations)}/' f'{self._sampler_total_iterations}', f'{final_progress:.1f}%', + ( + f'{self._last_sampler_log_posterior:.2f}' + if self._last_sampler_log_posterior is not None + else '' + ), self._last_sampler_phase or 'sampling', ] if not self._df_rows or self._df_rows[-1] != row: diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 801ab385..68fd3264 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -62,12 +62,14 @@ def __call__(self, history: object) -> None: """Forward sampler progress to the shared fit tracker.""" step = int(history.step[0]) if history.step else 0 generation = max(1, step) - reduced_chi2 = self._reduced_chi_square_from_nllf(float(history.value[0])) + nllf = float(history.value[0]) + reduced_chi2 = self._reduced_chi_square_from_nllf(nllf) self._tracker.track_sampler_progress( iteration=generation, total_iterations=self._total_generations, phase=self._phase_name(generation), progress_percent=self._progress_percent(generation), + log_posterior=-nllf, reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), ) @@ -78,12 +80,14 @@ def final(self, history: object, best: dict[str, object]) -> None: return step = int(history.step[0]) if history.step else 0 generation = max(1, step) - reduced_chi2 = self._reduced_chi_square_from_nllf(float(best['value'])) + best_nllf = float(best['value']) + reduced_chi2 = self._reduced_chi_square_from_nllf(best_nllf) self._tracker.track_sampler_progress( iteration=generation, total_iterations=self._total_generations, phase=self._phase_name(generation), progress_percent=self._progress_percent(generation), + log_posterior=-best_nllf, reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), ) diff --git a/src/easydiffraction/display/plotters/base.py b/src/easydiffraction/display/plotters/base.py index 85d09434..6f041161 100644 --- a/src/easydiffraction/display/plotters/base.py +++ b/src/easydiffraction/display/plotters/base.py @@ -62,6 +62,8 @@ class PowderMeasVsCalcSpec: y_bkg: np.ndarray | None = None predictive_lower_95: np.ndarray | None = None predictive_upper_95: np.ndarray | None = None + predictive_draws: np.ndarray | None = None + y_calc_name: str | None = None class XAxisType(StrEnum): diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 59bab8db..15e1ac11 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -67,6 +67,8 @@ COMPOSITE_MARGIN_BOTTOM = 45 PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.26)' PREDICTIVE_BAND_EDGE_COLOR = 'rgba(214, 39, 40, 0.45)' +PREDICTIVE_DRAW_COLOR = 'rgba(140, 140, 140, 0.18)' +PREDICTIVE_DRAW_PLOT_CAP = 50 @dataclass(frozen=True) @@ -463,12 +465,13 @@ def _powder_meas_vs_calc_hover_template(plot_spec: PowderMeasVsCalcSpec) -> str: """ Return a shared hover template for composite powder traces. """ + calc_label = plot_spec.y_calc_name or 'Icalc' if plot_spec.y_bkg is None: return ( 'x: %{x:,.2f}
' 'Imeas: %{customdata[0]:,.2f}
' - 'Icalc: %{customdata[1]:,.2f}
' - 'Imeas - Icalc: %{customdata[2]:,.2f}' + f'{calc_label}: %{{customdata[1]:,.2f}}
' + f'Imeas - {calc_label}: %{{customdata[2]:,.2f}}' '' ) @@ -476,8 +479,8 @@ def _powder_meas_vs_calc_hover_template(plot_spec: PowderMeasVsCalcSpec) -> str: 'x: %{x:,.2f}
' 'Imeas: %{customdata[0]:,.2f}
' 'Ibkg: %{customdata[1]:,.2f}
' - 'Icalc: %{customdata[2]:,.2f}
' - 'Imeas - Icalc: %{customdata[3]:,.2f}' + f'{calc_label}: %{{customdata[2]:,.2f}}
' + f'Imeas - {calc_label}: %{{customdata[3]:,.2f}}' '' ) @@ -1172,6 +1175,18 @@ def _get_main_intensity_range(cls, plot_spec: PowderMeasVsCalcSpec) -> tuple[flo y_bkg = np.asarray(plot_spec.y_bkg) if y_bkg.size > 0: main_series.append(y_bkg) + if plot_spec.predictive_lower_95 is not None: + lower_95 = np.asarray(plot_spec.predictive_lower_95) + if lower_95.size > 0: + main_series.append(lower_95) + if plot_spec.predictive_upper_95 is not None: + upper_95 = np.asarray(plot_spec.predictive_upper_95) + if upper_95.size > 0: + main_series.append(upper_95) + if plot_spec.predictive_draws is not None: + predictive_draws = np.asarray(plot_spec.predictive_draws) + if predictive_draws.ndim == 2 and predictive_draws.size > 0: + main_series.extend(predictive_draws) main_y_min = float(min(np.min(series) for series in main_series)) main_y_max = float(max(np.max(series) for series in main_series)) @@ -1244,24 +1259,24 @@ def plot_powder_meas_vs_calc( fig.add_trace(lower_trace, row=1, col=1) fig.add_trace(upper_trace, row=1, col=1) - main_traces = ( - ( - ('meas', plot_spec.y_meas), - ('bkg', plot_spec.y_bkg), - ('calc', plot_spec.y_calc), - ) - if plot_spec.y_bkg is not None - else ( - ('meas', plot_spec.y_meas), - ('calc', plot_spec.y_calc), - ) + fig.add_trace( + self._get_powder_trace( + plot_spec.x, + plot_spec.y_meas, + 'meas', + customdata=hover_data, + hovertemplate=hover_template, + ), + row=1, + col=1, ) - for label, y_values in main_traces: + + if plot_spec.y_bkg is not None: fig.add_trace( self._get_powder_trace( plot_spec.x, - y_values, - label, + plot_spec.y_bkg, + 'bkg', customdata=hover_data, hovertemplate=hover_template, ), @@ -1269,6 +1284,40 @@ def plot_powder_meas_vs_calc( col=1, ) + if plot_spec.predictive_draws is not None: + predictive_draws = np.asarray(plot_spec.predictive_draws) + if predictive_draws.ndim == 2 and predictive_draws.size > 0: + draw_cap = min(predictive_draws.shape[0], PREDICTIVE_DRAW_PLOT_CAP) + for index in range(draw_cap): + fig.add_trace( + go.Scatter( + x=plot_spec.x, + y=predictive_draws[index], + mode='lines', + line={'color': PREDICTIVE_DRAW_COLOR, 'width': 1}, + name='Posterior draw' if index == 0 else None, + showlegend=index == 0, + hovertemplate=( + 'Posterior draw
' + 'x: %{x:,.2f}
' + 'y: %{y:,.2f}' + ), + ), + row=1, + col=1, + ) + + calc_trace = self._get_powder_trace( + plot_spec.x, + plot_spec.y_calc, + 'calc', + customdata=hover_data, + hovertemplate=hover_template, + ) + if plot_spec.y_calc_name is not None: + calc_trace.name = plot_spec.y_calc_name + fig.add_trace(calc_trace, row=1, col=1) + if layout.bragg_row is not None: for idx, tick_set in enumerate(plot_spec.bragg_tick_sets): color = BRAGG_TICK_COLORS[idx % len(BRAGG_TICK_COLORS)] diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 4235f0c5..93d0b570 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -73,6 +73,8 @@ def description(self) -> str: DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP = 50 POSTERIOR_DENSITY_LINE_COLOR = 'rgb(99, 110, 250)' POSTERIOR_DENSITY_FILL_COLOR = 'rgba(99, 110, 250, 0.22)' +POSTERIOR_INTERVAL_95_FILL_COLOR = 'rgba(140, 140, 140, 0.08)' +POSTERIOR_INTERVAL_68_FILL_COLOR = 'rgba(140, 140, 140, 0.16)' POSTERIOR_MEDIAN_LINE_COLOR = 'rgb(140, 140, 140)' POSTERIOR_POINT_ESTIMATE_LINE_COLOR = 'rgb(214, 39, 40)' POSTERIOR_DRAW_LINE_COLOR = 'rgba(140, 140, 140, 0.18)' @@ -670,6 +672,11 @@ def plot_posterior_predictive( self, expt_name: str, style: str = 'band+draws', + x_min: float | None = None, + x_max: float | None = None, + *, + show_residual: bool | None = None, + x: object | None = None, ) -> None: """Plot posterior predictive curves for a powder experiment. @@ -681,6 +688,14 @@ def plot_posterior_predictive( ``'band'`` shows the 95% credible interval, ``'draws'`` shows sampled predictive curves, and ``'band+draws'`` shows both together. + x_min : float | None, default=None + Lower bound for the x-axis range. + x_max : float | None, default=None + Upper bound for the x-axis range. + show_residual : bool | None, default=None + Whether to include the residual row in the composite plot. + x : object | None, default=None + Optional explicit x-axis data to override stored values. """ if style not in {'band', 'draws', 'band+draws'}: msg = "style must be 'band', 'draws', or 'band+draws'." @@ -694,12 +709,30 @@ def plot_posterior_predictive( log.warning('Posterior predictive plots currently require the Plotly backend.') return + self._update_project_categories(expt_name) experiment = self._project.experiments[expt_name] - x_axis, _, sample_form, scattering_type, _ = self._resolve_x_axis(experiment.type, None) + x_axis, _, sample_form, scattering_type, _ = self._resolve_x_axis(experiment.type, x) if sample_form != SampleFormEnum.POWDER: log.warning('Posterior predictive plots currently support powder experiments only.') return + plot_options = _MeasVsCalcPlotOptions( + x_min=x_min, + x_max=x_max, + show_residual=show_residual, + x=x, + ) + + if scattering_type == ScatteringTypeEnum.BRAGG: + self._plot_posterior_predictive_data( + experiment=experiment, + expt_name=expt_name, + plot_options=plot_options, + x_axis=x_axis, + style=style, + ) + return + summary = self._get_or_build_posterior_predictive_summary( experiment=experiment, expt_name=expt_name, @@ -1109,14 +1142,16 @@ def _build_param_distribution_plot( fig.add_vrect( x0=summary.interval_95[0], x1=summary.interval_95[1], - fillcolor='rgba(99, 110, 250, 0.08)', + fillcolor=POSTERIOR_INTERVAL_95_FILL_COLOR, line_width=0, + layer='below', ) fig.add_vrect( x0=summary.interval_68[0], x1=summary.interval_68[1], - fillcolor='rgba(99, 110, 250, 0.18)', + fillcolor=POSTERIOR_INTERVAL_68_FILL_COLOR, line_width=0, + layer='below', ) density_trace = self._posterior_density_trace( @@ -1720,6 +1755,15 @@ def _plot_posterior_predictive_summary( ) ) + fig.add_trace( + go.Scatter( + x=summary.x, + y=y_meas, + mode='lines+markers', + line={'color': 'rgb(31, 119, 180)', 'width': 1.5}, + name='Measured', + ) + ) fig.add_trace( go.Scatter( x=summary.x, @@ -1734,16 +1778,114 @@ def _plot_posterior_predictive_summary( xaxis_title=axes_labels[0], yaxis_title=axes_labels[1], ) - fig.add_trace( - go.Scatter( - x=summary.x, - y=y_meas, - mode='lines+markers', - line={'color': 'rgb(31, 119, 180)', 'width': 1.5}, - name='Measured', + fig.show() + + def _plot_posterior_predictive_data( + self, + *, + experiment: object, + expt_name: str, + plot_options: _MeasVsCalcPlotOptions, + x_axis: object, + style: str, + ) -> None: + """Render posterior predictive curves on the composite powder layout.""" + pattern = intensity_category_for(experiment) + expt_type = experiment.type + ctx = self._prepare_powder_context( + pattern, + expt_name, + expt_type, + plot_options.x_min, + plot_options.x_max, + plot_options.x, + ) + if ctx is None: + return + + summary = self._get_or_build_posterior_predictive_summary( + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + ) + if summary is None: + return + + y_meas = self._filtered_y_array( + pattern.intensity_meas, + ctx['x_array'], + ctx['x_min'], + ctx['x_max'], + ) + y_bkg_raw = getattr(pattern, 'intensity_bkg', None) + y_bkg = ( + self._filtered_y_array(y_bkg_raw, ctx['x_array'], ctx['x_min'], ctx['x_max']) + if y_bkg_raw is not None + else None + ) + y_calc = self._filtered_y_array(summary.map_prediction, summary.x, ctx['x_min'], ctx['x_max']) + show_residual = True if plot_options.show_residual is None else plot_options.show_residual + y_resid = y_meas - y_calc if show_residual else None + + predictive_lower_95 = None + predictive_upper_95 = None + if style in {'band', 'band+draws'}: + predictive_lower_95 = self._filtered_y_array( + summary.lower_95, + summary.x, + ctx['x_min'], + ctx['x_max'], ) + predictive_upper_95 = self._filtered_y_array( + summary.upper_95, + summary.x, + ctx['x_min'], + ctx['x_max'], + ) + + predictive_draws = None + if style in {'draws', 'band+draws'}: + draws = getattr(summary, 'draws', None) + if draws is None: + log.warning('Posterior predictive draws are unavailable for plotting.') + return + predictive_draws = np.asarray( + [ + self._filtered_y_array(draw, summary.x, ctx['x_min'], ctx['x_max']) + for draw in draws + ], + dtype=float, + ) + + if np.asarray(ctx['x_filtered']).size == 0: + bragg_tick_sets = () + else: + bragg_tick_sets = self._extract_bragg_tick_sets( + experiment=experiment, + expt_name=expt_name, + x_axis=ctx['x_axis'], + x_min=ctx['x_min'], + x_max=ctx['x_max'], + ) + + plot_spec = PowderMeasVsCalcSpec( + x=ctx['x_filtered'], + y_meas=y_meas, + y_calc=y_calc, + y_resid=y_resid, + bragg_tick_sets=bragg_tick_sets, + axes_labels=ctx['axes_labels'], + title=f"Posterior predictive for experiment πŸ”¬ '{expt_name}'", + residual_height_fraction=DEFAULT_RESID_HEIGHT, + bragg_peaks_height_fraction=DEFAULT_BRAGG_ROW, + height=self._composite_plot_height(), + y_bkg=y_bkg, + predictive_lower_95=predictive_lower_95, + predictive_upper_95=predictive_upper_95, + predictive_draws=predictive_draws, + y_calc_name='Max posterior prediction', ) - fig.show() + self._backend.plot_powder_meas_vs_calc(plot_spec=plot_spec) @staticmethod def _resolve_posterior_parameter_names( diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index 7c8dc20b..a2c0986e 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -58,7 +58,7 @@ fract_z=0, wyckoff_letter='a', adp_type='Biso', - adp_iso=0.5, + adp_iso=0.5151, occupancy=0.5, ) structure.atom_sites.create( @@ -69,7 +69,7 @@ fract_z=0, wyckoff_letter='a', adp_type='Biso', - adp_iso=0.5, + adp_iso=0.5151, occupancy=0.5, ) structure.atom_sites.create( @@ -80,7 +80,7 @@ fract_z=0.5, wyckoff_letter='b', adp_type='Biso', - adp_iso=0.5, + adp_iso=0.2190, ) structure.atom_sites.create( label='O', @@ -90,7 +90,7 @@ fract_z=0.5, wyckoff_letter='c', adp_type='Biso', - adp_iso=0.5, + adp_iso=1.3916, ) # %% [markdown] @@ -130,7 +130,7 @@ # %% experiment.excluded_regions.create(id='1', start=0, end=20) -experiment.excluded_regions.create(id='2', start=160, end=180) +experiment.excluded_regions.create(id='2', start=105, end=180) # %% experiment.linked_phases.create(id='lbco', scale=9.1351) @@ -158,6 +158,9 @@ # %% project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=100, x_max=102) + # %% [markdown] # ## Step 5: Perform Bayesian Analysis @@ -199,6 +202,9 @@ # %% project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=100, x_max=102) + # %% project.display.plotter.plot_posterior_pairs() @@ -207,5 +213,4 @@ project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) # %% -project.display.plotter.plot_posterior_predictive(expt_name='hrpt', style='band') -project.display.plotter.plot_posterior_predictive(expt_name='hrpt', style='draws') +project.display.plotter.plot_posterior_predictive(expt_name='hrpt') From 2f592c87b1c2dde4b36a06be2176a5042b491af1 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 10:32:14 +0200 Subject: [PATCH 024/106] Use population mean log-posterior for progress tracking --- .../analysis/minimizers/bumps_dream.py | 34 ++++++++++++++----- tmp/bumps_dream/ed-2-bayesian-new-API.py | 5 +++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 68fd3264..f3f33f4d 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -56,7 +56,7 @@ def __init__( def config_history(self, history: object) -> None: """Declare the history fields needed for progress updates.""" - history.requires(time=1, step=1, value=1) + history.requires(time=1, step=1, value=1, population_values=1) def __call__(self, history: object) -> None: """Forward sampler progress to the shared fit tracker.""" @@ -64,12 +64,13 @@ def __call__(self, history: object) -> None: generation = max(1, step) nllf = float(history.value[0]) reduced_chi2 = self._reduced_chi_square_from_nllf(nllf) + log_posterior = self._population_mean_log_posterior(history) self._tracker.track_sampler_progress( iteration=generation, total_iterations=self._total_generations, phase=self._phase_name(generation), progress_percent=self._progress_percent(generation), - log_posterior=-nllf, + log_posterior=log_posterior, reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), ) @@ -87,7 +88,7 @@ def final(self, history: object, best: dict[str, object]) -> None: total_iterations=self._total_generations, phase=self._phase_name(generation), progress_percent=self._progress_percent(generation), - log_posterior=-best_nllf, + log_posterior=self._population_mean_log_posterior(history), reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), ) @@ -104,6 +105,19 @@ def _progress_percent(self, generation: int) -> float: clamped_generation = min(generation, self._total_generations) return 100.0 * clamped_generation / self._total_generations + @staticmethod + def _population_mean_log_posterior(history: object) -> float: + """Return the current mean log-posterior across the walker population.""" + population_values = history.population_values[0] if history.population_values else None + if population_values is None: + return -float(history.value[0]) + + nllf_values = np.asarray(population_values, dtype=float) + finite_mask = np.isfinite(nllf_values) + if not np.any(finite_mask): + return -float(history.value[0]) + return float(np.mean(-nllf_values[finite_mask])) + def _reduced_chi_square_from_nllf(self, nllf: float) -> float: """Convert DREAM's negative log-likelihood to reduced chi-square.""" dof = self._n_points - self._n_parameters @@ -491,12 +505,16 @@ def _sync_result_to_parameters( raw_result : object DREAM result object. """ - if getattr(raw_result, 'success', False): - values = raw_result.x - uncertainties = getattr(raw_result, 'dx', None) + if hasattr(raw_result, 'x'): + if getattr(raw_result, 'success', False): + values = raw_result.x + uncertainties = getattr(raw_result, 'dx', None) + else: + values = getattr(raw_result, 'starting_values', raw_result.x) + uncertainties = getattr(raw_result, 'starting_uncertainties', None) else: - values = getattr(raw_result, 'starting_values', None) - uncertainties = getattr(raw_result, 'starting_uncertainties', None) + values = raw_result + uncertainties = None if values is None: return diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index a2c0986e..6ebdb441 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -214,3 +214,8 @@ # %% project.display.plotter.plot_posterior_predictive(expt_name='hrpt') + +# %% +project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=100, x_max=102) + +# %% From 4dbc84def07f58cf1a3d37c92240be33fd994ed4 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 11:26:41 +0200 Subject: [PATCH 025/106] Polish Bayesian progress and posterior plots --- .../analysis/fit_helpers/tracking.py | 89 +++++++++++++++-- src/easydiffraction/display/plotting.py | 99 ++++++++++++------- 2 files changed, 148 insertions(+), 40 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py index 24d7ad5d..39328dcc 100644 --- a/src/easydiffraction/analysis/fit_helpers/tracking.py +++ b/src/easydiffraction/analysis/fit_helpers/tracking.py @@ -32,10 +32,10 @@ SAMPLER_PROGRESS_UPDATE_SECONDS = 5.0 TRACKING_MODE_FIT = 'fit' TRACKING_MODE_SAMPLER = 'sampling' -DEFAULT_HEADERS = ['iteration', 'χ²', 'change / status'] -DEFAULT_ALIGNMENTS = ['center', 'center', 'center'] -SAMPLER_HEADERS = ['iteration', 'progress', 'log posterior', 'phase'] -SAMPLER_ALIGNMENTS = ['center', 'center', 'center', 'center'] +DEFAULT_HEADERS = ['iteration', 'time (s)', 'χ²', 'change / status'] +DEFAULT_ALIGNMENTS = ['center', 'center', 'center', 'center'] +SAMPLER_HEADERS = ['iteration', 'progress', 'time (s)', 'log posterior', 'phase'] +SAMPLER_ALIGNMENTS = ['center', 'center', 'center', 'center', 'center'] class _TerminalLiveHandle: @@ -106,6 +106,8 @@ def __init__(self) -> None: self._best_chi2: float | None = None self._best_iteration: int | None = None self._fitting_time: float | None = None + self._start_time: float | None = None + self._end_time: float | None = None self._verbosity: VerbosityEnum = VerbosityEnum.FULL self._last_progress_time: float | None = None self._tracking_mode: str = TRACKING_MODE_FIT @@ -113,6 +115,7 @@ def __init__(self) -> None: self._last_sampler_phase: str | None = None self._last_sampler_progress_percent: float | None = None self._last_sampler_log_posterior: float | None = None + self._last_sampler_elapsed_time: float | None = None self._df_rows: list[list[str]] = [] self._display_handle: object | None = None @@ -128,12 +131,15 @@ def reset(self) -> None: self._best_chi2 = None self._best_iteration = None self._fitting_time = None + self._start_time = None + self._end_time = None self._last_progress_time = None self._tracking_mode = TRACKING_MODE_FIT self._sampler_total_iterations = None self._last_sampler_phase = None self._last_sampler_progress_percent = None self._last_sampler_log_posterior = None + self._last_sampler_elapsed_time = None def track( self, @@ -179,6 +185,7 @@ def track( row = [ str(self._iteration), + self._format_elapsed_time(), f'{reduced_chi2:.2f}', '', ] @@ -193,6 +200,7 @@ def track( row = [ str(self._iteration), + self._format_elapsed_time(), f'{reduced_chi2:.2f}', f'{change_in_percent:.1f}% ↓', ] @@ -254,6 +262,7 @@ def track_sampler_progress( self._last_sampler_phase = phase self._last_sampler_progress_percent = clamped_progress self._last_sampler_log_posterior = log_posterior + self._last_sampler_elapsed_time = elapsed_time row: list[str] = [] if self._previous_chi2 is None or self._best_chi2 is None: @@ -264,6 +273,7 @@ def track_sampler_progress( row = [ f'{clamped_iteration}/{self._sampler_total_iterations}', f'{clamped_progress:.1f}%', + self._format_elapsed_time(elapsed_time), f'{log_posterior:.2f}', phase, ] @@ -284,6 +294,7 @@ def track_sampler_progress( row = [ f'{clamped_iteration}/{self._sampler_total_iterations}', f'{clamped_progress:.1f}%', + self._format_elapsed_time(elapsed_time), f'{log_posterior:.2f}', phase, ] @@ -318,9 +329,13 @@ def fitting_time(self) -> float | None: def start_timer(self) -> None: """Begin timing of a fit run.""" self._start_time = time.perf_counter() + self._end_time = None def stop_timer(self) -> None: """Stop timing and store elapsed time for the run.""" + if self._start_time is None: + self._fitting_time = None + return self._end_time = time.perf_counter() self._fitting_time = self._end_time - self._start_time @@ -401,6 +416,11 @@ def finish_tracking(self) -> None: f'{min(self._last_iteration, self._sampler_total_iterations)}/' f'{self._sampler_total_iterations}', f'{final_progress:.1f}%', + self._format_elapsed_time( + self._fitting_time + if self._fitting_time is not None + else self._last_sampler_elapsed_time + ), ( f'{self._last_sampler_log_posterior:.2f}' if self._last_sampler_log_posterior is not None @@ -408,15 +428,24 @@ def finish_tracking(self) -> None: ), self._last_sampler_phase or 'sampling', ] - if not self._df_rows or self._df_rows[-1] != row: + if not self._df_rows: + self.add_tracking_info(row) + elif self._rows_match_on_columns(self._df_rows[-1], row, (0, 1, 3, 4)): + self._replace_last_tracking_row(row) + elif self._df_rows[-1] != row: self.add_tracking_info(row) elif self._last_iteration is not None: row: list[str] = [ str(self._last_iteration), + self._format_elapsed_time(self._fitting_time), f'{self._last_chi2:.2f}' if self._last_chi2 is not None else '', '', ] - if not self._df_rows or self._df_rows[-1][:2] != row[:2]: + if not self._df_rows: + self.add_tracking_info(row) + elif self._rows_match_on_columns(self._df_rows[-1], row, (0, 2)): + self._replace_last_tracking_row(row) + elif self._df_rows[-1][:3] != row[:3]: self.add_tracking_info(row) if self._verbosity is not VerbosityEnum.FULL: @@ -449,3 +478,51 @@ def _alignments(self) -> list[str]: if self._tracking_mode == TRACKING_MODE_SAMPLER: return SAMPLER_ALIGNMENTS return DEFAULT_ALIGNMENTS + + def _current_elapsed_time(self) -> float | None: + """Return elapsed run time in seconds when timing is active.""" + if self._start_time is None: + return None + + end_time = self._end_time if self._end_time is not None else time.perf_counter() + return max(end_time - self._start_time, 0.0) + + def _format_elapsed_time(self, elapsed_time: float | None = None) -> str: + """Format elapsed time in seconds with two decimal places.""" + resolved_time = elapsed_time + if resolved_time is None: + resolved_time = self._current_elapsed_time() + if resolved_time is None: + return '' + return f'{resolved_time:.2f}' + + @staticmethod + def _rows_match_on_columns( + current_row: list[str], + new_row: list[str], + column_indices: tuple[int, ...], + ) -> bool: + """Return whether two tracking rows match on selected columns.""" + return all( + len(current_row) > index + and len(new_row) > index + and current_row[index] == new_row[index] + for index in column_indices + ) + + def _replace_last_tracking_row(self, row: list[str]) -> None: + """Replace the last rendered tracking row and refresh the view.""" + if not self._df_rows: + self.add_tracking_info(row) + return + + self._df_rows[-1] = row + if self._verbosity is not VerbosityEnum.FULL: + return + + render_table( + columns_headers=self._headers(), + columns_alignment=self._alignments(), + columns_data=self._df_rows, + display_handle=self._display_handle, + ) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 93d0b570..ba592bda 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -573,6 +573,7 @@ def plot_param_correlations( self, threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, precision: int = 2, + show_diagonal: bool = False, ) -> None: """ Plot the parameter correlation matrix from the latest fit. @@ -581,8 +582,10 @@ def plot_param_correlations( the active engine is Plotly, an interactive heatmap is shown. Otherwise, a rounded correlation table is rendered. - Only the lower triangle is shown (without the diagonal), since - the matrix is symmetric and diagonal values are always ``1``. + By default only the lower triangle is shown (without the + diagonal), since the matrix is symmetric and diagonal values are + always ``1``. Set ``show_diagonal=True`` to keep blank diagonal + cells for a square lower-triangle layout. Parameters ---------- @@ -594,6 +597,9 @@ def plot_param_correlations( matrix. precision : int, default=2 Number of decimal places to show in the table fallback. + show_diagonal : bool, default=False + Whether to retain blank diagonal cells in the displayed + lower-triangle matrix. """ corr_df = self._get_param_correlation_dataframe() if corr_df is None: @@ -612,6 +618,7 @@ def plot_param_correlations( display_corr_df, row_numbers, col_numbers = self._trim_correlation_display_dataframe( corr_df, preserve_all_rows=not is_graphical, + show_diagonal=show_diagonal, ) if is_graphical: @@ -649,7 +656,7 @@ def plot_posterior_pairs( plot = self._build_posterior_pairs_plot(parameters=parameters) if plot is None: return - plot.show() + self._show_plot_figure(plot) def plot_param_distribution( self, @@ -666,7 +673,7 @@ def plot_param_distribution( plot = self._build_param_distribution_plot(param) if plot is None: return - plot.show() + self._show_plot_figure(plot) def plot_posterior_predictive( self, @@ -831,6 +838,7 @@ def _trim_correlation_display_dataframe( corr_df: pd.DataFrame, *, preserve_all_rows: bool, + show_diagonal: bool, ) -> tuple[pd.DataFrame, list[int], list[int]]: """ Trim empty outer rows/columns from the lower-triangle view. @@ -845,6 +853,8 @@ def _trim_correlation_display_dataframe( preserve_all_rows : bool Whether to keep the full row list so row labels continue to identify all numeric column headers in tabular output. + show_diagonal : bool + Whether blank diagonal cells should remain visible. Returns ------- @@ -856,7 +866,7 @@ def _trim_correlation_display_dataframe( row_numbers = list(range(1, num_rows + 1)) col_numbers = list(range(1, num_cols + 1)) - if min(num_rows, num_cols) <= 1: + if show_diagonal or min(num_rows, num_cols) <= 1: return corr_df, row_numbers, col_numbers if preserve_all_rows: @@ -1136,8 +1146,13 @@ def _build_param_distribution_plot( values = samples[:, 0] label = self._posterior_plot_labels(fit_results, [parameter_name])[0] summary = self._posterior_summary_by_name(fit_results).get(parameter_name) + title = f'Posterior distribution: {label}' + layout_factory = getattr(self._backend, '_get_layout', None) + if callable(layout_factory): + fig = go.Figure(layout=layout_factory(title, [label, 'Probability density'])) + else: + fig = go.Figure() - fig = go.Figure() if summary is not None: fig.add_vrect( x0=summary.interval_95[0], @@ -1154,31 +1169,36 @@ def _build_param_distribution_plot( layer='below', ) + histogram_density, _ = np.histogram(values, bins=50, density=True) + fig.add_trace( + go.Histogram( + x=values, + nbinsx=50, + histnorm='probability density', + marker={ + 'color': 'rgba(140, 140, 140, 0.28)', + 'line': {'color': 'rgba(140, 140, 140, 0.18)', 'width': 1}, + }, + opacity=0.65, + name='Posterior histogram', + hovertemplate='sample=%{x:.4f}
density=%{y:.4f}', + ) + ) + density_trace = self._posterior_density_trace( fit_results=fit_results, parameter_name=parameter_name, values=values, trace_name='Posterior density', ) - y_axis_range = None - if density_trace is None: - histogram_density, _ = np.histogram(values, bins=50, density=True) - y_axis_range = self._posterior_density_axis_range(histogram_density) - fig.add_trace( - go.Histogram( - x=values, - nbinsx=50, - histnorm='probability density', - marker={'color': POSTERIOR_DENSITY_LINE_COLOR}, - opacity=0.85, - name='Posterior density', - ) - ) - else: + density_sources = [histogram_density] + if density_trace is not None: density_trace.name = 'Posterior density' density_trace.showlegend = True fig.add_trace(density_trace) - y_axis_range = self._posterior_density_axis_range(np.asarray(density_trace.y)) + density_sources.append(np.asarray(density_trace.y, dtype=float)) + + y_axis_range = self._posterior_density_axis_range(np.concatenate(density_sources)) median = float(np.median(values)) if y_axis_range is not None: @@ -1202,22 +1222,33 @@ def _build_param_distribution_plot( ) ) - fig.update_layout( - title=f'Posterior distribution: {label}', - xaxis_title=label, - yaxis_title='Probability density', - legend={ - 'bgcolor': 'rgba(0, 0, 0, 0)', - 'xanchor': 'right', - 'x': 1.0, - 'yanchor': 'top', - 'y': 1.0, - }, - ) + if callable(layout_factory): + fig.update_layout(title={'text': title}) + else: + fig.update_layout( + title=title, + xaxis_title=label, + yaxis_title='Probability density', + legend={ + 'bgcolor': 'rgba(0, 0, 0, 0)', + 'xanchor': 'right', + 'x': 1.0, + 'yanchor': 'top', + 'y': 1.0, + }, + ) if y_axis_range is not None: fig.update_yaxes(range=list(y_axis_range)) return fig + def _show_plot_figure(self, figure: object) -> None: + """Display a figure through the active backend when possible.""" + show_figure = getattr(self._backend, '_show_figure', None) + if callable(show_figure): + show_figure(figure) + return + figure.show() + def _posterior_density_trace( self, *, From 16f9fc65ee3b253ac9c1bb79de40550277e8d8a2 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 12:09:14 +0200 Subject: [PATCH 026/106] Fix DREAM diagnostics and posterior KDEs --- .../analysis/fit_helpers/bayesian.py | 41 +++++- .../analysis/fit_helpers/tracking.py | 6 +- .../analysis/minimizers/bumps_dream.py | 70 ++++++++++ src/easydiffraction/display/plotting.py | 125 ++++++++++++++---- 4 files changed, 210 insertions(+), 32 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 2da05935..a85b3fbc 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -17,6 +17,7 @@ from easydiffraction.analysis.fit_helpers.reporting import _format_optional_float from easydiffraction.analysis.fit_helpers.reporting import FitResults from easydiffraction.utils.logging import console +from easydiffraction.utils.logging import log from easydiffraction.utils.utils import render_table R_HAT_CONVERGENCE_THRESHOLD = 1.01 @@ -338,6 +339,12 @@ def display_results( self._print_table_notes() + def _print_table_notes(self) -> None: + """Print parameter and posterior-diagnostic notes below tables.""" + super()._print_table_notes() + for note in _posterior_table_notes(self.posterior_parameter_summaries): + log.warning(note) + def compute_convergence_diagnostics(posterior_samples: PosteriorSamples) -> dict[str, object]: """Compute convergence diagnostics from posterior samples. @@ -511,7 +518,7 @@ def _format_convergence_summary(convergence_diagnostics: dict[str, object]) -> s parts: list[str] = [] converged = convergence_diagnostics.get('converged') if converged is not None: - status = 'yes' if converged else '[yellow]check diagnostics[/yellow]' + status = 'yes' if converged else '[red]failed[/red]' parts.append(f'converged={status}') max_r_hat = _maybe_scalar(convergence_diagnostics.get('max_r_hat')) @@ -643,7 +650,7 @@ def _format_r_hat(value: float | None) -> str: return 'N/A' formatted = f'{value:.3f}' if value > R_HAT_CONVERGENCE_THRESHOLD: - return f'[yellow]{formatted}[/yellow]' + return f'[red]{formatted}[/red]' return formatted @@ -652,5 +659,31 @@ def _format_ess_bulk(value: float | None) -> str: return 'N/A' formatted = f'{value:.1f}' if value < ESS_BULK_CONVERGENCE_THRESHOLD: - return f'[yellow]{formatted}[/yellow]' - return formatted \ No newline at end of file + return f'[red]{formatted}[/red]' + return formatted + + +def _posterior_table_notes( + posterior_parameter_summaries: list[PosteriorParameterSummary], +) -> list[str]: + """Return warning notes for posterior summary diagnostics.""" + if not posterior_parameter_summaries: + return [] + + has_failed_r_hat = any( + summary.r_hat is not None and summary.r_hat > R_HAT_CONVERGENCE_THRESHOLD + for summary in posterior_parameter_summaries + ) + has_failed_ess_bulk = any( + summary.ess_bulk is not None and summary.ess_bulk < ESS_BULK_CONVERGENCE_THRESHOLD + for summary in posterior_parameter_summaries + ) + + if not has_failed_r_hat and not has_failed_ess_bulk: + return [] + + return [ + '[red]Convergence warning:[/red] posterior diagnostics failed ' + '(r_hat > 1.01 or ess_bulk < 400). Consider longer sampling, ' + 'tighter bounds, or reparameterization.' + ] \ No newline at end of file diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py index 39328dcc..d85a705e 100644 --- a/src/easydiffraction/analysis/fit_helpers/tracking.py +++ b/src/easydiffraction/analysis/fit_helpers/tracking.py @@ -232,6 +232,7 @@ def track_sampler_progress( log_posterior: float, reduced_chi2: float, elapsed_time: float, + force_report: bool = False, ) -> None: """Update progress from a sampler monitor. @@ -251,6 +252,8 @@ def track_sampler_progress( Best reduced chi-square implied by the current best sample. elapsed_time : float Elapsed wall time in seconds. + force_report : bool, default=False + Whether to render the row regardless of heartbeat timing. """ self._iteration = iteration self._tracking_mode = TRACKING_MODE_SAMPLER @@ -285,7 +288,8 @@ def track_sampler_progress( if ( iteration != self._last_reported_iteration and ( - previous_phase != phase + force_report + or previous_phase != phase or self._last_progress_time is None or elapsed_time - self._last_progress_time >= SAMPLER_PROGRESS_UPDATE_SECONDS or clamped_iteration >= self._sampler_total_iterations diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index f3f33f4d..2ea64fe1 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -34,6 +34,8 @@ DEFAULT_ALPHA = 0.0 DEFAULT_OUTLIER_TEST = 'none' DEFAULT_TRIM = False +BURN_IN_PROGRESS_POINTS = 5 +SAMPLING_PROGRESS_POINTS = 20 class _DreamProgressMonitor(bumps_monitor.Monitor): @@ -53,6 +55,18 @@ def __init__( self._n_parameters = n_parameters self._total_generations = max(1, total_generations) self._burn_steps = max(0, burn_steps) + self._burn_targets = self._progress_targets( + start=1, + stop=self._burn_steps, + target_count=BURN_IN_PROGRESS_POINTS, + ) + self._sampling_targets = self._progress_targets( + start=self._burn_steps + 1, + stop=self._total_generations, + target_count=SAMPLING_PROGRESS_POINTS, + ) + self._next_burn_target_index = 0 + self._next_sampling_target_index = 0 def config_history(self, history: object) -> None: """Declare the history fields needed for progress updates.""" @@ -62,6 +76,8 @@ def __call__(self, history: object) -> None: """Forward sampler progress to the shared fit tracker.""" step = int(history.step[0]) if history.step else 0 generation = max(1, step) + if not self._should_report(generation): + return nllf = float(history.value[0]) reduced_chi2 = self._reduced_chi_square_from_nllf(nllf) log_posterior = self._population_mean_log_posterior(history) @@ -73,6 +89,7 @@ def __call__(self, history: object) -> None: log_posterior=log_posterior, reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), + force_report=True, ) def final(self, history: object, best: dict[str, object]) -> None: @@ -91,8 +108,61 @@ def final(self, history: object, best: dict[str, object]) -> None: log_posterior=self._population_mean_log_posterior(history), reduced_chi2=reduced_chi2, elapsed_time=float(history.time[0]), + force_report=True, + ) + + @staticmethod + def _progress_targets( + *, + start: int, + stop: int, + target_count: int, + ) -> list[int]: + """Return monotonically increasing reporting targets for one phase.""" + if target_count < 1 or stop < start: + return [] + + targets = np.linspace(start, stop, num=target_count) + rounded = np.rint(targets).astype(int) + unique_targets = sorted(set(int(value) for value in rounded if start <= value <= stop)) + if start not in unique_targets: + unique_targets.insert(0, start) + if stop not in unique_targets: + unique_targets.append(stop) + return unique_targets + + def _should_report(self, generation: int) -> bool: + """Return whether the current generation should be rendered.""" + clamped_generation = min(max(1, generation), self._total_generations) + if self._phase_name(clamped_generation) == 'burn-in': + return self._consume_progress_target( + clamped_generation, + phase_targets=self._burn_targets, + target_index_name='_next_burn_target_index', + ) + + return self._consume_progress_target( + clamped_generation, + phase_targets=self._sampling_targets, + target_index_name='_next_sampling_target_index', ) + def _consume_progress_target( + self, + generation: int, + *, + phase_targets: list[int], + target_index_name: str, + ) -> bool: + """Advance a phase target pointer when the generation reaches it.""" + target_index = getattr(self, target_index_name) + should_report = False + while target_index < len(phase_targets) and generation >= phase_targets[target_index]: + target_index += 1 + should_report = True + setattr(self, target_index_name, target_index) + return should_report + def _phase_name(self, generation: int) -> str: """Return the current sampler phase name.""" clamped_generation = min(generation, self._total_generations) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index ba592bda..38ddc174 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1168,6 +1168,18 @@ def _build_param_distribution_plot( line_width=0, layer='below', ) + fig.add_trace( + self._posterior_interval_legend_trace( + trace_name='95% credible interval', + color=POSTERIOR_INTERVAL_95_FILL_COLOR, + ) + ) + fig.add_trace( + self._posterior_interval_legend_trace( + trace_name='68% credible interval', + color=POSTERIOR_INTERVAL_68_FILL_COLOR, + ) + ) histogram_density, _ = np.histogram(values, bins=50, density=True) fig.add_trace( @@ -1298,10 +1310,30 @@ def _posterior_density_axis_range( data_min = float(np.min(data)) data_max = float(np.max(data)) data_range = data_max - data_min - padding = 0.08 * data_range if data_range > 0 else max(abs(data_max), 1.0) * 0.05 - if padding == 0: - padding = 1e-6 - return data_min - padding, data_max + padding + upper_padding = 0.08 * data_range if data_range > 0 else max(abs(data_max), 1.0) * 0.05 + if upper_padding == 0: + upper_padding = 1e-6 + lower = 0.0 if data_min >= 0.0 else data_min + return lower, data_max + upper_padding + + @staticmethod + def _posterior_interval_legend_trace( + *, + trace_name: str, + color: str, + ) -> object: + """Return a legend-only proxy trace for a credible interval.""" + go = __import__('plotly.graph_objects', fromlist=['Scatter']) + + return go.Scatter( + x=[None], + y=[None], + mode='markers', + marker={'size': 12, 'symbol': 'square', 'color': color}, + name=trace_name, + showlegend=True, + hoverinfo='skip', + ) @staticmethod def _posterior_reference_line_trace( @@ -1433,12 +1465,13 @@ def _posterior_density_curve( density = np.exp(-0.5 * ((grid - data[0]) / bandwidth) ** 2) density /= bandwidth * np.sqrt(2.0 * np.pi) else: - reflected_data = cls._reflected_density_samples( - data, + kde = gaussian_kde(data) + density = cls._evaluate_reflected_1d_kde( + kde, + grid, lower_bound=lower_bound, upper_bound=upper_bound, ) - density = np.asarray(gaussian_kde(reflected_data)(grid), dtype=float) area = np.trapezoid(density, grid) if area <= 0: @@ -1469,43 +1502,81 @@ def _posterior_pair_density_surface( if np.allclose(x_data, x_data[0]) and np.allclose(y_data, y_data[0]): return None - reflected_x = cls._reflected_density_samples( - x_data, - lower_bound=x_bounds[0], - upper_bound=x_bounds[1], - ) - reflected_y = cls._reflected_density_samples( - y_data, - lower_bound=y_bounds[0], - upper_bound=y_bounds[1], - ) - if reflected_x.shape != reflected_y.shape: - return None - x_grid = np.linspace(x_bounds[0], x_bounds[1], num=grid_size) y_grid = np.linspace(y_bounds[0], y_bounds[1], num=grid_size) mesh_x, mesh_y = np.meshgrid(x_grid, y_grid) - positions = np.vstack([mesh_x.ravel(), mesh_y.ravel()]) - density = gaussian_kde(np.vstack([reflected_x, reflected_y]))(positions) - density = np.asarray(density, dtype=float).reshape(mesh_x.shape) + density = cls._evaluate_reflected_2d_kde( + gaussian_kde(np.vstack([x_data, y_data])), + mesh_x=mesh_x, + mesh_y=mesh_y, + x_bounds=x_bounds, + y_bounds=y_bounds, + ) if not np.any(np.isfinite(density)): return None return x_grid, y_grid, density @staticmethod - def _reflected_density_samples( + def _reflection_positions_1d( values: np.ndarray, *, lower_bound: float | None, upper_bound: float | None, - ) -> np.ndarray: - """Reflect posterior samples across finite bounds for KDE stability.""" + ) -> list[np.ndarray]: + """Return mirrored evaluation positions for boundary-corrected KDEs.""" reflected = [values] if lower_bound is not None: reflected.append(2.0 * lower_bound - values) if upper_bound is not None: reflected.append(2.0 * upper_bound - values) - return np.concatenate(reflected) + return reflected + + @classmethod + def _evaluate_reflected_1d_kde( + cls, + kde: object, + grid: np.ndarray, + *, + lower_bound: float | None, + upper_bound: float | None, + ) -> np.ndarray: + """Evaluate a 1D KDE using mirrored-boundary correction.""" + density = np.zeros_like(grid, dtype=float) + for reflected_grid in cls._reflection_positions_1d( + grid, + lower_bound=lower_bound, + upper_bound=upper_bound, + ): + density += np.asarray(kde(reflected_grid), dtype=float) + return density + + @classmethod + def _evaluate_reflected_2d_kde( + cls, + kde: object, + *, + mesh_x: np.ndarray, + mesh_y: np.ndarray, + x_bounds: tuple[float, float], + y_bounds: tuple[float, float], + ) -> np.ndarray: + """Evaluate a 2D KDE using mirrored-boundary correction.""" + x_positions = cls._reflection_positions_1d( + mesh_x.ravel(), + lower_bound=x_bounds[0], + upper_bound=x_bounds[1], + ) + y_positions = cls._reflection_positions_1d( + mesh_y.ravel(), + lower_bound=y_bounds[0], + upper_bound=y_bounds[1], + ) + density = np.zeros(mesh_x.size, dtype=float) + for reflected_x in x_positions: + for reflected_y in y_positions: + positions = np.vstack([reflected_x, reflected_y]) + density += np.asarray(kde(positions), dtype=float) + return density.reshape(mesh_x.shape) def _get_or_build_posterior_predictive_summary( self, From 1dde15b864d718aaff1b81f8879b11628e231d2f Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 13:42:53 +0200 Subject: [PATCH 027/106] Refine posterior plot styling --- src/easydiffraction/display/plotting.py | 156 ++++++++++++++---------- 1 file changed, 91 insertions(+), 65 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 38ddc174..cc7530bd 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -73,13 +73,15 @@ def description(self) -> str: DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP = 50 POSTERIOR_DENSITY_LINE_COLOR = 'rgb(99, 110, 250)' POSTERIOR_DENSITY_FILL_COLOR = 'rgba(99, 110, 250, 0.22)' +POSTERIOR_HISTOGRAM_FILL_COLOR = 'rgba(120, 120, 120, 0.38)' +POSTERIOR_HISTOGRAM_LINE_COLOR = 'rgba(120, 120, 120, 0.24)' POSTERIOR_INTERVAL_95_FILL_COLOR = 'rgba(140, 140, 140, 0.08)' POSTERIOR_INTERVAL_68_FILL_COLOR = 'rgba(140, 140, 140, 0.16)' -POSTERIOR_MEDIAN_LINE_COLOR = 'rgb(140, 140, 140)' +POSTERIOR_MEDIAN_LINE_COLOR = 'rgb(80, 80, 80)' POSTERIOR_POINT_ESTIMATE_LINE_COLOR = 'rgb(214, 39, 40)' POSTERIOR_DRAW_LINE_COLOR = 'rgba(140, 140, 140, 0.18)' POSTERIOR_SCATTER_MARKER_COLOR = 'rgba(140, 140, 140, 0.20)' -POSTERIOR_CONTOUR_LINE_COLOR = 'rgba(99, 110, 250, 0.50)' +POSTERIOR_CONTOUR_LINE_COLOR = 'rgba(65, 85, 225, 0.85)' @dataclass(frozen=True) @@ -960,10 +962,10 @@ def _build_posterior_pairs_plot( ) make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots - samples = self._selected_posterior_samples(posterior_samples, parameter_names) - if samples is None: + density_samples = self._selected_posterior_samples(posterior_samples, parameter_names) + if density_samples is None: return None - samples = self._thin_posterior_samples(samples, max_points=1500) + scatter_samples = self._thin_posterior_samples(density_samples, max_points=1500) labels = self._posterior_plot_labels(fit_results, parameter_names) n_parameters = len(parameter_names) @@ -984,20 +986,22 @@ def _build_posterior_pairs_plot( fig.update_yaxes(visible=False, row=row, col=col) continue - x_values = samples[:, col_index] - y_values = samples[:, row_index] + x_density_values = density_samples[:, col_index] + y_density_values = density_samples[:, row_index] + x_scatter_values = scatter_samples[:, col_index] + y_scatter_values = scatter_samples[:, row_index] if row_index == col_index: density_trace = self._posterior_density_trace( fit_results=fit_results, parameter_name=parameter_names[col_index], - values=x_values, + values=x_density_values, trace_name=labels[col_index], ) diagonal_y_axis_range = None if density_trace is None: fig.add_trace( go.Histogram( - x=x_values, + x=x_density_values, nbinsx=40, histnorm='probability density', marker={'color': 'rgb(99, 110, 250)'}, @@ -1015,19 +1019,19 @@ def _build_posterior_pairs_plot( if diagonal_y_axis_range is not None: fig.update_yaxes(range=list(diagonal_y_axis_range), row=row, col=col) else: - contour_trace = self._posterior_contour_trace( + contour_traces = self._posterior_contour_traces( fit_results=fit_results, x_parameter_name=parameter_names[col_index], y_parameter_name=parameter_names[row_index], - x_values=x_values, - y_values=y_values, + x_values=x_density_values, + y_values=y_density_values, ) - if contour_trace is not None: - fig.add_trace(contour_trace, row=row, col=col) + if contour_traces is not None: + fig.add_trace(contour_traces[0], row=row, col=col) fig.add_trace( go.Scattergl( - x=x_values, - y=y_values, + x=x_scatter_values, + y=y_scatter_values, mode='markers', marker={ 'color': POSTERIOR_SCATTER_MARKER_COLOR, @@ -1042,6 +1046,8 @@ def _build_posterior_pairs_plot( row=row, col=col, ) + if contour_traces is not None: + fig.add_trace(contour_traces[1], row=row, col=col) fig.update_xaxes(showticklabels=(row_index == n_parameters - 1), row=row, col=col) fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) @@ -1056,7 +1062,7 @@ def _build_posterior_pairs_plot( ) return fig - def _posterior_contour_trace( + def _posterior_contour_traces( self, *, fit_results: object, @@ -1064,8 +1070,8 @@ def _posterior_contour_trace( y_parameter_name: str, x_values: np.ndarray, y_values: np.ndarray, - ) -> object | None: - """Return a 2D KDE contour trace for posterior pair plots.""" + ) -> tuple[object, object] | None: + """Return filled and line contour traces for posterior pair plots.""" go = __import__('plotly.graph_objects', fromlist=['Contour']) bounds = self._posterior_pair_bounds( @@ -1085,29 +1091,49 @@ def _posterior_contour_trace( return None x_grid, y_grid, density = density_surface - return go.Contour( + contour_start = float(np.max(density) * 0.20) + contour_end = float(np.max(density) * 0.95) + contour_size = float(np.max(density) * 0.15) + fill_trace = go.Contour( x=x_grid, y=y_grid, z=density, contours={ 'coloring': 'fill', 'showlabels': False, - 'start': float(np.max(density) * 0.15), - 'end': float(np.max(density) * 0.95), - 'size': float(np.max(density) * 0.16), + 'showlines': False, + 'start': contour_start, + 'end': contour_end, + 'size': contour_size, }, colorscale=[ [0.0, 'rgba(99, 110, 250, 0.00)'], [0.35, 'rgba(99, 110, 250, 0.00)'], - [0.60, 'rgba(99, 110, 250, 0.10)'], - [0.80, 'rgba(99, 110, 250, 0.18)'], - [1.0, 'rgba(99, 110, 250, 0.30)'], + [0.60, 'rgba(99, 110, 250, 0.12)'], + [0.80, 'rgba(99, 110, 250, 0.22)'], + [1.0, 'rgba(99, 110, 250, 0.34)'], ], - line={'color': POSTERIOR_CONTOUR_LINE_COLOR, 'width': 1.0}, hoverinfo='skip', showscale=False, showlegend=False, ) + line_trace = go.Contour( + x=x_grid, + y=y_grid, + z=density, + contours={ + 'coloring': 'lines', + 'showlabels': False, + 'start': contour_start, + 'end': contour_end, + 'size': contour_size, + }, + line={'color': POSTERIOR_CONTOUR_LINE_COLOR, 'width': 1.4}, + hoverinfo='skip', + showscale=False, + showlegend=False, + ) + return fill_trace, line_trace def _build_param_distribution_plot( self, @@ -1153,64 +1179,59 @@ def _build_param_distribution_plot( else: fig = go.Figure() - if summary is not None: - fig.add_vrect( - x0=summary.interval_95[0], - x1=summary.interval_95[1], - fillcolor=POSTERIOR_INTERVAL_95_FILL_COLOR, - line_width=0, - layer='below', - ) - fig.add_vrect( - x0=summary.interval_68[0], - x1=summary.interval_68[1], - fillcolor=POSTERIOR_INTERVAL_68_FILL_COLOR, - line_width=0, - layer='below', - ) + histogram_density, _ = np.histogram(values, bins=50, density=True) + density_trace = self._posterior_density_trace( + fit_results=fit_results, + parameter_name=parameter_name, + values=values, + trace_name='Posterior density', + ) + density_sources = [histogram_density] + if density_trace is not None: + density_trace.name = 'Posterior density' + density_trace.showlegend = True + density_sources.append(np.asarray(density_trace.y, dtype=float)) + + y_axis_range = self._posterior_density_axis_range(np.concatenate(density_sources)) + + if summary is not None and y_axis_range is not None: fig.add_trace( - self._posterior_interval_legend_trace( + self._posterior_interval_band_trace( + x0=summary.interval_95[0], + x1=summary.interval_95[1], + y_axis_range=y_axis_range, trace_name='95% credible interval', color=POSTERIOR_INTERVAL_95_FILL_COLOR, ) ) fig.add_trace( - self._posterior_interval_legend_trace( + self._posterior_interval_band_trace( + x0=summary.interval_68[0], + x1=summary.interval_68[1], + y_axis_range=y_axis_range, trace_name='68% credible interval', color=POSTERIOR_INTERVAL_68_FILL_COLOR, ) ) - histogram_density, _ = np.histogram(values, bins=50, density=True) fig.add_trace( go.Histogram( x=values, nbinsx=50, histnorm='probability density', marker={ - 'color': 'rgba(140, 140, 140, 0.28)', - 'line': {'color': 'rgba(140, 140, 140, 0.18)', 'width': 1}, + 'color': POSTERIOR_HISTOGRAM_FILL_COLOR, + 'line': {'color': POSTERIOR_HISTOGRAM_LINE_COLOR, 'width': 1}, }, - opacity=0.65, + opacity=0.82, name='Posterior histogram', hovertemplate='sample=%{x:.4f}
density=%{y:.4f}', ) ) - - density_trace = self._posterior_density_trace( - fit_results=fit_results, - parameter_name=parameter_name, - values=values, - trace_name='Posterior density', - ) - density_sources = [histogram_density] if density_trace is not None: density_trace.name = 'Posterior density' density_trace.showlegend = True fig.add_trace(density_trace) - density_sources.append(np.asarray(density_trace.y, dtype=float)) - - y_axis_range = self._posterior_density_axis_range(np.concatenate(density_sources)) median = float(np.median(values)) if y_axis_range is not None: @@ -1317,19 +1338,24 @@ def _posterior_density_axis_range( return lower, data_max + upper_padding @staticmethod - def _posterior_interval_legend_trace( + def _posterior_interval_band_trace( *, + x0: float, + x1: float, + y_axis_range: tuple[float, float], trace_name: str, color: str, ) -> object: - """Return a legend-only proxy trace for a credible interval.""" + """Return a hideable credible-interval band trace.""" go = __import__('plotly.graph_objects', fromlist=['Scatter']) return go.Scatter( - x=[None], - y=[None], - mode='markers', - marker={'size': 12, 'symbol': 'square', 'color': color}, + x=[x0, x1, x1, x0, x0], + y=[y_axis_range[0], y_axis_range[0], y_axis_range[1], y_axis_range[1], y_axis_range[0]], + mode='lines', + fill='toself', + fillcolor=color, + line={'color': color, 'width': 0}, name=trace_name, showlegend=True, hoverinfo='skip', From 8cf5f052ceca77938bf8229c66ed13d31d3976ee Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 14:02:49 +0200 Subject: [PATCH 028/106] Improve posterior pair plot UX --- src/easydiffraction/display/plotting.py | 69 ++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index cc7530bd..27f394ed 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -82,6 +82,17 @@ def description(self) -> str: POSTERIOR_DRAW_LINE_COLOR = 'rgba(140, 140, 140, 0.18)' POSTERIOR_SCATTER_MARKER_COLOR = 'rgba(140, 140, 140, 0.20)' POSTERIOR_CONTOUR_LINE_COLOR = 'rgba(65, 85, 225, 0.85)' +POSTERIOR_CONTOUR_FILL_COLORSCALE = [ + [0.0, 'rgba(68, 1, 84, 0.00)'], + [0.35, 'rgba(68, 1, 84, 0.00)'], + [0.58, 'rgba(59, 82, 139, 0.16)'], + [0.75, 'rgba(33, 145, 140, 0.28)'], + [0.88, 'rgba(94, 201, 98, 0.38)'], + [1.0, 'rgba(253, 231, 37, 0.48)'], +] +PAIR_PLOT_CELL_SIZE_PIXELS = 190 +PAIR_PLOT_MIN_SIZE_PIXELS = 680 +PAIR_PLOT_MARGIN_PIXELS = 120 @dataclass(frozen=True) @@ -967,6 +978,9 @@ def _build_posterior_pairs_plot( return None scatter_samples = self._thin_posterior_samples(density_samples, max_points=1500) labels = self._posterior_plot_labels(fit_results, parameter_names) + show_density_legend = True + show_scatter_legend = True + show_contour_legend = True n_parameters = len(parameter_names) fig = make_subplots( @@ -1012,7 +1026,11 @@ def _build_posterior_pairs_plot( col=col, ) else: + density_trace.name = 'Marginal density' + density_trace.legendgroup = 'posterior-marginal-density' + density_trace.showlegend = show_density_legend fig.add_trace(density_trace, row=row, col=col) + show_density_legend = False diagonal_y_axis_range = self._posterior_density_axis_range( np.asarray(density_trace.y) ) @@ -1027,7 +1045,13 @@ def _build_posterior_pairs_plot( y_values=y_density_values, ) if contour_traces is not None: + contour_traces[0].name = 'Posterior contours' + contour_traces[0].legendgroup = 'posterior-contours' + contour_traces[0].showlegend = show_contour_legend + contour_traces[1].legendgroup = 'posterior-contours' + contour_traces[1].showlegend = False fig.add_trace(contour_traces[0], row=row, col=col) + show_contour_legend = False fig.add_trace( go.Scattergl( x=x_scatter_values, @@ -1037,7 +1061,9 @@ def _build_posterior_pairs_plot( 'color': POSTERIOR_SCATTER_MARKER_COLOR, 'size': 3, }, - showlegend=False, + name='Posterior samples', + legendgroup='posterior-samples', + showlegend=show_scatter_legend, hovertemplate=( f'{labels[col_index]}: %{{x:.4f}}
' f'{labels[row_index]}: %{{y:.4f}}' @@ -1046,9 +1072,28 @@ def _build_posterior_pairs_plot( row=row, col=col, ) + show_scatter_legend = False if contour_traces is not None: fig.add_trace(contour_traces[1], row=row, col=col) + fig.update_xaxes( + showline=True, + mirror=True, + zeroline=False, + tickformat=',.6~g', + separatethousands=True, + row=row, + col=col, + ) + fig.update_yaxes( + showline=True, + mirror=True, + zeroline=False, + tickformat=',.6~g', + separatethousands=True, + row=row, + col=col, + ) fig.update_xaxes(showticklabels=(row_index == n_parameters - 1), row=row, col=col) fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) if row_index == n_parameters - 1: @@ -1056,9 +1101,23 @@ def _build_posterior_pairs_plot( if col_index == 0 and row_index > 0: fig.update_yaxes(title_text=labels[row_index], row=row, col=col) + figure_size = max( + PAIR_PLOT_MIN_SIZE_PIXELS, + PAIR_PLOT_CELL_SIZE_PIXELS * n_parameters + PAIR_PLOT_MARGIN_PIXELS, + ) fig.update_layout( title='Posterior pair plot', bargap=0.05, + width=figure_size, + height=figure_size, + legend={ + 'bgcolor': 'rgba(0, 0, 0, 0)', + 'xanchor': 'right', + 'x': 1.0, + 'yanchor': 'top', + 'y': 1.0, + 'groupclick': 'togglegroup', + }, ) return fig @@ -1106,13 +1165,7 @@ def _posterior_contour_traces( 'end': contour_end, 'size': contour_size, }, - colorscale=[ - [0.0, 'rgba(99, 110, 250, 0.00)'], - [0.35, 'rgba(99, 110, 250, 0.00)'], - [0.60, 'rgba(99, 110, 250, 0.12)'], - [0.80, 'rgba(99, 110, 250, 0.22)'], - [1.0, 'rgba(99, 110, 250, 0.34)'], - ], + colorscale=POSTERIOR_CONTOUR_FILL_COLORSCALE, hoverinfo='skip', showscale=False, showlegend=False, From 74930c1bacb4d084c976f315428c347e43858377 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 14:09:37 +0200 Subject: [PATCH 029/106] Add uncertainty-based fit bounds method --- src/easydiffraction/core/variable.py | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/easydiffraction/core/variable.py b/src/easydiffraction/core/variable.py index 84bbd2f4..6ae427f8 100644 --- a/src/easydiffraction/core/variable.py +++ b/src/easydiffraction/core/variable.py @@ -427,6 +427,75 @@ def fit_max(self, v: float) -> None: v, name=f'{self.unique_name}.fit_max', current=self._fit_max ) + def set_fit_bounds_from_uncertainty( + self, + multiplier: float = 8.0, + *, + clip_to_limits: bool = True, + ) -> tuple[float, float]: + """Set fit bounds from the current standard uncertainty. + + Parameters + ---------- + multiplier : float, default=8.0 + Positive finite factor applied symmetrically to the current + parameter uncertainty. + clip_to_limits : bool, default=True + Whether to clip the resolved fit bounds to the parameter's + physical lower and upper limits when those are finite. + + Returns + ------- + tuple[float, float] + The resolved ``(fit_min, fit_max)`` bounds. + + Raises + ------ + ValueError + If the current value, uncertainty, or multiplier is + missing, invalid, or produces non-increasing bounds. + """ + name = self.unique_name + value = self.value + uncertainty = self.uncertainty + + if value is None or not np.isfinite(float(value)): + msg = f'Cannot set fit bounds for {name}: current value is missing or invalid.' + raise ValueError(msg) + + if isinstance(multiplier, bool) or not np.isfinite(float(multiplier)): + msg = 'multiplier must be a positive finite number.' + raise ValueError(msg) + if float(multiplier) <= 0: + msg = 'multiplier must be a positive finite number.' + raise ValueError(msg) + + if uncertainty is None or uncertainty <= 0 or not np.isfinite(float(uncertainty)): + msg = f'Cannot set fit bounds for {name}: uncertainty is missing or invalid.' + raise ValueError(msg) + + lower = float(value) - float(multiplier) * float(uncertainty) + upper = float(value) + float(multiplier) * float(uncertainty) + + if clip_to_limits: + physical_lower = float(self._physical_lower_bound()) + physical_upper = float(self._physical_upper_bound()) + if np.isfinite(physical_lower): + lower = max(lower, physical_lower) + if np.isfinite(physical_upper): + upper = min(upper, physical_upper) + + if lower >= upper: + msg = ( + f'Cannot set fit bounds for {name}: resolved lower bound {lower} ' + f'is not below upper bound {upper}.' + ) + raise ValueError(msg) + + self.fit_min = lower + self.fit_max = upper + return lower, upper + # ====================================================================== From 46d2d813ca9c7236f50ff3fc1318c6e13970562a Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 14:18:12 +0200 Subject: [PATCH 030/106] Tighten posterior pair plot layout --- src/easydiffraction/display/plotting.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 27f394ed..51e61520 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -81,18 +81,19 @@ def description(self) -> str: POSTERIOR_POINT_ESTIMATE_LINE_COLOR = 'rgb(214, 39, 40)' POSTERIOR_DRAW_LINE_COLOR = 'rgba(140, 140, 140, 0.18)' POSTERIOR_SCATTER_MARKER_COLOR = 'rgba(140, 140, 140, 0.20)' -POSTERIOR_CONTOUR_LINE_COLOR = 'rgba(65, 85, 225, 0.85)' +POSTERIOR_CONTOUR_LINE_COLOR = 'rgba(58, 86, 224, 0.96)' POSTERIOR_CONTOUR_FILL_COLORSCALE = [ - [0.0, 'rgba(68, 1, 84, 0.00)'], - [0.35, 'rgba(68, 1, 84, 0.00)'], - [0.58, 'rgba(59, 82, 139, 0.16)'], - [0.75, 'rgba(33, 145, 140, 0.28)'], - [0.88, 'rgba(94, 201, 98, 0.38)'], - [1.0, 'rgba(253, 231, 37, 0.48)'], + [0.0, 'rgba(224, 233, 255, 0.62)'], + [0.35, 'rgba(183, 203, 255, 0.70)'], + [0.60, 'rgba(138, 169, 252, 0.78)'], + [0.82, 'rgba(96, 131, 242, 0.84)'], + [1.0, 'rgba(58, 86, 224, 0.90)'], ] PAIR_PLOT_CELL_SIZE_PIXELS = 190 PAIR_PLOT_MIN_SIZE_PIXELS = 680 PAIR_PLOT_MARGIN_PIXELS = 120 +PAIR_PLOT_SUBPLOT_SPACING = 0.015 +PAIR_PLOT_MAJOR_TICKS = 3 @dataclass(frozen=True) @@ -987,8 +988,8 @@ def _build_posterior_pairs_plot( rows=n_parameters, cols=n_parameters, shared_xaxes='columns', - horizontal_spacing=0.03, - vertical_spacing=0.03, + horizontal_spacing=PAIR_PLOT_SUBPLOT_SPACING, + vertical_spacing=PAIR_PLOT_SUBPLOT_SPACING, ) for row_index in range(n_parameters): @@ -1080,6 +1081,7 @@ def _build_posterior_pairs_plot( showline=True, mirror=True, zeroline=False, + nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', separatethousands=True, row=row, @@ -1089,6 +1091,7 @@ def _build_posterior_pairs_plot( showline=True, mirror=True, zeroline=False, + nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', separatethousands=True, row=row, From c68035573dfce2ef0cafe9d5d833daa50bfda96a Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 14:23:54 +0200 Subject: [PATCH 031/106] Make fit bounds helper a setter --- src/easydiffraction/core/variable.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/easydiffraction/core/variable.py b/src/easydiffraction/core/variable.py index 6ae427f8..cc5b9ec9 100644 --- a/src/easydiffraction/core/variable.py +++ b/src/easydiffraction/core/variable.py @@ -432,7 +432,7 @@ def set_fit_bounds_from_uncertainty( multiplier: float = 8.0, *, clip_to_limits: bool = True, - ) -> tuple[float, float]: + ) -> None: """Set fit bounds from the current standard uncertainty. Parameters @@ -444,11 +444,6 @@ def set_fit_bounds_from_uncertainty( Whether to clip the resolved fit bounds to the parameter's physical lower and upper limits when those are finite. - Returns - ------- - tuple[float, float] - The resolved ``(fit_min, fit_max)`` bounds. - Raises ------ ValueError @@ -494,7 +489,6 @@ def set_fit_bounds_from_uncertainty( self.fit_min = lower self.fit_max = upper - return lower, upper # ====================================================================== From 7fd16ced2e664ffa84d891125b3999627d45d81b Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 14:32:57 +0200 Subject: [PATCH 032/106] Refine posterior contour layering --- src/easydiffraction/display/plotting.py | 29 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 51e61520..27c85976 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -81,7 +81,6 @@ def description(self) -> str: POSTERIOR_POINT_ESTIMATE_LINE_COLOR = 'rgb(214, 39, 40)' POSTERIOR_DRAW_LINE_COLOR = 'rgba(140, 140, 140, 0.18)' POSTERIOR_SCATTER_MARKER_COLOR = 'rgba(140, 140, 140, 0.20)' -POSTERIOR_CONTOUR_LINE_COLOR = 'rgba(58, 86, 224, 0.96)' POSTERIOR_CONTOUR_FILL_COLORSCALE = [ [0.0, 'rgba(224, 233, 255, 0.62)'], [0.35, 'rgba(183, 203, 255, 0.70)'], @@ -89,6 +88,16 @@ def description(self) -> str: [0.82, 'rgba(96, 131, 242, 0.84)'], [1.0, 'rgba(58, 86, 224, 0.90)'], ] +POSTERIOR_CONTOUR_LINE_COLORSCALE = [ + [0.0, 'rgba(183, 203, 255, 0.94)'], + [0.35, 'rgba(183, 203, 255, 0.94)'], + [0.35, 'rgba(138, 169, 252, 0.95)'], + [0.60, 'rgba(138, 169, 252, 0.95)'], + [0.60, 'rgba(96, 131, 242, 0.96)'], + [0.82, 'rgba(96, 131, 242, 0.96)'], + [0.82, 'rgba(58, 86, 224, 0.98)'], + [1.0, 'rgba(58, 86, 224, 0.98)'], +] PAIR_PLOT_CELL_SIZE_PIXELS = 190 PAIR_PLOT_MIN_SIZE_PIXELS = 680 PAIR_PLOT_MARGIN_PIXELS = 120 @@ -1045,14 +1054,6 @@ def _build_posterior_pairs_plot( x_values=x_density_values, y_values=y_density_values, ) - if contour_traces is not None: - contour_traces[0].name = 'Posterior contours' - contour_traces[0].legendgroup = 'posterior-contours' - contour_traces[0].showlegend = show_contour_legend - contour_traces[1].legendgroup = 'posterior-contours' - contour_traces[1].showlegend = False - fig.add_trace(contour_traces[0], row=row, col=col) - show_contour_legend = False fig.add_trace( go.Scattergl( x=x_scatter_values, @@ -1075,7 +1076,14 @@ def _build_posterior_pairs_plot( ) show_scatter_legend = False if contour_traces is not None: + contour_traces[0].name = 'Posterior contours' + contour_traces[0].legendgroup = 'posterior-contours' + contour_traces[0].showlegend = show_contour_legend + contour_traces[1].legendgroup = 'posterior-contours' + contour_traces[1].showlegend = False + fig.add_trace(contour_traces[0], row=row, col=col) fig.add_trace(contour_traces[1], row=row, col=col) + show_contour_legend = False fig.update_xaxes( showline=True, @@ -1184,7 +1192,8 @@ def _posterior_contour_traces( 'end': contour_end, 'size': contour_size, }, - line={'color': POSTERIOR_CONTOUR_LINE_COLOR, 'width': 1.4}, + colorscale=POSTERIOR_CONTOUR_LINE_COLORSCALE, + line={'width': 0.9}, hoverinfo='skip', showscale=False, showlegend=False, From 0aaf2e9b5a8f14b46ba81f5a6755d9b9a7eb8f79 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 14:45:43 +0200 Subject: [PATCH 033/106] Fix posterior contour layering --- src/easydiffraction/display/plotting.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 27c85976..2f91fb09 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -979,7 +979,7 @@ def _build_posterior_pairs_plot( go = __import__( 'plotly.graph_objects', - fromlist=['Figure', 'Histogram', 'Scattergl', 'Contour'], + fromlist=['Figure', 'Histogram', 'Scatter', 'Contour'], ) make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots @@ -1055,7 +1055,7 @@ def _build_posterior_pairs_plot( y_values=y_density_values, ) fig.add_trace( - go.Scattergl( + go.Scatter( x=x_scatter_values, y=y_scatter_values, mode='markers', @@ -1164,10 +1164,12 @@ def _posterior_contour_traces( contour_start = float(np.max(density) * 0.20) contour_end = float(np.max(density) * 0.95) contour_size = float(np.max(density) * 0.15) + fill_density = np.array(density, copy=True) + fill_density[fill_density < contour_start] = np.nan fill_trace = go.Contour( x=x_grid, y=y_grid, - z=density, + z=fill_density, contours={ 'coloring': 'fill', 'showlabels': False, @@ -1177,6 +1179,9 @@ def _posterior_contour_traces( 'size': contour_size, }, colorscale=POSTERIOR_CONTOUR_FILL_COLORSCALE, + zmin=contour_start, + zmax=contour_end, + connectgaps=False, hoverinfo='skip', showscale=False, showlegend=False, @@ -1193,6 +1198,8 @@ def _posterior_contour_traces( 'size': contour_size, }, colorscale=POSTERIOR_CONTOUR_LINE_COLORSCALE, + zmin=contour_start, + zmax=contour_end, line={'width': 0.9}, hoverinfo='skip', showscale=False, From b4a00c38477377bd0c700035d1d9ee7b1c5bb275 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 14:58:32 +0200 Subject: [PATCH 034/106] Preserve pair plot sample hover --- src/easydiffraction/display/plotting.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 2f91fb09..0d41e9f3 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1054,6 +1054,10 @@ def _build_posterior_pairs_plot( x_values=x_density_values, y_values=y_density_values, ) + sample_hovertemplate = ( + f'{labels[col_index]}: %{{x:.4f}}
' + f'{labels[row_index]}: %{{y:.4f}}' + ) fig.add_trace( go.Scatter( x=x_scatter_values, @@ -1066,10 +1070,7 @@ def _build_posterior_pairs_plot( name='Posterior samples', legendgroup='posterior-samples', showlegend=show_scatter_legend, - hovertemplate=( - f'{labels[col_index]}: %{{x:.4f}}
' - f'{labels[row_index]}: %{{y:.4f}}' - ), + hoverinfo='skip', ), row=row, col=col, @@ -1084,6 +1085,21 @@ def _build_posterior_pairs_plot( fig.add_trace(contour_traces[0], row=row, col=col) fig.add_trace(contour_traces[1], row=row, col=col) show_contour_legend = False + fig.add_trace( + go.Scatter( + x=x_scatter_values, + y=y_scatter_values, + mode='markers', + marker={ + 'color': 'rgba(0, 0, 0, 0)', + 'size': 6, + }, + showlegend=False, + hovertemplate=sample_hovertemplate, + ), + row=row, + col=col, + ) fig.update_xaxes( showline=True, From c7de06201c2cdb6fb30820538205b2aad4d8dc60 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:04:45 +0200 Subject: [PATCH 035/106] Enforce pair plot trace z-order --- src/easydiffraction/display/plotting.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 0d41e9f3..356c617c 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1071,6 +1071,7 @@ def _build_posterior_pairs_plot( legendgroup='posterior-samples', showlegend=show_scatter_legend, hoverinfo='skip', + zorder=0, ), row=row, col=col, @@ -1096,6 +1097,7 @@ def _build_posterior_pairs_plot( }, showlegend=False, hovertemplate=sample_hovertemplate, + zorder=3, ), row=row, col=col, @@ -1201,6 +1203,7 @@ def _posterior_contour_traces( hoverinfo='skip', showscale=False, showlegend=False, + zorder=1, ) line_trace = go.Contour( x=x_grid, @@ -1220,6 +1223,7 @@ def _posterior_contour_traces( hoverinfo='skip', showscale=False, showlegend=False, + zorder=2, ) return fill_trace, line_trace From 2b501c975b196f7e05d61727ce0c35547d2521b0 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:10:37 +0200 Subject: [PATCH 036/106] Restore pair plot axis frames --- src/easydiffraction/display/plotting.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 356c617c..3b144c35 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1107,6 +1107,7 @@ def _build_posterior_pairs_plot( showline=True, mirror=True, zeroline=False, + layer='above traces', nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', separatethousands=True, @@ -1117,6 +1118,7 @@ def _build_posterior_pairs_plot( showline=True, mirror=True, zeroline=False, + layer='above traces', nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', separatethousands=True, From a71b706792cae7746a28ed5949137b051328a0db Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:16:47 +0200 Subject: [PATCH 037/106] Split posterior diagnostic warnings --- .../analysis/fit_helpers/bayesian.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index a85b3fbc..064c7e4e 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -682,8 +682,15 @@ def _posterior_table_notes( if not has_failed_r_hat and not has_failed_ess_bulk: return [] - return [ - '[red]Convergence warning:[/red] posterior diagnostics failed ' - '(r_hat > 1.01 or ess_bulk < 400). Consider longer sampling, ' - 'tighter bounds, or reparameterization.' - ] \ No newline at end of file + notes: list[str] = [] + if has_failed_r_hat: + notes.append( + f'[red]r_hat[/red]: exceeds {R_HAT_CONVERGENCE_THRESHOLD:.2f} ' + '(consider longer sampling, tighter bounds, or reparameterization).' + ) + if has_failed_ess_bulk: + notes.append( + f'[red]ess_bulk[/red]: less than {ESS_BULK_CONVERGENCE_THRESHOLD:.0f} ' + '(consider longer sampling, tighter bounds, or reparameterization).' + ) + return notes \ No newline at end of file From 62590849a0440e9a7874e044010e31b33ba11ee5 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:19:41 +0200 Subject: [PATCH 038/106] Strengthen pair plot axis borders --- src/easydiffraction/display/plotting.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 3b144c35..96fefb84 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -103,6 +103,8 @@ def description(self) -> str: PAIR_PLOT_MARGIN_PIXELS = 120 PAIR_PLOT_SUBPLOT_SPACING = 0.015 PAIR_PLOT_MAJOR_TICKS = 3 +POSTERIOR_PAIR_AXIS_LINE_COLOR = 'rgba(112, 129, 163, 0.88)' +POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 @dataclass(frozen=True) @@ -1108,6 +1110,8 @@ def _build_posterior_pairs_plot( mirror=True, zeroline=False, layer='above traces', + linecolor=POSTERIOR_PAIR_AXIS_LINE_COLOR, + linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', separatethousands=True, @@ -1119,6 +1123,8 @@ def _build_posterior_pairs_plot( mirror=True, zeroline=False, layer='above traces', + linecolor=POSTERIOR_PAIR_AXIS_LINE_COLOR, + linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', separatethousands=True, From bdcb0955a58c69261c6698e8e633f7c7c8aa2222 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:20:23 +0200 Subject: [PATCH 039/106] Free broad_gauss and set bounds from uncertainty --- tmp/bumps_dream/ed-2-bayesian-new-API.py | 42 ++++++++++-------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index 6ebdb441..13951a38 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -129,8 +129,8 @@ experiment.background.create(id='5', x=165, y=174.2813) # %% -experiment.excluded_regions.create(id='1', start=0, end=20) -experiment.excluded_regions.create(id='2', start=105, end=180) +experiment.excluded_regions.create(id='1', start=0, end=30) +experiment.excluded_regions.create(id='2', start=90, end=180) # %% experiment.linked_phases.create(id='lbco', scale=9.1351) @@ -140,6 +140,8 @@ # %% structure.cell.length_a.free = True +experiment.peak.broad_gauss_u.free = True +experiment.peak.broad_gauss_v.free = True experiment.instrument.calib_twotheta_offset.free = True # %% @@ -153,29 +155,25 @@ project.analysis.display.fit_results() # %% -project.display.plotter.plot_param_correlations() +project.display.plotter.plot_param_correlations(show_diagonal=True) # %% project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') # %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=100, x_max=102) +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=83, x_max=85) # %% [markdown] # ## Step 5: Perform Bayesian Analysis # %% -length_a = structure.cell.length_a.value -length_a_sigma = structure.cell.length_a.uncertainty or 0.001 -length_a_window = max(8.0 * length_a_sigma, 0.001) -structure.cell.length_a.fit_min = length_a - length_a_window -structure.cell.length_a.fit_max = length_a + length_a_window +project.analysis.display.free_params() -twotheta_offset = experiment.instrument.calib_twotheta_offset.value -twotheta_offset_sigma = experiment.instrument.calib_twotheta_offset.uncertainty or 0.01 -twotheta_offset_window = max(8.0 * twotheta_offset_sigma, 0.01) -experiment.instrument.calib_twotheta_offset.fit_min = twotheta_offset - twotheta_offset_window -experiment.instrument.calib_twotheta_offset.fit_max = twotheta_offset + twotheta_offset_window +# %% +structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=5) +experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=5) +experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=5) +experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=5) # %% project.analysis.display.free_params() @@ -185,8 +183,8 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' dream = project.analysis.fit.minimizer -dream.steps = 1000 -dream.burn = 200 +dream.steps = 200 #1000 +dream.burn = 50 #200 dream.thin = 1 dream.pop = 4 @@ -197,25 +195,21 @@ project.analysis.display.fit_results() # %% -project.display.plotter.plot_param_correlations() - -# %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') - -# %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=100, x_max=102) +project.display.plotter.plot_param_correlations(show_diagonal=True) # %% project.display.plotter.plot_posterior_pairs() # %% project.display.plotter.plot_param_distribution(structure.cell.length_a) +project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_u) +project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_v) project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) # %% project.display.plotter.plot_posterior_predictive(expt_name='hrpt') # %% -project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=100, x_max=102) +project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=83, x_max=85) # %% From 60bac37b3263e98072af19b7218fd72f3667b985 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:26:25 +0200 Subject: [PATCH 040/106] Draw explicit pair plot borders --- src/easydiffraction/display/plotting.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 96fefb84..4dfb51b7 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -995,6 +995,7 @@ def _build_posterior_pairs_plot( show_contour_legend = True n_parameters = len(parameter_names) + subplot_border_shapes: list[dict[str, object]] = [] fig = make_subplots( rows=n_parameters, cols=n_parameters, @@ -1138,6 +1139,25 @@ def _build_posterior_pairs_plot( if col_index == 0 and row_index > 0: fig.update_yaxes(title_text=labels[row_index], row=row, col=col) + subplot = fig.get_subplot(row, col) + subplot_border_shapes.append( + { + 'type': 'rect', + 'xref': 'paper', + 'yref': 'paper', + 'x0': subplot.xaxis.domain[0], + 'x1': subplot.xaxis.domain[1], + 'y0': subplot.yaxis.domain[0], + 'y1': subplot.yaxis.domain[1], + 'line': { + 'color': POSTERIOR_PAIR_AXIS_LINE_COLOR, + 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, + }, + 'fillcolor': 'rgba(0, 0, 0, 0)', + 'layer': 'above', + } + ) + figure_size = max( PAIR_PLOT_MIN_SIZE_PIXELS, PAIR_PLOT_CELL_SIZE_PIXELS * n_parameters + PAIR_PLOT_MARGIN_PIXELS, @@ -1147,6 +1167,7 @@ def _build_posterior_pairs_plot( bargap=0.05, width=figure_size, height=figure_size, + shapes=subplot_border_shapes, legend={ 'bgcolor': 'rgba(0, 0, 0, 0)', 'xanchor': 'right', From ca7bddef82546078e8592a5e5348ce36886da3b6 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:34:16 +0200 Subject: [PATCH 041/106] Align pair plot y-axis titles --- src/easydiffraction/display/plotting.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 4dfb51b7..0b1be094 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -105,6 +105,7 @@ def description(self) -> str: PAIR_PLOT_MAJOR_TICKS = 3 POSTERIOR_PAIR_AXIS_LINE_COLOR = 'rgba(112, 129, 163, 0.88)' POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 +POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 56 @dataclass(frozen=True) @@ -995,6 +996,7 @@ def _build_posterior_pairs_plot( show_contour_legend = True n_parameters = len(parameter_names) + subplot_title_annotations: list[dict[str, object]] = [] subplot_border_shapes: list[dict[str, object]] = [] fig = make_subplots( rows=n_parameters, @@ -1136,10 +1138,23 @@ def _build_posterior_pairs_plot( fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) if row_index == n_parameters - 1: fig.update_xaxes(title_text=labels[col_index], row=row, col=col) - if col_index == 0 and row_index > 0: - fig.update_yaxes(title_text=labels[row_index], row=row, col=col) subplot = fig.get_subplot(row, col) + if col_index == 0 and row_index > 0: + subplot_title_annotations.append( + { + 'x': subplot.xaxis.domain[0], + 'xref': 'paper', + 'xanchor': 'right', + 'xshift': -POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS, + 'y': 0.5 * (subplot.yaxis.domain[0] + subplot.yaxis.domain[1]), + 'yref': 'paper', + 'yanchor': 'middle', + 'text': labels[row_index], + 'textangle': -90, + 'showarrow': False, + } + ) subplot_border_shapes.append( { 'type': 'rect', @@ -1167,6 +1182,7 @@ def _build_posterior_pairs_plot( bargap=0.05, width=figure_size, height=figure_size, + annotations=subplot_title_annotations, shapes=subplot_border_shapes, legend={ 'bgcolor': 'rgba(0, 0, 0, 0)', From 659c30ae3757e140ab8678568d05b5c4ba8ebc77 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 15:39:17 +0200 Subject: [PATCH 042/106] Unify plot axis border colors --- src/easydiffraction/display/plotters/plotly.py | 9 +++++++++ src/easydiffraction/display/plotting.py | 15 +++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 15e1ac11..49d567af 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -161,6 +161,11 @@ def _correlation_grid_color(cls) -> str: return 'rgba(110, 145, 190, 0.35)' return 'rgba(120, 140, 160, 0.28)' + @classmethod + def _axis_frame_color(cls) -> str: + """Return the shared axis-frame color for Plotly figures.""" + return cls._correlation_grid_color() + @classmethod def _legend_background_color(cls) -> str: """Return a half-transparent legend background color.""" @@ -916,12 +921,14 @@ def _get_layout( xaxis={ 'title_text': axes_labels[0], 'showline': True, + 'linecolor': cls._axis_frame_color(), 'mirror': True, 'zeroline': False, }, yaxis={ 'title_text': axes_labels[1], 'showline': True, + 'linecolor': cls._axis_frame_color(), 'mirror': True, 'zeroline': False, }, @@ -1367,6 +1374,7 @@ def plot_powder_meas_vs_calc( x_axis_kwargs = { 'matches': 'x', 'showline': True, + 'linecolor': self._axis_frame_color(), 'mirror': True, 'zeroline': False, 'tickformat': ',.6~g', @@ -1377,6 +1385,7 @@ def plot_powder_meas_vs_calc( fig.update_xaxes(row=row_idx, col=1, **x_axis_kwargs) fig.update_yaxes( showline=True, + linecolor=self._axis_frame_color(), mirror=True, zeroline=False, tickformat=',.6~g', diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 0b1be094..f104e22a 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -103,7 +103,6 @@ def description(self) -> str: PAIR_PLOT_MARGIN_PIXELS = 120 PAIR_PLOT_SUBPLOT_SPACING = 0.015 PAIR_PLOT_MAJOR_TICKS = 3 -POSTERIOR_PAIR_AXIS_LINE_COLOR = 'rgba(112, 129, 163, 0.88)' POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 56 @@ -994,6 +993,7 @@ def _build_posterior_pairs_plot( show_density_legend = True show_scatter_legend = True show_contour_legend = True + axis_frame_color = self._plot_axis_frame_color() n_parameters = len(parameter_names) subplot_title_annotations: list[dict[str, object]] = [] @@ -1113,7 +1113,7 @@ def _build_posterior_pairs_plot( mirror=True, zeroline=False, layer='above traces', - linecolor=POSTERIOR_PAIR_AXIS_LINE_COLOR, + linecolor=axis_frame_color, linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', @@ -1126,7 +1126,7 @@ def _build_posterior_pairs_plot( mirror=True, zeroline=False, layer='above traces', - linecolor=POSTERIOR_PAIR_AXIS_LINE_COLOR, + linecolor=axis_frame_color, linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, nticks=PAIR_PLOT_MAJOR_TICKS, tickformat=',.6~g', @@ -1165,7 +1165,7 @@ def _build_posterior_pairs_plot( 'y0': subplot.yaxis.domain[0], 'y1': subplot.yaxis.domain[1], 'line': { - 'color': POSTERIOR_PAIR_AXIS_LINE_COLOR, + 'color': axis_frame_color, 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, }, 'fillcolor': 'rgba(0, 0, 0, 0)', @@ -1195,6 +1195,13 @@ def _build_posterior_pairs_plot( ) return fig + def _plot_axis_frame_color(self) -> str: + """Return the shared axis-frame color for Plotly-backed plots.""" + axis_frame_color = getattr(self._backend, '_axis_frame_color', None) + if callable(axis_frame_color): + return axis_frame_color() + return PlotlyPlotter._axis_frame_color() + def _posterior_contour_traces( self, *, From a1ad6c32d54b2c875a54711e3dc5a6b3b8b15e4c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 20:42:51 +0200 Subject: [PATCH 043/106] Lock posterior pair axis ranges --- src/easydiffraction/display/plotting.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index f104e22a..733232a6 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -994,6 +994,20 @@ def _build_posterior_pairs_plot( show_scatter_legend = True show_contour_legend = True axis_frame_color = self._plot_axis_frame_color() + parameter_axis_ranges = [ + self._posterior_axis_bounds( + density_samples[:, index], + lower_bound=self._posterior_parameter_bounds( + fit_results=fit_results, + parameter_name=parameter_names[index], + )[0], + upper_bound=self._posterior_parameter_bounds( + fit_results=fit_results, + parameter_name=parameter_names[index], + )[1], + ) + for index in range(len(parameter_names)) + ] n_parameters = len(parameter_names) subplot_title_annotations: list[dict[str, object]] = [] @@ -1111,6 +1125,7 @@ def _build_posterior_pairs_plot( fig.update_xaxes( showline=True, mirror=True, + range=list(parameter_axis_ranges[col_index]), zeroline=False, layer='above traces', linecolor=axis_frame_color, @@ -1134,6 +1149,8 @@ def _build_posterior_pairs_plot( row=row, col=col, ) + if row_index != col_index: + fig.update_yaxes(range=list(parameter_axis_ranges[row_index]), row=row, col=col) fig.update_xaxes(showticklabels=(row_index == n_parameters - 1), row=row, col=col) fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) if row_index == n_parameters - 1: From e87055e51971c09bf80256d8ae18620e05756094 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 21:13:58 +0200 Subject: [PATCH 044/106] Align pair plot title with modebar --- src/easydiffraction/display/plotting.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 733232a6..c2b111f7 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1195,7 +1195,13 @@ def _build_posterior_pairs_plot( PAIR_PLOT_CELL_SIZE_PIXELS * n_parameters + PAIR_PLOT_MARGIN_PIXELS, ) fig.update_layout( - title='Posterior pair plot', + margin={ + 'autoexpand': True, + 'r': 30, + 't': 40, + 'b': 45, + }, + title={'text': 'Posterior pair plot'}, bargap=0.05, width=figure_size, height=figure_size, From 2d58e561eadc2747836c8921e54cded07e9fbb0c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 21:23:42 +0200 Subject: [PATCH 045/106] Update diagonal subplot axis styling --- src/easydiffraction/display/plotting.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index c2b111f7..21b1eeaa 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1033,7 +1033,8 @@ def _build_posterior_pairs_plot( y_density_values = density_samples[:, row_index] x_scatter_values = scatter_samples[:, col_index] y_scatter_values = scatter_samples[:, row_index] - if row_index == col_index: + is_diagonal_subplot = row_index == col_index + if is_diagonal_subplot: density_trace = self._posterior_density_trace( fit_results=fit_results, parameter_name=parameter_names[col_index], @@ -1149,10 +1150,17 @@ def _build_posterior_pairs_plot( row=row, col=col, ) - if row_index != col_index: + if not is_diagonal_subplot: fig.update_yaxes(range=list(parameter_axis_ranges[row_index]), row=row, col=col) fig.update_xaxes(showticklabels=(row_index == n_parameters - 1), row=row, col=col) - fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) + fig.update_yaxes( + showticklabels=(col_index == 0 and not is_diagonal_subplot), + ticks='' if is_diagonal_subplot else None, + row=row, + col=col, + ) + if row_index == 0 and col_index == 0: + fig.update_yaxes(title_text='Probability density', row=row, col=col) if row_index == n_parameters - 1: fig.update_xaxes(title_text=labels[col_index], row=row, col=col) From 1da1f2e5cb63ec37b8ba8dc5ec0b4864a829f66f Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 21:35:54 +0200 Subject: [PATCH 046/106] Expose DREAM init and align pair labels --- .../analysis/minimizers/__init__.py | 1 + .../analysis/minimizers/bumps_dream.py | 31 +++++++++++++++++++ .../analysis/minimizers/enums.py | 9 ++++++ src/easydiffraction/display/plotting.py | 22 +++++++------ 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/easydiffraction/analysis/minimizers/__init__.py b/src/easydiffraction/analysis/minimizers/__init__.py index 7639dd8a..1006eefb 100644 --- a/src/easydiffraction/analysis/minimizers/__init__.py +++ b/src/easydiffraction/analysis/minimizers/__init__.py @@ -7,6 +7,7 @@ from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer from easydiffraction.analysis.minimizers.bumps_lm import BumpsLmMinimizer from easydiffraction.analysis.minimizers.dfols import DfolsMinimizer +from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum from easydiffraction.analysis.minimizers.lmfit import LmfitMinimizer from easydiffraction.analysis.minimizers.lmfit_least_squares import LmfitLeastSquaresMinimizer from easydiffraction.analysis.minimizers.lmfit_leastsq import LmfitLeastsqMinimizer diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 2ea64fe1..0ad88ef9 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -20,6 +20,7 @@ from easydiffraction.analysis.fit_helpers.bayesian import summarize_posterior_parameters from easydiffraction.analysis.minimizers.bumps import _EasyDiffractionFitness from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer +from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum from easydiffraction.analysis.minimizers.factory import MinimizerFactory from easydiffraction.core.metadata import TypeInfo @@ -31,6 +32,7 @@ DEFAULT_MIN_BURN = 50 DEFAULT_THIN = 1 DEFAULT_POP = 4 +DEFAULT_INIT = DreamPopulationInitializationEnum.EPS DEFAULT_ALPHA = 0.0 DEFAULT_OUTLIER_TEST = 'none' DEFAULT_TRIM = False @@ -220,6 +222,7 @@ def __init__( self._burn: int | None = None self._thin: int = DEFAULT_THIN self._pop: int = DEFAULT_POP + self._init: DreamPopulationInitializationEnum = DEFAULT_INIT @property def steps(self) -> int: @@ -260,6 +263,15 @@ def pop(self) -> int: def pop(self, value: int) -> None: self._pop = self._validated_positive_integer('pop', value) + @property + def init(self) -> DreamPopulationInitializationEnum: + """DREAM population initializer.""" + return self._init + + @init.setter + def init(self, value: DreamPopulationInitializationEnum | str) -> None: + self._init = self._validated_init(value) + def _resolve_random_seed(self, random_seed: int | None) -> int: """Return a user-provided or generated random seed. @@ -335,6 +347,20 @@ def _validated_non_negative_integer(name: str, value: int | float) -> int: raise ValueError(msg) return integer_value + @staticmethod + def _validated_init( + value: DreamPopulationInitializationEnum | str, + ) -> DreamPopulationInitializationEnum: + """Validate a DREAM population initializer.""" + try: + return DreamPopulationInitializationEnum(value) + except ValueError: + valid_values = ', '.join( + initialization.value for initialization in DreamPopulationInitializationEnum + ) + msg = f"DREAM setting 'init' must be one of: {valid_values}." + raise ValueError(msg) from None + def _resolved_burn(self, steps: int) -> int: """Return the configured or automatic DREAM burn-in length.""" if self.burn is None: @@ -355,6 +381,7 @@ def _sampler_settings( burn: int, thin: int, pop: int, + init: DreamPopulationInitializationEnum, n_parameters: int, ) -> dict[str, object]: """Build the sampler settings dictionary recorded in results.""" @@ -365,6 +392,7 @@ def _sampler_settings( 'burn': int(burn), 'thin': int(thin), 'pop': int(pop), + 'init': init.value, 'samples': int(samples), 'alpha': float(DEFAULT_ALPHA), 'outliers': DEFAULT_OUTLIER_TEST, @@ -405,12 +433,14 @@ def _run_solver( burn = self._resolved_burn(steps) thin = self.thin pop = self.pop + init = self.init sampler_settings = self._sampler_settings( random_seed=int(random_seed), steps=steps, burn=burn, thin=thin, pop=pop, + init=init, n_parameters=len(bumps_params), ) total_generations = int(steps + burn + 1) @@ -429,6 +459,7 @@ def _run_solver( burn=burn, thin=thin, pop=pop, + init=init.value, samples=sampler_settings['samples'], alpha=DEFAULT_ALPHA, outliers=DEFAULT_OUTLIER_TEST, diff --git a/src/easydiffraction/analysis/minimizers/enums.py b/src/easydiffraction/analysis/minimizers/enums.py index 5d8ad218..0d5bb086 100644 --- a/src/easydiffraction/analysis/minimizers/enums.py +++ b/src/easydiffraction/analysis/minimizers/enums.py @@ -51,3 +51,12 @@ def description(self) -> str: MinimizerTypeEnum.BUMPS_DE: ('BUMPS library with differential evolution method'), } return descriptions.get(self, '') + + +class DreamPopulationInitializationEnum(StrEnum): + """Supported DREAM population initializers.""" + + EPS = 'eps' + COV = 'cov' + LHS = 'lhs' + RANDOM = 'random' diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 21b1eeaa..08785cfe 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1153,19 +1153,23 @@ def _build_posterior_pairs_plot( if not is_diagonal_subplot: fig.update_yaxes(range=list(parameter_axis_ranges[row_index]), row=row, col=col) fig.update_xaxes(showticklabels=(row_index == n_parameters - 1), row=row, col=col) - fig.update_yaxes( - showticklabels=(col_index == 0 and not is_diagonal_subplot), - ticks='' if is_diagonal_subplot else None, - row=row, - col=col, - ) - if row_index == 0 and col_index == 0: - fig.update_yaxes(title_text='Probability density', row=row, col=col) + if is_diagonal_subplot: + fig.update_yaxes( + showticklabels=False, + ticks='', + ticklen=0, + showgrid=False, + title_text=None, + row=row, + col=col, + ) + else: + fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) if row_index == n_parameters - 1: fig.update_xaxes(title_text=labels[col_index], row=row, col=col) subplot = fig.get_subplot(row, col) - if col_index == 0 and row_index > 0: + if col_index == 0: subplot_title_annotations.append( { 'x': subplot.xaxis.domain[0], From 9cc934388d3d8e3e9d04698d8f5bf498344b0165 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 21:43:28 +0200 Subject: [PATCH 047/106] Tighten fit bounds multiplier from 5 to 4 --- tmp/bumps_dream/ed-2-bayesian-new-API.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index 13951a38..d4c6a910 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -170,10 +170,10 @@ project.analysis.display.free_params() # %% -structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=5) -experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=5) -experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=5) -experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=5) +structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=4) +experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=4) +experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=4) +experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=4) # %% project.analysis.display.free_params() From f4aa5ef331e6f0dca09ae7c42287fa78fad2881e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 21:54:28 +0200 Subject: [PATCH 048/106] Match pair plot axis title font sizes --- src/easydiffraction/display/plotting.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 08785cfe..35b0b33b 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -104,6 +104,7 @@ def description(self) -> str: PAIR_PLOT_SUBPLOT_SPACING = 0.015 PAIR_PLOT_MAJOR_TICKS = 3 POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 +POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE = 14 POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 56 @@ -1180,6 +1181,7 @@ def _build_posterior_pairs_plot( 'yref': 'paper', 'yanchor': 'middle', 'text': labels[row_index], + 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, 'textangle': -90, 'showarrow': False, } From ae98ffe918b7f550728ba3a10a8c5793987751d8 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 22:00:01 +0200 Subject: [PATCH 049/106] Disable Rich highlighting in Bayesian summaries --- src/easydiffraction/analysis/fit_helpers/bayesian.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 064c7e4e..4815a2c2 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -8,6 +8,7 @@ import arviz as az import numpy as np +from rich.text import Text from easydiffraction.analysis.fit_helpers.metrics import calculate_r_factor from easydiffraction.analysis.fit_helpers.metrics import calculate_r_factor_squared @@ -313,11 +314,11 @@ def display_results( sampler_settings = _format_sampler_settings(self.sampler_settings) if sampler_settings is not None: - console.print(f'βš™οΈ Sampler settings: {sampler_settings}') + console.print(Text(f'βš™οΈ Sampler settings: {sampler_settings}')) convergence_summary = _format_convergence_summary(self.convergence_diagnostics) if convergence_summary is not None: - console.print(f'πŸ“Š Convergence: {convergence_summary}') + console.print(Text.from_markup(f'πŸ“Š Convergence: {convergence_summary}')) if rf is not None: console.print(f'πŸ“ R-factor (Rf): {rf:.2f}%') From e5dd8b6f02aff87201c6a43ee8579b52a515e246 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 22:12:27 +0200 Subject: [PATCH 050/106] Tune DREAM and model parameters in fit --- tmp/bumps_dream/ed-2-bayesian-new-API.py | 26 +++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index d4c6a910..31c8a182 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -47,7 +47,7 @@ structure.space_group.it_coordinate_system_code = '1' # %% -structure.cell.length_a = 3.8909 +structure.cell.length_a = 3.88 # %% structure.atom_sites.create( @@ -113,11 +113,11 @@ # %% experiment.instrument.setup_wavelength = 1.494 -experiment.instrument.calib_twotheta_offset = 0.6226 +experiment.instrument.calib_twotheta_offset = 0.0 # %% -experiment.peak.broad_gauss_u = 0.0816 -experiment.peak.broad_gauss_v = -0.1159 +experiment.peak.broad_gauss_u = 0.1 +experiment.peak.broad_gauss_v = -0.1 experiment.peak.broad_gauss_w = 0.1204 experiment.peak.broad_lorentz_y = 0.0844 @@ -130,7 +130,7 @@ # %% experiment.excluded_regions.create(id='1', start=0, end=30) -experiment.excluded_regions.create(id='2', start=90, end=180) +experiment.excluded_regions.create(id='2', start=70, end=180) # %% experiment.linked_phases.create(id='lbco', scale=9.1351) @@ -161,7 +161,7 @@ project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') # %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=83, x_max=85) +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) # %% [markdown] # ## Step 5: Perform Bayesian Analysis @@ -180,13 +180,15 @@ # %% project.analysis.fit.show_minimizer_types() + +# %% project.analysis.fit.minimizer_type = 'bumps (dream)' -dream = project.analysis.fit.minimizer -dream.steps = 200 #1000 -dream.burn = 50 #200 -dream.thin = 1 -dream.pop = 4 +# %% +project.analysis.fit.minimizer.steps = 200 #1000 +project.analysis.fit.minimizer.burn = 40 #200 +project.analysis.fit.minimizer.thin = 1 +project.analysis.fit.minimizer.pop = 4 # %% project.analysis.fit() @@ -210,6 +212,6 @@ project.display.plotter.plot_posterior_predictive(expt_name='hrpt') # %% -project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=83, x_max=85) +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) # %% From 29f9db74f6cd9143ee4e0f88e594a57afd59f259 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 8 May 2026 22:13:53 +0200 Subject: [PATCH 051/106] Expand Bayesian tutorial walkthrough --- tmp/bumps_dream/ed-2-bayesian-new-API.py | 161 +++++++++++++++++++---- 1 file changed, 137 insertions(+), 24 deletions(-) diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index 31c8a182..8472c994 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -1,25 +1,25 @@ # %% [markdown] -# # Structure Refinement: LBCO, HRPT +# # Deterministic and Bayesian Refinement: LBCO, HRPT # -# This minimalistic example is designed to show how Rietveld refinement -# can be performed when both the crystal structure and experiment are -# defined directly in code. Only the experimentally measured data is -# loaded from an external file. It also shows how to switch calculation -# engine. +# This tutorial demonstrates a practical two-stage workflow for powder +# diffraction analysis with EasyDiffraction. # -# For this example, constant-wavelength neutron powder diffraction data -# for La0.5Ba0.5CoO3 from HRPT at PSI is used. +# In the first stage, we run a fast local refinement to obtain a sensible +# point estimate and parameter uncertainties. In the second stage, we use +# these refined values to define fit bounds and then sample the posterior +# distribution with DREAM. # -# It does not contain any advanced features or options, and includes no -# comments or explanations β€” these can be found in the other tutorials. -# Default values are used for all parameters if not specified. Only -# essential and self-explanatory code is provided. +# The example uses constant-wavelength neutron powder diffraction data +# for La0.5Ba0.5CoO3 measured on HRPT at PSI. # -# The example is intended for users who are already familiar with the -# EasyDiffraction library and want to quickly get started with a simple -# refinement. It is also useful for those who want to see what a -# refinement might look like in code. For a more detailed explanation of -# the code, please refer to the other tutorials. +# The goal is not only to obtain a good fit, but also to answer Bayesian +# questions such as: +# +# - Which parameter values are most probable? +# - How broad are the credible intervals? +# - Which parameters are strongly correlated? +# - How much uncertainty propagates into the calculated diffraction +# pattern? # %% [markdown] # ## Import Library @@ -28,13 +28,21 @@ import easydiffraction as ed # %% [markdown] -# ## Step 1: Define Project +# ## Step 1: Create a Project Container +# +# The project object keeps structures, experiments, fit settings, and +# plotting utilities together in a single place. We will build the full +# workflow inside this object. # %% project = ed.Project() # %% [markdown] -# ## Step 2: Define Structure +# ## Step 2: Build the Structural Model +# +# We define a simple cubic perovskite model for LBCO. La and Ba share the +# same crystallographic site with equal occupancy, while Co and O occupy +# the remaining ideal perovskite positions. # %% project.structures.create(name='lbco') @@ -49,6 +57,11 @@ # %% structure.cell.length_a = 3.88 +# %% [markdown] +# The atom-site definitions below form the starting structural model. The +# parameters are intentionally reasonable rather than fully optimized, +# because the refinement step will improve them. + # %% structure.atom_sites.create( label='La', @@ -94,11 +107,21 @@ ) # %% [markdown] -# ## Step 3: Define Experiment +# ## Step 3: Define the Diffraction Experiment +# +# Next we download the measured powder pattern, create a neutron powder +# experiment, and configure the instrument, profile, background, and +# excluded regions. + +# %% [markdown] +# #### Download the Measured Data # %% data_path = ed.download_data(id=3, destination='data') +# %% [markdown] +# #### Create the Experiment Object + # %% project.experiments.add_from_data_path( name='hrpt', @@ -111,6 +134,12 @@ # %% experiment = project.experiments['hrpt'] +# %% [markdown] +# #### Set Instrument and Peak-Profile Parameters +# +# These values provide the initial instrument description for the local +# refinement. Later, a subset of them will be refined. + # %% experiment.instrument.setup_wavelength = 1.494 experiment.instrument.calib_twotheta_offset = 0.0 @@ -121,6 +150,12 @@ experiment.peak.broad_gauss_w = 0.1204 experiment.peak.broad_lorentz_y = 0.0844 +# %% [markdown] +# #### Add Background Points and Excluded Regions +# +# The line-segment background is defined by a few anchor points. We also +# exclude regions that are not intended to contribute to the fit. + # %% experiment.background.create(id='1', x=10, y=168.5585) experiment.background.create(id='2', x=30, y=164.3357) @@ -132,11 +167,25 @@ experiment.excluded_regions.create(id='1', start=0, end=30) experiment.excluded_regions.create(id='2', start=70, end=180) +# %% [markdown] +# #### Link the Structural Phase to the Experiment + # %% experiment.linked_phases.create(id='lbco', scale=9.1351) # %% [markdown] -# ## Step 4: Perform Analysis +# ## Step 4: Run an Initial Local Refinement +# +# Before Bayesian sampling, it is useful to run a deterministic fit. This +# gives us: +# +# - a good point estimate near the best-fit region, +# - uncertainties from the local optimizer, +# - a quick check that the model and experiment are configured +# sensibly. +# +# In this tutorial we refine only a small set of parameters that are easy +# to interpret in the later Bayesian stage. # %% structure.cell.length_a.free = True @@ -144,6 +193,11 @@ experiment.peak.broad_gauss_v.free = True experiment.instrument.calib_twotheta_offset.free = True +# %% [markdown] +# We choose the BUMPS Levenberg-Marquardt minimizer as a fast local +# optimizer. Its main purpose here is to provide a stable starting point +# and uncertainty estimates for the Bayesian run. + # %% project.analysis.fit.show_minimizer_types() project.analysis.fit.minimizer_type = 'bumps (lm)' @@ -154,6 +208,12 @@ # %% project.analysis.display.fit_results() +# %% [markdown] +# The correlation plot shows how strongly the fitted parameters move +# together in the local refinement. The measured-vs-calculated plots show +# how well the refined model reproduces the data globally and in a zoomed +# region. + # %% project.display.plotter.plot_param_correlations(show_diagonal=True) @@ -164,7 +224,15 @@ project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) # %% [markdown] -# ## Step 5: Perform Bayesian Analysis +# ## Step 5: Prepare for Bayesian Sampling +# +# DREAM requires finite bounds for the free parameters. Instead of +# setting them manually, we derive them from the uncertainties estimated +# in the local refinement. +# +# The helper method `set_fit_bounds_from_uncertainty` centers the bounds +# on the current parameter value and expands them by a chosen multiple of +# the reported uncertainty. # %% project.analysis.display.free_params() @@ -175,9 +243,25 @@ experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=4) experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=4) +# %% [markdown] +# Displaying the free parameters again is a convenient way to confirm +# that the fit bounds have been assigned as expected before launching the +# sampler. + # %% project.analysis.display.free_params() +# %% [markdown] +# ## Step 6: Configure and Run DREAM +# +# We now switch from the local minimizer to the Bayesian DREAM sampler. +# +# The settings below are intentionally small so the tutorial runs +# quickly. For production analysis you would usually increase the number +# of steps and often the burn-in as well. When needed, the DREAM API +# also lets you tune how chains are initialized through the `init` +# setting. + # %% project.analysis.fit.show_minimizer_types() @@ -193,25 +277,54 @@ # %% project.analysis.fit() +# %% [markdown] +# ## Step 7: Inspect Bayesian Results +# +# The fit-results display now includes sampler settings, convergence +# diagnostics, committed parameter values, and posterior summary +# statistics. + # %% project.analysis.display.fit_results() +# %% [markdown] +# The correlation and posterior-pair plots are complementary: +# +# - `plot_param_correlations` summarizes pairwise structure in a compact +# matrix. +# - `plot_posterior_pairs` shows marginal densities on the diagonal and +# posterior contours off-diagonal. + # %% project.display.plotter.plot_param_correlations(show_diagonal=True) # %% project.display.plotter.plot_posterior_pairs() +# %% [markdown] +# The one-dimensional posterior distributions below make it easier to +# inspect individual parameters in isolation, including asymmetry or +# multimodality. + # %% project.display.plotter.plot_param_distribution(structure.cell.length_a) project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_u) project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_v) project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) +# %% [markdown] +# Finally, the posterior predictive plot propagates the sampled parameter +# uncertainty into the calculated diffraction pattern. Comparing this to +# the zoomed measured-vs-calculated view helps assess whether the sampled +# model family explains the data in the region of interest. + # %% project.display.plotter.plot_posterior_predictive(expt_name='hrpt') -# %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) +# %% [markdown] +# A final zoomed measured-vs-calculated plot is useful for checking how +# the posterior-supported model behaves in a narrow region of the pattern +# after the Bayesian run. # %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) From af27c2f4a1d97c3a271879214d4b008d5514915e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sat, 9 May 2026 00:04:41 +0200 Subject: [PATCH 052/106] Apply linting rules and formatting --- docs/dev/architecture.md | 44 +- docs/dev/package-structure-full.md | 17 +- docs/dev/package-structure-short.md | 2 + .../analysis/fit_helpers/bayesian.py | 270 ++-- .../analysis/fit_helpers/reporting.py | 12 +- .../analysis/fit_helpers/tracking.py | 359 +++-- .../analysis/minimizers/base.py | 9 +- .../analysis/minimizers/bumps_dream.py | 377 ++++-- src/easydiffraction/core/variable.py | 7 +- .../display/plotters/plotly.py | 415 ++++-- src/easydiffraction/display/plotting.py | 1156 +++++++++++------ .../fitting/test_bayesian_dream.py | 178 +++ .../analysis/fit_helpers/test_bayesian.py | 188 +++ .../analysis/minimizers/test_bumps.py | 12 + .../analysis/minimizers/test_bumps_dream.py | 236 ++++ .../analysis/minimizers/test_enums.py | 7 + .../analysis/minimizers/test_factory.py | 12 +- .../easydiffraction/core/test_parameters.py | 65 + .../easydiffraction/display/test_plotting.py | 168 +++ tmp/bumps_dream/ed-2-bayesian-new-API.py | 3 + 20 files changed, 2645 insertions(+), 892 deletions(-) create mode 100644 tests/integration/fitting/test_bayesian_dream.py create mode 100644 tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py create mode 100644 tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index dbfe59c8..8c30e378 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md @@ -527,28 +527,28 @@ from .line_segment import LineSegmentBackground ### 5.5 All Factories -| Factory | Domain | Tags resolve to | -| --- | --- | --- | -| `BackgroundFactory` | Background categories | `LineSegmentBackground`, `ChebyshevPolynomialBackground` | -| `PeakFactory` | Peak profiles | `CwlPseudoVoigt`, `TofJorgensen`, `TofJorgensenVonDreele`, … | -| `InstrumentFactory` | Instruments | `CwlPdInstrument`, `TofPdInstrument`, … | -| `DataFactory` | Data collections | `PdCwlData`, `PdTofData`, `TotalData` | -| `ReflnFactory` | Reflection collections | `ReflnData`, `PowderCwlReflnData`, `PowderTofReflnData` | -| `ExtinctionFactory` | Extinction models | `BeckerCoppensExtinction` | -| `LinkedCrystalFactory` | Linked-crystal refs | `LinkedCrystal` | -| `ExcludedRegionsFactory` | Excluded regions | `ExcludedRegions` | -| `LinkedPhasesFactory` | Linked phases | `LinkedPhases` | -| `ExperimentTypeFactory` | Experiment descriptors | `ExperimentType` | -| `CellFactory` | Unit cells | `Cell` | -| `SpaceGroupFactory` | Space groups | `SpaceGroup` | -| `AtomSitesFactory` | Atom sites | `AtomSites` | -| `AtomSiteAnisoFactory` | Anisotropic ADPs | `AtomSiteAnisoCollection` | -| `AliasesFactory` | Parameter aliases | `Aliases` | -| `ConstraintsFactory` | Parameter constraints | `Constraints` | -| `FitModeFactory` | Fit-mode category | `FitMode` | -| `JointFitExperimentsFactory` | Joint-fit weights | `JointFitExperiments` | -| `CalculatorFactory` | Calculation engines | `CryspyCalculator`, `CrysfmlCalculator`, `PdffitCalculator` | -| `MinimizerFactory` | Minimisers | `LmfitMinimizer`, `LmfitLeastsqMinimizer`, `LmfitLeastSquaresMinimizer`, `DfolsMinimizer`, `BumpsMinimizer`, `BumpsLmMinimizer`, `BumpsDreamMinimizer`, `BumpsAmoebaMinimizer`, `BumpsDEMinimizer` | +| Factory | Domain | Tags resolve to | +| ---------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `BackgroundFactory` | Background categories | `LineSegmentBackground`, `ChebyshevPolynomialBackground` | +| `PeakFactory` | Peak profiles | `CwlPseudoVoigt`, `TofJorgensen`, `TofJorgensenVonDreele`, … | +| `InstrumentFactory` | Instruments | `CwlPdInstrument`, `TofPdInstrument`, … | +| `DataFactory` | Data collections | `PdCwlData`, `PdTofData`, `TotalData` | +| `ReflnFactory` | Reflection collections | `ReflnData`, `PowderCwlReflnData`, `PowderTofReflnData` | +| `ExtinctionFactory` | Extinction models | `BeckerCoppensExtinction` | +| `LinkedCrystalFactory` | Linked-crystal refs | `LinkedCrystal` | +| `ExcludedRegionsFactory` | Excluded regions | `ExcludedRegions` | +| `LinkedPhasesFactory` | Linked phases | `LinkedPhases` | +| `ExperimentTypeFactory` | Experiment descriptors | `ExperimentType` | +| `CellFactory` | Unit cells | `Cell` | +| `SpaceGroupFactory` | Space groups | `SpaceGroup` | +| `AtomSitesFactory` | Atom sites | `AtomSites` | +| `AtomSiteAnisoFactory` | Anisotropic ADPs | `AtomSiteAnisoCollection` | +| `AliasesFactory` | Parameter aliases | `Aliases` | +| `ConstraintsFactory` | Parameter constraints | `Constraints` | +| `FitModeFactory` | Fit-mode category | `FitMode` | +| `JointFitExperimentsFactory` | Joint-fit weights | `JointFitExperiments` | +| `CalculatorFactory` | Calculation engines | `CryspyCalculator`, `CrysfmlCalculator`, `PdffitCalculator` | +| `MinimizerFactory` | Minimisers | `LmfitMinimizer`, `LmfitLeastsqMinimizer`, `LmfitLeastSquaresMinimizer`, `DfolsMinimizer`, `BumpsMinimizer`, `BumpsLmMinimizer`, `BumpsDreamMinimizer`, `BumpsAmoebaMinimizer`, `BumpsDEMinimizer` | > **Note:** `ExperimentFactory` and `StructureFactory` are _builder_ > factories with `from_cif_path`, `from_cif_str`, `from_data_path`, and diff --git a/docs/dev/package-structure-full.md b/docs/dev/package-structure-full.md index be35bb07..d1901351 100644 --- a/docs/dev/package-structure-full.md +++ b/docs/dev/package-structure-full.md @@ -49,10 +49,16 @@ β”‚ β”‚ └── πŸ“„ __init__.py β”‚ β”œβ”€β”€ πŸ“ fit_helpers β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py +β”‚ β”‚ β”œβ”€β”€ πŸ“„ bayesian.py +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PosteriorParameterSummary +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PosteriorPredictiveSummary +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PosteriorSamples +β”‚ β”‚ β”‚ └── 🏷️ class BayesianFitResults β”‚ β”‚ β”œβ”€β”€ πŸ“„ metrics.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ reporting.py β”‚ β”‚ β”‚ └── 🏷️ class FitResults β”‚ β”‚ └── πŸ“„ tracking.py +β”‚ β”‚ β”œβ”€β”€ 🏷️ class SamplerProgressUpdate β”‚ β”‚ β”œβ”€β”€ 🏷️ class _TerminalLiveHandle β”‚ β”‚ └── 🏷️ class FitProgressTracker β”‚ β”œβ”€β”€ πŸ“ minimizers @@ -66,12 +72,18 @@ β”‚ β”‚ β”‚ └── 🏷️ class BumpsAmoebaMinimizer β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_de.py β”‚ β”‚ β”‚ └── 🏷️ class BumpsDEMinimizer +β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_dream.py +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class _DreamRunContext +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class _DreamDriverResult +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class _DreamProgressMonitor +β”‚ β”‚ β”‚ └── 🏷️ class BumpsDreamMinimizer β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_lm.py β”‚ β”‚ β”‚ └── 🏷️ class BumpsLmMinimizer β”‚ β”‚ β”œβ”€β”€ πŸ“„ dfols.py β”‚ β”‚ β”‚ └── 🏷️ class DfolsMinimizer β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py -β”‚ β”‚ β”‚ └── 🏷️ class MinimizerTypeEnum +β”‚ β”‚ β”‚ β”œβ”€β”€ 🏷️ class MinimizerTypeEnum +β”‚ β”‚ β”‚ └── 🏷️ class DreamPopulationInitializationEnum β”‚ β”‚ β”œβ”€β”€ πŸ“„ factory.py β”‚ β”‚ β”‚ └── 🏷️ class MinimizerFactory β”‚ β”‚ β”œβ”€β”€ πŸ“„ lmfit.py @@ -366,6 +378,9 @@ β”‚ β”‚ β”œβ”€β”€ 🏷️ class PlotterEngineEnum β”‚ β”‚ β”œβ”€β”€ 🏷️ class _MeasVsCalcPlotOptions β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PowderMeasVsCalcSeries +β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PosteriorDistributionContext +β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PosteriorPairsContext +β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PosteriorPairsLegendState β”‚ β”‚ β”œβ”€β”€ 🏷️ class Plotter β”‚ β”‚ └── 🏷️ class PlotterFactory β”‚ β”œβ”€β”€ πŸ“„ tables.py diff --git a/docs/dev/package-structure-short.md b/docs/dev/package-structure-short.md index ba2a0b33..9ce283eb 100644 --- a/docs/dev/package-structure-short.md +++ b/docs/dev/package-structure-short.md @@ -31,6 +31,7 @@ β”‚ β”‚ └── πŸ“„ __init__.py β”‚ β”œβ”€β”€ πŸ“ fit_helpers β”‚ β”‚ β”œβ”€β”€ πŸ“„ __init__.py +β”‚ β”‚ β”œβ”€β”€ πŸ“„ bayesian.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ metrics.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ reporting.py β”‚ β”‚ └── πŸ“„ tracking.py @@ -40,6 +41,7 @@ β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_amoeba.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_de.py +β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_dream.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ bumps_lm.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ dfols.py β”‚ β”‚ β”œβ”€β”€ πŸ“„ enums.py diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 4815a2c2..243ce872 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -14,22 +14,29 @@ from easydiffraction.analysis.fit_helpers.metrics import calculate_r_factor_squared from easydiffraction.analysis.fit_helpers.metrics import calculate_rb_factor from easydiffraction.analysis.fit_helpers.metrics import calculate_weighted_r_factor +from easydiffraction.analysis.fit_helpers.reporting import FitResults from easydiffraction.analysis.fit_helpers.reporting import _build_parameter_row from easydiffraction.analysis.fit_helpers.reporting import _format_optional_float -from easydiffraction.analysis.fit_helpers.reporting import FitResults from easydiffraction.utils.logging import console from easydiffraction.utils.logging import log from easydiffraction.utils.utils import render_table R_HAT_CONVERGENCE_THRESHOLD = 1.01 ESS_BULK_CONVERGENCE_THRESHOLD = 400.0 +POSTERIOR_SAMPLE_NDIM = 3 +DEFAULT_CI_LEVELS = (0.68, 0.95) +DEFAULT_CREDIBLE_INTERVAL_LEVELS = DEFAULT_CI_LEVELS +IntervalLevels = tuple[float, ...] +SettingsMap = dict[str, object] | None +DiagnosticsMap = dict[str, object] | None @dataclass(slots=True) class PosteriorParameterSummary: - """Posterior summary statistics for one fitted parameter. + r""" + Posterior summary statistics for one fitted parameter. - Parameters + Attributes ---------- unique_name : str Unique parameter name used across EasyDiffraction. @@ -48,7 +55,7 @@ class PosteriorParameterSummary: ess_bulk : float | None, default=None Bulk effective sample size when available. r_hat : float | None, default=None - Rank-normalized split-$\\hat{R}$ when available. + Rank-normalized split-$\hat{R}$ when available. """ unique_name: str @@ -64,9 +71,10 @@ class PosteriorParameterSummary: @dataclass(slots=True) class PosteriorPredictiveSummary: - """Posterior predictive summaries for one experiment. + """ + Posterior predictive summaries for one experiment. - Parameters + Attributes ---------- experiment_name : str Experiment identifier. @@ -101,9 +109,10 @@ class PosteriorPredictiveSummary: @dataclass(slots=True) class PosteriorSamples: - """Posterior samples and sample statistics from a Bayesian fit. + """ + Posterior samples and sample statistics from a Bayesian fit. - Parameters + Attributes ---------- parameter_names : list[str] Parameter names in the preserved EasyDiffraction order. @@ -123,7 +132,8 @@ class PosteriorSamples: draw_index: np.ndarray | None = None def flattened(self) -> np.ndarray: - """Return flattened posterior samples by parameter. + """ + Return flattened posterior samples by parameter. Returns ------- @@ -133,7 +143,8 @@ def flattened(self) -> np.ndarray: return np.asarray(self.parameter_samples).reshape(-1, len(self.parameter_names)) def to_arviz(self) -> object: - """Convert posterior samples to an ArviZ ``InferenceData`` object. + """ + Convert posterior samples to an ArviZ ``InferenceData`` object. Returns ------- @@ -146,10 +157,8 @@ def to_arviz(self) -> object: ValueError If the stored arrays do not have the expected shapes. """ - import arviz as az - posterior_array = np.asarray(self.parameter_samples, dtype=float) - if posterior_array.ndim != 3: + if posterior_array.ndim != POSTERIOR_SAMPLE_NDIM: msg = 'Posterior sample array must have shape (n_draws, n_chains, n_parameters).' raise ValueError(msg) @@ -178,10 +187,16 @@ def to_arviz(self) -> object: return az.from_dict(data) +SummaryList = list[PosteriorParameterSummary] | None +PredictiveMap = dict[str, PosteriorPredictiveSummary] | None + + +@dataclass(kw_only=True) class BayesianFitResults(FitResults): - """Container for Bayesian fit results and posterior summaries. + """ + Container for Bayesian fit results and posterior summaries. - Parameters + Attributes ---------- success : bool, default=False Whether the Bayesian fit produced usable posterior results. @@ -201,15 +216,15 @@ class BayesianFitResults(FitResults): Name of the point estimate committed back to the project. posterior_samples : PosteriorSamples | None, default=None Stored posterior samples. - posterior_parameter_summaries : list[PosteriorParameterSummary] | None, default=None + posterior_parameter_summaries : SummaryList, default=None Posterior summaries for each sampled parameter. - posterior_predictive : dict[str, PosteriorPredictiveSummary] | None, default=None + posterior_predictive : PredictiveMap, default=None Posterior predictive summaries keyed by experiment name. - credible_interval_levels : tuple[float, ...], default=(0.68, 0.95) + credible_interval_levels : IntervalLevels, default=DEFAULT_CI_LEVELS Interval levels available in the summaries. - sampler_settings : dict[str, object] | None, default=None + sampler_settings : SettingsMap, default=None Sampler settings recorded for reproducibility. - convergence_diagnostics : dict[str, object] | None, default=None + convergence_diagnostics : DiagnosticsMap, default=None Convergence diagnostics and status metadata. sampler_completed : bool, default=False Whether the sampler completed a run and returned posterior data. @@ -217,50 +232,47 @@ class BayesianFitResults(FitResults): Best log-posterior value reported by the sampler. """ - def __init__( - self, - *, - success: bool = False, - parameters: list[object] | None = None, - reduced_chi_square: float | None = None, - engine_result: object | None = None, - starting_parameters: list[object] | None = None, - fitting_time: float | None = None, - sampler_name: str = 'dream', - point_estimate_name: str = 'map', - posterior_samples: PosteriorSamples | None = None, - posterior_parameter_summaries: list[PosteriorParameterSummary] | None = None, - posterior_predictive: dict[str, PosteriorPredictiveSummary] | None = None, - credible_interval_levels: tuple[float, ...] = (0.68, 0.95), - sampler_settings: dict[str, object] | None = None, - convergence_diagnostics: dict[str, object] | None = None, - sampler_completed: bool = False, - best_log_posterior: float | None = None, - ) -> None: + success: bool = False + parameters: list[object] | None = None + reduced_chi_square: float | None = None + engine_result: object | None = None + starting_parameters: list[object] | None = None + fitting_time: float | None = None + sampler_name: str = 'dream' + point_estimate_name: str = 'map' + posterior_samples: PosteriorSamples | None = None + posterior_parameter_summaries: SummaryList = None + posterior_predictive: PredictiveMap = None + credible_interval_levels: IntervalLevels = DEFAULT_CI_LEVELS + sampler_settings: SettingsMap = None + convergence_diagnostics: DiagnosticsMap = None + sampler_completed: bool = False + best_log_posterior: float | None = None + + def __post_init__(self) -> None: + """ + Initialize inherited FitResults state and normalize containers. + """ super().__init__( - success=success, - parameters=parameters, - reduced_chi_square=reduced_chi_square, - engine_result=engine_result, - starting_parameters=starting_parameters, - fitting_time=fitting_time, + success=self.success, + parameters=self.parameters, + reduced_chi_square=self.reduced_chi_square, + engine_result=self.engine_result, + starting_parameters=self.starting_parameters, + fitting_time=self.fitting_time, ) - self.sampler_name = sampler_name - self.point_estimate_name = point_estimate_name - self.posterior_samples = posterior_samples self.posterior_parameter_summaries = ( - posterior_parameter_summaries if posterior_parameter_summaries is not None else [] + list(self.posterior_parameter_summaries) + if self.posterior_parameter_summaries is not None + else [] ) self.posterior_predictive = ( - posterior_predictive if posterior_predictive is not None else {} + dict(self.posterior_predictive) if self.posterior_predictive is not None else {} ) - self.credible_interval_levels = credible_interval_levels - self.sampler_settings = sampler_settings if sampler_settings is not None else {} + self.sampler_settings = dict(self.sampler_settings) if self.sampler_settings else {} self.convergence_diagnostics = ( - convergence_diagnostics if convergence_diagnostics is not None else {} + dict(self.convergence_diagnostics) if self.convergence_diagnostics is not None else {} ) - self.sampler_completed = sampler_completed - self.best_log_posterior = best_log_posterior def display_results( self, @@ -270,7 +282,8 @@ def display_results( f_obs: list[float] | None = None, f_calc: list[float] | None = None, ) -> None: - """Render a Bayesian fit summary with posterior diagnostics. + """ + Render a Bayesian fit summary with posterior diagnostics. Parameters ---------- @@ -285,30 +298,53 @@ def display_results( f_calc : list[float] | None, default=None Calculated structure-factor magnitudes for Bragg R. """ + metrics = _calculate_fit_quality_metrics( + y_obs=y_obs, + y_calc=y_calc, + y_err=y_err, + f_obs=f_obs, + f_calc=f_calc, + ) + + self._display_summary_header() + _print_fit_quality_metrics(metrics) + + console.print('πŸ“ˆ Committed parameters:') + _render_committed_parameter_table(self.parameters) + + console.print('πŸ“Š Posterior parameter summaries:') + _render_posterior_summary_table( + parameters=self.parameters, + posterior_parameter_summaries=self.posterior_parameter_summaries, + ) + + self._print_table_notes() + + def _print_table_notes(self) -> None: + """ + Print parameter and posterior-diagnostic notes below tables. + """ + super()._print_table_notes() + for note in _posterior_table_notes(self.posterior_parameter_summaries): + log.warning(note) + + def _display_summary_header(self) -> None: + """Render the high-level Bayesian fit summary.""" status_icon = 'βœ…' if self.success else '❌' - rf = rf2 = wr = br = None - if y_obs is not None and y_calc is not None: - rf = calculate_r_factor(y_obs, y_calc) * 100 - rf2 = calculate_r_factor_squared(y_obs, y_calc) * 100 - if y_obs is not None and y_calc is not None and y_err is not None: - wr = calculate_weighted_r_factor(y_obs, y_calc, y_err) * 100 - if f_obs is not None and f_calc is not None: - br = calculate_rb_factor(f_obs, f_calc) * 100 + fitting_time = _format_optional_float(self.fitting_time, suffix=' seconds') + goodness_of_fit = _format_optional_float(self.reduced_chi_square) console.paragraph('Bayesian fit results') console.print(f'{status_icon} Success: {self.success}') if self.message: - console.print(f'ℹ️ Status: {self.message}') + console.print(f'i Status: {self.message}') console.print(f'πŸ§ͺ Sampler: {self.sampler_name}') console.print( f'🎯 Committed point estimate: {_format_point_estimate_name(self.point_estimate_name)}' ) console.print(f'πŸ” Sampler completed: {self.sampler_completed}') - console.print(f'⏱️ Fitting time: {_format_optional_float(self.fitting_time, suffix=" seconds")}') - console.print( - 'πŸ“ Goodness-of-fit (reduced χ²): ' - f'{_format_optional_float(self.reduced_chi_square)}' - ) + console.print(f'⏱️ Fitting time: {fitting_time}') + console.print(f'πŸ“ Goodness-of-fit (reduced χ²): {goodness_of_fit}') if self.best_log_posterior is not None: console.print(f'πŸ“‰ Best log-posterior: {self.best_log_posterior:.2f}') @@ -320,35 +356,10 @@ def display_results( if convergence_summary is not None: console.print(Text.from_markup(f'πŸ“Š Convergence: {convergence_summary}')) - if rf is not None: - console.print(f'πŸ“ R-factor (Rf): {rf:.2f}%') - if rf2 is not None: - console.print(f'πŸ“ R-factor squared (RfΒ²): {rf2:.2f}%') - if wr is not None: - console.print(f'πŸ“ Weighted R-factor (wR): {wr:.2f}%') - if br is not None: - console.print(f'πŸ“ Bragg R-factor (BR): {br:.2f}%') - - console.print('πŸ“ˆ Committed parameters:') - _render_committed_parameter_table(self.parameters) - - console.print('πŸ“Š Posterior parameter summaries:') - _render_posterior_summary_table( - parameters=self.parameters, - posterior_parameter_summaries=self.posterior_parameter_summaries, - ) - - self._print_table_notes() - - def _print_table_notes(self) -> None: - """Print parameter and posterior-diagnostic notes below tables.""" - super()._print_table_notes() - for note in _posterior_table_notes(self.posterior_parameter_summaries): - log.warning(note) - def compute_convergence_diagnostics(posterior_samples: PosteriorSamples) -> dict[str, object]: - """Compute convergence diagnostics from posterior samples. + """ + Compute convergence diagnostics from posterior samples. Parameters ---------- @@ -395,7 +406,8 @@ def summarize_posterior_parameters( parameter_display_names: list[str] | None = None, convergence_diagnostics: dict[str, object] | None = None, ) -> list[PosteriorParameterSummary]: - """Build posterior parameter summaries in EasyDiffraction order. + """ + Build posterior parameter summaries in EasyDiffraction order. Parameters ---------- @@ -418,14 +430,16 @@ def summarize_posterior_parameters( Raises ------ ValueError - If the posterior sample array is incompatible with the - parameter name list. + If the posterior sample array is incompatible with the parameter + name list. """ flattened = posterior_samples.flattened() if flattened.shape[1] != len(parameter_names): msg = 'Posterior samples do not match the sampled parameter name list length.' raise ValueError(msg) - if parameter_display_names is not None and len(parameter_display_names) != len(parameter_names): + if parameter_display_names is not None and len(parameter_display_names) != len( + parameter_names + ): msg = 'Posterior display-name list must match the sampled parameter name list length.' raise ValueError(msg) @@ -465,7 +479,8 @@ def summarize_posterior_parameters( def standard_deviations_from_summaries( summaries: list[PosteriorParameterSummary], ) -> np.ndarray: - """Return posterior standard deviations in summary order. + """ + Return posterior standard deviations in summary order. Parameters ---------- @@ -497,13 +512,52 @@ def _format_sampler_settings(sampler_settings: dict[str, object]) -> str | None: if not sampler_settings: return None - parts: list[str] = [] - for key in ('random_seed', 'steps', 'burn', 'thin', 'pop', 'samples'): - if key in sampler_settings: - parts.append(f'{key}={sampler_settings[key]}') + parts = [ + f'{key}={sampler_settings[key]}' + for key in ('random_seed', 'steps', 'burn', 'thin', 'pop', 'samples') + if key in sampler_settings + ] return ', '.join(parts) if parts else None +def _calculate_fit_quality_metrics( + *, + y_obs: list[float] | None, + y_calc: list[float] | None, + y_err: list[float] | None, + f_obs: list[float] | None, + f_calc: list[float] | None, +) -> dict[str, float | None]: + """Compute optional fit-quality metrics for summary rendering.""" + metrics: dict[str, float | None] = { + 'rf': None, + 'rf2': None, + 'wr': None, + 'br': None, + } + if y_obs is not None and y_calc is not None: + metrics['rf'] = calculate_r_factor(y_obs, y_calc) * 100 + metrics['rf2'] = calculate_r_factor_squared(y_obs, y_calc) * 100 + if y_obs is not None and y_calc is not None and y_err is not None: + metrics['wr'] = calculate_weighted_r_factor(y_obs, y_calc, y_err) * 100 + if f_obs is not None and f_calc is not None: + metrics['br'] = calculate_rb_factor(f_obs, f_calc) * 100 + return metrics + + +def _print_fit_quality_metrics(metrics: dict[str, float | None]) -> None: + """Render any available fit-quality metrics.""" + metric_labels = ( + ('πŸ“ R-factor (Rf)', metrics['rf']), + ('πŸ“ R-factor squared (RfΒ²)', metrics['rf2']), + ('πŸ“ Weighted R-factor (wR)', metrics['wr']), + ('πŸ“ Bragg R-factor (BR)', metrics['br']), + ) + for label, value in metric_labels: + if value is not None: + console.print(f'{label}: {value:.2f}%') + + def _format_point_estimate_name(point_estimate_name: str) -> str: """Return a user-facing label for the committed point estimate.""" normalized_name = point_estimate_name.strip().lower().replace('_', ' ') @@ -694,4 +748,4 @@ def _posterior_table_notes( f'[red]ess_bulk[/red]: less than {ESS_BULK_CONVERGENCE_THRESHOLD:.0f} ' '(consider longer sampling, tighter bounds, or reparameterization).' ) - return notes \ No newline at end of file + return notes diff --git a/src/easydiffraction/analysis/fit_helpers/reporting.py b/src/easydiffraction/analysis/fit_helpers/reporting.py index 329f77e6..0e867156 100644 --- a/src/easydiffraction/analysis/fit_helpers/reporting.py +++ b/src/easydiffraction/analysis/fit_helpers/reporting.py @@ -108,11 +108,10 @@ def display_results( console.paragraph('Fit results') console.print(f'{status_icon} Success: {self.success}') - console.print(f'⏱️ Fitting time: {_format_optional_float(self.fitting_time, suffix=" seconds")}') - console.print( - 'πŸ“ Goodness-of-fit (reduced χ²): ' - f'{_format_optional_float(self.reduced_chi_square)}' - ) + fitting_time = _format_optional_float(self.fitting_time, suffix=' seconds') + goodness_of_fit = _format_optional_float(self.reduced_chi_square) + console.print(f'⏱️ Fitting time: {fitting_time}') + console.print(f'πŸ“ Goodness-of-fit (reduced χ²): {goodness_of_fit}') if rf is not None: console.print(f'πŸ“ R-factor (Rf): {rf:.2f}%') if rf2 is not None: @@ -258,7 +257,8 @@ def _format_optional_float( *, suffix: str = '', ) -> str: - """Format an optional float for console output. + """ + Format an optional float for console output. Parameters ---------- diff --git a/src/easydiffraction/analysis/fit_helpers/tracking.py b/src/easydiffraction/analysis/fit_helpers/tracking.py index d85a705e..b5cfb11a 100644 --- a/src/easydiffraction/analysis/fit_helpers/tracking.py +++ b/src/easydiffraction/analysis/fit_helpers/tracking.py @@ -3,6 +3,7 @@ import time from contextlib import suppress +from dataclasses import dataclass import numpy as np @@ -38,6 +39,22 @@ SAMPLER_ALIGNMENTS = ['center', 'center', 'center', 'center', 'center'] +@dataclass(frozen=True, slots=True) +class SamplerProgressUpdate: + """ + Normalized sampler progress payload forwarded by monitor hooks. + """ + + iteration: int + total_iterations: int + phase: str + progress_percent: float + log_posterior: float + reduced_chi2: float + elapsed_time: float + force_report: bool = False + + class _TerminalLiveHandle: """ Adapter that exposes update()/close() for terminal live updates. @@ -222,93 +239,45 @@ def track( return residuals - def track_sampler_progress( - self, - *, - iteration: int, - total_iterations: int, - phase: str, - progress_percent: float, - log_posterior: float, - reduced_chi2: float, - elapsed_time: float, - force_report: bool = False, - ) -> None: - """Update progress from a sampler monitor. + def track_sampler_progress(self, update: SamplerProgressUpdate) -> None: + """ + Update progress from a sampler monitor. Parameters ---------- - iteration : int - Sampler iteration or generation index. - total_iterations : int - Total sampler generations configured for the run. - phase : str - Current sampler phase, e.g. ``'burn-in'`` or ``'sampling'``. - progress_percent : float - Completed fraction expressed in percent. - log_posterior : float - Current best log-posterior implied by the sampler state. - reduced_chi2 : float - Best reduced chi-square implied by the current best sample. - elapsed_time : float - Elapsed wall time in seconds. - force_report : bool, default=False - Whether to render the row regardless of heartbeat timing. + update : SamplerProgressUpdate + Sampler iteration, phase, timing, and fit-quality payload. """ - self._iteration = iteration + self._iteration = update.iteration self._tracking_mode = TRACKING_MODE_SAMPLER - self._sampler_total_iterations = max(1, total_iterations) + self._sampler_total_iterations = max(1, update.total_iterations) - clamped_iteration = min(max(1, iteration), self._sampler_total_iterations) - clamped_progress = min(max(progress_percent, 0.0), 100.0) + clamped_iteration = min(max(1, update.iteration), self._sampler_total_iterations) + clamped_progress = min(max(update.progress_percent, 0.0), 100.0) previous_phase = self._last_sampler_phase - self._last_sampler_phase = phase + self._last_sampler_phase = update.phase self._last_sampler_progress_percent = clamped_progress - self._last_sampler_log_posterior = log_posterior - self._last_sampler_elapsed_time = elapsed_time + self._last_sampler_log_posterior = update.log_posterior + self._last_sampler_elapsed_time = update.elapsed_time - row: list[str] = [] - if self._previous_chi2 is None or self._best_chi2 is None: - self._previous_chi2 = reduced_chi2 - self._best_chi2 = reduced_chi2 - self._best_iteration = iteration - self._last_progress_time = elapsed_time - row = [ - f'{clamped_iteration}/{self._sampler_total_iterations}', - f'{clamped_progress:.1f}%', - self._format_elapsed_time(elapsed_time), - f'{log_posterior:.2f}', - phase, - ] - else: - if reduced_chi2 < self._best_chi2: - self._best_chi2 = reduced_chi2 - self._best_iteration = iteration - - if ( - iteration != self._last_reported_iteration - and ( - force_report - or previous_phase != phase - or self._last_progress_time is None - or elapsed_time - self._last_progress_time >= SAMPLER_PROGRESS_UPDATE_SECONDS - or clamped_iteration >= self._sampler_total_iterations - ) - ): - row = [ - f'{clamped_iteration}/{self._sampler_total_iterations}', - f'{clamped_progress:.1f}%', - self._format_elapsed_time(elapsed_time), - f'{log_posterior:.2f}', - phase, - ] - self._last_progress_time = elapsed_time + row = self._initial_sampler_progress_row( + update=update, + clamped_iteration=clamped_iteration, + clamped_progress=clamped_progress, + ) + if not row: + row = self._continued_sampler_progress_row( + update=update, + previous_phase=previous_phase, + clamped_iteration=clamped_iteration, + clamped_progress=clamped_progress, + ) if row: self.add_tracking_info(row) - self._last_chi2 = reduced_chi2 - self._last_iteration = iteration + self._last_chi2 = update.reduced_chi2 + self._last_iteration = update.iteration @property def best_chi2(self) -> float | None: @@ -351,7 +320,7 @@ def start_tracking(self, minimizer_name: str, *, mode: str = TRACKING_MODE_FIT) ---------- minimizer_name : str Name of the minimizer used for the run. - mode : str, default='fit' + mode : str, default=TRACKING_MODE_FIT Tracking mode for the run. """ self._tracking_mode = ( @@ -367,7 +336,7 @@ def start_tracking(self, minimizer_name: str, *, mode: str = TRACKING_MODE_FIT) if self._tracking_mode == TRACKING_MODE_SAMPLER: console.print('πŸ“ˆ Bayesian sampling progress:') else: - console.print('πŸ“ˆ Fit progress:') + console.print('πŸ“ˆ Goodness-of-fit progress:') # Reset rows and create an environment-appropriate handle self._df_rows = [] @@ -409,62 +378,204 @@ def add_tracking_info(self, row: list[str]) -> None: def finish_tracking(self) -> None: """Finalize progress display and print best result summary.""" if self._tracking_mode == TRACKING_MODE_SAMPLER: - if self._last_iteration is not None and self._sampler_total_iterations is not None: - final_progress = self._last_sampler_progress_percent - if final_progress is None: - final_progress = 100.0 * min( - self._last_iteration, - self._sampler_total_iterations, - ) / self._sampler_total_iterations - row = [ - f'{min(self._last_iteration, self._sampler_total_iterations)}/' - f'{self._sampler_total_iterations}', - f'{final_progress:.1f}%', - self._format_elapsed_time( - self._fitting_time - if self._fitting_time is not None - else self._last_sampler_elapsed_time - ), - ( - f'{self._last_sampler_log_posterior:.2f}' - if self._last_sampler_log_posterior is not None - else '' - ), - self._last_sampler_phase or 'sampling', - ] - if not self._df_rows: - self.add_tracking_info(row) - elif self._rows_match_on_columns(self._df_rows[-1], row, (0, 1, 3, 4)): - self._replace_last_tracking_row(row) - elif self._df_rows[-1] != row: - self.add_tracking_info(row) - elif self._last_iteration is not None: - row: list[str] = [ - str(self._last_iteration), - self._format_elapsed_time(self._fitting_time), - f'{self._last_chi2:.2f}' if self._last_chi2 is not None else '', - '', - ] - if not self._df_rows: - self.add_tracking_info(row) - elif self._rows_match_on_columns(self._df_rows[-1], row, (0, 2)): - self._replace_last_tracking_row(row) - elif self._df_rows[-1][:3] != row[:3]: - self.add_tracking_info(row) + self._finalize_sampler_tracking_row() + else: + self._finalize_fit_tracking_row() if self._verbosity is not VerbosityEnum.FULL: return - # Close terminal live if used + self._close_display_handle() + self._print_completion_summary() + + def _initial_sampler_progress_row( + self, + *, + update: SamplerProgressUpdate, + clamped_iteration: int, + clamped_progress: float, + ) -> list[str]: + if self._previous_chi2 is not None and self._best_chi2 is not None: + return [] + + self._previous_chi2 = update.reduced_chi2 + self._best_chi2 = update.reduced_chi2 + self._best_iteration = update.iteration + self._last_progress_time = update.elapsed_time + return self._sampler_progress_row( + clamped_iteration=clamped_iteration, + clamped_progress=clamped_progress, + log_posterior=update.log_posterior, + phase=update.phase, + elapsed_time=update.elapsed_time, + ) + + def _continued_sampler_progress_row( + self, + *, + update: SamplerProgressUpdate, + previous_phase: str | None, + clamped_iteration: int, + clamped_progress: float, + ) -> list[str]: + if self._best_chi2 is not None and update.reduced_chi2 < self._best_chi2: + self._best_chi2 = update.reduced_chi2 + self._best_iteration = update.iteration + + if not self._should_render_sampler_row( + iteration=update.iteration, + previous_phase=previous_phase, + phase=update.phase, + elapsed_time=update.elapsed_time, + force_report=update.force_report, + clamped_iteration=clamped_iteration, + ): + return [] + + self._last_progress_time = update.elapsed_time + return self._sampler_progress_row( + clamped_iteration=clamped_iteration, + clamped_progress=clamped_progress, + log_posterior=update.log_posterior, + phase=update.phase, + elapsed_time=update.elapsed_time, + ) + + def _should_render_sampler_row( + self, + *, + iteration: int, + previous_phase: str | None, + phase: str, + elapsed_time: float, + force_report: bool, + clamped_iteration: int, + ) -> bool: + if iteration == self._last_reported_iteration: + return False + + return ( + force_report + or previous_phase != phase + or self._last_progress_time is None + or elapsed_time - self._last_progress_time >= SAMPLER_PROGRESS_UPDATE_SECONDS + or clamped_iteration >= self._sampler_total_iterations + ) + + def _sampler_progress_row( + self, + *, + clamped_iteration: int, + clamped_progress: float, + log_posterior: float, + phase: str, + elapsed_time: float, + ) -> list[str]: + return [ + self._sampler_iteration_label(clamped_iteration), + f'{clamped_progress:.1f}%', + self._format_elapsed_time(elapsed_time), + f'{log_posterior:.2f}', + phase, + ] + + def _finalize_sampler_tracking_row(self) -> None: + row = self._final_sampler_tracking_row() + if row is None: + return + + if not self._df_rows: + self.add_tracking_info(row) + return + + if self._rows_match_on_columns(self._df_rows[-1], row, (0, 1, 3, 4)): + self._replace_last_tracking_row(row) + return + + if self._df_rows[-1] != row: + self.add_tracking_info(row) + + def _final_sampler_tracking_row(self) -> list[str] | None: + if self._last_iteration is None or self._sampler_total_iterations is None: + return None + + final_progress = self._resolved_final_sampler_progress() + elapsed_time = self._resolved_final_sampler_elapsed_time() + log_posterior = ( + f'{self._last_sampler_log_posterior:.2f}' + if self._last_sampler_log_posterior is not None + else '' + ) + return [ + self._sampler_iteration_label(self._last_iteration), + f'{final_progress:.1f}%', + self._format_elapsed_time(elapsed_time), + log_posterior, + self._last_sampler_phase or 'sampling', + ] + + def _finalize_fit_tracking_row(self) -> None: + row = self._final_fit_tracking_row() + if row is None: + return + + if not self._df_rows: + self.add_tracking_info(row) + return + + if self._rows_match_on_columns(self._df_rows[-1], row, (0, 2)): + self._replace_last_tracking_row(row) + return + + if self._df_rows[-1][:3] != row[:3]: + self.add_tracking_info(row) + + def _final_fit_tracking_row(self) -> list[str] | None: + if self._last_iteration is None: + return None + + return [ + str(self._last_iteration), + self._format_elapsed_time(self._fitting_time), + f'{self._last_chi2:.2f}' if self._last_chi2 is not None else '', + '', + ] + + def _resolved_final_sampler_progress(self) -> float: + if self._last_sampler_progress_percent is not None: + return self._last_sampler_progress_percent + + if self._last_iteration is None or self._sampler_total_iterations is None: + msg = 'Sampler progress is unavailable without final iteration counts.' + raise RuntimeError(msg) + return ( + 100.0 + * min(self._last_iteration, self._sampler_total_iterations) + / self._sampler_total_iterations + ) + + def _resolved_final_sampler_elapsed_time(self) -> float | None: + if self._fitting_time is not None: + return self._fitting_time + return self._last_sampler_elapsed_time + + def _sampler_iteration_label(self, iteration: int) -> str: + if self._sampler_total_iterations is None: + msg = 'Sampler iteration labels require a configured total iteration count.' + raise RuntimeError(msg) + clamped_iteration = min(iteration, self._sampler_total_iterations) + return f'{clamped_iteration}/{self._sampler_total_iterations}' + + def _close_display_handle(self) -> None: if self._display_handle is not None and hasattr(self._display_handle, 'close'): with suppress(Exception): self._display_handle.close() + def _print_completion_summary(self) -> None: if self._tracking_mode == TRACKING_MODE_SAMPLER: console.print('βœ… Bayesian sampling complete.') return - # Print best result console.print( f'πŸ† Best goodness-of-fit (reduced χ²) is {self._best_chi2:.2f} ' f'at iteration {self._best_iteration}' @@ -506,7 +617,9 @@ def _rows_match_on_columns( new_row: list[str], column_indices: tuple[int, ...], ) -> bool: - """Return whether two tracking rows match on selected columns.""" + """ + Return whether two tracking rows match on selected columns. + """ return all( len(current_row) > index and len(new_row) > index @@ -515,7 +628,9 @@ def _rows_match_on_columns( ) def _replace_last_tracking_row(self, row: list[str]) -> None: - """Replace the last rendered tracking row and refresh the view.""" + """ + Replace the last rendered tracking row and refresh the view. + """ if not self._df_rows: self.add_tracking_info(row) return diff --git a/src/easydiffraction/analysis/minimizers/base.py b/src/easydiffraction/analysis/minimizers/base.py index 84d5371d..142ed569 100644 --- a/src/easydiffraction/analysis/minimizers/base.py +++ b/src/easydiffraction/analysis/minimizers/base.py @@ -69,7 +69,8 @@ def _stop_tracking(self) -> None: self.tracker.stop_timer() self.tracker.finish_tracking() - def _tracking_mode(self) -> str: + @staticmethod + def _tracking_mode() -> str: """Return the tracker mode for the current minimizer.""" return 'fit' @@ -143,7 +144,8 @@ def _build_fit_results( raw_result: object, success: bool, ) -> FitResults: - """Build the final fit-result object for this minimizer. + """ + Build the final fit-result object for this minimizer. Parameters ---------- @@ -266,7 +268,8 @@ def _check_success(self, raw_result: object) -> bool: """Determine whether the fit was successful.""" def _resolve_random_seed(self, random_seed: int | None) -> int | None: - """Validate or normalize the random seed for this minimizer. + """ + Validate or normalize the random seed for this minimizer. Parameters ---------- diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 0ad88ef9..d2fb1773 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -5,6 +5,7 @@ from __future__ import annotations import random +from dataclasses import dataclass import numpy as np from bumps.fitproblem import FitProblem @@ -18,8 +19,9 @@ from easydiffraction.analysis.fit_helpers.bayesian import compute_convergence_diagnostics from easydiffraction.analysis.fit_helpers.bayesian import standard_deviations_from_summaries from easydiffraction.analysis.fit_helpers.bayesian import summarize_posterior_parameters -from easydiffraction.analysis.minimizers.bumps import _EasyDiffractionFitness +from easydiffraction.analysis.fit_helpers.tracking import SamplerProgressUpdate from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer +from easydiffraction.analysis.minimizers.bumps import _EasyDiffractionFitness from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum from easydiffraction.analysis.minimizers.factory import MinimizerFactory @@ -38,10 +40,39 @@ DEFAULT_TRIM = False BURN_IN_PROGRESS_POINTS = 5 SAMPLING_PROGRESS_POINTS = 20 +DREAM_SAMPLE_ARRAY_NDIM = 3 +DREAM_DRIVER_FAILURES = (ArithmeticError, RuntimeError, TypeError, ValueError) + + +@dataclass(slots=True) +class _DreamRunContext: + """Prepared driver state and metadata for one DREAM run.""" + + driver: FitDriver + parameter_names: list[str] + parameter_display_names: list[str] + parameter_uids: list[str] + sampler_settings: dict[str, object] + starting_values: np.ndarray + starting_uncertainties: list[float | None] + + +@dataclass(slots=True) +class _DreamDriverResult: + """ + Raw driver outcome captured before EasyDiffraction normalization. + """ + + best_values: object | None + best_nllf: float | None + raw_state: object | None + error: Exception | None = None class _DreamProgressMonitor(bumps_monitor.Monitor): - """Progress monitor translating DREAM updates into chi-square rows.""" + """ + Progress monitor translating DREAM updates into chi-square rows. + """ def __init__( self, @@ -70,7 +101,8 @@ def __init__( self._next_burn_target_index = 0 self._next_sampling_target_index = 0 - def config_history(self, history: object) -> None: + @staticmethod + def config_history(history: object) -> None: """Declare the history fields needed for progress updates.""" history.requires(time=1, step=1, value=1, population_values=1) @@ -84,14 +116,16 @@ def __call__(self, history: object) -> None: reduced_chi2 = self._reduced_chi_square_from_nllf(nllf) log_posterior = self._population_mean_log_posterior(history) self._tracker.track_sampler_progress( - iteration=generation, - total_iterations=self._total_generations, - phase=self._phase_name(generation), - progress_percent=self._progress_percent(generation), - log_posterior=log_posterior, - reduced_chi2=reduced_chi2, - elapsed_time=float(history.time[0]), - force_report=True, + SamplerProgressUpdate( + iteration=generation, + total_iterations=self._total_generations, + phase=self._phase_name(generation), + progress_percent=self._progress_percent(generation), + log_posterior=log_posterior, + reduced_chi2=reduced_chi2, + elapsed_time=float(history.time[0]), + force_report=True, + ) ) def final(self, history: object, best: dict[str, object]) -> None: @@ -103,14 +137,16 @@ def final(self, history: object, best: dict[str, object]) -> None: best_nllf = float(best['value']) reduced_chi2 = self._reduced_chi_square_from_nllf(best_nllf) self._tracker.track_sampler_progress( - iteration=generation, - total_iterations=self._total_generations, - phase=self._phase_name(generation), - progress_percent=self._progress_percent(generation), - log_posterior=self._population_mean_log_posterior(history), - reduced_chi2=reduced_chi2, - elapsed_time=float(history.time[0]), - force_report=True, + SamplerProgressUpdate( + iteration=generation, + total_iterations=self._total_generations, + phase=self._phase_name(generation), + progress_percent=self._progress_percent(generation), + log_posterior=self._population_mean_log_posterior(history), + reduced_chi2=reduced_chi2, + elapsed_time=float(history.time[0]), + force_report=True, + ) ) @staticmethod @@ -120,13 +156,15 @@ def _progress_targets( stop: int, target_count: int, ) -> list[int]: - """Return monotonically increasing reporting targets for one phase.""" + """ + Return monotonically increasing reporting targets for one phase. + """ if target_count < 1 or stop < start: return [] targets = np.linspace(start, stop, num=target_count) rounded = np.rint(targets).astype(int) - unique_targets = sorted(set(int(value) for value in rounded if start <= value <= stop)) + unique_targets = sorted({int(value) for value in rounded if start <= value <= stop}) if start not in unique_targets: unique_targets.insert(0, start) if stop not in unique_targets: @@ -156,7 +194,9 @@ def _consume_progress_target( phase_targets: list[int], target_index_name: str, ) -> bool: - """Advance a phase target pointer when the generation reaches it.""" + """ + Advance a phase target pointer when the generation reaches it. + """ target_index = getattr(self, target_index_name) should_report = False while target_index < len(phase_targets) and generation >= phase_targets[target_index]: @@ -179,7 +219,7 @@ def _progress_percent(self, generation: int) -> float: @staticmethod def _population_mean_log_posterior(history: object) -> float: - """Return the current mean log-posterior across the walker population.""" + """Return the mean log-posterior across the population.""" population_values = history.population_values[0] if history.population_values else None if population_values is None: return -float(history.value[0]) @@ -191,7 +231,9 @@ def _population_mean_log_posterior(history: object) -> float: return float(np.mean(-nllf_values[finite_mask])) def _reduced_chi_square_from_nllf(self, nllf: float) -> float: - """Convert DREAM's negative log-likelihood to reduced chi-square.""" + """ + Convert DREAM's negative log-likelihood to reduced chi-square. + """ dof = self._n_points - self._n_parameters chi_square = 2.0 * nllf if dof <= 0: @@ -273,7 +315,8 @@ def init(self, value: DreamPopulationInitializationEnum | str) -> None: self._init = self._validated_init(value) def _resolve_random_seed(self, random_seed: int | None) -> int: - """Return a user-provided or generated random seed. + """ + Return a user-provided or generated random seed. Parameters ---------- @@ -292,7 +335,8 @@ def _resolve_random_seed(self, random_seed: int | None) -> int: self._resolved_random_seed = int(random_seed) return self._resolved_random_seed - def _tracking_mode(self) -> str: + @staticmethod + def _tracking_mode() -> str: """Use sampler-style progress reporting for DREAM runs.""" return 'sampling' @@ -300,7 +344,8 @@ def _prepare_solver_args( self, parameters: list[object], ) -> dict[str, object]: - """Prepare DREAM solver arguments in EasyDiffraction order. + """ + Prepare DREAM solver arguments in EasyDiffraction order. Parameters ---------- @@ -322,11 +367,11 @@ def _prepare_solver_args( return solver_args @staticmethod - def _validated_positive_integer(name: str, value: int | float) -> int: + def _validated_positive_integer(name: str, value: float) -> int: """Validate a DREAM setting that must be a positive integer.""" if isinstance(value, bool): msg = f"DREAM setting '{name}' must be a positive integer." - raise ValueError(msg) + raise TypeError(msg) integer_value = int(value) if integer_value != value or integer_value < 1: @@ -335,11 +380,13 @@ def _validated_positive_integer(name: str, value: int | float) -> int: return integer_value @staticmethod - def _validated_non_negative_integer(name: str, value: int | float) -> int: - """Validate a DREAM setting that must be a non-negative integer.""" + def _validated_non_negative_integer(name: str, value: float) -> int: + """ + Validate a DREAM setting that must be a non-negative integer. + """ if isinstance(value, bool): msg = f"DREAM setting '{name}' must be a non-negative integer." - raise ValueError(msg) + raise TypeError(msg) integer_value = int(value) if integer_value != value or integer_value < 0: @@ -373,8 +420,8 @@ def _resolved_burn(self, steps: int) -> int: raise ValueError(msg) return burn + @staticmethod def _sampler_settings( - self, *, random_seed: int, steps: int, @@ -404,7 +451,8 @@ def _run_solver( objective_function: object, **kwargs: object, ) -> object: - """Run the DREAM sampler and normalize its posterior outputs. + """ + Run the DREAM sampler and normalize its posterior outputs. Parameters ---------- @@ -418,47 +466,114 @@ def _run_solver( object Normalized DREAM result stored in an ``OptimizeResult``. """ + context = self._prepare_run_context(objective_function=objective_function, kwargs=kwargs) + driver_result = self._execute_driver( + driver=context.driver, + random_seed=int(context.sampler_settings['random_seed']), + ) + if driver_result.error is not None: + return self._failure_result( + context=context, + message=f'DREAM sampling failed: {driver_result.error}', + raw_state=driver_result.raw_state, + sampler_completed=False, + ) + if driver_result.best_values is None or driver_result.raw_state is None: + return self._failure_result( + context=context, + message='DREAM sampling did not produce usable posterior samples.', + raw_state=driver_result.raw_state, + sampler_completed=False, + ) + + return self._build_success_result( + context=context, + raw_state=driver_result.raw_state, + best_nllf=driver_result.best_nllf, + ) + + def _prepare_run_context( + self, + *, + objective_function: object, + kwargs: dict[str, object], + ) -> _DreamRunContext: + """Prepare a driver and metadata for one DREAM solver run.""" bumps_params = kwargs.get('bumps_params') parameter_names = kwargs.get('parameter_names') parameter_display_names = kwargs.get('parameter_display_names') parameter_uids = kwargs.get('parameter_uids') - random_seed = kwargs.get('random_seed') + random_seed = int(kwargs.get('random_seed')) starting_uncertainties = kwargs.get('starting_uncertainties') + fitness = _EasyDiffractionFitness(bumps_params, objective_function) fitness.nllf() - problem = FitProblem(fitness) - fitclass = next(cls for cls in FITTERS if cls.id == self.method) steps = self.steps burn = self._resolved_burn(steps) - thin = self.thin - pop = self.pop init = self.init sampler_settings = self._sampler_settings( - random_seed=int(random_seed), + random_seed=random_seed, + steps=steps, + burn=burn, + thin=self.thin, + pop=self.pop, + init=init, + n_parameters=len(bumps_params), + ) + driver = self._build_driver( + fitclass=fitclass, + fitness=fitness, steps=steps, burn=burn, - thin=thin, - pop=pop, init=init, + sampler_settings=sampler_settings, n_parameters=len(bumps_params), ) + starting_values = np.array([parameter.value for parameter in bumps_params], dtype=float) + resolved_uncertainties = ( + list(starting_uncertainties) + if starting_uncertainties is not None + else [None] * len(bumps_params) + ) + return _DreamRunContext( + driver=driver, + parameter_names=parameter_names, + parameter_display_names=parameter_display_names, + parameter_uids=parameter_uids, + sampler_settings=sampler_settings, + starting_values=starting_values, + starting_uncertainties=resolved_uncertainties, + ) + + def _build_driver( + self, + *, + fitclass: object, + fitness: object, + steps: int, + burn: int, + init: DreamPopulationInitializationEnum, + sampler_settings: dict[str, object], + n_parameters: int, + ) -> FitDriver: + """Build and clip the BUMPS DREAM driver.""" total_generations = int(steps + burn + 1) progress_monitor = _DreamProgressMonitor( tracker=self.tracker, n_points=fitness.numpoints(), - n_parameters=len(bumps_params), + n_parameters=n_parameters, total_generations=total_generations, burn_steps=int(burn), ) driver = FitDriver( fitclass=fitclass, - problem=problem, + problem=FitProblem(fitness), monitors=[progress_monitor], steps=steps, burn=burn, - thin=thin, - pop=pop, + thin=self.thin, + pop=self.pop, init=init.value, samples=sampler_settings['samples'], alpha=DEFAULT_ALPHA, @@ -466,101 +581,105 @@ def _run_solver( trim=DEFAULT_TRIM, ) driver.clip() + return driver - starting_values = np.array([parameter.value for parameter in bumps_params], dtype=float) - if starting_uncertainties is None: - starting_uncertainties = [None] * len(bumps_params) - - numpy_state = np.random.get_state() + @staticmethod + def _execute_driver(*, driver: FitDriver, random_seed: int) -> _DreamDriverResult: + """ + Run the DREAM driver under a deterministic RNG-state guard. + """ + numpy_rng = np.random.mtrand._rand + numpy_state = numpy_rng.get_state() python_state = random.getstate() - np.random.seed(random_seed) + numpy_rng.seed(random_seed) random.seed(random_seed) try: best_values, best_nllf = driver.fit() - except Exception as error: # pragma: no cover - defensive runtime path - return OptimizeResult( - x=starting_values, - dx=None, - fun=None, - success=False, - status=-1, - message=f'DREAM sampling failed: {error}', - var_names=parameter_names, - posterior_samples=None, - posterior_parameter_summaries=[], - convergence_diagnostics={}, - sampler_settings=sampler_settings, - sampler_completed=False, - raw_state=None, - best_log_posterior=None, - starting_values=starting_values, - starting_uncertainties=starting_uncertainties, + except DREAM_DRIVER_FAILURES as error: # pragma: no cover - backend-specific + return _DreamDriverResult( + best_values=None, + best_nllf=None, + raw_state=getattr(driver.fitter, 'state', None), + error=error, ) finally: - np.random.set_state(numpy_state) + numpy_rng.set_state(numpy_state) random.setstate(python_state) - state = getattr(driver.fitter, 'state', None) - if best_values is None or state is None: - return OptimizeResult( - x=starting_values, - dx=None, - fun=None, - success=False, - status=-1, - message='DREAM sampling did not produce usable posterior samples.', - var_names=parameter_names, - posterior_samples=None, - posterior_parameter_summaries=[], - convergence_diagnostics={}, - sampler_settings=sampler_settings, - sampler_completed=False, - raw_state=state, - best_log_posterior=None, - starting_values=starting_values, - starting_uncertainties=starting_uncertainties, - ) + return _DreamDriverResult( + best_values=best_values, + best_nllf=float(best_nllf), + raw_state=getattr(driver.fitter, 'state', None), + ) + + @staticmethod + def _failure_result( + *, + context: _DreamRunContext, + message: str, + raw_state: object, + sampler_completed: bool, + ) -> OptimizeResult: + """ + Build a normalized failure result for an incomplete DREAM run. + """ + return OptimizeResult( + x=context.starting_values, + dx=None, + fun=None, + success=False, + status=-1, + message=message, + var_names=context.parameter_names, + posterior_samples=None, + posterior_parameter_summaries=[], + convergence_diagnostics={}, + sampler_settings=context.sampler_settings, + sampler_completed=sampler_completed, + raw_state=raw_state, + best_log_posterior=None, + starting_values=context.starting_values, + starting_uncertainties=context.starting_uncertainties, + ) - draw_index, parameter_samples_array, log_posterior = state.chains() - if parameter_samples_array.ndim != 3 or parameter_samples_array.size == 0: - return OptimizeResult( - x=starting_values, - dx=None, - fun=None, - success=False, - status=-1, + def _build_success_result( + self, + *, + context: _DreamRunContext, + raw_state: object, + best_nllf: float | None, + ) -> OptimizeResult: + """Normalize a completed DREAM run into an OptimizeResult.""" + draw_index, parameter_samples_array, log_posterior = raw_state.chains() + if ( + parameter_samples_array.ndim != DREAM_SAMPLE_ARRAY_NDIM + or parameter_samples_array.size == 0 + ): + return self._failure_result( + context=context, message='DREAM sampling did not return a usable posterior sample array.', - var_names=parameter_names, - posterior_samples=None, - posterior_parameter_summaries=[], - convergence_diagnostics={}, - sampler_settings=sampler_settings, + raw_state=raw_state, sampler_completed=True, - raw_state=state, - best_log_posterior=None, - starting_values=starting_values, - starting_uncertainties=starting_uncertainties, ) - state_best_values, best_log_posterior = state.best() - best_by_name = dict(zip(state.labels, state_best_values, strict=True)) - label_to_index = {label: index for index, label in enumerate(state.labels)} - ordered_indices = [label_to_index[uid] for uid in parameter_uids] + state_best_values, best_log_posterior = raw_state.best() + best_by_name = dict(zip(raw_state.labels, state_best_values, strict=True)) + label_to_index = {label: index for index, label in enumerate(raw_state.labels)} + ordered_indices = [label_to_index[uid] for uid in context.parameter_uids] ordered_samples = np.asarray(parameter_samples_array, dtype=float)[:, :, ordered_indices] - map_values = np.array([best_by_name[uid] for uid in parameter_uids], dtype=float) - + map_values = np.array([best_by_name[uid] for uid in context.parameter_uids], dtype=float) posterior_samples = PosteriorSamples( - parameter_names=parameter_names, + parameter_names=context.parameter_names, parameter_samples=ordered_samples, log_posterior=np.asarray(log_posterior, dtype=float), draw_index=np.asarray(draw_index, dtype=float), ) convergence_diagnostics = compute_convergence_diagnostics(posterior_samples) posterior_parameter_summaries = summarize_posterior_parameters( - parameter_names=parameter_names, + parameter_names=context.parameter_names, posterior_samples=posterior_samples, map_values=map_values, - parameter_display_names=parameter_display_names, + parameter_display_names=context.parameter_display_names, convergence_diagnostics=convergence_diagnostics, ) posterior_standard_deviations = standard_deviations_from_summaries( @@ -580,24 +699,25 @@ def _run_solver( success=True, status=0, message='DREAM sampling completed', - var_names=parameter_names, + var_names=context.parameter_names, posterior_samples=posterior_samples, posterior_parameter_summaries=posterior_parameter_summaries, convergence_diagnostics=convergence_diagnostics, - sampler_settings=sampler_settings, + sampler_settings=context.sampler_settings, sampler_completed=True, - raw_state=state, + raw_state=raw_state, best_log_posterior=float(best_log_posterior), - starting_values=starting_values, - starting_uncertainties=starting_uncertainties, + starting_values=context.starting_values, + starting_uncertainties=context.starting_uncertainties, ) + @staticmethod def _sync_result_to_parameters( - self, parameters: list[object], raw_result: object, ) -> None: - """Commit MAP values on success and restore starts on failure. + """ + Commit MAP values on success and restore starts on failure. Parameters ---------- @@ -636,7 +756,8 @@ def _build_fit_results( raw_result: object, success: bool, ) -> BayesianFitResults: - """Build the Bayesian fit result container. + """ + Build the Bayesian fit result container. Parameters ---------- @@ -662,9 +783,7 @@ def _build_fit_results( sampler_name='dream', point_estimate_name='map', posterior_samples=getattr(raw_result, 'posterior_samples', None), - posterior_parameter_summaries=getattr( - raw_result, 'posterior_parameter_summaries', [] - ), + posterior_parameter_summaries=getattr(raw_result, 'posterior_parameter_summaries', []), posterior_predictive={}, credible_interval_levels=(0.68, 0.95), sampler_settings=getattr(raw_result, 'sampler_settings', {}), @@ -675,4 +794,4 @@ def _build_fit_results( fit_results.message = getattr(raw_result, 'message', '') fit_results.iterations = int(fit_results.sampler_settings.get('steps', self.steps)) fit_results.result = raw_result - return fit_results \ No newline at end of file + return fit_results diff --git a/src/easydiffraction/core/variable.py b/src/easydiffraction/core/variable.py index cc5b9ec9..a09f502f 100644 --- a/src/easydiffraction/core/variable.py +++ b/src/easydiffraction/core/variable.py @@ -433,7 +433,8 @@ def set_fit_bounds_from_uncertainty( *, clip_to_limits: bool = True, ) -> None: - """Set fit bounds from the current standard uncertainty. + """ + Set fit bounds from the current standard uncertainty. Parameters ---------- @@ -447,8 +448,8 @@ def set_fit_bounds_from_uncertainty( Raises ------ ValueError - If the current value, uncertainty, or multiplier is - missing, invalid, or produces non-increasing bounds. + If the current value, uncertainty, or multiplier is missing, + invalid, or produces non-increasing bounds. """ name = self.unique_name value = self.value diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 49d567af..fcc07fa9 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -69,6 +69,7 @@ PREDICTIVE_BAND_EDGE_COLOR = 'rgba(214, 39, 40, 0.45)' PREDICTIVE_DRAW_COLOR = 'rgba(140, 140, 140, 0.18)' PREDICTIVE_DRAW_PLOT_CAP = 50 +PREDICTIVE_DRAW_ARRAY_NDIM = 2 @dataclass(frozen=True) @@ -1177,23 +1178,7 @@ def _get_main_intensity_range(cls, plot_spec: PowderMeasVsCalcSpec) -> tuple[flo if min(y_meas.size, y_calc.size) == 0: return 0.0, 1.0 - main_series = [y_meas, y_calc] - if plot_spec.y_bkg is not None: - y_bkg = np.asarray(plot_spec.y_bkg) - if y_bkg.size > 0: - main_series.append(y_bkg) - if plot_spec.predictive_lower_95 is not None: - lower_95 = np.asarray(plot_spec.predictive_lower_95) - if lower_95.size > 0: - main_series.append(lower_95) - if plot_spec.predictive_upper_95 is not None: - upper_95 = np.asarray(plot_spec.predictive_upper_95) - if upper_95.size > 0: - main_series.append(upper_95) - if plot_spec.predictive_draws is not None: - predictive_draws = np.asarray(plot_spec.predictive_draws) - if predictive_draws.ndim == 2 and predictive_draws.size > 0: - main_series.extend(predictive_draws) + main_series = cls._main_intensity_series(plot_spec, y_meas=y_meas, y_calc=y_calc) main_y_min = float(min(np.min(series) for series in main_series)) main_y_max = float(max(np.max(series) for series in main_series)) @@ -1204,6 +1189,49 @@ def _get_main_intensity_range(cls, plot_spec: PowderMeasVsCalcSpec) -> tuple[flo return main_y_min - 1.0, main_y_max + 1.0 + @classmethod + def _main_intensity_series( + cls, + plot_spec: PowderMeasVsCalcSpec, + *, + y_meas: np.ndarray, + y_calc: np.ndarray, + ) -> list[np.ndarray]: + main_series = [y_meas, y_calc] + for values in ( + plot_spec.y_bkg, + plot_spec.predictive_lower_95, + plot_spec.predictive_upper_95, + ): + cls._append_non_empty_series(main_series, values) + + predictive_draws = cls._predictive_draw_array(plot_spec.predictive_draws) + if predictive_draws is not None: + main_series.extend(predictive_draws) + return main_series + + @staticmethod + def _append_non_empty_series( + main_series: list[np.ndarray], + values: np.ndarray | None, + ) -> None: + if values is None: + return + + array = np.asarray(values) + if array.size > 0: + main_series.append(array) + + @staticmethod + def _predictive_draw_array(values: object | None) -> np.ndarray | None: + if values is None: + return None + + predictive_draws = np.asarray(values) + if predictive_draws.ndim != PREDICTIVE_DRAW_ARRAY_NDIM or predictive_draws.size == 0: + return None + return predictive_draws + @classmethod def _get_residual_limit(cls, plot_spec: PowderMeasVsCalcSpec) -> float: """Return a symmetric residual limit matched to the main row.""" @@ -1245,11 +1273,40 @@ def plot_powder_meas_vs_calc( layout = self._get_powder_composite_rows(plot_spec) x_min, x_max = self._composite_x_range(np.asarray(plot_spec.x)) main_y_min, main_y_max = self._get_main_intensity_range(plot_spec) - residual_limit = None hover_data = self._powder_meas_vs_calc_hover_data(plot_spec) hover_template = self._powder_meas_vs_calc_hover_template(plot_spec) + fig = self._create_powder_composite_figure(layout) + self._add_predictive_band_traces(fig=fig, plot_spec=plot_spec) + self._add_main_intensity_traces( + fig=fig, + plot_spec=plot_spec, + hover_data=hover_data, + hover_template=hover_template, + ) + self._add_predictive_draw_traces(fig=fig, plot_spec=plot_spec) + self._add_bragg_tick_traces(fig=fig, plot_spec=plot_spec, layout=layout) + residual_limit = self._add_residual_trace( + fig=fig, + plot_spec=plot_spec, + layout=layout, + hover_data=hover_data, + hover_template=hover_template, + ) + self._configure_powder_composite_layout(fig=fig, plot_spec=plot_spec, layout=layout) + self._configure_powder_composite_axes( + fig=fig, + plot_spec=plot_spec, + layout=layout, + x_range=(x_min, x_max), + main_y_range=(main_y_min, main_y_max), + residual_limit=residual_limit, + ) + + self._show_figure(fig) - fig = make_subplots( + @staticmethod + def _create_powder_composite_figure(layout: PowderCompositeRows) -> object: + return make_subplots( rows=layout.row_count, cols=1, shared_xaxes=True, @@ -1257,62 +1314,49 @@ def plot_powder_meas_vs_calc( row_heights=layout.row_heights, ) - if plot_spec.predictive_lower_95 is not None and plot_spec.predictive_upper_95 is not None: - lower_trace, upper_trace = self._get_predictive_band_traces( - x=plot_spec.x, - lower=plot_spec.predictive_lower_95, - upper=plot_spec.predictive_upper_95, - ) - fig.add_trace(lower_trace, row=1, col=1) - fig.add_trace(upper_trace, row=1, col=1) + def _add_predictive_band_traces( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + ) -> None: + if plot_spec.predictive_lower_95 is None or plot_spec.predictive_upper_95 is None: + return - fig.add_trace( - self._get_powder_trace( - plot_spec.x, - plot_spec.y_meas, - 'meas', - customdata=hover_data, - hovertemplate=hover_template, - ), - row=1, - col=1, + lower_trace, upper_trace = self._get_predictive_band_traces( + x=plot_spec.x, + lower=plot_spec.predictive_lower_95, + upper=plot_spec.predictive_upper_95, ) + fig.add_trace(lower_trace, row=1, col=1) + fig.add_trace(upper_trace, row=1, col=1) + + def _add_main_intensity_traces( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + hover_data: object, + hover_template: str, + ) -> None: + meas_trace = self._get_powder_trace( + plot_spec.x, + plot_spec.y_meas, + 'meas', + customdata=hover_data, + hovertemplate=hover_template, + ) + fig.add_trace(meas_trace, row=1, col=1) if plot_spec.y_bkg is not None: - fig.add_trace( - self._get_powder_trace( - plot_spec.x, - plot_spec.y_bkg, - 'bkg', - customdata=hover_data, - hovertemplate=hover_template, - ), - row=1, - col=1, + bkg_trace = self._get_powder_trace( + plot_spec.x, + plot_spec.y_bkg, + 'bkg', + customdata=hover_data, + hovertemplate=hover_template, ) - - if plot_spec.predictive_draws is not None: - predictive_draws = np.asarray(plot_spec.predictive_draws) - if predictive_draws.ndim == 2 and predictive_draws.size > 0: - draw_cap = min(predictive_draws.shape[0], PREDICTIVE_DRAW_PLOT_CAP) - for index in range(draw_cap): - fig.add_trace( - go.Scatter( - x=plot_spec.x, - y=predictive_draws[index], - mode='lines', - line={'color': PREDICTIVE_DRAW_COLOR, 'width': 1}, - name='Posterior draw' if index == 0 else None, - showlegend=index == 0, - hovertemplate=( - 'Posterior draw
' - 'x: %{x:,.2f}
' - 'y: %{y:,.2f}' - ), - ), - row=1, - col=1, - ) + fig.add_trace(bkg_trace, row=1, col=1) calc_trace = self._get_powder_trace( plot_spec.x, @@ -1325,33 +1369,89 @@ def plot_powder_meas_vs_calc( calc_trace.name = plot_spec.y_calc_name fig.add_trace(calc_trace, row=1, col=1) - if layout.bragg_row is not None: - for idx, tick_set in enumerate(plot_spec.bragg_tick_sets): - color = BRAGG_TICK_COLORS[idx % len(BRAGG_TICK_COLORS)] - fig.add_trace( - self._get_bragg_tick_trace( - tick_set=tick_set, - row_y=float(idx + 1), - color=color, + def _add_predictive_draw_traces( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + ) -> None: + predictive_draws = self._predictive_draw_array(plot_spec.predictive_draws) + if predictive_draws is None: + return + + draw_cap = min(predictive_draws.shape[0], PREDICTIVE_DRAW_PLOT_CAP) + for index in range(draw_cap): + fig.add_trace( + go.Scatter( + x=plot_spec.x, + y=predictive_draws[index], + mode='lines', + line={'color': PREDICTIVE_DRAW_COLOR, 'width': 1}, + name='Posterior draw' if index == 0 else None, + showlegend=index == 0, + hovertemplate=( + 'Posterior draw
x: %{x:,.2f}
y: %{y:,.2f}' ), - row=layout.bragg_row, - col=1, - ) + ), + row=1, + col=1, + ) + + def _add_bragg_tick_traces( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + layout: PowderCompositeRows, + ) -> None: + if layout.bragg_row is None: + return - if layout.residual_row is not None and plot_spec.y_resid is not None: - residual_limit = self._get_residual_limit(plot_spec) + for idx, tick_set in enumerate(plot_spec.bragg_tick_sets): + color = BRAGG_TICK_COLORS[idx % len(BRAGG_TICK_COLORS)] fig.add_trace( - self._get_powder_trace( - plot_spec.x, - plot_spec.y_resid, - 'resid', - customdata=hover_data, - hovertemplate=hover_template, + self._get_bragg_tick_trace( + tick_set=tick_set, + row_y=float(idx + 1), + color=color, ), - row=layout.residual_row, + row=layout.bragg_row, col=1, ) + def _add_residual_trace( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + layout: PowderCompositeRows, + hover_data: object, + hover_template: str, + ) -> float | None: + if layout.residual_row is None or plot_spec.y_resid is None: + return None + + residual_limit = self._get_residual_limit(plot_spec) + fig.add_trace( + self._get_powder_trace( + plot_spec.x, + plot_spec.y_resid, + 'resid', + customdata=hover_data, + hovertemplate=hover_template, + ), + row=layout.residual_row, + col=1, + ) + return residual_limit + + def _configure_powder_composite_layout( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + layout: PowderCompositeRows, + ) -> None: fig.update_layout( height=self._composite_figure_height(plot_spec, layout), margin={ @@ -1370,11 +1470,58 @@ def plot_powder_meas_vs_calc( }, ) - for row_idx in range(1, layout.row_count + 1): + def _configure_powder_composite_axes( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + layout: PowderCompositeRows, + x_range: tuple[float | None, float | None], + main_y_range: tuple[float, float], + residual_limit: float | None, + ) -> None: + self._configure_shared_composite_axes( + fig=fig, + row_count=layout.row_count, + x_min=x_range[0], + x_max=x_range[1], + ) + fig.update_xaxes(showticklabels=(layout.row_count == 1), row=1, col=1) + fig.update_yaxes( + title_text=plot_spec.axes_labels[1], + range=list(main_y_range), + row=1, + col=1, + ) + + if layout.bragg_row is not None: + self._configure_bragg_axes(fig=fig, plot_spec=plot_spec, layout=layout) + if layout.residual_row is not None and residual_limit is not None: + self._configure_residual_axes( + fig=fig, + plot_spec=plot_spec, + layout=layout, + residual_limit=residual_limit, + ) + return + + terminal_row = layout.bragg_row if layout.bragg_row is not None else 1 + fig.update_xaxes(title_text=plot_spec.axes_labels[0], row=terminal_row, col=1) + + def _configure_shared_composite_axes( + self, + *, + fig: object, + row_count: int, + x_min: float | None, + x_max: float | None, + ) -> None: + axis_frame_color = self._axis_frame_color() + for row_idx in range(1, row_count + 1): x_axis_kwargs = { 'matches': 'x', 'showline': True, - 'linecolor': self._axis_frame_color(), + 'linecolor': axis_frame_color, 'mirror': True, 'zeroline': False, 'tickformat': ',.6~g', @@ -1385,7 +1532,7 @@ def plot_powder_meas_vs_calc( fig.update_xaxes(row=row_idx, col=1, **x_axis_kwargs) fig.update_yaxes( showline=True, - linecolor=self._axis_frame_color(), + linecolor=axis_frame_color, mirror=True, zeroline=False, tickformat=',.6~g', @@ -1394,50 +1541,48 @@ def plot_powder_meas_vs_calc( col=1, ) - fig.update_xaxes(showticklabels=(layout.row_count == 1), row=1, col=1) + @staticmethod + def _configure_bragg_axes( + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + layout: PowderCompositeRows, + ) -> None: fig.update_yaxes( - title_text=plot_spec.axes_labels[1], - range=[main_y_min, main_y_max], - row=1, + tickmode='array', + tickvals=[float(idx + 1) for idx in range(len(plot_spec.bragg_tick_sets))], + ticktext=[tick_set.phase_id for tick_set in plot_spec.bragg_tick_sets], + range=[float(len(plot_spec.bragg_tick_sets)) + 0.5, 0.5], + showgrid=False, + row=layout.bragg_row, + col=1, + ) + fig.update_xaxes( + showticklabels=layout.residual_row is None, + row=layout.bragg_row, col=1, ) - if layout.bragg_row is not None: - fig.update_yaxes( - # title_text='Bragg peaks', - tickmode='array', - tickvals=[float(idx + 1) for idx in range(len(plot_spec.bragg_tick_sets))], - ticktext=[tick_set.phase_id for tick_set in plot_spec.bragg_tick_sets], - range=[float(len(plot_spec.bragg_tick_sets)) + 0.5, 0.5], - showgrid=False, - row=layout.bragg_row, - col=1, - ) - fig.update_xaxes( - showticklabels=layout.residual_row is None, - row=layout.bragg_row, - col=1, - ) - - if layout.residual_row is not None and plot_spec.y_resid is not None: - residual_tick_limit = self._get_display_tick_limit(residual_limit) - fig.update_yaxes( - # title_text='Residual', - range=[-residual_limit, residual_limit], - tickmode='array', - tickvals=[-residual_tick_limit, 0.0, residual_tick_limit], - scaleanchor='y', - scaleratio=1, - zeroline=False, - row=layout.residual_row, - col=1, - ) - fig.update_xaxes(title_text=plot_spec.axes_labels[0], row=layout.residual_row, col=1) - else: - terminal_row = layout.bragg_row if layout.bragg_row is not None else 1 - fig.update_xaxes(title_text=plot_spec.axes_labels[0], row=terminal_row, col=1) - - self._show_figure(fig) + def _configure_residual_axes( + self, + *, + fig: object, + plot_spec: PowderMeasVsCalcSpec, + layout: PowderCompositeRows, + residual_limit: float, + ) -> None: + residual_tick_limit = self._get_display_tick_limit(residual_limit) + fig.update_yaxes( + range=[-residual_limit, residual_limit], + tickmode='array', + tickvals=[-residual_tick_limit, 0.0, residual_tick_limit], + scaleanchor='y', + scaleratio=1, + zeroline=False, + row=layout.residual_row, + col=1, + ) + fig.update_xaxes(title_text=plot_spec.axes_labels[0], row=layout.residual_row, col=1) @staticmethod def _get_predictive_band_traces( @@ -1446,7 +1591,9 @@ def _get_predictive_band_traces( lower: np.ndarray, upper: np.ndarray, ) -> tuple[go.Scatter, go.Scatter]: - """Return Plotly traces for a filled predictive interval band.""" + """ + Return Plotly traces for a filled predictive interval band. + """ lower_trace = go.Scatter( x=x, y=lower, diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 35b0b33b..2fee1031 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -16,6 +16,7 @@ import numpy as np import pandas as pd +from easydiffraction.analysis.fit_helpers.bayesian import PosteriorPredictiveSummary from easydiffraction.datablocks.experiment.item.base import intensity_category_for from easydiffraction.datablocks.experiment.item.enums import SampleFormEnum from easydiffraction.datablocks.experiment.item.enums import ScatteringTypeEnum @@ -71,6 +72,9 @@ def description(self) -> str: DEFAULT_BRAGG_ROW = DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION DEFAULT_POSTERIOR_PREDICTIVE_DRAWS = 200 DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP = 50 +POSTERIOR_FLATTENED_SAMPLE_NDIM = 2 +MIN_POSTERIOR_PARAMETER_COUNT = 2 +MIN_POSTERIOR_SAMPLE_COUNT = 2 POSTERIOR_DENSITY_LINE_COLOR = 'rgb(99, 110, 250)' POSTERIOR_DENSITY_FILL_COLOR = 'rgba(99, 110, 250, 0.22)' POSTERIOR_HISTOGRAM_FILL_COLOR = 'rgba(120, 120, 120, 0.38)' @@ -127,6 +131,45 @@ class _PowderMeasVsCalcSeries: y_bkg: np.ndarray | None = None +@dataclass(frozen=True) +class _PosteriorDistributionContext: + """Inputs needed to build a posterior distribution plot.""" + + fit_results: object + parameter_name: str + values: np.ndarray + label: str + title: str + summary: object | None + + +@dataclass(frozen=True) +class _PosteriorPairsContext: + """Inputs needed to build a posterior pair plot.""" + + fit_results: object + parameter_names: list[str] + labels: list[str] + density_samples: np.ndarray + scatter_samples: np.ndarray + axis_frame_color: str + axis_ranges: list[tuple[float, float]] + + @property + def n_parameters(self) -> int: + """Return the number of plotted parameters.""" + return len(self.parameter_names) + + +@dataclass(slots=True) +class _PosteriorPairsLegendState: + """Legend-visibility state for posterior pair plots.""" + + show_density: bool = True + show_scatter: bool = True + show_contour: bool = True + + class Plotter(RendererBase): """User-facing plotting facade backed by concrete plotters.""" @@ -599,6 +642,7 @@ def plot_param_correlations( self, threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, precision: int = 2, + *, show_diagonal: bool = False, ) -> None: """ @@ -671,7 +715,8 @@ def plot_posterior_pairs( self, parameters: list[object] | None = None, ) -> None: - """Plot posterior pair relationships for sampled parameters. + """ + Plot posterior pair relationships for sampled parameters. Parameters ---------- @@ -688,7 +733,8 @@ def plot_param_distribution( self, param: object, ) -> None: - """Plot the posterior distribution for one sampled parameter. + """ + Plot the posterior distribution for one sampled parameter. Parameters ---------- @@ -711,16 +757,17 @@ def plot_posterior_predictive( show_residual: bool | None = None, x: object | None = None, ) -> None: - """Plot posterior predictive curves for a powder experiment. + """ + Plot posterior predictive curves for a powder experiment. Parameters ---------- expt_name : str Experiment name to plot. style : str, default='band+draws' - ``'band'`` shows the 95% credible interval, - ``'draws'`` shows sampled predictive curves, and - ``'band+draws'`` shows both together. + ``'band'`` shows the 95% credible interval, ``'draws'`` + shows sampled predictive curves, and ``'band+draws'`` shows + both together. x_min : float | None, default=None Lower bound for the x-axis range. x_max : float | None, default=None @@ -729,6 +776,12 @@ def plot_posterior_predictive( Whether to include the residual row in the composite plot. x : object | None, default=None Optional explicit x-axis data to override stored values. + + Raises + ------ + ValueError + If ``style`` is not one of ``'band'``, ``'draws'``, or + ``'band+draws'``. """ if style not in {'band', 'draws', 'band+draws'}: msg = "style must be 'band', 'draws', or 'band+draws'." @@ -913,12 +966,40 @@ def _get_param_correlation_dataframe(self) -> pd.DataFrame | None: if fit_results is None: return None + corr_df = self._posterior_correlation_dataframe(fit_results) + if corr_df is not None: + return corr_df + + raw_result = self._raw_fit_result_for_correlation(fit_results) + if raw_result is None: + return None + + corr_df = self._correlation_dataframe_from_engine_result( + raw_result=raw_result, + parameters=fit_results.parameters, + ) + if corr_df is not None: + return corr_df + + log.warning( + 'Correlation matrix is unavailable for this fit. ' + 'Use a minimizer that returns covariance information or posterior samples.' + ) + return None + + def _posterior_correlation_dataframe( + self, + fit_results: object, + ) -> pd.DataFrame | None: + """Return posterior-sample correlations when available.""" posterior_samples = getattr(fit_results, 'posterior_samples', None) - if posterior_samples is not None: - corr_df = self._correlation_from_posterior_samples(posterior_samples) - if corr_df is not None: - return corr_df + if posterior_samples is None: + return None + return self._correlation_from_posterior_samples(posterior_samples) + @staticmethod + def _raw_fit_result_for_correlation(fit_results: object) -> object | None: + """Return raw fit results for correlation fallback.""" raw_result = getattr(fit_results, 'result', None) if raw_result is None: raw_result = getattr(fit_results, 'engine_result', None) @@ -930,30 +1011,34 @@ def _get_param_correlation_dataframe(self) -> pd.DataFrame | None: if not var_names: log.warning('Fit result does not expose variable names for a correlation matrix.') return None + return raw_result + def _correlation_dataframe_from_engine_result( + self, + *, + raw_result: object, + parameters: list[object], + ) -> pd.DataFrame | None: + """Return correlations derived from engine result fields.""" covar = getattr(raw_result, 'covar', None) if covar is not None: - return self._correlation_from_covariance(covar, var_names, fit_results.parameters) - - corr_df = self._get_param_correlation_dataframe_from_engine_params( + return self._correlation_from_covariance( + covar, + getattr(raw_result, 'var_names', None), + parameters, + ) + return self._get_param_correlation_dataframe_from_engine_params( raw_result=raw_result, - parameters=fit_results.parameters, - ) - if corr_df is not None: - return corr_df - - log.warning( - 'Correlation matrix is unavailable for this fit. ' - 'Use a minimizer that returns covariance information or posterior samples.' + parameters=parameters, ) - return None def _build_posterior_pairs_plot( self, *, parameters: list[object] | None, ) -> object | None: - """Build a Plotly posterior pair plot. + """ + Build a Plotly posterior pair plot. Parameters ---------- @@ -966,6 +1051,47 @@ def _build_posterior_pairs_plot( Plotly figure, or ``None`` when posterior plotting is unavailable. """ + context = self._posterior_pairs_context(parameters) + if context is None: + return None + + make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots + subplot_title_annotations: list[dict[str, object]] = [] + subplot_border_shapes: list[dict[str, object]] = [] + legend_state = _PosteriorPairsLegendState() + fig = make_subplots( + rows=context.n_parameters, + cols=context.n_parameters, + shared_xaxes='columns', + horizontal_spacing=PAIR_PLOT_SUBPLOT_SPACING, + vertical_spacing=PAIR_PLOT_SUBPLOT_SPACING, + ) + + for row_index in range(context.n_parameters): + for col_index in range(context.n_parameters): + self._populate_posterior_pair_panel( + fig=fig, + context=context, + row_index=row_index, + col_index=col_index, + legend_state=legend_state, + subplot_title_annotations=subplot_title_annotations, + subplot_border_shapes=subplot_border_shapes, + ) + + self._finalize_posterior_pairs_figure( + fig=fig, + context=context, + subplot_title_annotations=subplot_title_annotations, + subplot_border_shapes=subplot_border_shapes, + ) + return fig + + def _posterior_pairs_context( + self, + parameters: list[object] | None, + ) -> _PosteriorPairsContext | None: + """Return the resolved inputs for a posterior pair plot.""" posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() if posterior_samples is None or fit_results is None: return None @@ -976,245 +1102,343 @@ def _build_posterior_pairs_plot( ) if parameter_names is None: return None - if len(parameter_names) < 2: + if len(parameter_names) < MIN_POSTERIOR_PARAMETER_COUNT: log.warning('Posterior pair plots require at least two sampled parameters.') return None - go = __import__( - 'plotly.graph_objects', - fromlist=['Figure', 'Histogram', 'Scatter', 'Contour'], - ) - make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots - density_samples = self._selected_posterior_samples(posterior_samples, parameter_names) if density_samples is None: return None - scatter_samples = self._thin_posterior_samples(density_samples, max_points=1500) - labels = self._posterior_plot_labels(fit_results, parameter_names) - show_density_legend = True - show_scatter_legend = True - show_contour_legend = True - axis_frame_color = self._plot_axis_frame_color() - parameter_axis_ranges = [ - self._posterior_axis_bounds( - density_samples[:, index], - lower_bound=self._posterior_parameter_bounds( - fit_results=fit_results, - parameter_name=parameter_names[index], - )[0], - upper_bound=self._posterior_parameter_bounds( - fit_results=fit_results, - parameter_name=parameter_names[index], - )[1], + + return _PosteriorPairsContext( + fit_results=fit_results, + parameter_names=parameter_names, + labels=self._posterior_plot_labels(fit_results, parameter_names), + density_samples=density_samples, + scatter_samples=self._thin_posterior_samples(density_samples, max_points=1500), + axis_frame_color=self._plot_axis_frame_color(), + axis_ranges=self._posterior_pair_axis_ranges( + fit_results=fit_results, + parameter_names=parameter_names, + density_samples=density_samples, + ), + ) + + def _posterior_pair_axis_ranges( + self, + *, + fit_results: object, + parameter_names: list[str], + density_samples: np.ndarray, + ) -> list[tuple[float, float]]: + """Return per-parameter axis ranges for a pair plot.""" + axis_ranges: list[tuple[float, float]] = [] + for index, parameter_name in enumerate(parameter_names): + lower_bound, upper_bound = self._posterior_parameter_bounds( + fit_results=fit_results, + parameter_name=parameter_name, ) - for index in range(len(parameter_names)) - ] + axis_ranges.append( + self._posterior_axis_bounds( + density_samples[:, index], + lower_bound=lower_bound, + upper_bound=upper_bound, + ) + ) + return axis_ranges - n_parameters = len(parameter_names) - subplot_title_annotations: list[dict[str, object]] = [] - subplot_border_shapes: list[dict[str, object]] = [] - fig = make_subplots( - rows=n_parameters, - cols=n_parameters, - shared_xaxes='columns', - horizontal_spacing=PAIR_PLOT_SUBPLOT_SPACING, - vertical_spacing=PAIR_PLOT_SUBPLOT_SPACING, + def _populate_posterior_pair_panel( + self, + *, + fig: object, + context: _PosteriorPairsContext, + row_index: int, + col_index: int, + legend_state: _PosteriorPairsLegendState, + subplot_title_annotations: list[dict[str, object]], + subplot_border_shapes: list[dict[str, object]], + ) -> None: + """Populate one panel in the posterior pair plot grid.""" + row = row_index + 1 + col = col_index + 1 + if col_index > row_index: + self._hide_posterior_pair_panel(fig=fig, row=row, col=col) + return + + if row_index == col_index: + self._add_posterior_pair_diagonal( + fig=fig, + context=context, + row=row, + col=col, + parameter_index=col_index, + legend_state=legend_state, + ) + else: + self._add_posterior_pair_off_diagonal( + fig=fig, + context=context, + row=row, + col=col, + row_index=row_index, + col_index=col_index, + legend_state=legend_state, + ) + + self._configure_posterior_pair_panel_axes( + fig=fig, + context=context, + row=row, + col=col, + row_index=row_index, + col_index=col_index, + ) + self._collect_posterior_pair_panel_decorations( + fig=fig, + context=context, + row_index=row_index, + col_index=col_index, + subplot_title_annotations=subplot_title_annotations, + subplot_border_shapes=subplot_border_shapes, ) - for row_index in range(n_parameters): - for col_index in range(n_parameters): - row = row_index + 1 - col = col_index + 1 - if col_index > row_index: - fig.update_xaxes(visible=False, row=row, col=col) - fig.update_yaxes(visible=False, row=row, col=col) - continue + @staticmethod + def _hide_posterior_pair_panel( + *, + fig: object, + row: int, + col: int, + ) -> None: + """Hide an upper-triangle panel in the pair plot grid.""" + fig.update_xaxes(visible=False, row=row, col=col) + fig.update_yaxes(visible=False, row=row, col=col) - x_density_values = density_samples[:, col_index] - y_density_values = density_samples[:, row_index] - x_scatter_values = scatter_samples[:, col_index] - y_scatter_values = scatter_samples[:, row_index] - is_diagonal_subplot = row_index == col_index - if is_diagonal_subplot: - density_trace = self._posterior_density_trace( - fit_results=fit_results, - parameter_name=parameter_names[col_index], - values=x_density_values, - trace_name=labels[col_index], - ) - diagonal_y_axis_range = None - if density_trace is None: - fig.add_trace( - go.Histogram( - x=x_density_values, - nbinsx=40, - histnorm='probability density', - marker={'color': 'rgb(99, 110, 250)'}, - showlegend=False, - hovertemplate='%{x:.4f}
density=%{y:.4f}', - ), - row=row, - col=col, - ) - else: - density_trace.name = 'Marginal density' - density_trace.legendgroup = 'posterior-marginal-density' - density_trace.showlegend = show_density_legend - fig.add_trace(density_trace, row=row, col=col) - show_density_legend = False - diagonal_y_axis_range = self._posterior_density_axis_range( - np.asarray(density_trace.y) - ) - if diagonal_y_axis_range is not None: - fig.update_yaxes(range=list(diagonal_y_axis_range), row=row, col=col) - else: - contour_traces = self._posterior_contour_traces( - fit_results=fit_results, - x_parameter_name=parameter_names[col_index], - y_parameter_name=parameter_names[row_index], - x_values=x_density_values, - y_values=y_density_values, - ) - sample_hovertemplate = ( - f'{labels[col_index]}: %{{x:.4f}}
' - f'{labels[row_index]}: %{{y:.4f}}' - ) - fig.add_trace( - go.Scatter( - x=x_scatter_values, - y=y_scatter_values, - mode='markers', - marker={ - 'color': POSTERIOR_SCATTER_MARKER_COLOR, - 'size': 3, - }, - name='Posterior samples', - legendgroup='posterior-samples', - showlegend=show_scatter_legend, - hoverinfo='skip', - zorder=0, - ), - row=row, - col=col, - ) - show_scatter_legend = False - if contour_traces is not None: - contour_traces[0].name = 'Posterior contours' - contour_traces[0].legendgroup = 'posterior-contours' - contour_traces[0].showlegend = show_contour_legend - contour_traces[1].legendgroup = 'posterior-contours' - contour_traces[1].showlegend = False - fig.add_trace(contour_traces[0], row=row, col=col) - fig.add_trace(contour_traces[1], row=row, col=col) - show_contour_legend = False - fig.add_trace( - go.Scatter( - x=x_scatter_values, - y=y_scatter_values, - mode='markers', - marker={ - 'color': 'rgba(0, 0, 0, 0)', - 'size': 6, - }, - showlegend=False, - hovertemplate=sample_hovertemplate, - zorder=3, - ), - row=row, - col=col, - ) + def _add_posterior_pair_diagonal( + self, + *, + fig: object, + context: _PosteriorPairsContext, + row: int, + col: int, + parameter_index: int, + legend_state: _PosteriorPairsLegendState, + ) -> None: + """Add the diagonal marginal-density panel.""" + go = __import__('plotly.graph_objects', fromlist=['Histogram']) + density_values = context.density_samples[:, parameter_index] + density_trace = self._posterior_density_trace( + fit_results=context.fit_results, + parameter_name=context.parameter_names[parameter_index], + values=density_values, + trace_name=context.labels[parameter_index], + ) + if density_trace is None: + fig.add_trace( + go.Histogram( + x=density_values, + nbinsx=40, + histnorm='probability density', + marker={'color': 'rgb(99, 110, 250)'}, + showlegend=False, + hovertemplate='%{x:.4f}
density=%{y:.4f}', + ), + row=row, + col=col, + ) + return - fig.update_xaxes( - showline=True, - mirror=True, - range=list(parameter_axis_ranges[col_index]), - zeroline=False, - layer='above traces', - linecolor=axis_frame_color, - linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, - nticks=PAIR_PLOT_MAJOR_TICKS, - tickformat=',.6~g', - separatethousands=True, - row=row, - col=col, - ) - fig.update_yaxes( - showline=True, - mirror=True, - zeroline=False, - layer='above traces', - linecolor=axis_frame_color, - linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, - nticks=PAIR_PLOT_MAJOR_TICKS, - tickformat=',.6~g', - separatethousands=True, - row=row, - col=col, - ) - if not is_diagonal_subplot: - fig.update_yaxes(range=list(parameter_axis_ranges[row_index]), row=row, col=col) - fig.update_xaxes(showticklabels=(row_index == n_parameters - 1), row=row, col=col) - if is_diagonal_subplot: - fig.update_yaxes( - showticklabels=False, - ticks='', - ticklen=0, - showgrid=False, - title_text=None, - row=row, - col=col, - ) - else: - fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) - if row_index == n_parameters - 1: - fig.update_xaxes(title_text=labels[col_index], row=row, col=col) - - subplot = fig.get_subplot(row, col) - if col_index == 0: - subplot_title_annotations.append( - { - 'x': subplot.xaxis.domain[0], - 'xref': 'paper', - 'xanchor': 'right', - 'xshift': -POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS, - 'y': 0.5 * (subplot.yaxis.domain[0] + subplot.yaxis.domain[1]), - 'yref': 'paper', - 'yanchor': 'middle', - 'text': labels[row_index], - 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, - 'textangle': -90, - 'showarrow': False, - } - ) - subplot_border_shapes.append( - { - 'type': 'rect', - 'xref': 'paper', - 'yref': 'paper', - 'x0': subplot.xaxis.domain[0], - 'x1': subplot.xaxis.domain[1], - 'y0': subplot.yaxis.domain[0], - 'y1': subplot.yaxis.domain[1], - 'line': { - 'color': axis_frame_color, - 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, - }, - 'fillcolor': 'rgba(0, 0, 0, 0)', - 'layer': 'above', - } - ) + density_trace.name = 'Marginal density' + density_trace.legendgroup = 'posterior-marginal-density' + density_trace.showlegend = legend_state.show_density + fig.add_trace(density_trace, row=row, col=col) + legend_state.show_density = False + y_axis_range = self._posterior_density_axis_range(np.asarray(density_trace.y)) + if y_axis_range is not None: + fig.update_yaxes(range=list(y_axis_range), row=row, col=col) + + def _add_posterior_pair_off_diagonal( + self, + *, + fig: object, + context: _PosteriorPairsContext, + row: int, + col: int, + row_index: int, + col_index: int, + legend_state: _PosteriorPairsLegendState, + ) -> None: + """Add one off-diagonal pair-relationship panel.""" + go = __import__('plotly.graph_objects', fromlist=['Scatter']) + x_density_values = context.density_samples[:, col_index] + y_density_values = context.density_samples[:, row_index] + x_scatter_values = context.scatter_samples[:, col_index] + y_scatter_values = context.scatter_samples[:, row_index] + contour_traces = self._posterior_contour_traces( + fit_results=context.fit_results, + x_parameter_name=context.parameter_names[col_index], + y_parameter_name=context.parameter_names[row_index], + x_values=x_density_values, + y_values=y_density_values, + ) + sample_hovertemplate = ( + f'{context.labels[col_index]}: %{{x:.4f}}
' + f'{context.labels[row_index]}: %{{y:.4f}}' + ) + fig.add_trace( + go.Scatter( + x=x_scatter_values, + y=y_scatter_values, + mode='markers', + marker={'color': POSTERIOR_SCATTER_MARKER_COLOR, 'size': 3}, + name='Posterior samples', + legendgroup='posterior-samples', + showlegend=legend_state.show_scatter, + hoverinfo='skip', + zorder=0, + ), + row=row, + col=col, + ) + legend_state.show_scatter = False + if contour_traces is not None: + contour_traces[0].name = 'Posterior contours' + contour_traces[0].legendgroup = 'posterior-contours' + contour_traces[0].showlegend = legend_state.show_contour + contour_traces[1].legendgroup = 'posterior-contours' + contour_traces[1].showlegend = False + fig.add_trace(contour_traces[0], row=row, col=col) + fig.add_trace(contour_traces[1], row=row, col=col) + legend_state.show_contour = False + fig.add_trace( + go.Scatter( + x=x_scatter_values, + y=y_scatter_values, + mode='markers', + marker={'color': 'rgba(0, 0, 0, 0)', 'size': 6}, + showlegend=False, + hovertemplate=sample_hovertemplate, + zorder=3, + ), + row=row, + col=col, + ) + @staticmethod + def _configure_posterior_pair_panel_axes( + *, + fig: object, + context: _PosteriorPairsContext, + row: int, + col: int, + row_index: int, + col_index: int, + ) -> None: + """Apply axis styling and labels to one pair-plot panel.""" + is_diagonal = row_index == col_index + fig.update_xaxes( + showline=True, + mirror=True, + range=list(context.axis_ranges[col_index]), + zeroline=False, + layer='above traces', + linecolor=context.axis_frame_color, + linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, + nticks=PAIR_PLOT_MAJOR_TICKS, + tickformat=',.6~g', + separatethousands=True, + row=row, + col=col, + ) + fig.update_yaxes( + showline=True, + mirror=True, + zeroline=False, + layer='above traces', + linecolor=context.axis_frame_color, + linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, + nticks=PAIR_PLOT_MAJOR_TICKS, + tickformat=',.6~g', + separatethousands=True, + row=row, + col=col, + ) + if not is_diagonal: + fig.update_yaxes(range=list(context.axis_ranges[row_index]), row=row, col=col) + fig.update_xaxes(showticklabels=(row_index == context.n_parameters - 1), row=row, col=col) + if is_diagonal: + fig.update_yaxes( + showticklabels=False, + ticks='', + ticklen=0, + showgrid=False, + title_text=None, + row=row, + col=col, + ) + else: + fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) + if row_index == context.n_parameters - 1: + fig.update_xaxes(title_text=context.labels[col_index], row=row, col=col) + + @staticmethod + def _collect_posterior_pair_panel_decorations( + *, + fig: object, + context: _PosteriorPairsContext, + row_index: int, + col_index: int, + subplot_title_annotations: list[dict[str, object]], + subplot_border_shapes: list[dict[str, object]], + ) -> None: + """Collect annotations and frame shapes for one pair panel.""" + row = row_index + 1 + col = col_index + 1 + subplot = fig.get_subplot(row, col) + if col_index == 0: + subplot_title_annotations.append({ + 'x': subplot.xaxis.domain[0], + 'xref': 'paper', + 'xanchor': 'right', + 'xshift': -POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS, + 'y': 0.5 * (subplot.yaxis.domain[0] + subplot.yaxis.domain[1]), + 'yref': 'paper', + 'yanchor': 'middle', + 'text': context.labels[row_index], + 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + 'textangle': -90, + 'showarrow': False, + }) + subplot_border_shapes.append({ + 'type': 'rect', + 'xref': 'paper', + 'yref': 'paper', + 'x0': subplot.xaxis.domain[0], + 'x1': subplot.xaxis.domain[1], + 'y0': subplot.yaxis.domain[0], + 'y1': subplot.yaxis.domain[1], + 'line': { + 'color': context.axis_frame_color, + 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, + }, + 'fillcolor': 'rgba(0, 0, 0, 0)', + 'layer': 'above', + }) + + @staticmethod + def _finalize_posterior_pairs_figure( + *, + fig: object, + context: _PosteriorPairsContext, + subplot_title_annotations: list[dict[str, object]], + subplot_border_shapes: list[dict[str, object]], + ) -> None: + """Apply final layout settings to the posterior pair plot.""" figure_size = max( PAIR_PLOT_MIN_SIZE_PIXELS, - PAIR_PLOT_CELL_SIZE_PIXELS * n_parameters + PAIR_PLOT_MARGIN_PIXELS, + PAIR_PLOT_CELL_SIZE_PIXELS * context.n_parameters + PAIR_PLOT_MARGIN_PIXELS, ) fig.update_layout( - margin={ - 'autoexpand': True, - 'r': 30, - 't': 40, - 'b': 45, - }, + margin={'autoexpand': True, 'r': 30, 't': 40, 'b': 45}, title={'text': 'Posterior pair plot'}, bargap=0.05, width=figure_size, @@ -1230,10 +1454,11 @@ def _build_posterior_pairs_plot( 'groupclick': 'togglegroup', }, ) - return fig def _plot_axis_frame_color(self) -> str: - """Return the shared axis-frame color for Plotly-backed plots.""" + """ + Return the shared axis-frame color for Plotly-backed plots. + """ axis_frame_color = getattr(self._backend, '_axis_frame_color', None) if callable(axis_frame_color): return axis_frame_color() @@ -1248,7 +1473,9 @@ def _posterior_contour_traces( x_values: np.ndarray, y_values: np.ndarray, ) -> tuple[object, object] | None: - """Return filled and line contour traces for posterior pair plots.""" + """ + Return filled and line contour traces for posterior pair plots. + """ go = __import__('plotly.graph_objects', fromlist=['Contour']) bounds = self._posterior_pair_bounds( @@ -1320,7 +1547,8 @@ def _build_param_distribution_plot( self, param: object, ) -> object | None: - """Build a Plotly posterior distribution plot for one parameter. + """ + Build a Plotly posterior distribution plot for one parameter. Parameters ---------- @@ -1333,6 +1561,58 @@ def _build_param_distribution_plot( Plotly figure, or ``None`` when posterior plotting is unavailable. """ + context = self._posterior_distribution_context(param) + if context is None: + return None + + go = __import__('plotly.graph_objects', fromlist=['Figure', 'Histogram']) + fig, layout_factory = self._posterior_distribution_figure( + go=go, + title=context.title, + label=context.label, + ) + density_trace = self._posterior_density_trace( + fit_results=context.fit_results, + parameter_name=context.parameter_name, + values=context.values, + trace_name='Posterior density', + ) + y_axis_range = self._posterior_distribution_y_axis_range( + values=context.values, + density_trace=density_trace, + ) + + self._add_posterior_distribution_interval_traces( + fig=fig, + summary=context.summary, + y_axis_range=y_axis_range, + ) + self._add_posterior_distribution_histogram( + fig=fig, + go=go, + values=context.values, + ) + self._add_posterior_distribution_density_trace(fig=fig, density_trace=density_trace) + self._add_posterior_distribution_reference_traces( + fig=fig, + summary=context.summary, + values=context.values, + y_axis_range=y_axis_range, + ) + self._apply_posterior_distribution_layout( + fig=fig, + layout_factory=layout_factory, + title=context.title, + label=context.label, + y_axis_range=y_axis_range, + ) + return fig + + def _posterior_distribution_context( + self, + param: object, + ) -> _PosteriorDistributionContext | None: + """Return the context for a posterior distribution plot.""" posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() if posterior_samples is None or fit_results is None: return None @@ -1344,57 +1624,86 @@ def _build_param_distribution_plot( if parameter_names is None: return None - go = __import__('plotly.graph_objects', fromlist=['Figure', 'Histogram']) - parameter_name = parameter_names[0] samples = self._selected_posterior_samples(posterior_samples, [parameter_name]) if samples is None: return None - values = samples[:, 0] + label = self._posterior_plot_labels(fit_results, [parameter_name])[0] - summary = self._posterior_summary_by_name(fit_results).get(parameter_name) - title = f'Posterior distribution: {label}' + return _PosteriorDistributionContext( + fit_results=fit_results, + parameter_name=parameter_name, + values=samples[:, 0], + label=label, + title=f'Posterior distribution: {label}', + summary=self._posterior_summary_by_name(fit_results).get(parameter_name), + ) + + def _posterior_distribution_figure( + self, + *, + go: object, + title: str, + label: str, + ) -> tuple[object, object | None]: + """Return the figure and optional backend layout factory.""" layout_factory = getattr(self._backend, '_get_layout', None) if callable(layout_factory): - fig = go.Figure(layout=layout_factory(title, [label, 'Probability density'])) - else: - fig = go.Figure() + figure = go.Figure(layout=layout_factory(title, [label, 'Probability density'])) + return figure, layout_factory + return go.Figure(), layout_factory + def _posterior_distribution_y_axis_range( + self, + *, + values: np.ndarray, + density_trace: object | None, + ) -> tuple[float, float] | None: + """Return the y-axis range for a posterior distribution plot.""" histogram_density, _ = np.histogram(values, bins=50, density=True) - density_trace = self._posterior_density_trace( - fit_results=fit_results, - parameter_name=parameter_name, - values=values, - trace_name='Posterior density', - ) density_sources = [histogram_density] if density_trace is not None: - density_trace.name = 'Posterior density' - density_trace.showlegend = True density_sources.append(np.asarray(density_trace.y, dtype=float)) + return self._posterior_density_axis_range(np.concatenate(density_sources)) - y_axis_range = self._posterior_density_axis_range(np.concatenate(density_sources)) + def _add_posterior_distribution_interval_traces( + self, + *, + fig: object, + summary: object | None, + y_axis_range: tuple[float, float] | None, + ) -> None: + """Add credible-interval bands to the distribution plot.""" + if summary is None or y_axis_range is None: + return - if summary is not None and y_axis_range is not None: - fig.add_trace( - self._posterior_interval_band_trace( - x0=summary.interval_95[0], - x1=summary.interval_95[1], - y_axis_range=y_axis_range, - trace_name='95% credible interval', - color=POSTERIOR_INTERVAL_95_FILL_COLOR, - ) + fig.add_trace( + self._posterior_interval_band_trace( + x0=summary.interval_95[0], + x1=summary.interval_95[1], + y_axis_range=y_axis_range, + trace_name='95% credible interval', + color=POSTERIOR_INTERVAL_95_FILL_COLOR, ) - fig.add_trace( - self._posterior_interval_band_trace( - x0=summary.interval_68[0], - x1=summary.interval_68[1], - y_axis_range=y_axis_range, - trace_name='68% credible interval', - color=POSTERIOR_INTERVAL_68_FILL_COLOR, - ) + ) + fig.add_trace( + self._posterior_interval_band_trace( + x0=summary.interval_68[0], + x1=summary.interval_68[1], + y_axis_range=y_axis_range, + trace_name='68% credible interval', + color=POSTERIOR_INTERVAL_68_FILL_COLOR, ) + ) + @staticmethod + def _add_posterior_distribution_histogram( + *, + fig: object, + go: object, + values: np.ndarray, + ) -> None: + """Add the histogram trace for a posterior distribution plot.""" fig.add_trace( go.Histogram( x=values, @@ -1409,33 +1718,65 @@ def _build_param_distribution_plot( hovertemplate='sample=%{x:.4f}
density=%{y:.4f}', ) ) - if density_trace is not None: - density_trace.name = 'Posterior density' - density_trace.showlegend = True - fig.add_trace(density_trace) - median = float(np.median(values)) - if y_axis_range is not None: - fig.add_trace( - self._posterior_reference_line_trace( - x_value=median, - y_axis_range=y_axis_range, - trace_name='Median', - color=POSTERIOR_MEDIAN_LINE_COLOR, - dash='dash', - ) + @staticmethod + def _add_posterior_distribution_density_trace( + *, + fig: object, + density_trace: object | None, + ) -> None: + """Add the KDE trace for a posterior distribution plot.""" + if density_trace is None: + return + + density_trace.name = 'Posterior density' + density_trace.showlegend = True + fig.add_trace(density_trace) + + def _add_posterior_distribution_reference_traces( + self, + *, + fig: object, + summary: object | None, + values: np.ndarray, + y_axis_range: tuple[float, float] | None, + ) -> None: + """Add posterior median and MAP reference lines.""" + if y_axis_range is None: + return + + fig.add_trace( + self._posterior_reference_line_trace( + x_value=float(np.median(values)), + y_axis_range=y_axis_range, + trace_name='Median', + color=POSTERIOR_MEDIAN_LINE_COLOR, + dash='dash', ) - if summary is not None: - fig.add_trace( - self._posterior_reference_line_trace( - x_value=summary.map_value, - y_axis_range=y_axis_range, - trace_name='Max posterior', - color=POSTERIOR_POINT_ESTIMATE_LINE_COLOR, - dash='dot', - ) - ) + ) + if summary is None: + return + + fig.add_trace( + self._posterior_reference_line_trace( + x_value=summary.map_value, + y_axis_range=y_axis_range, + trace_name='Max posterior', + color=POSTERIOR_POINT_ESTIMATE_LINE_COLOR, + dash='dot', + ) + ) + @staticmethod + def _apply_posterior_distribution_layout( + *, + fig: object, + layout_factory: object | None, + title: str, + label: str, + y_axis_range: tuple[float, float] | None, + ) -> None: + """Apply layout settings to the distribution plot.""" if callable(layout_factory): fig.update_layout(title={'text': title}) else: @@ -1453,7 +1794,6 @@ def _build_param_distribution_plot( ) if y_axis_range is not None: fig.update_yaxes(range=list(y_axis_range)) - return fig def _show_plot_figure(self, figure: object) -> None: """Display a figure through the active backend when possible.""" @@ -1515,7 +1855,7 @@ def _posterior_density_axis_range( upper_padding = 0.08 * data_range if data_range > 0 else max(abs(data_max), 1.0) * 0.05 if upper_padding == 0: upper_padding = 1e-6 - lower = 0.0 if data_min >= 0.0 else data_min + lower = min(0.0, data_min) return lower, data_max + upper_padding @staticmethod @@ -1532,7 +1872,13 @@ def _posterior_interval_band_trace( return go.Scatter( x=[x0, x1, x1, x0, x0], - y=[y_axis_range[0], y_axis_range[0], y_axis_range[1], y_axis_range[1], y_axis_range[0]], + y=[ + y_axis_range[0], + y_axis_range[0], + y_axis_range[1], + y_axis_range[1], + y_axis_range[0], + ], mode='lines', fill='toself', fillcolor=color, @@ -1551,7 +1897,9 @@ def _posterior_reference_line_trace( color: str, dash: str, ) -> object: - """Return a named vertical reference line for posterior plots.""" + """ + Return a named vertical reference line for posterior plots. + """ go = __import__('plotly.graph_objects', fromlist=['Scatter']) return go.Scatter( @@ -1570,9 +1918,10 @@ def _posterior_parameter_bounds( fit_results: object, parameter_name: str, ) -> tuple[float | None, float | None]: - """Return finite fit bounds for a posterior parameter when available.""" + """Return finite fit bounds for a posterior parameter.""" parameters_by_name = { - getattr(parameter, 'unique_name', ''): parameter for parameter in fit_results.parameters + getattr(parameter, 'unique_name', ''): parameter + for parameter in fit_results.parameters } parameter = parameters_by_name.get(parameter_name) if parameter is None: @@ -1651,7 +2000,7 @@ def _posterior_density_curve( data = np.asarray(values, dtype=float) data = data[np.isfinite(data)] - if data.size < 2: + if data.size < MIN_POSTERIOR_SAMPLE_COUNT: return None data_min = float(np.min(data)) @@ -1703,7 +2052,7 @@ def _posterior_pair_density_surface( mask = np.isfinite(x_data) & np.isfinite(y_data) x_data = x_data[mask] y_data = y_data[mask] - if x_data.size < 2 or y_data.size < 2: + if x_data.size < MIN_POSTERIOR_SAMPLE_COUNT or y_data.size < MIN_POSTERIOR_SAMPLE_COUNT: return None if np.allclose(x_data, x_data[0]) and np.allclose(y_data, y_data[0]): @@ -1730,7 +2079,7 @@ def _reflection_positions_1d( lower_bound: float | None, upper_bound: float | None, ) -> list[np.ndarray]: - """Return mirrored evaluation positions for boundary-corrected KDEs.""" + """Return mirrored positions for boundary-corrected KDEs.""" reflected = [values] if lower_bound is not None: reflected.append(2.0 * lower_bound - values) @@ -1792,7 +2141,9 @@ def _get_or_build_posterior_predictive_summary( expt_name: str, x_axis: object, ) -> object | None: - """Return a cached or newly built posterior predictive summary.""" + """ + Return a cached or newly built posterior predictive summary. + """ fit_results = self._get_fit_result_for_correlation() if fit_results is None: return None @@ -1829,22 +2180,73 @@ def _build_posterior_predictive_summary( x_axis: object, ) -> object | None: """Build posterior predictive summaries from posterior draws.""" - from easydiffraction.analysis.fit_helpers.bayesian import PosteriorPredictiveSummary + sampling_inputs = self._posterior_predictive_sampling_inputs(fit_results) + if sampling_inputs is None: + return None + flattened_samples, parameter_names = sampling_inputs + sampled_parameters = self._posterior_predictive_parameters( + fit_results=fit_results, + parameter_names=parameter_names, + ) + if sampled_parameters is None: + return None + + predictive_data = self._evaluate_posterior_predictive_draws( + flattened_samples=flattened_samples, + sampled_parameters=sampled_parameters, + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + ) + if predictive_data is None: + return None + + map_prediction, x_values, predictive_draw_array = predictive_data + lower_68, upper_68 = np.quantile(predictive_draw_array, [0.16, 0.84], axis=0) + lower_95, upper_95 = np.quantile(predictive_draw_array, [0.025, 0.975], axis=0) + x_axis_name = getattr(x_axis, 'value', x_axis) + + return PosteriorPredictiveSummary( + experiment_name=expt_name, + x_axis_name=str(x_axis_name), + x=np.asarray(x_values, dtype=float), + map_prediction=np.asarray(map_prediction, dtype=float), + lower_95=np.asarray(lower_95, dtype=float), + upper_95=np.asarray(upper_95, dtype=float), + lower_68=np.asarray(lower_68, dtype=float), + upper_68=np.asarray(upper_68, dtype=float), + draws=predictive_draw_array, + ) + + @staticmethod + def _posterior_predictive_sampling_inputs( + fit_results: object, + ) -> tuple[np.ndarray, list[str]] | None: + """Return predictive-sampling arrays and parameter names.""" posterior_samples = getattr(fit_results, 'posterior_samples', None) if posterior_samples is None: return None flattened_samples = np.asarray(posterior_samples.flattened(), dtype=float) parameter_names = getattr(posterior_samples, 'parameter_names', None) - if flattened_samples.ndim != 2 or not parameter_names: + if flattened_samples.ndim != POSTERIOR_FLATTENED_SAMPLE_NDIM or not parameter_names: log.warning('Posterior samples are unavailable for predictive summaries.') return None + return flattened_samples, list(parameter_names) + @staticmethod + def _posterior_predictive_parameters( + *, + fit_results: object, + parameter_names: list[str], + ) -> list[object] | None: + """Return fitted parameters in posterior sample order.""" parameters_by_name = { - getattr(parameter, 'unique_name', ''): parameter for parameter in fit_results.parameters + getattr(parameter, 'unique_name', ''): parameter + for parameter in fit_results.parameters } - sampled_parameters = [] + sampled_parameters: list[object] = [] for name in parameter_names: parameter = parameters_by_name.get(name) if parameter is None: @@ -1854,14 +2256,26 @@ def _build_posterior_predictive_summary( ) return None sampled_parameters.append(parameter) + return sampled_parameters - original_values = np.array([parameter.value for parameter in sampled_parameters], dtype=float) + def _evaluate_posterior_predictive_draws( + self, + *, + flattened_samples: np.ndarray, + sampled_parameters: list[object], + experiment: object, + expt_name: str, + x_axis: object, + ) -> tuple[np.ndarray, np.ndarray, np.ndarray] | None: + """Return MAP and sampled predictive curves.""" + original_values = np.array( + [parameter.value for parameter in sampled_parameters], + dtype=float, + ) original_uncertainties = [parameter.uncertainty for parameter in sampled_parameters] - - map_prediction = None - x_values = None predictive_draws: list[np.ndarray] = [] draw_indices = self._posterior_predictive_draw_indices(flattened_samples.shape[0]) + try: map_prediction, x_values = self._evaluate_posterior_predictive_state( sampled_parameters=sampled_parameters, @@ -1888,33 +2302,38 @@ def _build_posterior_predictive_summary( return None predictive_draws.append(prediction) finally: - for parameter, value, uncertainty in zip( - sampled_parameters, - original_values, - original_uncertainties, - strict=True, - ): - parameter._set_value_from_minimizer(float(value)) - parameter.uncertainty = uncertainty - self._update_project_categories(expt_name) - - predictive_draw_array = np.asarray(predictive_draws, dtype=float) - lower_68, upper_68 = np.quantile(predictive_draw_array, [0.16, 0.84], axis=0) - lower_95, upper_95 = np.quantile(predictive_draw_array, [0.025, 0.975], axis=0) - x_axis_name = getattr(x_axis, 'value', x_axis) + self._restore_posterior_predictive_parameters( + sampled_parameters=sampled_parameters, + original_values=original_values, + original_uncertainties=original_uncertainties, + expt_name=expt_name, + ) - return PosteriorPredictiveSummary( - experiment_name=expt_name, - x_axis_name=str(x_axis_name), - x=np.asarray(x_values, dtype=float), - map_prediction=np.asarray(map_prediction, dtype=float), - lower_95=np.asarray(lower_95, dtype=float), - upper_95=np.asarray(upper_95, dtype=float), - lower_68=np.asarray(lower_68, dtype=float), - upper_68=np.asarray(upper_68, dtype=float), - draws=predictive_draw_array, + return ( + np.asarray(map_prediction, dtype=float), + np.asarray(x_values, dtype=float), + np.asarray(predictive_draws, dtype=float), ) + def _restore_posterior_predictive_parameters( + self, + *, + sampled_parameters: list[object], + original_values: np.ndarray, + original_uncertainties: list[float | None], + expt_name: str, + ) -> None: + """Restore parameter state after predictive sampling.""" + for parameter, value, uncertainty in zip( + sampled_parameters, + original_values, + original_uncertainties, + strict=True, + ): + parameter._set_value_from_minimizer(float(value)) + parameter.uncertainty = uncertainty + self._update_project_categories(expt_name) + def _evaluate_posterior_predictive_state( self, *, @@ -1944,7 +2363,9 @@ def _evaluate_posterior_predictive_state( @staticmethod def _posterior_predictive_draw_indices(n_draws: int) -> np.ndarray: - """Select evenly spaced posterior draws for predictive summaries.""" + """ + Select evenly spaced posterior draws for predictive summaries. + """ if n_draws <= DEFAULT_POSTERIOR_PREDICTIVE_DRAWS: return np.arange(n_draws, dtype=int) @@ -1965,7 +2386,8 @@ def _posterior_predictive_key(expt_name: str, x_axis_name: str) -> str: def _get_posterior_inference_data( self, ) -> tuple[object | None, object | None]: - """Return posterior inference data for the current Bayesian fit. + """ + Return posterior inference data for the current Bayesian fit. Returns ------- @@ -2007,8 +2429,8 @@ def _get_posterior_samples_and_fit_results( return posterior_samples, fit_results + @staticmethod def _plot_posterior_predictive_summary( - self, *, expt_name: str, summary: object, @@ -2098,13 +2520,12 @@ def _plot_posterior_predictive_data( x_axis: object, style: str, ) -> None: - """Render posterior predictive curves on the composite powder layout.""" + """Render posterior predictive curves on the powder layout.""" pattern = intensity_category_for(experiment) - expt_type = experiment.type ctx = self._prepare_powder_context( pattern, expt_name, - expt_type, + experiment.type, plot_options.x_min, plot_options.x_max, plot_options.x, @@ -2132,7 +2553,9 @@ def _plot_posterior_predictive_data( if y_bkg_raw is not None else None ) - y_calc = self._filtered_y_array(summary.map_prediction, summary.x, ctx['x_min'], ctx['x_max']) + y_calc = self._filtered_y_array( + summary.map_prediction, summary.x, ctx['x_min'], ctx['x_max'] + ) show_residual = True if plot_options.show_residual is None else plot_options.show_residual y_resid = y_meas - y_calc if show_residual else None @@ -2202,7 +2625,8 @@ def _resolve_posterior_parameter_names( fit_results: object, parameters: list[object] | None, ) -> list[str] | None: - """Resolve posterior parameter names from descriptors. + """ + Resolve posterior parameter names from descriptors. Parameters ---------- @@ -2251,7 +2675,7 @@ def _selected_posterior_samples( return None flattened = np.asarray(posterior_samples.flattened(), dtype=float) - if flattened.ndim != 2: + if flattened.ndim != POSTERIOR_FLATTENED_SAMPLE_NDIM: return None return flattened[:, indices] @@ -2273,9 +2697,12 @@ def _posterior_plot_labels( fit_results: object, parameter_names: list[str], ) -> list[str]: - """Return readable posterior plot labels for selected parameters.""" + """ + Return readable posterior plot labels for selected parameters. + """ parameters_by_name = { - getattr(parameter, 'unique_name', ''): parameter for parameter in fit_results.parameters + getattr(parameter, 'unique_name', ''): parameter + for parameter in fit_results.parameters } labels: list[str] = [] for parameter_name in parameter_names: @@ -2325,7 +2752,8 @@ def _get_fit_result_for_correlation( def _correlation_from_posterior_samples( posterior_samples: object, ) -> pd.DataFrame | None: - """Convert posterior samples into a correlation DataFrame. + """ + Convert posterior samples into a correlation DataFrame. Parameters ---------- @@ -2345,10 +2773,12 @@ def _correlation_from_posterior_samples( return None flattened = np.asarray(posterior_samples.flattened(), dtype=float) - if flattened.ndim != 2 or flattened.shape[1] != len(parameter_names): + if flattened.ndim != POSTERIOR_FLATTENED_SAMPLE_NDIM or flattened.shape[1] != len( + parameter_names + ): log.warning('Posterior sample array has an invalid shape for correlations.') return None - if flattened.shape[0] < 2: + if flattened.shape[0] < MIN_POSTERIOR_SAMPLE_COUNT: log.warning('At least two posterior draws are required for correlations.') return None diff --git a/tests/integration/fitting/test_bayesian_dream.py b/tests/integration/fitting/test_bayesian_dream.py new file mode 100644 index 00000000..23e0de58 --- /dev/null +++ b/tests/integration/fitting/test_bayesian_dream.py @@ -0,0 +1,178 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +import tempfile + +import numpy as np + +from easydiffraction import ExperimentFactory +from easydiffraction import Project +from easydiffraction import StructureFactory +from easydiffraction import download_data + +TEMP_DIR = tempfile.gettempdir() + + +def _create_lbco_project() -> Project: + model = StructureFactory.from_scratch(name='lbco') + model.space_group.name_h_m = 'P m -3 m' + model.cell.length_a = 3.88 + model.atom_sites.create( + label='La', + type_symbol='La', + fract_x=0, + fract_y=0, + fract_z=0, + wyckoff_letter='a', + occupancy=0.5, + adp_iso=0.1, + ) + model.atom_sites.create( + label='Ba', + type_symbol='Ba', + fract_x=0, + fract_y=0, + fract_z=0, + wyckoff_letter='a', + occupancy=0.5, + adp_iso=0.1, + ) + model.atom_sites.create( + label='Co', + type_symbol='Co', + fract_x=0.5, + fract_y=0.5, + fract_z=0.5, + wyckoff_letter='b', + adp_iso=0.1, + ) + model.atom_sites.create( + label='O', + type_symbol='O', + fract_x=0, + fract_y=0.5, + fract_z=0.5, + wyckoff_letter='c', + adp_iso=0.1, + ) + + data_path = download_data(id=3, destination=TEMP_DIR) + experiment = ExperimentFactory.from_data_path(name='hrpt', data_path=data_path) + experiment.instrument.setup_wavelength = 1.494 + experiment.instrument.calib_twotheta_offset = 0.0 + experiment.peak.broad_gauss_u = 0.1 + experiment.peak.broad_gauss_v = -0.1 + experiment.peak.broad_gauss_w = 0.2 + experiment.peak.broad_lorentz_x = 0.0 + experiment.peak.broad_lorentz_y = 0.0 + experiment.linked_phases.create(id='lbco', scale=5.0) + experiment.background.create(id='1', x=10, y=170) + experiment.background.create(id='2', x=165, y=170) + + project = Project(name='lbco_bayesian') + project.structures.add(model) + project.experiments.add(experiment) + return project + + +def _dream_parameters(project: Project) -> tuple[object, object, object]: + structure = project.structures['lbco'] + experiment = project.experiments['hrpt'] + return ( + structure.cell.length_a, + experiment.linked_phases['lbco'].scale, + experiment.instrument.calib_twotheta_offset, + ) + + +def _configure_small_dream(project: Project) -> None: + project.analysis.fit.minimizer_type = 'bumps (dream)' + minimizer = project.analysis.fit.minimizer + minimizer.steps = 20 + minimizer.burn = 5 + minimizer.thin = 1 + minimizer.pop = 4 + minimizer.init = 'lhs' + + +def test_small_bounded_dream_refinement_produces_posterior_results(): + project = _create_lbco_project() + length_a, scale, offset = _dream_parameters(project) + for parameter in (length_a, scale, offset): + parameter.free = True + + length_a.fit_min = 3.84 + length_a.fit_max = 3.92 + scale.fit_min = 1.0 + scale.fit_max = 12.0 + offset.fit_min = -1.0 + offset.fit_max = 1.0 + + _configure_small_dream(project) + project.analysis.fit(verbosity='silent', random_seed=11) + + results = project.analysis.fit_results + assert results.success is True + assert results.sampler_completed is True + assert results.sampler_name == 'dream' + assert results.posterior_samples is not None + assert results.posterior_samples.parameter_samples.ndim == 3 + assert results.sampler_settings['random_seed'] == 11 + assert results.sampler_settings['init'] == 'lhs' + assert len(results.posterior_parameter_summaries) == 3 + + +def test_lm_prefit_followed_by_dream_uses_uncertainty_based_bounds(): + project = _create_lbco_project() + length_a, scale, offset = _dream_parameters(project) + for parameter in (length_a, scale, offset): + parameter.free = True + + project.analysis.fit.minimizer_type = 'bumps (lm)' + project.analysis.fit(verbosity='silent') + + for parameter in (length_a, scale, offset): + assert parameter.uncertainty is not None + parameter.set_fit_bounds_from_uncertainty(multiplier=4) + assert np.isfinite(parameter.fit_min) + assert np.isfinite(parameter.fit_max) + + _configure_small_dream(project) + project.analysis.fit(verbosity='silent', random_seed=13) + + results = project.analysis.fit_results + assert results.success is True + assert results.posterior_samples is not None + assert results.sampler_settings['random_seed'] == 13 + assert len(results.posterior_parameter_summaries) == 3 + + +def test_bayesian_fit_results_are_runtime_only_after_save_load(tmp_path): + project = _create_lbco_project() + length_a, scale, offset = _dream_parameters(project) + for parameter in (length_a, scale, offset): + parameter.free = True + + length_a.fit_min = 3.84 + length_a.fit_max = 3.92 + scale.fit_min = 1.0 + scale.fit_max = 12.0 + offset.fit_min = -1.0 + offset.fit_max = 1.0 + + _configure_small_dream(project) + project.analysis.fit(verbosity='silent', random_seed=17) + + assert project.analysis.fit_results.posterior_samples is not None + + proj_dir = tmp_path / 'dream_project' + project.save_as(str(proj_dir)) + + analysis_cif = proj_dir / 'analysis' / 'analysis.cif' + assert analysis_cif.is_file() + assert 'posterior' not in analysis_cif.read_text().lower() + + loaded = Project.load(str(proj_dir)) + assert loaded.analysis.fit_results is None diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py new file mode 100644 index 00000000..58fee092 --- /dev/null +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py @@ -0,0 +1,188 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +import numpy as np +import pytest + + +class Identity: + def __init__(self) -> None: + self.datablock_entry_name = 'db' + self.category_code = 'cat' + self.category_entry_name = 'entry' + + +class Param: + def __init__(self, unique_name: str, start: float, value: float, uncertainty: float) -> None: + self._identity = Identity() + self._fit_start_value = start + self.unique_name = unique_name + self.name = unique_name + self.value = value + self.uncertainty = uncertainty + self.units = 'arb' + + +def test_module_import(): + import easydiffraction.analysis.fit_helpers.bayesian as MUT + + assert MUT.__name__ == 'easydiffraction.analysis.fit_helpers.bayesian' + + +def test_posterior_samples_flatten_and_to_arviz(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + + posterior_samples = PosteriorSamples( + parameter_names=['a', 'b'], + parameter_samples=np.array( + [ + [[1.0, 10.0], [2.0, 20.0]], + [[3.0, 30.0], [4.0, 40.0]], + ], + dtype=float, + ), + log_posterior=np.array([[0.1, 0.2], [0.3, 0.4]], dtype=float), + ) + + flattened = posterior_samples.flattened() + inference_data = posterior_samples.to_arviz() + + assert flattened.shape == (4, 2) + np.testing.assert_allclose(flattened[:, 0], np.array([1.0, 2.0, 3.0, 4.0])) + np.testing.assert_allclose(flattened[:, 1], np.array([10.0, 20.0, 30.0, 40.0])) + assert set(inference_data.posterior.data_vars) == {'a', 'b'} + assert inference_data.posterior['a'].shape == (2, 2) + assert inference_data.sample_stats['lp'].shape == (2, 2) + + +def test_posterior_samples_to_arviz_validates_shapes(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + + posterior_samples = PosteriorSamples( + parameter_names=['a'], + parameter_samples=np.array([1.0, 2.0]), + ) + + with pytest.raises( + ValueError, + match=r'Posterior sample array must have shape \(n_draws, n_chains, n_parameters\)\.', + ): + posterior_samples.to_arviz() + + +def test_summarize_posterior_parameters_preserves_order_and_display_names(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.analysis.fit_helpers.bayesian import summarize_posterior_parameters + + posterior_samples = PosteriorSamples( + parameter_names=['beta', 'alpha'], + parameter_samples=np.array( + [ + [[2.0, 1.0], [2.2, 1.2]], + [[1.8, 0.8], [2.1, 1.1]], + ], + dtype=float, + ), + ) + + summaries = summarize_posterior_parameters( + parameter_names=['beta', 'alpha'], + posterior_samples=posterior_samples, + map_values=np.array([2.05, 1.05]), + parameter_display_names=['Beta width', 'Alpha shift'], + convergence_diagnostics={ + 'r_hat_by_parameter': {'beta': 1.02, 'alpha': 1.0}, + 'ess_bulk_by_parameter': {'beta': 120.0, 'alpha': 800.0}, + }, + ) + + assert [summary.unique_name for summary in summaries] == ['beta', 'alpha'] + assert [summary.display_name for summary in summaries] == ['Beta width', 'Alpha shift'] + assert summaries[0].r_hat == pytest.approx(1.02) + assert summaries[0].ess_bulk == pytest.approx(120.0) + assert summaries[1].r_hat == pytest.approx(1.0) + assert summaries[1].ess_bulk == pytest.approx(800.0) + + +def test_bayesian_fit_results_display_results_prints_sampler_and_convergence(capsys, monkeypatch): + from easydiffraction.analysis.fit_helpers.bayesian import BayesianFitResults + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.utils.logging import Logger + + monkeypatch.setattr(Logger, '_reaction', Logger.Reaction.WARN, raising=True) + + results = BayesianFitResults( + success=True, + parameters=[Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05)], + reduced_chi_square=1.2345, + fitting_time=0.9876, + sampler_name='dream', + sampler_completed=True, + sampler_settings={ + 'random_seed': 1313900679, + 'steps': 200, + 'burn': 50, + 'thin': 1, + 'pop': 4, + 'samples': 3200, + }, + convergence_diagnostics={ + 'converged': False, + 'max_r_hat': 1.107, + 'min_ess_bulk': 125.9, + 'n_draws': 200, + 'n_chains': 16, + }, + posterior_parameter_summaries=[ + PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.2, + median=1.15, + standard_deviation=0.05, + interval_68=(1.1, 1.2), + interval_95=(1.0, 1.3), + r_hat=1.107, + ess_bulk=125.9, + ) + ], + best_log_posterior=-12.34, + ) + + results.display_results(y_obs=[10.0, 20.0], y_calc=[9.5, 19.5]) + + out = capsys.readouterr().out + assert 'Bayesian fit results' in out + assert 'Sampler: dream' in out + assert 'random_seed=1313900679' in out + assert 'steps=200' in out + assert 'max_r_hat=1.107' in out + assert 'min_ess_bulk=125.9' in out + assert 'Posterior parameter summaries:' in out + + monkeypatch.setattr(Logger, '_reaction', Logger.Reaction.RAISE, raising=True) + + +def test_posterior_table_notes_split_failed_diagnostics(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import _posterior_table_notes + + notes = _posterior_table_notes([ + PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.0, + median=1.0, + standard_deviation=0.1, + interval_68=(0.9, 1.1), + interval_95=(0.8, 1.2), + r_hat=1.02, + ess_bulk=100.0, + ) + ]) + + assert len(notes) == 2 + assert 'r_hat' in notes[0] + assert 'ess_bulk' in notes[1] diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps.py index 668524ea..1a73fdbc 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_bumps.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps.py @@ -38,6 +38,18 @@ def test_default_max_iterations(): assert m.max_iterations == 1000 +def test_bumps_minimizer_rejects_random_seed(): + from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer + + m = BumpsMinimizer() + + with pytest.raises( + ValueError, + match=r"Minimizer 'bumps' does not support random_seed\.", + ): + m._resolve_random_seed(17) + + def test_is_subclass_of_base(): from easydiffraction.analysis.minimizers.base import MinimizerBase from easydiffraction.analysis.minimizers.bumps import BumpsMinimizer diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py new file mode 100644 index 00000000..783b37aa --- /dev/null +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py @@ -0,0 +1,236 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +from types import SimpleNamespace +from unittest.mock import MagicMock +from unittest.mock import patch + +import numpy as np +import pytest + + +class FakeParam: + """Minimal stand-in for an EasyDiffraction parameter.""" + + def __init__(self, uid: str, value: float, uncertainty: float | None = None) -> None: + self._minimizer_uid = uid + self.unique_name = uid + self.name = uid.upper() + self.value = value + self.uncertainty = uncertainty + + def _set_value_from_minimizer(self, value: float) -> None: + self.value = value + + +def test_module_import(): + import easydiffraction.analysis.minimizers.bumps_dream as MUT + + assert MUT.__name__ == 'easydiffraction.analysis.minimizers.bumps_dream' + + +def test_type_info_and_default_init(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum + from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum + + minimizer = BumpsDreamMinimizer() + + assert minimizer.type_info.tag == MinimizerTypeEnum.BUMPS_DREAM + assert minimizer.init is DreamPopulationInitializationEnum.EPS + assert minimizer.steps == 1000 + + +def test_init_accepts_enum_or_string_and_rejects_invalid(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum + + minimizer = BumpsDreamMinimizer() + + minimizer.init = DreamPopulationInitializationEnum.LHS + assert minimizer.init is DreamPopulationInitializationEnum.LHS + + minimizer.init = 'random' + assert minimizer.init is DreamPopulationInitializationEnum.RANDOM + + with pytest.raises( + ValueError, + match=r"DREAM setting 'init' must be one of: eps, cov, lhs, random\.", + ): + minimizer.init = 'bad-init' + + +def test_resolve_random_seed_returns_provided_or_generated(monkeypatch): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + assert minimizer._resolve_random_seed(17) == 17 + assert minimizer._resolved_random_seed == 17 + + generator = SimpleNamespace(integers=lambda *args, **kwargs: 123456) + monkeypatch.setattr(np.random, 'default_rng', lambda: generator) + + assert minimizer._resolve_random_seed(None) == 123456 + assert minimizer._resolved_random_seed == 123456 + + +def test_resolved_burn_uses_auto_or_explicit_and_validates(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + assert minimizer._resolved_burn(steps=200) == 50 + + minimizer.burn = 20 + assert minimizer._resolved_burn(steps=200) == 20 + + minimizer.burn = 200 + with pytest.raises( + ValueError, + match=r"DREAM setting 'burn' must be smaller than 'steps'\.", + ): + minimizer._resolved_burn(steps=200) + + +def test_sampler_settings_include_init_and_sample_count(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum + + minimizer = BumpsDreamMinimizer() + settings = minimizer._sampler_settings( + random_seed=7, + steps=10, + burn=2, + thin=1, + pop=4, + init=DreamPopulationInitializationEnum.LHS, + n_parameters=3, + ) + + assert settings['random_seed'] == 7 + assert settings['init'] == 'lhs' + assert settings['samples'] == 120 + + +def test_sync_result_to_parameters_restores_starting_values_on_failure(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + parameters = [FakeParam('a', 10.0, uncertainty=0.7), FakeParam('b', 20.0, uncertainty=0.8)] + raw_result = SimpleNamespace( + x=np.array([99.0, 88.0]), + success=False, + starting_values=np.array([1.5, 2.5]), + starting_uncertainties=[0.1, None], + ) + + minimizer._sync_result_to_parameters(parameters, raw_result) + + assert parameters[0].value == 1.5 + assert parameters[0].uncertainty == 0.1 + assert parameters[1].value == 2.5 + assert parameters[1].uncertainty is None + + +def test_run_solver_preserves_parameter_order_and_forwards_init(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + minimizer.steps = 4 + minimizer.burn = 1 + minimizer.thin = 1 + minimizer.pop = 2 + minimizer.init = 'lhs' + + draw_index = np.array([0.0, 1.0]) + parameter_samples = np.array( + [ + [[1.0, 10.0], [2.0, 20.0]], + [[3.0, 30.0], [4.0, 40.0]], + ], + dtype=float, + ) + log_posterior = np.array([[0.1, 0.2], [0.3, 0.4]], dtype=float) + + class FakeState: + labels = ['uid_a', 'uid_b'] + + def chains(self): + return draw_index, parameter_samples, log_posterior + + def best(self): + return np.array([11.0, 22.0]), 3.5 + + fake_fitter = SimpleNamespace(id='dream') + + with ( + patch('easydiffraction.analysis.minimizers.bumps_dream.FitDriver') as mock_driver_cls, + patch('easydiffraction.analysis.minimizers.bumps_dream.FitProblem'), + patch('easydiffraction.analysis.minimizers.bumps_dream.FITTERS', [fake_fitter]), + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.compute_convergence_diagnostics', + return_value={'converged': True}, + ), + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.summarize_posterior_parameters', + return_value=[ + PosteriorParameterSummary( + unique_name='beta', + display_name='Beta', + map_value=22.0, + median=21.0, + standard_deviation=0.4, + interval_68=(20.5, 21.5), + interval_95=(20.0, 22.0), + ), + PosteriorParameterSummary( + unique_name='alpha', + display_name='Alpha', + map_value=11.0, + median=10.5, + standard_deviation=0.3, + interval_68=(10.0, 11.0), + interval_95=(9.5, 11.5), + ), + ], + ) as summarize_mock, + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.standard_deviations_from_summaries', + return_value=np.array([0.4, 0.3]), + ), + ): + driver_instance = mock_driver_cls.return_value + driver_instance.clip = MagicMock() + driver_instance.fit.return_value = (np.array([22.0, 11.0]), 0.25) + driver_instance.fitter = SimpleNamespace(state=FakeState()) + + result = minimizer._run_solver( + lambda values: np.array([0.0, 0.0]), + bumps_params=[ + SimpleNamespace(name='uid_a', value=1.0), + SimpleNamespace(name='uid_b', value=2.0), + ], + parameter_names=['beta', 'alpha'], + parameter_display_names=['Beta', 'Alpha'], + parameter_uids=['uid_b', 'uid_a'], + random_seed=17, + starting_uncertainties=[0.01, 0.02], + ) + + assert mock_driver_cls.call_args.kwargs['init'] == 'lhs' + np.testing.assert_allclose(result.x, np.array([22.0, 11.0])) + np.testing.assert_allclose(result.dx, np.array([0.4, 0.3])) + assert result.posterior_samples.parameter_names == ['beta', 'alpha'] + np.testing.assert_allclose( + result.posterior_samples.parameter_samples[:, :, 0], parameter_samples[:, :, 1] + ) + np.testing.assert_allclose( + result.posterior_samples.parameter_samples[:, :, 1], parameter_samples[:, :, 0] + ) + assert result.sampler_settings['init'] == 'lhs' + assert result.sampler_settings['random_seed'] == 17 + assert summarize_mock.call_args.kwargs['parameter_names'] == ['beta', 'alpha'] diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_enums.py b/tests/unit/easydiffraction/analysis/minimizers/test_enums.py index 23e44e5b..5551b9b7 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_enums.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_enums.py @@ -9,12 +9,19 @@ def test_module_import(): def test_enum_members(): + from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum assert MinimizerTypeEnum.LMFIT == 'lmfit' assert MinimizerTypeEnum.LMFIT_LEASTSQ == 'lmfit (leastsq)' assert MinimizerTypeEnum.LMFIT_LEAST_SQUARES == 'lmfit (least_squares)' assert MinimizerTypeEnum.DFOLS == 'dfols' + assert MinimizerTypeEnum.BUMPS_DREAM == 'bumps (dream)' + + assert DreamPopulationInitializationEnum.EPS == 'eps' + assert DreamPopulationInitializationEnum.COV == 'cov' + assert DreamPopulationInitializationEnum.LHS == 'lhs' + assert DreamPopulationInitializationEnum.RANDOM == 'random' def test_enum_default(): diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_factory.py b/tests/unit/easydiffraction/analysis/minimizers/test_factory.py index 7351d84b..406a5e09 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_factory.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_factory.py @@ -9,11 +9,12 @@ def test_minimizer_factory_list_and_show(capsys): lst = MinimizerFactory.supported_tags() assert isinstance(lst, list) - assert len(lst) >= 4 + assert len(lst) >= 5 assert 'lmfit' in lst assert 'lmfit (leastsq)' in lst assert 'lmfit (least_squares)' in lst assert 'dfols' in lst + assert 'bumps (dream)' in lst MinimizerFactory.show_supported() out = capsys.readouterr().out assert 'Supported types' in out @@ -75,3 +76,12 @@ def test_minimizer_factory_create_lmfit_least_squares(): m = MinimizerFactory.create('lmfit (least_squares)') assert isinstance(m, LmfitLeastSquaresMinimizer) assert m.method == 'least_squares' + + +def test_minimizer_factory_create_bumps_dream(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.factory import MinimizerFactory + + m = MinimizerFactory.create('bumps (dream)') + assert isinstance(m, BumpsDreamMinimizer) + assert m.method == 'dream' diff --git a/tests/unit/easydiffraction/core/test_parameters.py b/tests/unit/easydiffraction/core/test_parameters.py index e7d102d9..0a4c95cc 100644 --- a/tests/unit/easydiffraction/core/test_parameters.py +++ b/tests/unit/easydiffraction/core/test_parameters.py @@ -103,6 +103,71 @@ def test_parameter_fit_bounds_assign_and_read(): assert np.isclose(p.fit_max, 10.0) +def test_parameter_set_fit_bounds_from_uncertainty_sets_bounds_and_returns_none(): + from easydiffraction.core.validation import AttributeSpec + from easydiffraction.core.variable import Parameter + from easydiffraction.io.cif.handler import CifHandler + + p = Parameter( + name='d', + value_spec=AttributeSpec(default=0.0), + cif_handler=CifHandler(names=['_param.d']), + ) + p.value = 2.0 + p.uncertainty = 0.25 + + result = p.set_fit_bounds_from_uncertainty(multiplier=4) + + assert result is None + assert np.isclose(p.fit_min, 1.0) + assert np.isclose(p.fit_max, 3.0) + + +def test_parameter_set_fit_bounds_from_uncertainty_clips_to_physical_limits(): + from easydiffraction.core.validation import AttributeSpec + from easydiffraction.core.validation import DataTypes + from easydiffraction.core.validation import RangeValidator + from easydiffraction.core.variable import Parameter + from easydiffraction.io.cif.handler import CifHandler + + p = Parameter( + name='bounded', + value_spec=AttributeSpec( + data_type=DataTypes.NUMERIC, + default=1.0, + validator=RangeValidator(ge=0.5, le=1.5), + ), + cif_handler=CifHandler(names=['_param.bounded']), + ) + p.value = 1.0 + p.uncertainty = 0.3 + + p.set_fit_bounds_from_uncertainty(multiplier=4) + + assert np.isclose(p.fit_min, 0.5) + assert np.isclose(p.fit_max, 1.5) + + +def test_parameter_set_fit_bounds_from_uncertainty_requires_valid_uncertainty(): + from easydiffraction.core.validation import AttributeSpec + from easydiffraction.core.variable import Parameter + from easydiffraction.io.cif.handler import CifHandler + + p = Parameter( + name='invalid', + value_spec=AttributeSpec(default=0.0), + cif_handler=CifHandler(names=['_param.invalid']), + ) + p.value = 2.0 + p.uncertainty = None + + with pytest.raises( + ValueError, + match=r'Cannot set fit bounds for invalid: uncertainty is missing or invalid\.', + ): + p.set_fit_bounds_from_uncertainty(multiplier=4) + + def _make_param() -> object: from easydiffraction.core.validation import AttributeSpec from easydiffraction.core.variable import Parameter diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 5e1cc4da..6117b5cb 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -2,6 +2,10 @@ # SPDX-License-Identifier: BSD-3-Clause import re +from types import MethodType +from types import SimpleNamespace + +import numpy as np import pytest @@ -233,6 +237,170 @@ class Experiment: assert tick_sets == () +def _make_bayesian_plotter_fixture(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.display.plotting import Plotter + + samples = np.array( + [ + [[3.8900, 0.0760, -0.1170, 0.6290], [3.8908, 0.0775, -0.1185, 0.6300]], + [[3.8912, 0.0785, -0.1190, 0.6310], [3.8916, 0.0790, -0.1200, 0.6320]], + ], + dtype=float, + ) + parameter_names = ['length_a', 'broad_gauss_u', 'broad_gauss_v', 'twotheta_offset'] + posterior_samples = PosteriorSamples( + parameter_names=parameter_names, + parameter_samples=samples, + log_posterior=np.array([[0.1, 0.2], [0.3, 0.4]], dtype=float), + ) + parameters = [ + SimpleNamespace(unique_name='length_a', name='length_a', fit_min=3.8895, fit_max=3.8920), + SimpleNamespace( + unique_name='broad_gauss_u', name='broad_gauss_u', fit_min=0.05, fit_max=0.11 + ), + SimpleNamespace( + unique_name='broad_gauss_v', name='broad_gauss_v', fit_min=-0.14, fit_max=-0.10 + ), + SimpleNamespace( + unique_name='twotheta_offset', name='twotheta_offset', fit_min=0.625, fit_max=0.64 + ), + ] + summaries = [ + PosteriorParameterSummary( + unique_name=name, + display_name=name, + map_value=float(samples[-1, -1, index]), + median=float(np.median(samples[:, :, index])), + standard_deviation=float(np.std(samples[:, :, index], ddof=1)), + interval_68=tuple(np.quantile(samples[:, :, index], [0.16, 0.84]).tolist()), + interval_95=tuple(np.quantile(samples[:, :, index], [0.025, 0.975]).tolist()), + ) + for index, name in enumerate(parameter_names) + ] + fit_results = SimpleNamespace( + posterior_samples=posterior_samples, + posterior_parameter_summaries=summaries, + posterior_predictive={}, + parameters=parameters, + ) + plotter = Plotter() + plotter._get_posterior_samples_and_fit_results = MethodType( + lambda self: (posterior_samples, fit_results), + plotter, + ) + plotter._get_fit_result_for_correlation = MethodType(lambda self: fit_results, plotter) + return plotter, fit_results, posterior_samples + + +def test_correlation_from_posterior_samples_returns_labeled_dataframe(): + from easydiffraction.display.plotting import Plotter + + _, _, posterior_samples = _make_bayesian_plotter_fixture() + + corr_df = Plotter()._correlation_from_posterior_samples(posterior_samples) + + assert list(corr_df.index) == posterior_samples.parameter_names + assert list(corr_df.columns) == posterior_samples.parameter_names + np.testing.assert_allclose(np.diag(corr_df.to_numpy()), np.ones(len(corr_df))) + + +def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): + plotter, _, _ = _make_bayesian_plotter_fixture() + + figure = plotter._build_posterior_pairs_plot(parameters=None) + + assert figure.layout.title.text == 'Posterior pair plot' + assert [annotation.text for annotation in figure.layout.annotations] == [ + 'length_a', + 'broad_gauss_u', + 'broad_gauss_v', + 'twotheta_offset', + ] + subplot = figure.get_subplot(1, 1) + assert subplot.yaxis.showticklabels is False + assert subplot.yaxis.ticks == '' + assert subplot.yaxis.ticklen == 0 + assert subplot.yaxis.title.text is None + + +def test_build_param_distribution_plot_returns_plotly_figure(): + plotter, fit_results, _ = _make_bayesian_plotter_fixture() + parameter = fit_results.parameters[0] + + figure = plotter._build_param_distribution_plot(parameter) + + assert figure.layout.title.text == 'Posterior distribution: length_a' + assert {trace.name for trace in figure.data} >= { + 'Posterior histogram', + 'Posterior density', + '68% credible interval', + '95% credible interval', + 'Median', + 'Max posterior', + } + + +def test_build_posterior_predictive_summary_restores_parameter_state(monkeypatch): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorPredictiveSummary + from easydiffraction.display.plotting import Plotter + + class FakePredictiveParameter: + def __init__(self, unique_name, value, uncertainty): + self.unique_name = unique_name + self.value = value + self.uncertainty = uncertainty + + def _set_value_from_minimizer(self, value): + self.value = value + + sampled_parameters = [ + FakePredictiveParameter('a', 1.0, 0.1), + FakePredictiveParameter('b', 2.0, 0.2), + ] + posterior_samples = SimpleNamespace( + parameter_names=['a', 'b'], + flattened=lambda: np.array( + [ + [1.0, 2.0], + [1.1, 2.1], + [0.9, 1.9], + [1.2, 2.2], + ], + dtype=float, + ), + ) + fit_results = SimpleNamespace( + posterior_samples=posterior_samples, + parameters=sampled_parameters, + ) + plotter = Plotter() + + def fake_evaluate(self, *, sampled_parameters, values, experiment, expt_name, x_axis): + x = np.array([0.0, 1.0], dtype=float) + y = np.array([values[0] + values[1], values[0] - values[1]], dtype=float) + return y, x + + monkeypatch.setattr(Plotter, '_evaluate_posterior_predictive_state', fake_evaluate) + monkeypatch.setattr(Plotter, '_update_project_categories', lambda self, expt_name: None) + + summary = plotter._build_posterior_predictive_summary( + fit_results=fit_results, + experiment=object(), + expt_name='hrpt', + x_axis='two_theta', + ) + + assert isinstance(summary, PosteriorPredictiveSummary) + assert summary.experiment_name == 'hrpt' + assert summary.x_axis_name == 'two_theta' + assert summary.draws.shape == (4, 2) + np.testing.assert_allclose(summary.map_prediction, np.array([3.0, -1.0])) + np.testing.assert_allclose([parameter.value for parameter in sampled_parameters], [1.0, 2.0]) + assert [parameter.uncertainty for parameter in sampled_parameters] == [0.1, 0.2] + + def test_extract_bragg_tick_sets_uses_derived_d_spacing_for_cwl_ticks(): import numpy as np diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py index 8472c994..571cd01f 100644 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ b/tmp/bumps_dream/ed-2-bayesian-new-API.py @@ -191,6 +191,7 @@ structure.cell.length_a.free = True experiment.peak.broad_gauss_u.free = True experiment.peak.broad_gauss_v.free = True +experiment.peak.broad_gauss_w.free = True experiment.instrument.calib_twotheta_offset.free = True # %% [markdown] @@ -241,6 +242,7 @@ structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=4) experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=4) experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=4) +experiment.peak.broad_gauss_w.set_fit_bounds_from_uncertainty(multiplier=4) experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=4) # %% [markdown] @@ -310,6 +312,7 @@ project.display.plotter.plot_param_distribution(structure.cell.length_a) project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_u) project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_v) +project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_w) project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) # %% [markdown] From 506e5f474e80a7378e3b2198448f71e4ddb2ec11 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sat, 9 May 2026 00:09:45 +0200 Subject: [PATCH 053/106] Add LBCO Bayesian tutorial --- docs/docs/tutorials/ed-21.py | 330 +++++++++++++++++++++++++++++++++++ docs/docs/tutorials/index.md | 9 + docs/mkdocs.yml | 2 + 3 files changed, 341 insertions(+) create mode 100644 docs/docs/tutorials/ed-21.py diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py new file mode 100644 index 00000000..9e3f62e9 --- /dev/null +++ b/docs/docs/tutorials/ed-21.py @@ -0,0 +1,330 @@ +# %% [markdown] +# # Deterministic and Bayesian Refinement: LBCO, HRPT +# +# This tutorial demonstrates a practical two-stage workflow for powder +# diffraction analysis with EasyDiffraction. +# +# In the first stage, we run a fast local refinement to obtain a sensible +# point estimate and parameter uncertainties. In the second stage, we use +# these refined values to define fit bounds and then sample the posterior +# distribution with DREAM. +# +# The example uses constant-wavelength neutron powder diffraction data +# for La0.5Ba0.5CoO3 measured on HRPT at PSI. +# +# The goal is not only to obtain a good fit, but also to answer Bayesian +# questions such as: +# +# - Which parameter values are most probable? +# - How broad are the credible intervals? +# - Which parameters are strongly correlated? +# - How much uncertainty propagates into the calculated diffraction +# pattern? + +# %% [markdown] +# ## Import Library + +# %% +import easydiffraction as ed + +# %% [markdown] +# ## Step 1: Create a Project Container +# +# The project object keeps structures, experiments, fit settings, and +# plotting utilities together in a single place. We will build the full +# workflow inside this object. + +# %% +project = ed.Project() + +# %% [markdown] +# ## Step 2: Build the Structural Model +# +# We define a simple cubic perovskite model for LBCO. La and Ba share the +# same crystallographic site with equal occupancy, while Co and O occupy +# the remaining ideal perovskite positions. + +# %% +project.structures.create(name='lbco') + +# %% +structure = project.structures['lbco'] + +# %% +structure.space_group.name_h_m = 'P m -3 m' +structure.space_group.it_coordinate_system_code = '1' + +# %% +structure.cell.length_a = 3.88 + +# %% [markdown] +# The atom-site definitions below form the starting structural model. The +# parameters are intentionally reasonable rather than fully optimized, +# because the refinement step will improve them. + +# %% +structure.atom_sites.create( + label='La', + type_symbol='La', + fract_x=0, + fract_y=0, + fract_z=0, + wyckoff_letter='a', + adp_type='Biso', + adp_iso=0.5151, + occupancy=0.5, +) +structure.atom_sites.create( + label='Ba', + type_symbol='Ba', + fract_x=0, + fract_y=0, + fract_z=0, + wyckoff_letter='a', + adp_type='Biso', + adp_iso=0.5151, + occupancy=0.5, +) +structure.atom_sites.create( + label='Co', + type_symbol='Co', + fract_x=0.5, + fract_y=0.5, + fract_z=0.5, + wyckoff_letter='b', + adp_type='Biso', + adp_iso=0.2190, +) +structure.atom_sites.create( + label='O', + type_symbol='O', + fract_x=0, + fract_y=0.5, + fract_z=0.5, + wyckoff_letter='c', + adp_type='Biso', + adp_iso=1.3916, +) + +# %% [markdown] +# ## Step 3: Define the Diffraction Experiment +# +# Next we download the measured powder pattern, create a neutron powder +# experiment, and configure the instrument, profile, background, and +# excluded regions. + +# %% [markdown] +# #### Download the Measured Data + +# %% +data_path = ed.download_data(id=3, destination='data') + +# %% [markdown] +# #### Create the Experiment Object + +# %% +project.experiments.add_from_data_path( + name='hrpt', + data_path=data_path, + sample_form='powder', + beam_mode='constant wavelength', + radiation_probe='neutron', +) + +# %% +experiment = project.experiments['hrpt'] + +# %% [markdown] +# #### Set Instrument and Peak-Profile Parameters +# +# These values provide the initial instrument description for the local +# refinement. Later, a subset of them will be refined. + +# %% +experiment.instrument.setup_wavelength = 1.494 +experiment.instrument.calib_twotheta_offset = 0.0 + +# %% +experiment.peak.broad_gauss_u = 0.1 +experiment.peak.broad_gauss_v = -0.1 +experiment.peak.broad_gauss_w = 0.1204 +experiment.peak.broad_lorentz_y = 0.0844 + +# %% [markdown] +# #### Add Background Points and Excluded Regions +# +# The line-segment background is defined by a few anchor points. We also +# exclude regions that are not intended to contribute to the fit. + +# %% +experiment.background.create(id='1', x=10, y=168.5585) +experiment.background.create(id='2', x=30, y=164.3357) +experiment.background.create(id='3', x=50, y=166.8881) +experiment.background.create(id='4', x=110, y=175.4006) +experiment.background.create(id='5', x=165, y=174.2813) + +# %% +experiment.excluded_regions.create(id='1', start=0, end=30) +experiment.excluded_regions.create(id='2', start=70, end=180) + +# %% [markdown] +# #### Link the Structural Phase to the Experiment + +# %% +experiment.linked_phases.create(id='lbco', scale=9.1351) + +# %% [markdown] +# ## Step 4: Run an Initial Local Refinement +# +# Before Bayesian sampling, it is useful to run a deterministic fit. This +# gives us: +# +# - a good point estimate near the best-fit region, +# - uncertainties from the local optimizer, +# - a quick check that the model and experiment are configured +# sensibly. +# +# In this tutorial we refine only a small set of parameters that are easy +# to interpret in the later Bayesian stage. + +# %% +structure.cell.length_a.free = True +experiment.peak.broad_gauss_u.free = True +experiment.peak.broad_gauss_v.free = True +experiment.instrument.calib_twotheta_offset.free = True + +# %% [markdown] +# We choose the BUMPS Levenberg-Marquardt minimizer as a fast local +# optimizer. Its main purpose here is to provide a stable starting point +# and uncertainty estimates for the Bayesian run. + +# %% +project.analysis.fit.show_minimizer_types() +project.analysis.fit.minimizer_type = 'bumps (lm)' + +# %% +project.analysis.fit() + +# %% +project.analysis.display.fit_results() + +# %% [markdown] +# The correlation plot shows how strongly the fitted parameters move +# together in the local refinement. The measured-vs-calculated plots show +# how well the refined model reproduces the data globally and in a zoomed +# region. + +# %% +project.display.plotter.plot_param_correlations(show_diagonal=True) + +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') + +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) + +# %% [markdown] +# ## Step 5: Prepare for Bayesian Sampling +# +# DREAM requires finite bounds for the free parameters. Instead of +# setting them manually, we derive them from the uncertainties estimated +# in the local refinement. +# +# The helper method `set_fit_bounds_from_uncertainty` centers the bounds +# on the current parameter value and expands them by a chosen multiple of +# the reported uncertainty. + +# %% +project.analysis.display.free_params() + +# %% +structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=4) +experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=4) +experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=4) +experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=4) + +# %% [markdown] +# Displaying the free parameters again is a convenient way to confirm +# that the fit bounds have been assigned as expected before launching the +# sampler. + +# %% +project.analysis.display.free_params() + +# %% [markdown] +# ## Step 6: Configure and Run DREAM +# +# We now switch from the local minimizer to the Bayesian DREAM sampler. +# +# The settings below are intentionally small so the tutorial runs +# quickly. For production analysis you would usually increase the number +# of steps and often the burn-in as well. When needed, the DREAM API +# also lets you tune how chains are initialized through the `init` +# setting. + +# %% +project.analysis.fit.show_minimizer_types() + +# %% +project.analysis.fit.minimizer_type = 'bumps (dream)' + +# %% +project.analysis.fit.minimizer.steps = 200 # 1000 +project.analysis.fit.minimizer.burn = 40 # 200 +project.analysis.fit.minimizer.thin = 1 +project.analysis.fit.minimizer.pop = 4 + +# %% +project.analysis.fit() + +# %% [markdown] +# ## Step 7: Inspect Bayesian Results +# +# The fit-results display now includes sampler settings, convergence +# diagnostics, committed parameter values, and posterior summary +# statistics. + +# %% +project.analysis.display.fit_results() + +# %% [markdown] +# The correlation and posterior-pair plots are complementary: +# +# - `plot_param_correlations` summarizes pairwise structure in a compact +# matrix. +# - `plot_posterior_pairs` shows marginal densities on the diagonal and +# posterior contours off-diagonal. + +# %% +project.display.plotter.plot_param_correlations(show_diagonal=True) + +# %% +project.display.plotter.plot_posterior_pairs() + +# %% [markdown] +# The one-dimensional posterior distributions below make it easier to +# inspect individual parameters in isolation, including asymmetry or +# multimodality. + +# %% +project.display.plotter.plot_param_distribution(structure.cell.length_a) +project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_u) +project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_v) +project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) + +# %% [markdown] +# Finally, the posterior predictive plot propagates the sampled parameter +# uncertainty into the calculated diffraction pattern. Comparing this to +# the zoomed measured-vs-calculated view helps assess whether the sampled +# model family explains the data in the region of interest. + +# %% +project.display.plotter.plot_posterior_predictive(expt_name='hrpt') + +# %% [markdown] +# A final zoomed measured-vs-calculated plot is useful for checking how +# the posterior-supported model behaves in a narrow region of the pattern +# after the Bayesian run. + +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md index 69b9d0ca..18c2e143 100644 --- a/docs/docs/tutorials/index.md +++ b/docs/docs/tutorials/index.md @@ -98,6 +98,15 @@ The tutorials are organized into the following categories: - [BEER McStas](ed-20.ipynb) – Rietveld refinement based on the data simulated with McStas for the BEER instrument at ESS. +## Bayesian Analysis + +- [LBCO Bayesian](ed-21.ipynb) – Demonstrates how to perform a Bayesian + analysis of the La0.5Ba0.5CoO3 crystal structure using constant + wavelength neutron powder diffraction data from HRPT at PSI. This + tutorial covers the use of Markov Chain Monte Carlo (MCMC) sampling to + explore the posterior distribution of the refined parameters, + providing insights into parameter uncertainties and correlations. + ## Workshops & Schools - [DMSC Summer School](ed-13.ipynb) – A workshop tutorial that diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 45c2ce5f..6ad6b770 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -214,6 +214,8 @@ nav: - Simulated Data: - LBCO+Si McStas: tutorials/ed-9.ipynb - BEER McStas: tutorials/ed-20.ipynb + - Bayesian Analysis: + - LBCO Bayesian: tutorials/ed-21.ipynb - Workshops & Schools: - DMSC Summer School: tutorials/ed-13.ipynb - API Reference: From 9cf4ffec9142995e390d3ec5f72ee52d13d67c6e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sat, 9 May 2026 00:22:13 +0200 Subject: [PATCH 054/106] Make posterior pair plots responsive --- .../display/plotters/plotly.py | 133 +++++++++++++++++- src/easydiffraction/display/plotting.py | 64 ++++++++- .../display/plotters/test_plotly.py | 117 +++++++++++++++ .../easydiffraction/display/test_plotting.py | 20 +++ 4 files changed, 324 insertions(+), 10 deletions(-) diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index fcc07fa9..c514b743 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -70,6 +70,7 @@ PREDICTIVE_DRAW_COLOR = 'rgba(140, 140, 140, 0.18)' PREDICTIVE_DRAW_PLOT_CAP = 50 PREDICTIVE_DRAW_ARRAY_NDIM = 2 +RESPONSIVE_PAIR_PLOT_META_KEY = 'responsive_pair_plot' @dataclass(frozen=True) @@ -789,6 +790,134 @@ def _modebar_legend_toggle_post_script() -> str: window.requestAnimationFrame(installLegendToggleButton); """ + @staticmethod + def _responsive_pair_plot_post_script() -> str: + """ + Return client-side code for responsive posterior pair plots. + """ + return r""" +const graphDiv = document.getElementById('{plot_id}'); +if (!graphDiv || !window.Plotly || !graphDiv.layout || !graphDiv.layout.meta) { + return; +} + +const responsivePairPlot = graphDiv.layout.meta.responsive_pair_plot; +if (!responsivePairPlot) { + return; +} + +const readPositiveNumber = function (value, fallback) { + const numberValue = Number(value); + return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : fallback; +}; + +const nParameters = Math.max( + 1, + Math.round(readPositiveNumber(responsivePairPlot.n_parameters, 1)) +); +const marginPx = readPositiveNumber(responsivePairPlot.margin_px, 0); +const minCellSizePx = readPositiveNumber(responsivePairPlot.min_cell_size_px, 90); +const maxCellSizePx = readPositiveNumber(responsivePairPlot.max_cell_size_px, 190); + +let lastHeight = null; +let resizeFrame = null; + +const applyResponsivePairPlotSize = function () { + const containerWidth = graphDiv.clientWidth || graphDiv.getBoundingClientRect().width; + if (!Number.isFinite(containerWidth) || containerWidth <= 0) { + return; + } + + const plotWidth = Math.max(minCellSizePx, containerWidth - marginPx); + const cellSizePx = Math.min(maxCellSizePx, Math.max(minCellSizePx, plotWidth / nParameters)); + const nextHeight = Math.round(cellSizePx * nParameters + marginPx); + + if (lastHeight === nextHeight) { + window.Plotly.Plots.resize(graphDiv); + return; + } + + lastHeight = nextHeight; + window.Plotly.relayout(graphDiv, {autosize: true, height: nextHeight}); +}; + +const scheduleResponsivePairPlotSize = function () { + if (resizeFrame !== null) { + return; + } + + resizeFrame = window.requestAnimationFrame(function () { + resizeFrame = null; + applyResponsivePairPlotSize(); + }); +}; + +if (typeof ResizeObserver === 'function') { + const resizeObserver = new ResizeObserver(scheduleResponsivePairPlotSize); + resizeObserver.observe(graphDiv); +} +else { + window.addEventListener('resize', scheduleResponsivePairPlotSize); +} + +if (graphDiv.on) { + graphDiv.on('plotly_afterplot', scheduleResponsivePairPlotSize); +} + +scheduleResponsivePairPlotSize(); +""" + + @staticmethod + def _figure_meta(fig: object) -> dict[str, object] | None: + """Return figure layout metadata when available.""" + layout = getattr(fig, 'layout', None) + if layout is None: + return None + + meta = getattr(layout, 'meta', None) + if isinstance(meta, dict): + return meta + + layout_kwargs = getattr(layout, 'kwargs', None) + if isinstance(layout_kwargs, dict): + meta = layout_kwargs.get('meta') + if isinstance(meta, dict): + return meta + return None + + @classmethod + def _has_responsive_pair_plot(cls, fig: object) -> bool: + """ + Return whether a figure requests responsive pair-plot sizing. + """ + meta = cls._figure_meta(fig) + if not isinstance(meta, dict): + return False + + responsive_pair_plot = meta.get(RESPONSIVE_PAIR_PLOT_META_KEY) + if not isinstance(responsive_pair_plot, dict): + return False + return bool(responsive_pair_plot.get('n_parameters')) + + @classmethod + def _html_post_script(cls, fig: object) -> str | None: + """Return concatenated HTML post scripts for a Plotly figure.""" + scripts: list[str] = [] + if cls._has_visible_legend(fig): + scripts.append(cls._modebar_legend_toggle_post_script()) + if cls._has_responsive_pair_plot(fig): + scripts.append(cls._responsive_pair_plot_post_script()) + if not scripts: + return None + return '\n'.join(cls._scoped_html_post_script(script) for script in scripts) + + @staticmethod + def _scoped_html_post_script(script: str) -> str: + """ + Return one HTML post script wrapped in its own block scope. + """ + return '{\n' + script.strip() + '\n}' + @staticmethod def _get_figure( data: object, @@ -866,9 +995,7 @@ def _show_figure( if in_pycharm() or display is None or HTML is None: fig.show(config=config) else: - post_script = None - if self._has_visible_legend(fig): - post_script = self._modebar_legend_toggle_post_script() + post_script = self._html_post_script(fig) html_fig = pio.to_html( fig, include_plotlyjs='cdn', diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 2fee1031..98f718de 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -103,8 +103,10 @@ def description(self) -> str: [1.0, 'rgba(58, 86, 224, 0.98)'], ] PAIR_PLOT_CELL_SIZE_PIXELS = 190 +PAIR_PLOT_MIN_CELL_SIZE_PIXELS = 90 PAIR_PLOT_MIN_SIZE_PIXELS = 680 PAIR_PLOT_MARGIN_PIXELS = 120 +PAIR_PLOT_ESTIMATED_CONTAINER_WIDTH_PIXELS = 980 PAIR_PLOT_SUBPLOT_SPACING = 0.015 PAIR_PLOT_MAJOR_TICKS = 3 POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 @@ -1424,8 +1426,8 @@ def _collect_posterior_pair_panel_decorations( 'layer': 'above', }) - @staticmethod def _finalize_posterior_pairs_figure( + self, *, fig: object, context: _PosteriorPairsContext, @@ -1433,18 +1435,16 @@ def _finalize_posterior_pairs_figure( subplot_border_shapes: list[dict[str, object]], ) -> None: """Apply final layout settings to the posterior pair plot.""" - figure_size = max( - PAIR_PLOT_MIN_SIZE_PIXELS, - PAIR_PLOT_CELL_SIZE_PIXELS * context.n_parameters + PAIR_PLOT_MARGIN_PIXELS, - ) + figure_height = self._posterior_pair_figure_height_pixels(context.n_parameters) fig.update_layout( + autosize=True, margin={'autoexpand': True, 'r': 30, 't': 40, 'b': 45}, title={'text': 'Posterior pair plot'}, bargap=0.05, - width=figure_size, - height=figure_size, + height=figure_height, annotations=subplot_title_annotations, shapes=subplot_border_shapes, + meta=self._posterior_pair_layout_meta(context.n_parameters), legend={ 'bgcolor': 'rgba(0, 0, 0, 0)', 'xanchor': 'right', @@ -1455,6 +1455,56 @@ def _finalize_posterior_pairs_figure( }, ) + @staticmethod + def _posterior_pair_layout_meta(n_parameters: int) -> dict[str, object]: + """ + Return responsive layout metadata for posterior pair plots. + """ + return { + 'responsive_pair_plot': { + 'n_parameters': int(n_parameters), + 'margin_px': PAIR_PLOT_MARGIN_PIXELS, + 'min_cell_size_px': PAIR_PLOT_MIN_CELL_SIZE_PIXELS, + 'max_cell_size_px': PAIR_PLOT_CELL_SIZE_PIXELS, + } + } + + @staticmethod + def _posterior_pair_cell_size_pixels( + n_parameters: int, + *, + available_width_pixels: float, + ) -> int: + """Return an estimated square cell size for a pair plot.""" + if n_parameters < 1: + return PAIR_PLOT_CELL_SIZE_PIXELS + + plot_width = max( + PAIR_PLOT_MIN_CELL_SIZE_PIXELS, + available_width_pixels - PAIR_PLOT_MARGIN_PIXELS, + ) + cell_size = plot_width / n_parameters + return round( + min( + PAIR_PLOT_CELL_SIZE_PIXELS, + max(PAIR_PLOT_MIN_CELL_SIZE_PIXELS, cell_size), + ) + ) + + @classmethod + def _posterior_pair_figure_height_pixels(cls, n_parameters: int) -> int: + """ + Return the initial figure height for a responsive pair plot. + """ + cell_size = cls._posterior_pair_cell_size_pixels( + n_parameters, + available_width_pixels=PAIR_PLOT_ESTIMATED_CONTAINER_WIDTH_PIXELS, + ) + return max( + PAIR_PLOT_MIN_SIZE_PIXELS, + cell_size * n_parameters + PAIR_PLOT_MARGIN_PIXELS, + ) + def _plot_axis_frame_color(self) -> str: """ Return the shared axis-frame color for Plotly-backed plots. diff --git a/tests/unit/easydiffraction/display/plotters/test_plotly.py b/tests/unit/easydiffraction/display/plotters/test_plotly.py index 3905ee27..cdd847db 100644 --- a/tests/unit/easydiffraction/display/plotters/test_plotly.py +++ b/tests/unit/easydiffraction/display/plotters/test_plotly.py @@ -278,6 +278,123 @@ def __init__(self, html): assert captured['displayed_html'] == '
plot
' +def test_show_figure_adds_responsive_pair_plot_script(monkeypatch): + import easydiffraction.display.plotters.plotly as pp + + monkeypatch.setattr(pp, 'in_pycharm', lambda: False) + + captured = {} + + class DummyLayout: + def __init__(self): + self.meta = { + 'responsive_pair_plot': { + 'n_parameters': 4, + 'margin_px': 120, + 'min_cell_size_px': 90, + 'max_cell_size_px': 190, + } + } + self.showlegend = False + + class DummyFig: + def __init__(self): + self.data = [] + self.layout = DummyLayout() + + def show(self, **kwargs): + captured['show_called'] = True + + class DummyPIO: + @staticmethod + def to_html(fig, include_plotlyjs=None, full_html=None, config=None, post_script=None): + captured['post_script'] = post_script + return '
plot
' + + def dummy_display(obj): + captured['displayed_html'] = obj.html + + class DummyHTML: + def __init__(self, html): + self.html = html + + monkeypatch.setattr(pp, 'pio', DummyPIO) + monkeypatch.setattr(pp, 'display', dummy_display) + monkeypatch.setattr(pp, 'HTML', DummyHTML) + + plotter = pp.PlotlyPlotter() + plotter._show_figure(DummyFig()) + + assert captured.get('show_called') is not True + assert 'responsive_pair_plot' in captured['post_script'] + assert 'ResizeObserver' in captured['post_script'] + assert 'window.Plotly.relayout' in captured['post_script'] + assert 'containerWidth' in captured['post_script'] + assert captured['displayed_html'] == '
plot
' + + +def test_show_figure_scopes_multiple_post_scripts(monkeypatch): + import easydiffraction.display.plotters.plotly as pp + + monkeypatch.setattr(pp, 'in_pycharm', lambda: False) + + captured = {} + + class DummyTrace: + def __init__(self): + self.name = 'Posterior samples' + self.showlegend = True + self.visible = True + + class DummyLayout: + def __init__(self): + self.meta = { + 'responsive_pair_plot': { + 'n_parameters': 4, + 'margin_px': 120, + 'min_cell_size_px': 90, + 'max_cell_size_px': 190, + } + } + self.showlegend = True + + class DummyFig: + def __init__(self): + self.data = [DummyTrace()] + self.layout = DummyLayout() + + def show(self, **kwargs): + captured['show_called'] = True + + class DummyPIO: + @staticmethod + def to_html(fig, include_plotlyjs=None, full_html=None, config=None, post_script=None): + captured['post_script'] = post_script + return '
plot
' + + def dummy_display(obj): + captured['displayed_html'] = obj.html + + class DummyHTML: + def __init__(self, html): + self.html = html + + monkeypatch.setattr(pp, 'pio', DummyPIO) + monkeypatch.setattr(pp, 'display', dummy_display) + monkeypatch.setattr(pp, 'HTML', DummyHTML) + + plotter = pp.PlotlyPlotter() + plotter._show_figure(DummyFig()) + + assert captured.get('show_called') is not True + assert ( + captured['post_script'].count("const graphDiv = document.getElementById('{plot_id}');") + == 2 + ) + assert '\n}\n{\n' in captured['post_script'] + assert captured['displayed_html'] == '
plot
' + + def test_plotly_single_crystal_trace_and_plot(monkeypatch): import easydiffraction.display.plotters.plotly as pp diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 6117b5cb..d0f23651 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -307,11 +307,22 @@ def test_correlation_from_posterior_samples_returns_labeled_dataframe(): def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): + from easydiffraction.display.plotting import PAIR_PLOT_CELL_SIZE_PIXELS + from easydiffraction.display.plotting import PAIR_PLOT_MARGIN_PIXELS + plotter, _, _ = _make_bayesian_plotter_fixture() figure = plotter._build_posterior_pairs_plot(parameters=None) assert figure.layout.title.text == 'Posterior pair plot' + assert figure.layout.autosize is True + assert figure.layout.width is None + assert figure.layout.meta['responsive_pair_plot']['n_parameters'] == 4 + assert ( + figure.layout.meta['responsive_pair_plot']['max_cell_size_px'] + == PAIR_PLOT_CELL_SIZE_PIXELS + ) + assert figure.layout.meta['responsive_pair_plot']['margin_px'] == PAIR_PLOT_MARGIN_PIXELS assert [annotation.text for annotation in figure.layout.annotations] == [ 'length_a', 'broad_gauss_u', @@ -325,6 +336,15 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): assert subplot.yaxis.title.text is None +def test_posterior_pair_figure_height_shrinks_cells_for_many_parameters(): + from easydiffraction.display.plotting import PAIR_PLOT_CELL_SIZE_PIXELS + from easydiffraction.display.plotting import Plotter + + cell_size = Plotter._posterior_pair_cell_size_pixels(8, available_width_pixels=980) + + assert cell_size < PAIR_PLOT_CELL_SIZE_PIXELS + + def test_build_param_distribution_plot_returns_plotly_figure(): plotter, fit_results, _ = _make_bayesian_plotter_fixture() parameter = fit_results.parameters[0] From 3443981846d9bbb95494f5a624efd6e025618883 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sat, 9 May 2026 00:46:58 +0200 Subject: [PATCH 055/106] Add DREAM bound validation and flexible parameter selection --- .github/copilot-instructions.md | 7 +- docs/dev/plan_bayesian-analysis.md | 6 +- docs/docs/tutorials/ed-13.ipynb | 2 +- docs/docs/tutorials/ed-21.ipynb | 2284 +++++++++++++++++ docs/docs/tutorials/ed-21.py | 4 +- .../analysis/minimizers/bumps_dream.py | 75 + src/easydiffraction/display/plotting.py | 132 +- .../analysis/minimizers/test_bumps_dream.py | 52 +- .../easydiffraction/display/test_plotting.py | 72 + 9 files changed, 2615 insertions(+), 19 deletions(-) create mode 100644 docs/docs/tutorials/ed-21.ipynb diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 5613d742..0a54cc94 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -146,13 +146,12 @@ Non-trivial changes use a two-phase workflow: Notes: -- `pixi run fix` regenerates `docs/architecture/package-structure-*.md` +- `pixi run fix` regenerates `docs/dev/package-structure-*.md` automatically β€” never edit those by hand. Don't review auto-fixes; accept and move on. Then `pixi run check` until clean. - Open issues / design questions / planned improvements live in - `docs/architecture/issues_open.md` (priority-ordered). On resolution, - move to `docs/architecture/issues_closed.md` and update - `architecture.md` if affected. + `docs/dev/issues_open.md` (priority-ordered). On resolution, move to + `docs/dev/issues_closed.md` and update `architecture.md` if affected. ### Planning diff --git a/docs/dev/plan_bayesian-analysis.md b/docs/dev/plan_bayesian-analysis.md index 76be62c3..4a5697b8 100644 --- a/docs/dev/plan_bayesian-analysis.md +++ b/docs/dev/plan_bayesian-analysis.md @@ -7,9 +7,9 @@ branch:** `feature/bayesian-analysis` **Design doc:** ## Context This plan follows `.github/copilot-instructions.md`. The instructions -refer to `docs/architecture/architecture.md`, but this checkout does not -contain that file. The matching living architecture document used for -this plan is `docs/dev/architecture.md`. +refer to `docs/dev/architecture.md`, but this checkout does not contain +that file. The matching living architecture document used for this plan +is `docs/dev/architecture.md`. Relevant current seams: diff --git a/docs/docs/tutorials/ed-13.ipynb b/docs/docs/tutorials/ed-13.ipynb index 4d605962..69eae9aa 100644 --- a/docs/docs/tutorials/ed-13.ipynb +++ b/docs/docs/tutorials/ed-13.ipynb @@ -2665,7 +2665,7 @@ ], "metadata": { "jupytext": { - "cell_metadata_filter": "tags,title,-all", + "cell_metadata_filter": "title,tags,-all", "main_language": "python", "notebook_metadata_filter": "-all" } diff --git a/docs/docs/tutorials/ed-21.ipynb b/docs/docs/tutorials/ed-21.ipynb new file mode 100644 index 00000000..c9b1236e --- /dev/null +++ b/docs/docs/tutorials/ed-21.ipynb @@ -0,0 +1,2284 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "0", + "metadata": { + "tags": [ + "hide-in-docs" + ] + }, + "outputs": [], + "source": [ + "# Check whether easydiffraction is installed; install it if needed.\n", + "# Required for remote environments such as Google Colab.\n", + "import importlib.util\n", + "\n", + "if importlib.util.find_spec('easydiffraction') is None:\n", + " %pip install easydiffraction" + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "# Deterministic and Bayesian Refinement: LBCO, HRPT\n", + "\n", + "This tutorial demonstrates a practical two-stage workflow for powder\n", + "diffraction analysis with EasyDiffraction.\n", + "\n", + "In the first stage, we run a fast local refinement to obtain a sensible\n", + "point estimate and parameter uncertainties. In the second stage, we use\n", + "these refined values to define fit bounds and then sample the posterior\n", + "distribution with DREAM.\n", + "\n", + "The example uses constant-wavelength neutron powder diffraction data\n", + "for La0.5Ba0.5CoO3 measured on HRPT at PSI.\n", + "\n", + "The goal is not only to obtain a good fit, but also to answer Bayesian\n", + "questions such as:\n", + "\n", + "- Which parameter values are most probable?\n", + "- How broad are the credible intervals?\n", + "- Which parameters are strongly correlated?\n", + "- How much uncertainty propagates into the calculated diffraction\n", + " pattern?" + ] + }, + { + "cell_type": "markdown", + "id": "2", + "metadata": {}, + "source": [ + "## Import Library" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "import easydiffraction as ed" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": {}, + "source": [ + "## Step 1: Create a Project Container\n", + "\n", + "The project object keeps structures, experiments, fit settings, and\n", + "plotting utilities together in a single place. We will build the full\n", + "workflow inside this object." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "project = ed.Project()" + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": {}, + "source": [ + "## Step 2: Build the Structural Model\n", + "\n", + "We define a simple cubic perovskite model for LBCO. La and Ba share the\n", + "same crystallographic site with equal occupancy, while Co and O occupy\n", + "the remaining ideal perovskite positions." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "project.structures.create(name='lbco')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "structure = project.structures['lbco']" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "9", + "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": 7, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "structure.cell.length_a = 3.88" + ] + }, + { + "cell_type": "markdown", + "id": "11", + "metadata": {}, + "source": [ + "The atom-site definitions below form the starting structural model. The\n", + "parameters are intentionally reasonable rather than fully optimized,\n", + "because the refinement step will improve them." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "12", + "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", + " adp_type='Biso',\n", + " adp_iso=0.5151,\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", + " adp_type='Biso',\n", + " adp_iso=0.5151,\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", + " adp_type='Biso',\n", + " adp_iso=0.2190,\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", + " adp_type='Biso',\n", + " adp_iso=1.3916,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "13", + "metadata": {}, + "source": [ + "## Step 3: Define the Diffraction Experiment\n", + "\n", + "Next we download the measured powder pattern, create a neutron powder\n", + "experiment, and configure the instrument, profile, background, and\n", + "excluded regions." + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": {}, + "source": [ + "#### Download the Measured Data" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "15", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mGetting data\u001b[0m\u001b[1;34m...\u001b[0m\n", + "Data #\u001b[1;36m3\u001b[0m: La0.5Ba0.5CoO3, HRPT \u001b[1m(\u001b[0mPSI\u001b[1m)\u001b[0m, \u001b[1;36m300\u001b[0m K\n", + "βœ… Data #\u001b[1;36m3\u001b[0m already present at \u001b[32m'data/ed-3.xye'\u001b[0m. Keeping existing file.\n" + ] + } + ], + "source": [ + "data_path = ed.download_data(id=3, destination='data')" + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "#### Create the Experiment Object" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "17", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mData loaded successfully\u001b[0m\n", + "Experiment πŸ”¬ \u001b[32m'hrpt'\u001b[0m. Number of data points: \u001b[1;36m3098\u001b[0m.\n" + ] + } + ], + "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": 11, + "id": "18", + "metadata": {}, + "outputs": [], + "source": [ + "experiment = project.experiments['hrpt']" + ] + }, + { + "cell_type": "markdown", + "id": "19", + "metadata": {}, + "source": [ + "#### Set Instrument and Peak-Profile Parameters\n", + "\n", + "These values provide the initial instrument description for the local\n", + "refinement. Later, a subset of them will be refined." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "20", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.instrument.setup_wavelength = 1.494\n", + "experiment.instrument.calib_twotheta_offset = 0.0" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "21", + "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.1204\n", + "experiment.peak.broad_lorentz_y = 0.0844" + ] + }, + { + "cell_type": "markdown", + "id": "22", + "metadata": {}, + "source": [ + "#### Add Background Points and Excluded Regions\n", + "\n", + "The line-segment background is defined by a few anchor points. We also\n", + "exclude regions that are not intended to contribute to the fit." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "23", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.background.create(id='1', x=10, y=168.5585)\n", + "experiment.background.create(id='2', x=30, y=164.3357)\n", + "experiment.background.create(id='3', x=50, y=166.8881)\n", + "experiment.background.create(id='4', x=110, y=175.4006)\n", + "experiment.background.create(id='5', x=165, y=174.2813)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "24", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.excluded_regions.create(id='1', start=0, end=30)\n", + "experiment.excluded_regions.create(id='2', start=70, end=180)" + ] + }, + { + "cell_type": "markdown", + "id": "25", + "metadata": {}, + "source": [ + "#### Link the Structural Phase to the Experiment" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "26", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.linked_phases.create(id='lbco', scale=9.1351)" + ] + }, + { + "cell_type": "markdown", + "id": "27", + "metadata": {}, + "source": [ + "## Step 4: Run an Initial Local Refinement\n", + "\n", + "Before Bayesian sampling, it is useful to run a deterministic fit. This\n", + "gives us:\n", + "\n", + "- a good point estimate near the best-fit region,\n", + "- uncertainties from the local optimizer,\n", + "- a quick check that the model and experiment are configured\n", + " sensibly.\n", + "\n", + "In this tutorial we refine only a small set of parameters that are easy\n", + "to interpret in the later Bayesian stage." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "28", + "metadata": {}, + "outputs": [], + "source": [ + "structure.cell.length_a.free = True\n", + "experiment.peak.broad_gauss_u.free = True\n", + "experiment.peak.broad_gauss_v.free = True\n", + "experiment.instrument.calib_twotheta_offset.free = True" + ] + }, + { + "cell_type": "markdown", + "id": "29", + "metadata": {}, + "source": [ + "We choose the BUMPS Levenberg-Marquardt minimizer as a fast local\n", + "optimizer. Its main purpose here is to provide a stable starting point\n", + "and uncertainty estimates for the Bayesian run." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "30", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mMinimizer types\u001b[0m\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 TypeDescription
1bumpsBumps library using the default Levenberg-Marquardt method
2bumps (amoeba)Bumps library with Nelder-Mead simplex method
3bumps (de)Bumps library with differential evolution method
4bumps (dream)Bumps library with DREAM Bayesian sampling
5bumps (lm)Bumps library with Levenberg-Marquardt method
6dfolsDFO-LS library for derivative-free least-squares optimization
7lmfitLMFIT library using the default Levenberg-Marquardt least squares method
8lmfit (least_squares)LMFIT library with SciPy's trust region reflective algorithm
9*lmfit (leastsq)LMFIT library with Levenberg-Marquardt least squares method
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mCurrent minimizer changed to\u001b[0m\n", + "bumps \u001b[1m(\u001b[0mlm\u001b[1m)\u001b[0m\n" + ] + } + ], + "source": [ + "project.analysis.fit.show_minimizer_types()\n", + "project.analysis.fit.minimizer_type = 'bumps (lm)'" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "31", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mStandard fitting\u001b[0m\n", + "πŸ“‹ Using experiment πŸ”¬ \u001b[32m'hrpt'\u001b[0m for \u001b[32m'single'\u001b[0m fitting\n", + "πŸš€ Starting fit process with \u001b[32m'bumps \u001b[0m\u001b[32m(\u001b[0m\u001b[32mlm\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n", + "πŸ“ˆ Goodness-of-fit progress:\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 iterationtime (s)χ²change / status
110.14736.04
270.25315.2257.2% ↓
3120.3493.9770.2% ↓
4170.4340.3357.1% ↓
5210.5139.063.1% ↓
6220.5428.5027.0% ↓
7260.6124.6913.4% ↓
8270.6316.2334.2% ↓
9310.7114.779.0% ↓
10320.732.7481.4% ↓
11370.821.4547.1% ↓
12420.911.375.6% ↓
13691.391.37
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "πŸ† Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m1.37\u001b[0m at iteration \u001b[1;36m68\u001b[0m\n", + "βœ… Fitting complete.\n" + ] + } + ], + "source": [ + "project.analysis.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "32", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mFit results\u001b[0m\n", + "βœ… Success: \u001b[3;92mTrue\u001b[0m\n", + "⏱️ Fitting time: \u001b[1;36m1.39\u001b[0m seconds\n", + "πŸ“ Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m1.37\u001b[0m\n", + "πŸ“ R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m5.27\u001b[0m%\n", + "πŸ“ R-factor squared \u001b[1m(\u001b[0mRfΒ²\u001b[1m)\u001b[0m: \u001b[1;36m4.42\u001b[0m%\n", + "πŸ“ Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m3.78\u001b[0m%\n", + "πŸ“ˆ Fitted parameters:\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 datablockcategoryentryparameterstartfitteduncertaintyunitschange
1lbcocelllength_a3.88003.89070.0002Γ…0.27 % ↑
2hrptpeakbroad_gauss_u0.10000.03330.0163degΒ²66.71 % ↓
3hrptpeakbroad_gauss_v-0.1000-0.09340.0091degΒ²6.57 % ↓
4hrptinstrumenttwotheta_offset0.00000.62210.0029degN/A
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.analysis.display.fit_results()" + ] + }, + { + "cell_type": "markdown", + "id": "33", + "metadata": {}, + "source": [ + "The correlation plot shows how strongly the fitted parameters move\n", + "together in the local refinement. The measured-vs-calculated plots show\n", + "how well the refined model reproduces the data globally and in a zoomed\n", + "region." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "34", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.display.plotter.plot_param_correlations(show_diagonal=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "35", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.display.plotter.plot_meas_vs_calc(expt_name='hrpt')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "36", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68)" + ] + }, + { + "cell_type": "markdown", + "id": "37", + "metadata": {}, + "source": [ + "## Step 5: Prepare for Bayesian Sampling\n", + "\n", + "DREAM requires finite bounds for the free parameters. Instead of\n", + "setting them manually, we derive them from the uncertainties estimated\n", + "in the local refinement.\n", + "\n", + "The helper method `set_fit_bounds_from_uncertainty` centers the bounds\n", + "on the current parameter value and expands them by a chosen multiple of\n", + "the reported uncertainty." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "38", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mFree parameters for both structures \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m🧩 data blocks\u001b[0m\u001b[1;34m)\u001b[0m\u001b[1;34m and experiments \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34mπŸ”¬ data blocks\u001b[0m\u001b[1;34m)\u001b[0m\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 datablockcategoryentryparametervalueuncertaintyminmaxunits
1lbcocelllength_a3.890660.00021-infinfΓ…
2hrptpeakbroad_gauss_u0.033290.01633-infinfdegΒ²
3hrptpeakbroad_gauss_v-0.093430.00911-infinfdegΒ²
4hrptinstrumenttwotheta_offset0.622070.00294-infinfdeg
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.analysis.display.free_params()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "39", + "metadata": {}, + "outputs": [], + "source": [ + "structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=4)\n", + "experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=4)\n", + "experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=4)\n", + "experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=4)" + ] + }, + { + "cell_type": "markdown", + "id": "40", + "metadata": {}, + "source": [ + "Displaying the free parameters again is a convenient way to confirm\n", + "that the fit bounds have been assigned as expected before launching the\n", + "sampler." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "41", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mFree parameters for both structures \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m🧩 data blocks\u001b[0m\u001b[1;34m)\u001b[0m\u001b[1;34m and experiments \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34mπŸ”¬ data blocks\u001b[0m\u001b[1;34m)\u001b[0m\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 datablockcategoryentryparametervalueuncertaintyminmaxunits
1lbcocelllength_a3.890660.000213.889833.89148Γ…
2hrptpeakbroad_gauss_u0.033290.01633-0.032050.09863degΒ²
3hrptpeakbroad_gauss_v-0.093430.00911-0.12988-0.05699degΒ²
4hrptinstrumenttwotheta_offset0.622070.002940.610310.63383deg
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.analysis.display.free_params()" + ] + }, + { + "cell_type": "markdown", + "id": "42", + "metadata": {}, + "source": [ + "## Step 6: Configure and Run DREAM\n", + "\n", + "We now switch from the local minimizer to the Bayesian DREAM sampler.\n", + "\n", + "The settings below are intentionally small so the tutorial runs\n", + "quickly. For production analysis you would usually increase the number\n", + "of steps and often the burn-in as well. When needed, the DREAM API\n", + "also lets you tune how chains are initialized through the `init`\n", + "setting." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "43", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mMinimizer types\u001b[0m\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 TypeDescription
1bumpsBumps library using the default Levenberg-Marquardt method
2bumps (amoeba)Bumps library with Nelder-Mead simplex method
3bumps (de)Bumps library with differential evolution method
4bumps (dream)Bumps library with DREAM Bayesian sampling
5*bumps (lm)Bumps library with Levenberg-Marquardt method
6dfolsDFO-LS library for derivative-free least-squares optimization
7lmfitLMFIT library using the default Levenberg-Marquardt least squares method
8lmfit (least_squares)LMFIT library with SciPy's trust region reflective algorithm
9lmfit (leastsq)LMFIT library with Levenberg-Marquardt least squares method
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.analysis.fit.show_minimizer_types()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "44", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mCurrent minimizer changed to\u001b[0m\n", + "bumps \u001b[1m(\u001b[0mdream\u001b[1m)\u001b[0m\n" + ] + } + ], + "source": [ + "project.analysis.fit.minimizer_type = 'bumps (dream)'" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "45", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.fit.minimizer.steps = 2000 # 1000\n", + "project.analysis.fit.minimizer.burn = 400 # 200\n", + "project.analysis.fit.minimizer.thin = 1\n", + "project.analysis.fit.minimizer.pop = 4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;34mStandard fitting\u001b[0m\n", + "πŸ“‹ Using experiment πŸ”¬ \u001b[32m'hrpt'\u001b[0m for \u001b[32m'single'\u001b[0m fitting\n", + "πŸš€ Starting fit process with \u001b[32m'bumps \u001b[0m\u001b[32m(\u001b[0m\u001b[32mdream\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n", + "πŸ“ˆ Bayesian sampling progress:\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 iterationprogresstime (s)log posteriorphase
11/24010.0%0.30-543.37burn-in
2101/24014.2%27.35-545.75burn-in
3200/24018.3%53.82-545.34burn-in
4300/240112.5%80.18-545.22burn-in
5400/240116.7%106.78-545.39burn-in
6401/240116.7%107.05-545.35sampling
7506/240121.1%134.74-545.28sampling
8612/240125.5%164.08-545.50sampling
9717/240129.9%192.06-546.77sampling
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.analysis.fit()" + ] + }, + { + "cell_type": "markdown", + "id": "47", + "metadata": {}, + "source": [ + "## Step 7: Inspect Bayesian Results\n", + "\n", + "The fit-results display now includes sampler settings, convergence\n", + "diagnostics, committed parameter values, and posterior summary\n", + "statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.display.fit_results()" + ] + }, + { + "cell_type": "markdown", + "id": "49", + "metadata": {}, + "source": [ + "The correlation and posterior-pair plots are complementary:\n", + "\n", + "- `plot_param_correlations` summarizes pairwise structure in a compact\n", + " matrix.\n", + "- `plot_posterior_pairs` shows marginal densities on the diagonal and\n", + " posterior contours off-diagonal." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_param_correlations(show_diagonal=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_posterior_pairs()" + ] + }, + { + "cell_type": "markdown", + "id": "52", + "metadata": {}, + "source": [ + "The one-dimensional posterior distributions below make it easier to\n", + "inspect individual parameters in isolation, including asymmetry or\n", + "multimodality." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_param_distribution(structure.cell.length_a)\n", + "project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_u)\n", + "project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_v)\n", + "project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset)" + ] + }, + { + "cell_type": "markdown", + "id": "54", + "metadata": {}, + "source": [ + "Finally, the posterior predictive plot propagates the sampled parameter\n", + "uncertainty into the calculated diffraction pattern. Comparing this to\n", + "the zoomed measured-vs-calculated view helps assess whether the sampled\n", + "model family explains the data in the region of interest." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_posterior_predictive(expt_name='hrpt')" + ] + }, + { + "cell_type": "markdown", + "id": "56", + "metadata": {}, + "source": [ + "A final zoomed measured-vs-calculated plot is useful for checking how\n", + "the posterior-supported model behaves in a narrow region of the pattern\n", + "after the Bayesian run." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68)" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "main_language": "python", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 9e3f62e9..543c3085 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -269,8 +269,8 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' # %% -project.analysis.fit.minimizer.steps = 200 # 1000 -project.analysis.fit.minimizer.burn = 40 # 200 +project.analysis.fit.minimizer.steps = 2000 # 1000 +project.analysis.fit.minimizer.burn = 400 # 200 project.analysis.fit.minimizer.thin = 1 project.analysis.fit.minimizer.pop = 4 diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index d2fb1773..7eab3f23 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -357,6 +357,7 @@ def _prepare_solver_args( dict[str, object] BUMPS parameters plus EasyDiffraction parameter metadata. """ + self._validate_sampled_parameter_bounds(parameters) solver_args = super()._prepare_solver_args(parameters) solver_args['parameter_names'] = [parameter.unique_name for parameter in parameters] solver_args['parameter_display_names'] = [ @@ -366,6 +367,80 @@ def _prepare_solver_args( solver_args['starting_uncertainties'] = [parameter.uncertainty for parameter in parameters] return solver_args + @classmethod + def _validate_sampled_parameter_bounds( + cls, + parameters: list[object], + ) -> None: + """ + Validate finite ordered bounds for sampled DREAM parameters. + """ + issues: list[str] = [] + for parameter in parameters: + parameter_name = cls._parameter_name_for_bound_validation(parameter) + parameter_issues = cls._parameter_bound_issues(parameter) + if parameter_issues: + issues.append(f'- {parameter_name}: {"; ".join(parameter_issues)}') + + if not issues: + return + + message = 'DREAM requires finite valid bounds for every sampled parameter:\n' + '\n'.join( + issues + ) + raise ValueError(message) + + @staticmethod + def _parameter_name_for_bound_validation(parameter: object) -> str: + """Return the user-facing name for DREAM bound validation.""" + unique_name = getattr(parameter, 'unique_name', None) + if unique_name: + return str(unique_name) + + parameter_name = getattr(parameter, 'name', None) + if parameter_name: + return str(parameter_name) + return '' + + @classmethod + def _parameter_bound_issues( + cls, + parameter: object, + ) -> list[str]: + """Return bound-validation issues for one sampled parameter.""" + lower_bound = getattr(parameter, 'fit_min', None) + upper_bound = getattr(parameter, 'fit_max', None) + value = getattr(parameter, 'value', None) + issues: list[str] = [] + + lower_is_finite = cls._is_finite_bound_value(lower_bound) + upper_is_finite = cls._is_finite_bound_value(upper_bound) + value_is_finite = cls._is_finite_bound_value(value) + + if not lower_is_finite: + issues.append(f'fit_min must be finite (got {lower_bound!r})') + if not upper_is_finite: + issues.append(f'fit_max must be finite (got {upper_bound!r})') + + bounds_are_ordered = lower_is_finite and upper_is_finite and lower_bound < upper_bound + if lower_is_finite and upper_is_finite and not bounds_are_ordered: + issues.append(f'fit_min ({lower_bound}) must be smaller than fit_max ({upper_bound})') + + if not value_is_finite: + issues.append(f'starting value must be finite (got {value!r})') + elif bounds_are_ordered and not lower_bound <= value <= upper_bound: + issues.append(f'starting value {value} is outside [{lower_bound}, {upper_bound}]') + + return issues + + @staticmethod + def _is_finite_bound_value(value: object) -> bool: + """Return whether a bound-validation value is finite.""" + try: + return bool(np.isfinite(value)) + except TypeError: + return False + @staticmethod def _validated_positive_integer(name: str, value: float) -> int: """Validate a DREAM setting that must be a positive integer.""" diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 98f718de..8d8a99bd 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -741,8 +741,9 @@ def plot_param_distribution( Parameters ---------- param : object - Parameter descriptor whose posterior distribution should be - plotted. + Parameter descriptor or string identifier selecting the + posterior to plot. Strings may be unique names or + user-facing labels. """ plot = self._build_param_distribution_plot(param) if plot is None: @@ -2700,13 +2701,128 @@ def _resolve_posterior_parameter_names( if parameters is None: return list(available_names) - requested_names = [getattr(parameter, 'unique_name', None) for parameter in parameters] - missing_names = [name for name in requested_names if name not in available_names] - if missing_names: - missing = ', '.join(str(name) for name in missing_names) - log.warning(f'Posterior samples do not contain the selected parameters: {missing}') + resolved_names: list[str] = [] + for parameter in parameters: + resolved_name = Plotter._resolve_posterior_parameter_name( + fit_results=fit_results, + available_names=list(available_names), + parameter=parameter, + ) + if resolved_name is None: + return None + resolved_names.append(resolved_name) + return resolved_names + + @staticmethod + def _resolve_posterior_parameter_name( + *, + fit_results: object, + available_names: list[str], + parameter: object, + ) -> str | None: + """ + Resolve one posterior parameter selection into a unique name. + """ + if isinstance(parameter, str): + return Plotter._resolve_posterior_parameter_name_from_string( + fit_results=fit_results, + available_names=available_names, + selection=parameter, + ) + + unique_name = getattr(parameter, 'unique_name', None) + if unique_name is None: + log.warning( + 'Posterior parameter selection expects parameter objects ' + 'or strings matching a unique name or label.' + ) return None - return [str(name) for name in requested_names if name is not None] + if unique_name not in available_names: + log.warning(f'Posterior samples do not contain the selected parameter: {unique_name}') + return None + return str(unique_name) + + @staticmethod + def _resolve_posterior_parameter_name_from_string( + *, + fit_results: object, + available_names: list[str], + selection: str, + ) -> str | None: + """Resolve a string posterior parameter selection.""" + stripped_selection = selection.strip() + if not stripped_selection: + log.warning('Posterior parameter selection cannot use an empty string.') + return None + if stripped_selection in available_names: + return stripped_selection + + selection_candidates = Plotter._posterior_parameter_selection_candidates( + fit_results=fit_results, + available_names=available_names, + ) + matching_names = [ + unique_name + for unique_name, candidates in selection_candidates.items() + if stripped_selection in candidates + ] + if len(matching_names) == 1: + return matching_names[0] + if len(matching_names) > 1: + matches = ', '.join(matching_names) + log.warning( + f"Posterior parameter selection '{stripped_selection}' is ambiguous. " + f'Matches: {matches}' + ) + return None + + log.warning( + f'Posterior samples do not contain the selected parameter or label: ' + f'{stripped_selection}' + ) + return None + + @staticmethod + def _posterior_parameter_selection_candidates( + *, + fit_results: object, + available_names: list[str], + ) -> dict[str, set[str]]: + """ + Return string identifiers accepted for posterior selection. + """ + parameters_by_name = { + getattr(parameter, 'unique_name', ''): parameter + for parameter in fit_results.parameters + } + summaries_by_name = Plotter._posterior_summary_by_name(fit_results) + plot_labels = dict( + zip( + available_names, + Plotter._posterior_plot_labels(fit_results, available_names), + strict=True, + ) + ) + candidates_by_name: dict[str, set[str]] = {} + for unique_name in available_names: + candidates = {unique_name} + parameter = parameters_by_name.get(unique_name) + if parameter is not None: + parameter_name = getattr(parameter, 'name', None) + if isinstance(parameter_name, str) and parameter_name.strip(): + candidates.add(parameter_name.strip()) + + summary = summaries_by_name.get(unique_name) + summary_label = getattr(summary, 'display_name', None) + if isinstance(summary_label, str) and summary_label.strip(): + candidates.add(summary_label.strip()) + + plot_label = plot_labels.get(unique_name) + if isinstance(plot_label, str) and plot_label.strip(): + candidates.add(plot_label.strip()) + + candidates_by_name[unique_name] = candidates + return candidates_by_name @staticmethod def _selected_posterior_samples( diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py index 783b37aa..9fa85263 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py @@ -14,12 +14,22 @@ class FakeParam: """Minimal stand-in for an EasyDiffraction parameter.""" - def __init__(self, uid: str, value: float, uncertainty: float | None = None) -> None: + def __init__( + self, + uid: str, + value: float, + uncertainty: float | None = None, + *, + fit_min: float | None = 0.0, + fit_max: float | None = 1.0, + ) -> None: self._minimizer_uid = uid self.unique_name = uid self.name = uid.upper() self.value = value self.uncertainty = uncertainty + self.fit_min = fit_min + self.fit_max = fit_max def _set_value_from_minimizer(self, value: float) -> None: self.value = value @@ -115,6 +125,46 @@ def test_sampler_settings_include_init_and_sample_count(): assert settings['samples'] == 120 +@pytest.mark.parametrize( + ('fit_min', 'fit_max', 'value', 'message'), + [ + (None, 1.0, 0.5, r'fit_min must be finite'), + (0.0, np.inf, 0.5, r'fit_max must be finite'), + (2.0, 1.0, 1.5, r'fit_min \(2\.0\) must be smaller than fit_max \(1\.0\)'), + (0.0, 1.0, 2.0, r'starting value 2\.0 is outside \[0\.0, 1\.0\]'), + ], +) +def test_prepare_solver_args_rejects_invalid_dream_bounds( + fit_min, + fit_max, + value, + message, +): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + parameter = FakeParam('alpha', value, fit_min=fit_min, fit_max=fit_max) + + with pytest.raises(ValueError, match=message): + minimizer._prepare_solver_args([parameter]) + + +def test_prepare_solver_args_lists_all_offending_dream_parameters(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + parameters = [ + FakeParam('alpha', 2.0, fit_min=0.0, fit_max=1.0), + FakeParam('beta', 0.5, fit_min=None, fit_max=1.0), + ] + + with pytest.raises( + ValueError, + match=r'alpha: .*outside \[0\.0, 1\.0\][\s\S]*beta: .*fit_min', + ): + minimizer._prepare_solver_args(parameters) + + def test_sync_result_to_parameters_restores_starting_values_on_failure(): from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index d0f23651..076db1f5 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -362,6 +362,78 @@ def test_build_param_distribution_plot_returns_plotly_figure(): } +def test_build_param_distribution_plot_accepts_unique_name_string(): + plotter, _, _ = _make_bayesian_plotter_fixture() + + figure = plotter._build_param_distribution_plot('length_a') + + assert figure.layout.title.text == 'Posterior distribution: length_a' + + +def test_build_param_distribution_plot_accepts_user_facing_label_string(): + plotter, fit_results, _ = _make_bayesian_plotter_fixture() + fit_results.posterior_parameter_summaries[0].display_name = 'Cell a' + + figure = plotter._build_param_distribution_plot('Cell a') + + assert figure.layout.title.text == 'Posterior distribution: length_a' + + +def test_resolve_posterior_parameter_names_warns_on_ambiguous_label(monkeypatch): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.display.plotting import Plotter + + posterior_samples = PosteriorSamples( + parameter_names=['phase_a.length_a', 'phase_b.length_a'], + parameter_samples=np.ones((2, 2, 2), dtype=float), + ) + fit_results = SimpleNamespace( + posterior_samples=posterior_samples, + posterior_parameter_summaries=[ + PosteriorParameterSummary( + unique_name='phase_a.length_a', + display_name='length_a', + map_value=1.0, + median=1.0, + standard_deviation=0.1, + interval_68=(0.9, 1.1), + interval_95=(0.8, 1.2), + ), + PosteriorParameterSummary( + unique_name='phase_b.length_a', + display_name='length_a', + map_value=2.0, + median=2.0, + standard_deviation=0.1, + interval_68=(1.9, 2.1), + interval_95=(1.8, 2.2), + ), + ], + parameters=[ + SimpleNamespace(unique_name='phase_a.length_a', name='length_a'), + SimpleNamespace(unique_name='phase_b.length_a', name='length_a'), + ], + ) + warning_messages: list[str] = [] + + monkeypatch.setattr( + 'easydiffraction.display.plotting.log.warning', + lambda message: warning_messages.append(message), + ) + + result = Plotter._resolve_posterior_parameter_names( + fit_results=fit_results, + parameters=['length_a'], + ) + + assert result is None + assert warning_messages + assert 'ambiguous' in warning_messages[0] + assert 'phase_a.length_a' in warning_messages[0] + assert 'phase_b.length_a' in warning_messages[0] + + def test_build_posterior_predictive_summary_restores_parameter_state(monkeypatch): from easydiffraction.analysis.fit_helpers.bayesian import PosteriorPredictiveSummary from easydiffraction.display.plotting import Plotter From 83019002ca403daab7dea12dcb0e295c43eefe4a Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 00:30:04 +0200 Subject: [PATCH 056/106] Adopt fixed-aspect CSS for posterior pair plots --- .../display/plotters/plotly.py | 156 ++++++--------- src/easydiffraction/display/plotting.py | 177 ++++++++++++------ .../display/plotters/test_plotly.py | 135 +------------ .../easydiffraction/display/test_plotting.py | 22 ++- 4 files changed, 198 insertions(+), 292 deletions(-) diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index c514b743..9186b166 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -70,7 +70,8 @@ PREDICTIVE_DRAW_COLOR = 'rgba(140, 140, 140, 0.18)' PREDICTIVE_DRAW_PLOT_CAP = 50 PREDICTIVE_DRAW_ARRAY_NDIM = 2 -RESPONSIVE_PAIR_PLOT_META_KEY = 'responsive_pair_plot' +FIXED_ASPECT_WRAPPER_META_KEY = 'fixed_aspect_wrapper' +FIXED_ASPECT_WRAPPER_CLASS_NAME = 'ed-fixed-aspect-plotly-wrapper' @dataclass(frozen=True) @@ -790,82 +791,22 @@ def _modebar_legend_toggle_post_script() -> str: window.requestAnimationFrame(installLegendToggleButton); """ + @classmethod + def _html_post_script(cls, fig: object) -> str | None: + """Return concatenated HTML post scripts for a Plotly figure.""" + scripts: list[str] = [] + if cls._has_visible_legend(fig): + scripts.append(cls._modebar_legend_toggle_post_script()) + if not scripts: + return None + return '\n'.join(cls._scoped_html_post_script(script) for script in scripts) + @staticmethod - def _responsive_pair_plot_post_script() -> str: + def _scoped_html_post_script(script: str) -> str: """ - Return client-side code for responsive posterior pair plots. + Return one HTML post script wrapped in its own block scope. """ - return r""" -const graphDiv = document.getElementById('{plot_id}'); -if (!graphDiv || !window.Plotly || !graphDiv.layout || !graphDiv.layout.meta) { - return; -} - -const responsivePairPlot = graphDiv.layout.meta.responsive_pair_plot; -if (!responsivePairPlot) { - return; -} - -const readPositiveNumber = function (value, fallback) { - const numberValue = Number(value); - return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : fallback; -}; - -const nParameters = Math.max( - 1, - Math.round(readPositiveNumber(responsivePairPlot.n_parameters, 1)) -); -const marginPx = readPositiveNumber(responsivePairPlot.margin_px, 0); -const minCellSizePx = readPositiveNumber(responsivePairPlot.min_cell_size_px, 90); -const maxCellSizePx = readPositiveNumber(responsivePairPlot.max_cell_size_px, 190); - -let lastHeight = null; -let resizeFrame = null; - -const applyResponsivePairPlotSize = function () { - const containerWidth = graphDiv.clientWidth || graphDiv.getBoundingClientRect().width; - if (!Number.isFinite(containerWidth) || containerWidth <= 0) { - return; - } - - const plotWidth = Math.max(minCellSizePx, containerWidth - marginPx); - const cellSizePx = Math.min(maxCellSizePx, Math.max(minCellSizePx, plotWidth / nParameters)); - const nextHeight = Math.round(cellSizePx * nParameters + marginPx); - - if (lastHeight === nextHeight) { - window.Plotly.Plots.resize(graphDiv); - return; - } - - lastHeight = nextHeight; - window.Plotly.relayout(graphDiv, {autosize: true, height: nextHeight}); -}; - -const scheduleResponsivePairPlotSize = function () { - if (resizeFrame !== null) { - return; - } - - resizeFrame = window.requestAnimationFrame(function () { - resizeFrame = null; - applyResponsivePairPlotSize(); - }); -}; - -if (typeof ResizeObserver === 'function') { - const resizeObserver = new ResizeObserver(scheduleResponsivePairPlotSize); - resizeObserver.observe(graphDiv); -} -else { - window.addEventListener('resize', scheduleResponsivePairPlotSize); -} - -if (graphDiv.on) { - graphDiv.on('plotly_afterplot', scheduleResponsivePairPlotSize); -} - -scheduleResponsivePairPlotSize(); -""" + return '{\n' + script.strip() + '\n}' @staticmethod def _figure_meta(fig: object) -> dict[str, object] | None: @@ -886,37 +827,53 @@ def _figure_meta(fig: object) -> dict[str, object] | None: return None @classmethod - def _has_responsive_pair_plot(cls, fig: object) -> bool: - """ - Return whether a figure requests responsive pair-plot sizing. - """ + def _fixed_aspect_wrapper_aspect_ratio(cls, fig: object) -> str | None: + """Return the fixed aspect ratio requested for inline HTML.""" meta = cls._figure_meta(fig) if not isinstance(meta, dict): - return False + return None - responsive_pair_plot = meta.get(RESPONSIVE_PAIR_PLOT_META_KEY) - if not isinstance(responsive_pair_plot, dict): - return False - return bool(responsive_pair_plot.get('n_parameters')) + wrapper = meta.get(FIXED_ASPECT_WRAPPER_META_KEY) + if not isinstance(wrapper, dict): + return None - @classmethod - def _html_post_script(cls, fig: object) -> str | None: - """Return concatenated HTML post scripts for a Plotly figure.""" - scripts: list[str] = [] - if cls._has_visible_legend(fig): - scripts.append(cls._modebar_legend_toggle_post_script()) - if cls._has_responsive_pair_plot(fig): - scripts.append(cls._responsive_pair_plot_post_script()) - if not scripts: + aspect_ratio = wrapper.get('aspect_ratio') + if not isinstance(aspect_ratio, str): return None - return '\n'.join(cls._scoped_html_post_script(script) for script in scripts) - @staticmethod - def _scoped_html_post_script(script: str) -> str: - """ - Return one HTML post script wrapped in its own block scope. - """ - return '{\n' + script.strip() + '\n}' + aspect_ratio = aspect_ratio.strip() + if not aspect_ratio: + return None + return aspect_ratio + + @classmethod + def _wrap_html_figure(cls, fig: object, html_fig: str) -> str: + """Wrap inline Plotly HTML in a fixed-aspect container.""" + aspect_ratio = cls._fixed_aspect_wrapper_aspect_ratio(fig) + if aspect_ratio is None: + return html_fig + + return ( + '\n\n' + f'
\n' + f'{html_fig}\n' + '
' + ) @staticmethod def _get_figure( @@ -1003,6 +960,7 @@ def _show_figure( config=config, post_script=post_script, ) + html_fig = self._wrap_html_figure(fig, html_fig) display(HTML(html_fig)) @classmethod diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 8d8a99bd..a26d97a4 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -107,11 +107,20 @@ def description(self) -> str: PAIR_PLOT_MIN_SIZE_PIXELS = 680 PAIR_PLOT_MARGIN_PIXELS = 120 PAIR_PLOT_ESTIMATED_CONTAINER_WIDTH_PIXELS = 980 -PAIR_PLOT_SUBPLOT_SPACING = 0.015 -PAIR_PLOT_MAJOR_TICKS = 3 +PAIR_PLOT_SUBPLOT_SPACING = 0.01 POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE = 14 -POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 56 +POSTERIOR_PAIR_TITLE_FONT_SIZE = 16 +POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 16 +POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS = 10 +POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS = 2 +POSTERIOR_PAIR_GUIDE_LINE_COLOR = 'rgba(125, 140, 173, 0.18)' +POSTERIOR_PAIR_FIXED_ASPECT_RATIO = '1 / 1' +POSTERIOR_PAIR_FIXED_ASPECT_META_KEY = 'fixed_aspect_wrapper' +POSTERIOR_PAIR_LEFT_MARGIN_PIXELS = 58 +POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS = 10 +POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 26 +POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 42 @dataclass(frozen=True) @@ -1084,7 +1093,6 @@ def _build_posterior_pairs_plot( self._finalize_posterior_pairs_figure( fig=fig, - context=context, subplot_title_annotations=subplot_title_annotations, subplot_border_shapes=subplot_border_shapes, ) @@ -1343,12 +1351,14 @@ def _configure_posterior_pair_panel_axes( mirror=True, range=list(context.axis_ranges[col_index]), zeroline=False, + showgrid=False, layer='above traces', linecolor=context.axis_frame_color, linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, - nticks=PAIR_PLOT_MAJOR_TICKS, - tickformat=',.6~g', - separatethousands=True, + ticks='', + ticklen=0, + tickwidth=0, + showticklabels=False, row=row, col=col, ) @@ -1356,32 +1366,26 @@ def _configure_posterior_pair_panel_axes( showline=True, mirror=True, zeroline=False, + showgrid=False, layer='above traces', linecolor=context.axis_frame_color, linewidth=POSTERIOR_PAIR_AXIS_LINE_WIDTH, - nticks=PAIR_PLOT_MAJOR_TICKS, - tickformat=',.6~g', - separatethousands=True, + ticks='', + ticklen=0, + tickwidth=0, + showticklabels=False, row=row, col=col, ) if not is_diagonal: fig.update_yaxes(range=list(context.axis_ranges[row_index]), row=row, col=col) - fig.update_xaxes(showticklabels=(row_index == context.n_parameters - 1), row=row, col=col) if is_diagonal: fig.update_yaxes( - showticklabels=False, - ticks='', - ticklen=0, - showgrid=False, title_text=None, row=row, col=col, ) - else: - fig.update_yaxes(showticklabels=(col_index == 0), row=row, col=col) - if row_index == context.n_parameters - 1: - fig.update_xaxes(title_text=context.labels[col_index], row=row, col=col) + fig.update_xaxes(title_text=None, row=row, col=col) @staticmethod def _collect_posterior_pair_panel_decorations( @@ -1397,6 +1401,8 @@ def _collect_posterior_pair_panel_decorations( row = row_index + 1 col = col_index + 1 subplot = fig.get_subplot(row, col) + x_mid = 0.5 * (subplot.xaxis.domain[0] + subplot.xaxis.domain[1]) + y_mid = 0.5 * (subplot.yaxis.domain[0] + subplot.yaxis.domain[1]) if col_index == 0: subplot_title_annotations.append({ 'x': subplot.xaxis.domain[0], @@ -1411,65 +1417,126 @@ def _collect_posterior_pair_panel_decorations( 'textangle': -90, 'showarrow': False, }) - subplot_border_shapes.append({ - 'type': 'rect', + if row_index == context.n_parameters - 1: + subplot_title_annotations.append({ + 'x': x_mid, + 'xref': 'paper', + 'xanchor': 'center', + 'y': subplot.yaxis.domain[0], + 'yref': 'paper', + 'yanchor': 'top', + 'yshift': -POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS, + 'text': context.labels[col_index], + 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + 'showarrow': False, + }) + subplot_border_shapes.extend([ + { + 'type': 'line', + 'xref': 'paper', + 'yref': 'paper', + 'x0': x_mid, + 'x1': x_mid, + 'y0': subplot.yaxis.domain[0], + 'y1': subplot.yaxis.domain[1], + 'line': { + 'color': POSTERIOR_PAIR_GUIDE_LINE_COLOR, + 'width': 1, + }, + 'layer': 'above', + }, + { + 'type': 'line', + 'xref': 'paper', + 'yref': 'paper', + 'x0': subplot.xaxis.domain[0], + 'x1': subplot.xaxis.domain[1], + 'y0': y_mid, + 'y1': y_mid, + 'line': { + 'color': POSTERIOR_PAIR_GUIDE_LINE_COLOR, + 'width': 1, + }, + 'layer': 'above', + }, + { + 'type': 'rect', + 'xref': 'paper', + 'yref': 'paper', + 'x0': subplot.xaxis.domain[0], + 'x1': subplot.xaxis.domain[1], + 'y0': subplot.yaxis.domain[0], + 'y1': subplot.yaxis.domain[1], + 'line': { + 'color': context.axis_frame_color, + 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, + }, + 'fillcolor': 'rgba(0, 0, 0, 0)', + 'layer': 'above', + }, + ]) + + @staticmethod + def _posterior_pair_title_annotation() -> dict[str, object]: + """Return the outer title annotation for the pair plot.""" + return { + 'x': 0.0, 'xref': 'paper', + 'xanchor': 'left', + 'y': 1.0, 'yref': 'paper', - 'x0': subplot.xaxis.domain[0], - 'x1': subplot.xaxis.domain[1], - 'y0': subplot.yaxis.domain[0], - 'y1': subplot.yaxis.domain[1], - 'line': { - 'color': context.axis_frame_color, - 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, - }, - 'fillcolor': 'rgba(0, 0, 0, 0)', - 'layer': 'above', - }) + 'yanchor': 'bottom', + 'yshift': POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS, + 'text': 'Posterior pair plot', + 'font': {'size': POSTERIOR_PAIR_TITLE_FONT_SIZE}, + 'showarrow': False, + } + + @staticmethod + def _posterior_pair_layout_meta() -> dict[str, object]: + """Return layout metadata used by the Plotly HTML wrapper.""" + return { + POSTERIOR_PAIR_FIXED_ASPECT_META_KEY: { + 'aspect_ratio': POSTERIOR_PAIR_FIXED_ASPECT_RATIO, + } + } def _finalize_posterior_pairs_figure( self, *, fig: object, - context: _PosteriorPairsContext, subplot_title_annotations: list[dict[str, object]], subplot_border_shapes: list[dict[str, object]], ) -> None: """Apply final layout settings to the posterior pair plot.""" - figure_height = self._posterior_pair_figure_height_pixels(context.n_parameters) fig.update_layout( autosize=True, - margin={'autoexpand': True, 'r': 30, 't': 40, 'b': 45}, - title={'text': 'Posterior pair plot'}, + margin={ + 'autoexpand': False, + 'l': POSTERIOR_PAIR_LEFT_MARGIN_PIXELS, + 'r': POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS, + 't': POSTERIOR_PAIR_TOP_MARGIN_PIXELS, + 'b': POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS, + }, bargap=0.05, - height=figure_height, - annotations=subplot_title_annotations, + annotations=[ + self._posterior_pair_title_annotation(), + *subplot_title_annotations, + ], shapes=subplot_border_shapes, - meta=self._posterior_pair_layout_meta(context.n_parameters), + meta=self._posterior_pair_layout_meta(), legend={ 'bgcolor': 'rgba(0, 0, 0, 0)', 'xanchor': 'right', - 'x': 1.0, + 'x': 0.995, 'yanchor': 'top', - 'y': 1.0, + 'y': 0.995, 'groupclick': 'togglegroup', }, + paper_bgcolor='white', + plot_bgcolor='white', ) - @staticmethod - def _posterior_pair_layout_meta(n_parameters: int) -> dict[str, object]: - """ - Return responsive layout metadata for posterior pair plots. - """ - return { - 'responsive_pair_plot': { - 'n_parameters': int(n_parameters), - 'margin_px': PAIR_PLOT_MARGIN_PIXELS, - 'min_cell_size_px': PAIR_PLOT_MIN_CELL_SIZE_PIXELS, - 'max_cell_size_px': PAIR_PLOT_CELL_SIZE_PIXELS, - } - } - @staticmethod def _posterior_pair_cell_size_pixels( n_parameters: int, diff --git a/tests/unit/easydiffraction/display/plotters/test_plotly.py b/tests/unit/easydiffraction/display/plotters/test_plotly.py index cdd847db..54c2d5d6 100644 --- a/tests/unit/easydiffraction/display/plotters/test_plotly.py +++ b/tests/unit/easydiffraction/display/plotters/test_plotly.py @@ -13,62 +13,9 @@ def test_module_import(): assert expected_module_name == actual_module_name -def test_default_template_name_prefers_jupyter_theme(monkeypatch): - import easydiffraction.display.plotters.plotly as pp - - monkeypatch.setattr(pp, 'in_jupyter', lambda: True) - monkeypatch.setattr(pp, 'is_dark', lambda: True) - monkeypatch.setattr(pp.darkdetect, 'isDark', lambda: False) - - assert pp.PlotlyPlotter._default_template_name() == 'plotly_dark' - - -def test_correlation_colorscale_uses_black_center_in_dark_mode(monkeypatch): - import easydiffraction.display.plotters.plotly as pp - - monkeypatch.setattr(pp.PlotlyPlotter, '_is_dark_mode', staticmethod(lambda: True)) - - assert pp.PlotlyPlotter._correlation_colorscale()[1] == (0.5, '#000000') - - -def test_default_template_name_uses_system_theme_outside_jupyter(monkeypatch): - import easydiffraction.display.plotters.plotly as pp - - monkeypatch.setattr(pp, 'in_jupyter', lambda: False) - monkeypatch.setattr(pp, 'is_dark', lambda: False) - monkeypatch.setattr(pp.darkdetect, 'isDark', lambda: False) - - assert pp.PlotlyPlotter._default_template_name() == 'plotly_white' - - -def test_correlation_colorscale_uses_white_center_in_light_mode(monkeypatch): - import easydiffraction.display.plotters.plotly as pp - - monkeypatch.setattr(pp.PlotlyPlotter, '_is_dark_mode', staticmethod(lambda: False)) - - assert pp.PlotlyPlotter._correlation_colorscale()[1] == (0.5, '#f7f7f7') - - -def test_legend_background_color_uses_light_overlay_in_light_mode(monkeypatch): - import easydiffraction.display.plotters.plotly as pp - - monkeypatch.setattr(pp.PlotlyPlotter, '_is_dark_mode', staticmethod(lambda: False)) - - assert pp.PlotlyPlotter._legend_background_color() == 'rgba(255, 255, 255, 0.5)' - - -def test_legend_background_color_uses_dark_overlay_in_dark_mode(monkeypatch): - import easydiffraction.display.plotters.plotly as pp - - monkeypatch.setattr(pp.PlotlyPlotter, '_is_dark_mode', staticmethod(lambda: True)) - - assert pp.PlotlyPlotter._legend_background_color() == 'rgba(0, 0, 0, 0.5)' - - def test_get_trace_and_plot(monkeypatch): import easydiffraction.display.plotters.plotly as pp - # Arrange: force non-PyCharm branch and stub fig.show/HTML/display so nothing opens monkeypatch.setattr(pp, 'in_pycharm', lambda: False) shown = {'count': 0} @@ -83,7 +30,6 @@ def update_yaxes(self, **kwargs): def show(self, **kwargs): shown['count'] += 1 - # Patch go.Scatter and go.Figure to minimal dummies class DummyScatter: def __init__(self, **kwargs): self.kwargs = kwargs @@ -122,7 +68,6 @@ def __init__(self, html): plotter = pp.PlotlyPlotter() - # Exercise _get_powder_trace x = [0, 1, 2] y = [1, 2, 3] trace = plotter._get_powder_trace(x, y, label='calc') @@ -278,7 +223,7 @@ def __init__(self, html): assert captured['displayed_html'] == '
plot
' -def test_show_figure_adds_responsive_pair_plot_script(monkeypatch): +def test_show_figure_wraps_fixed_aspect_html(monkeypatch): import easydiffraction.display.plotters.plotly as pp monkeypatch.setattr(pp, 'in_pycharm', lambda: False) @@ -288,11 +233,8 @@ def test_show_figure_adds_responsive_pair_plot_script(monkeypatch): class DummyLayout: def __init__(self): self.meta = { - 'responsive_pair_plot': { - 'n_parameters': 4, - 'margin_px': 120, - 'min_cell_size_px': 90, - 'max_cell_size_px': 190, + 'fixed_aspect_wrapper': { + 'aspect_ratio': '1 / 1', } } self.showlegend = False @@ -326,73 +268,10 @@ def __init__(self, html): plotter._show_figure(DummyFig()) assert captured.get('show_called') is not True - assert 'responsive_pair_plot' in captured['post_script'] - assert 'ResizeObserver' in captured['post_script'] - assert 'window.Plotly.relayout' in captured['post_script'] - assert 'containerWidth' in captured['post_script'] - assert captured['displayed_html'] == '
plot
' - - -def test_show_figure_scopes_multiple_post_scripts(monkeypatch): - import easydiffraction.display.plotters.plotly as pp - - monkeypatch.setattr(pp, 'in_pycharm', lambda: False) - - captured = {} - - class DummyTrace: - def __init__(self): - self.name = 'Posterior samples' - self.showlegend = True - self.visible = True - - class DummyLayout: - def __init__(self): - self.meta = { - 'responsive_pair_plot': { - 'n_parameters': 4, - 'margin_px': 120, - 'min_cell_size_px': 90, - 'max_cell_size_px': 190, - } - } - self.showlegend = True - - class DummyFig: - def __init__(self): - self.data = [DummyTrace()] - self.layout = DummyLayout() - - def show(self, **kwargs): - captured['show_called'] = True - - class DummyPIO: - @staticmethod - def to_html(fig, include_plotlyjs=None, full_html=None, config=None, post_script=None): - captured['post_script'] = post_script - return '
plot
' - - def dummy_display(obj): - captured['displayed_html'] = obj.html - - class DummyHTML: - def __init__(self, html): - self.html = html - - monkeypatch.setattr(pp, 'pio', DummyPIO) - monkeypatch.setattr(pp, 'display', dummy_display) - monkeypatch.setattr(pp, 'HTML', DummyHTML) - - plotter = pp.PlotlyPlotter() - plotter._show_figure(DummyFig()) - - assert captured.get('show_called') is not True - assert ( - captured['post_script'].count("const graphDiv = document.getElementById('{plot_id}');") - == 2 - ) - assert '\n}\n{\n' in captured['post_script'] - assert captured['displayed_html'] == '
plot
' + assert captured['post_script'] is None + assert 'aspect-ratio: 1 / 1;' in captured['displayed_html'] + assert 'ed-fixed-aspect-plotly-wrapper' in captured['displayed_html'] + assert '
plot
' in captured['displayed_html'] def test_plotly_single_crystal_trace_and_plot(monkeypatch): diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 076db1f5..a049fdaa 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -307,33 +307,35 @@ def test_correlation_from_posterior_samples_returns_labeled_dataframe(): def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): - from easydiffraction.display.plotting import PAIR_PLOT_CELL_SIZE_PIXELS - from easydiffraction.display.plotting import PAIR_PLOT_MARGIN_PIXELS - plotter, _, _ = _make_bayesian_plotter_fixture() figure = plotter._build_posterior_pairs_plot(parameters=None) - assert figure.layout.title.text == 'Posterior pair plot' + assert figure.layout.title.text is None assert figure.layout.autosize is True assert figure.layout.width is None - assert figure.layout.meta['responsive_pair_plot']['n_parameters'] == 4 - assert ( - figure.layout.meta['responsive_pair_plot']['max_cell_size_px'] - == PAIR_PLOT_CELL_SIZE_PIXELS - ) - assert figure.layout.meta['responsive_pair_plot']['margin_px'] == PAIR_PLOT_MARGIN_PIXELS + assert figure.layout.height is None + assert figure.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] == '1 / 1' assert [annotation.text for annotation in figure.layout.annotations] == [ + 'Posterior pair plot', + 'length_a', + 'broad_gauss_u', + 'broad_gauss_v', + 'twotheta_offset', 'length_a', 'broad_gauss_u', 'broad_gauss_v', 'twotheta_offset', ] subplot = figure.get_subplot(1, 1) + bottom_subplot = figure.get_subplot(4, 1) assert subplot.yaxis.showticklabels is False assert subplot.yaxis.ticks == '' assert subplot.yaxis.ticklen == 0 assert subplot.yaxis.title.text is None + assert bottom_subplot.xaxis.showticklabels is False + assert bottom_subplot.xaxis.title.text is None + assert len(figure.layout.shapes) == 30 def test_posterior_pair_figure_height_shrinks_cells_for_many_parameters(): From 1282c95ff835a57e872506082410bf3b81151474 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 12:34:15 +0200 Subject: [PATCH 057/106] Add posterior pair plot rendering modes --- src/easydiffraction/display/plotting.py | 143 ++++++++++++++++-- .../easydiffraction/display/test_plotting.py | 75 +++++++++ 2 files changed, 205 insertions(+), 13 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index a26d97a4..2f199574 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -64,6 +64,14 @@ def description(self) -> str: return '' +class PosteriorPairPlotStyleEnum(StrEnum): + """Available posterior pair-plot rendering modes.""" + + AUTO = 'auto' + FAST = 'fast' + FULL = 'full' + + DEFAULT_CORRELATION_THRESHOLD = 0.7 EXPECTED_COVAR_NDIM = 2 DEFAULT_RESIDUAL_HEIGHT_FRACTION = 0.25 @@ -102,6 +110,14 @@ def description(self) -> str: [0.82, 'rgba(58, 86, 224, 0.98)'], [1.0, 'rgba(58, 86, 224, 0.98)'], ] +POSTERIOR_PAIR_SCATTER_MAX_POINTS = 1500 +POSTERIOR_PAIR_MAX_DENSITY_SAMPLES = 4000 +POSTERIOR_PAIR_MIN_DENSITY_SAMPLES = 800 +POSTERIOR_PAIR_TARGET_DENSITY_SAMPLE_BUDGET = 24000 +POSTERIOR_PAIR_MAX_CONTOUR_GRID_SIZE = 96 +POSTERIOR_PAIR_MIN_CONTOUR_GRID_SIZE = 56 +POSTERIOR_PAIR_TARGET_CONTOUR_GRID_POINT_BUDGET = 73728 +POSTERIOR_PAIR_AUTO_MAX_CONTOUR_PARAMETERS = 6 PAIR_PLOT_CELL_SIZE_PIXELS = 190 PAIR_PLOT_MIN_CELL_SIZE_PIXELS = 90 PAIR_PLOT_MIN_SIZE_PIXELS = 680 @@ -163,6 +179,8 @@ class _PosteriorPairsContext: labels: list[str] density_samples: np.ndarray scatter_samples: np.ndarray + show_contours: bool + contour_grid_size: int axis_frame_color: str axis_ranges: list[tuple[float, float]] @@ -725,6 +743,7 @@ def plot_param_correlations( def plot_posterior_pairs( self, parameters: list[object] | None = None, + style: PosteriorPairPlotStyleEnum | str = PosteriorPairPlotStyleEnum.AUTO, ) -> None: """ Plot posterior pair relationships for sampled parameters. @@ -734,8 +753,12 @@ def plot_posterior_pairs( parameters : list[object] | None, default=None Optional subset of sampled parameters to include. When ``None``, all sampled parameters are shown. + style : PosteriorPairPlotStyleEnum | str, default='auto' + ``'auto'`` keeps contours for compact plots and disables + them for wide grids. ``'fast'`` always skips contours. + ``'full'`` always renders contours. """ - plot = self._build_posterior_pairs_plot(parameters=parameters) + plot = self._build_posterior_pairs_plot(parameters=parameters, style=style) if plot is None: return self._show_plot_figure(plot) @@ -1048,6 +1071,7 @@ def _build_posterior_pairs_plot( self, *, parameters: list[object] | None, + style: PosteriorPairPlotStyleEnum | str = PosteriorPairPlotStyleEnum.AUTO, ) -> object | None: """ Build a Plotly posterior pair plot. @@ -1056,6 +1080,8 @@ def _build_posterior_pairs_plot( ---------- parameters : list[object] | None Optional subset of sampled parameters to include. + style : PosteriorPairPlotStyleEnum | str, default='auto' + Posterior pair-plot rendering mode. Returns ------- @@ -1063,7 +1089,7 @@ def _build_posterior_pairs_plot( Plotly figure, or ``None`` when posterior plotting is unavailable. """ - context = self._posterior_pairs_context(parameters) + context = self._posterior_pairs_context(parameters, style=style) if context is None: return None @@ -1101,12 +1127,16 @@ def _build_posterior_pairs_plot( def _posterior_pairs_context( self, parameters: list[object] | None, + *, + style: PosteriorPairPlotStyleEnum | str = PosteriorPairPlotStyleEnum.AUTO, ) -> _PosteriorPairsContext | None: """Return the resolved inputs for a posterior pair plot.""" posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() if posterior_samples is None or fit_results is None: return None + plot_style = self._validated_posterior_pair_plot_style(style) + parameter_names = self._resolve_posterior_parameter_names( fit_results=fit_results, parameters=parameters, @@ -1117,21 +1147,44 @@ def _posterior_pairs_context( log.warning('Posterior pair plots require at least two sampled parameters.') return None - density_samples = self._selected_posterior_samples(posterior_samples, parameter_names) - if density_samples is None: + selected_samples = self._selected_posterior_samples(posterior_samples, parameter_names) + if selected_samples is None: return None + n_parameters = len(parameter_names) + show_contours = self._posterior_pair_show_contours( + n_parameters=n_parameters, + style=plot_style, + ) + if plot_style is PosteriorPairPlotStyleEnum.AUTO and not show_contours: + log.warning( + 'Posterior pair plot auto mode disabled contours for ' + f'{n_parameters} parameters. Use style="full" to force ' + 'contours.' + ) + + density_samples = self._thin_posterior_samples( + selected_samples, + max_points=self._posterior_pair_density_max_points(n_parameters), + ) + scatter_samples = self._thin_posterior_samples( + selected_samples, + max_points=POSTERIOR_PAIR_SCATTER_MAX_POINTS, + ) + return _PosteriorPairsContext( fit_results=fit_results, parameter_names=parameter_names, labels=self._posterior_plot_labels(fit_results, parameter_names), density_samples=density_samples, - scatter_samples=self._thin_posterior_samples(density_samples, max_points=1500), + scatter_samples=scatter_samples, + show_contours=show_contours, + contour_grid_size=self._posterior_pair_contour_grid_size(n_parameters), axis_frame_color=self._plot_axis_frame_color(), axis_ranges=self._posterior_pair_axis_ranges( fit_results=fit_results, parameter_names=parameter_names, - density_samples=density_samples, + density_samples=selected_samples, ), ) @@ -1284,13 +1337,16 @@ def _add_posterior_pair_off_diagonal( y_density_values = context.density_samples[:, row_index] x_scatter_values = context.scatter_samples[:, col_index] y_scatter_values = context.scatter_samples[:, row_index] - contour_traces = self._posterior_contour_traces( - fit_results=context.fit_results, - x_parameter_name=context.parameter_names[col_index], - y_parameter_name=context.parameter_names[row_index], - x_values=x_density_values, - y_values=y_density_values, - ) + contour_traces = None + if context.show_contours: + contour_traces = self._posterior_contour_traces( + fit_results=context.fit_results, + x_parameter_name=context.parameter_names[col_index], + y_parameter_name=context.parameter_names[row_index], + x_values=x_density_values, + y_values=y_density_values, + grid_size=context.contour_grid_size, + ) sample_hovertemplate = ( f'{context.labels[col_index]}: %{{x:.4f}}
' f'{context.labels[row_index]}: %{{y:.4f}}' @@ -1573,6 +1629,65 @@ def _posterior_pair_figure_height_pixels(cls, n_parameters: int) -> int: cell_size * n_parameters + PAIR_PLOT_MARGIN_PIXELS, ) + @staticmethod + def _posterior_pair_contour_panel_count(n_parameters: int) -> int: + """Return the number of lower-triangle contour panels.""" + if n_parameters < MIN_POSTERIOR_PARAMETER_COUNT: + return 1 + return n_parameters * (n_parameters - 1) // 2 + + @classmethod + def _posterior_pair_density_max_points(cls, n_parameters: int) -> int: + """Return a KDE sample cap for interactive pair plots.""" + panel_count = cls._posterior_pair_contour_panel_count(n_parameters) + estimated_limit = round( + POSTERIOR_PAIR_TARGET_DENSITY_SAMPLE_BUDGET / panel_count, + ) + return max( + POSTERIOR_PAIR_MIN_DENSITY_SAMPLES, + min(POSTERIOR_PAIR_MAX_DENSITY_SAMPLES, estimated_limit), + ) + + @classmethod + def _posterior_pair_contour_grid_size(cls, n_parameters: int) -> int: + """Return contour grid size for current pair-plot width.""" + panel_count = cls._posterior_pair_contour_panel_count(n_parameters) + estimated_grid_size = round( + np.sqrt(POSTERIOR_PAIR_TARGET_CONTOUR_GRID_POINT_BUDGET / panel_count), + ) + return max( + POSTERIOR_PAIR_MIN_CONTOUR_GRID_SIZE, + min(POSTERIOR_PAIR_MAX_CONTOUR_GRID_SIZE, estimated_grid_size), + ) + + @staticmethod + def _validated_posterior_pair_plot_style( + style: PosteriorPairPlotStyleEnum | str, + ) -> PosteriorPairPlotStyleEnum: + """Return a validated posterior pair-plot rendering mode.""" + try: + return PosteriorPairPlotStyleEnum(style) + except ValueError as exc: + supported_styles = ', '.join(item.value for item in PosteriorPairPlotStyleEnum) + msg = ( + 'style must be one of ' + f'{supported_styles} for posterior pair plots.' + ) + raise ValueError(msg) from exc + + @staticmethod + def _posterior_pair_show_contours( + *, + n_parameters: int, + style: PosteriorPairPlotStyleEnum, + ) -> bool: + """Return whether contours should be rendered.""" + if style is PosteriorPairPlotStyleEnum.FULL: + return True + if style is PosteriorPairPlotStyleEnum.FAST: + return False + return n_parameters <= POSTERIOR_PAIR_AUTO_MAX_CONTOUR_PARAMETERS + def _plot_axis_frame_color(self) -> str: """ Return the shared axis-frame color for Plotly-backed plots. @@ -1590,6 +1705,7 @@ def _posterior_contour_traces( y_parameter_name: str, x_values: np.ndarray, y_values: np.ndarray, + grid_size: int, ) -> tuple[object, object] | None: """ Return filled and line contour traces for posterior pair plots. @@ -1608,6 +1724,7 @@ def _posterior_contour_traces( y_values=y_values, x_bounds=bounds[0], y_bounds=bounds[1], + grid_size=grid_size, ) if density_surface is None: return None diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index a049fdaa..1840388f 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -336,6 +336,15 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): assert bottom_subplot.xaxis.showticklabels is False assert bottom_subplot.xaxis.title.text is None assert len(figure.layout.shapes) == 30 + assert any(trace.name == 'Posterior contours' for trace in figure.data) + + +def test_build_posterior_pairs_plot_fast_mode_skips_contours(): + plotter, _, _ = _make_bayesian_plotter_fixture() + + figure = plotter._build_posterior_pairs_plot(parameters=None, style='fast') + + assert all(trace.name != 'Posterior contours' for trace in figure.data) def test_posterior_pair_figure_height_shrinks_cells_for_many_parameters(): @@ -347,6 +356,72 @@ def test_posterior_pair_figure_height_shrinks_cells_for_many_parameters(): assert cell_size < PAIR_PLOT_CELL_SIZE_PIXELS +def test_posterior_pair_density_budget_scales_with_parameter_count(): + from easydiffraction.display.plotting import Plotter + + assert Plotter._posterior_pair_density_max_points(8) < Plotter._posterior_pair_density_max_points(4) + assert Plotter._posterior_pair_contour_grid_size(8) < Plotter._posterior_pair_contour_grid_size(4) + + +def test_posterior_pairs_context_thins_kde_samples_and_preserves_axis_ranges(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.display.plotting import POSTERIOR_PAIR_SCATTER_MAX_POINTS + from easydiffraction.display.plotting import Plotter + + parameter_count = 8 + sample_count = 5000 + parameter_names = [f'param_{index}' for index in range(parameter_count)] + samples = np.zeros((1, sample_count, parameter_count), dtype=float) + samples[0, 1, 0] = 100.0 + samples[0, 2, 1] = -50.0 + for index in range(2, parameter_count): + samples[0, :, index] = np.linspace(index, index + 1, sample_count, dtype=float) + + posterior_samples = PosteriorSamples( + parameter_names=parameter_names, + parameter_samples=samples, + log_posterior=np.zeros((1, sample_count), dtype=float), + ) + parameters = [ + SimpleNamespace(unique_name=name, name=name, fit_min=None, fit_max=None) + for name in parameter_names + ] + fit_results = SimpleNamespace( + posterior_samples=posterior_samples, + posterior_parameter_summaries=[], + posterior_predictive={}, + parameters=parameters, + ) + plotter = Plotter() + plotter._get_posterior_samples_and_fit_results = MethodType( + lambda self: (posterior_samples, fit_results), + plotter, + ) + + context = plotter._posterior_pairs_context(parameters=None) + + assert context is not None + assert context.density_samples.shape == ( + Plotter._posterior_pair_density_max_points(parameter_count), + parameter_count, + ) + assert context.scatter_samples.shape == (POSTERIOR_PAIR_SCATTER_MAX_POINTS, parameter_count) + assert context.show_contours is False + assert context.contour_grid_size == Plotter._posterior_pair_contour_grid_size(parameter_count) + assert context.axis_ranges[0][1] > 100.0 + assert context.axis_ranges[1][0] < -50.0 + + +def test_build_posterior_pairs_plot_rejects_unknown_style(): + plotter, _, _ = _make_bayesian_plotter_fixture() + + with pytest.raises( + ValueError, + match=r'style must be one of auto, fast, full for posterior pair plots\.', + ): + plotter._build_posterior_pairs_plot(parameters=None, style='slow') + + def test_build_param_distribution_plot_returns_plotly_figure(): plotter, fit_results, _ = _make_bayesian_plotter_fixture() parameter = fit_results.parameters[0] From 65c4a28e4500be0c48f086061d76d39adfda7c49 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 16:04:15 +0200 Subject: [PATCH 058/106] Add multiline axis titles to posterior pair plots --- src/easydiffraction/analysis/analysis.py | 4 +- src/easydiffraction/display/plotting.py | 72 ++++++++++++++++--- src/easydiffraction/project/project.py | 5 ++ .../easydiffraction/display/test_plotting.py | 26 +++++++ .../easydiffraction/project/test_project.py | 14 ++++ 5 files changed, 108 insertions(+), 13 deletions(-) diff --git a/src/easydiffraction/analysis/analysis.py b/src/easydiffraction/analysis/analysis.py index dd4de8c0..d389fd27 100644 --- a/src/easydiffraction/analysis/analysis.py +++ b/src/easydiffraction/analysis/analysis.py @@ -184,9 +184,7 @@ def free_params(self) -> None: """Print only currently free (varying) parameters.""" project = self._analysis.project self._flush_structure_categories() - structures_params = project.structures.free_parameters - experiments_params = project.experiments.free_parameters - free_params = structures_params + experiments_params + free_params = project.free_parameters if not free_params: log.warning('No free parameters found.') diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 2f199574..8f7ea759 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -125,7 +125,7 @@ class PosteriorPairPlotStyleEnum(StrEnum): PAIR_PLOT_ESTIMATED_CONTAINER_WIDTH_PIXELS = 980 PAIR_PLOT_SUBPLOT_SPACING = 0.01 POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 -POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE = 14 +POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE = 12 POSTERIOR_PAIR_TITLE_FONT_SIZE = 16 POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 16 POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS = 10 @@ -137,6 +137,7 @@ class PosteriorPairPlotStyleEnum(StrEnum): POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS = 10 POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 26 POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 42 +POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS = 18 @dataclass(frozen=True) @@ -177,6 +178,7 @@ class _PosteriorPairsContext: fit_results: object parameter_names: list[str] labels: list[str] + annotation_labels: list[str] density_samples: np.ndarray scatter_samples: np.ndarray show_contours: bool @@ -1119,6 +1121,7 @@ def _build_posterior_pairs_plot( self._finalize_posterior_pairs_figure( fig=fig, + context=context, subplot_title_annotations=subplot_title_annotations, subplot_border_shapes=subplot_border_shapes, ) @@ -1176,6 +1179,7 @@ def _posterior_pairs_context( fit_results=fit_results, parameter_names=parameter_names, labels=self._posterior_plot_labels(fit_results, parameter_names), + annotation_labels=self._posterior_pair_axis_title_labels(parameter_names), density_samples=density_samples, scatter_samples=scatter_samples, show_contours=show_contours, @@ -1468,7 +1472,8 @@ def _collect_posterior_pair_panel_decorations( 'y': 0.5 * (subplot.yaxis.domain[0] + subplot.yaxis.domain[1]), 'yref': 'paper', 'yanchor': 'middle', - 'text': context.labels[row_index], + 'text': context.annotation_labels[row_index], + 'align': 'center', 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, 'textangle': -90, 'showarrow': False, @@ -1482,7 +1487,8 @@ def _collect_posterior_pair_panel_decorations( 'yref': 'paper', 'yanchor': 'top', 'yshift': -POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS, - 'text': context.labels[col_index], + 'text': context.annotation_labels[col_index], + 'align': 'center', 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, 'showarrow': False, }) @@ -1561,19 +1567,14 @@ def _finalize_posterior_pairs_figure( self, *, fig: object, + context: _PosteriorPairsContext, subplot_title_annotations: list[dict[str, object]], subplot_border_shapes: list[dict[str, object]], ) -> None: """Apply final layout settings to the posterior pair plot.""" fig.update_layout( autosize=True, - margin={ - 'autoexpand': False, - 'l': POSTERIOR_PAIR_LEFT_MARGIN_PIXELS, - 'r': POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS, - 't': POSTERIOR_PAIR_TOP_MARGIN_PIXELS, - 'b': POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS, - }, + margin=self._posterior_pair_layout_margin(context.annotation_labels), bargap=0.05, annotations=[ self._posterior_pair_title_annotation(), @@ -1593,6 +1594,37 @@ def _finalize_posterior_pairs_figure( plot_bgcolor='white', ) + @staticmethod + def _posterior_pair_layout_margin(annotation_labels: list[str]) -> dict[str, int | bool]: + """Return outer margins sized for multiline pair-plot labels.""" + extra_margin = Plotter._posterior_pair_extra_axis_title_margin(annotation_labels) + return { + 'autoexpand': False, + 'l': POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + extra_margin, + 'r': POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS, + 't': POSTERIOR_PAIR_TOP_MARGIN_PIXELS, + 'b': POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + extra_margin, + } + + @staticmethod + def _posterior_pair_extra_axis_title_margin(annotation_labels: list[str]) -> int: + """Return extra margin needed for multiline axis labels.""" + if not annotation_labels: + return 0 + + max_line_count = max( + Plotter._posterior_pair_axis_title_line_count(label) + for label in annotation_labels + ) + return max(0, max_line_count - 1) * POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS + + @staticmethod + def _posterior_pair_axis_title_line_count(label: str) -> int: + """Return the number of display lines in one axis title.""" + if not label: + return 1 + return label.count('
') + 1 + @staticmethod def _posterior_pair_cell_size_pixels( n_parameters: int, @@ -3069,6 +3101,26 @@ def _posterior_plot_labels( labels.append(short_name) return labels + @staticmethod + def _posterior_pair_axis_title_labels( + parameter_names: list[str], + ) -> list[str]: + """Return compact multiline labels for pair-plot axes.""" + return [Plotter._posterior_pair_axis_title_label(name) for name in parameter_names] + + @staticmethod + def _posterior_pair_axis_title_label(unique_name: str) -> str: + """Return one compact multiline axis title for a pair plot.""" + normalized_name = unique_name.strip() + if not normalized_name or '.' not in normalized_name: + return normalized_name + + name_parts = [part.strip() for part in normalized_name.split('.') if part.strip()] + if not name_parts: + return normalized_name + + return '
'.join([*(f'{part}.' for part in name_parts[:-1]), name_parts[-1]]) + @staticmethod def _posterior_summary_by_name( fit_results: object, diff --git a/src/easydiffraction/project/project.py b/src/easydiffraction/project/project.py index 7dc42cf6..58d7e97f 100644 --- a/src/easydiffraction/project/project.py +++ b/src/easydiffraction/project/project.py @@ -171,6 +171,11 @@ def parameters(self) -> list: """Return parameters from all structures and experiments.""" return self.structures.parameters + self.experiments.parameters + @property + def free_parameters(self) -> list: + """Return free parameters from structures and experiments.""" + return self.structures.free_parameters + self.experiments.free_parameters + @property def as_cif(self) -> str: """Export whole project as CIF text.""" diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 1840388f..1eb130b4 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -347,6 +347,32 @@ def test_build_posterior_pairs_plot_fast_mode_skips_contours(): assert all(trace.name != 'Posterior contours' for trace in figure.data) +def test_build_posterior_pairs_plot_formats_dotted_axis_titles_multiline(): + from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + from easydiffraction.display.plotting import POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + + plotter, fit_results, _ = _make_bayesian_plotter_fixture() + dotted_parameter_names = [ + 'lbco.cell.length_a', + 'hrpt.peak.broad_gauss_u', + 'hrpt.peak.broad_gauss_v', + 'hrpt.instrument.twotheta_offset', + ] + fit_results.posterior_samples.parameter_names = dotted_parameter_names + for index, unique_name in enumerate(dotted_parameter_names): + fit_results.parameters[index].unique_name = unique_name + fit_results.posterior_parameter_summaries[index].unique_name = unique_name + + figure = plotter._build_posterior_pairs_plot(parameters=None) + + annotation_texts = [annotation.text for annotation in figure.layout.annotations] + assert 'hrpt.
peak.
broad_gauss_u' in annotation_texts + assert 'hrpt.
instrument.
twotheta_offset' in annotation_texts + assert all('None broad_gauss_u' not in text for text in annotation_texts) + assert figure.layout.margin.l > POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + assert figure.layout.margin.b > POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + + def test_posterior_pair_figure_height_shrinks_cells_for_many_parameters(): from easydiffraction.display.plotting import PAIR_PLOT_CELL_SIZE_PIXELS from easydiffraction.display.plotting import Plotter diff --git a/tests/unit/easydiffraction/project/test_project.py b/tests/unit/easydiffraction/project/test_project.py index 92907f66..090ce540 100644 --- a/tests/unit/easydiffraction/project/test_project.py +++ b/tests/unit/easydiffraction/project/test_project.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2025 EasyScience contributors # SPDX-License-Identifier: BSD-3-Clause +from types import SimpleNamespace + def test_module_import(): import easydiffraction.project.project as MUT @@ -49,3 +51,15 @@ def test_project_verbosity_invalid(): p = Project() with pytest.raises(ValueError, match="'verbose' is not a valid VerbosityEnum"): p.verbosity = 'verbose' + + +def test_project_free_params_aggregate_structures_and_experiments(): + from easydiffraction.project.project import Project + + project = Project() + structure_param = object() + experiment_param = object() + project._structures = SimpleNamespace(free_parameters=[structure_param]) + project._experiments = SimpleNamespace(free_parameters=[experiment_param]) + + assert project.free_parameters == [structure_param, experiment_param] From 46a9cb697b17ff3aaecb5465fe4f7087eecd34a9 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 22:35:02 +0200 Subject: [PATCH 059/106] Redesign correlation heatmap display --- src/easydiffraction/analysis/analysis.py | 6 +- src/easydiffraction/display/plotting.py | 422 ++++++++++++++++-- .../easydiffraction/display/test_plotting.py | 124 +++-- 3 files changed, 494 insertions(+), 58 deletions(-) diff --git a/src/easydiffraction/analysis/analysis.py b/src/easydiffraction/analysis/analysis.py index d389fd27..23b9fcf3 100644 --- a/src/easydiffraction/analysis/analysis.py +++ b/src/easydiffraction/analysis/analysis.py @@ -184,7 +184,11 @@ def free_params(self) -> None: """Print only currently free (varying) parameters.""" project = self._analysis.project self._flush_structure_categories() - free_params = project.free_parameters + free_params = getattr(project, 'free_parameters', None) + if free_params is None: + structures_params = project.structures.free_parameters + experiments_params = project.experiments.free_parameters + free_params = structures_params + experiments_params if not free_params: log.warning('No free parameters found.') diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 8f7ea759..4f35e498 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -72,7 +72,7 @@ class PosteriorPairPlotStyleEnum(StrEnum): FULL = 'full' -DEFAULT_CORRELATION_THRESHOLD = 0.7 +DEFAULT_CORRELATION_THRESHOLD = 0.0 EXPECTED_COVAR_NDIM = 2 DEFAULT_RESIDUAL_HEIGHT_FRACTION = 0.25 DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION = 0.10 @@ -85,6 +85,9 @@ class PosteriorPairPlotStyleEnum(StrEnum): MIN_POSTERIOR_SAMPLE_COUNT = 2 POSTERIOR_DENSITY_LINE_COLOR = 'rgb(99, 110, 250)' POSTERIOR_DENSITY_FILL_COLOR = 'rgba(99, 110, 250, 0.22)' +POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR = 'rgb(44, 160, 44)' +POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR = 'rgba(44, 160, 44, 0.22)' +POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH = 1 POSTERIOR_HISTOGRAM_FILL_COLOR = 'rgba(120, 120, 120, 0.38)' POSTERIOR_HISTOGRAM_LINE_COLOR = 'rgba(120, 120, 120, 0.24)' POSTERIOR_INTERVAL_95_FILL_COLOR = 'rgba(140, 140, 140, 0.08)' @@ -100,6 +103,13 @@ class PosteriorPairPlotStyleEnum(StrEnum): [0.82, 'rgba(96, 131, 242, 0.84)'], [1.0, 'rgba(58, 86, 224, 0.90)'], ] +POSTERIOR_NEGATIVE_CONTOUR_FILL_COLORSCALE = [ + [0.0, 'rgba(255, 224, 224, 0.62)'], + [0.35, 'rgba(250, 188, 188, 0.70)'], + [0.60, 'rgba(245, 148, 148, 0.78)'], + [0.82, 'rgba(237, 104, 104, 0.84)'], + [1.0, 'rgba(215, 48, 39, 0.90)'], +] POSTERIOR_CONTOUR_LINE_COLORSCALE = [ [0.0, 'rgba(183, 203, 255, 0.94)'], [0.35, 'rgba(183, 203, 255, 0.94)'], @@ -110,6 +120,16 @@ class PosteriorPairPlotStyleEnum(StrEnum): [0.82, 'rgba(58, 86, 224, 0.98)'], [1.0, 'rgba(58, 86, 224, 0.98)'], ] +POSTERIOR_NEGATIVE_CONTOUR_LINE_COLORSCALE = [ + [0.0, 'rgba(250, 188, 188, 0.94)'], + [0.35, 'rgba(250, 188, 188, 0.94)'], + [0.35, 'rgba(245, 148, 148, 0.95)'], + [0.60, 'rgba(245, 148, 148, 0.95)'], + [0.60, 'rgba(237, 104, 104, 0.96)'], + [0.82, 'rgba(237, 104, 104, 0.96)'], + [0.82, 'rgba(215, 48, 39, 0.98)'], + [1.0, 'rgba(215, 48, 39, 0.98)'], +] POSTERIOR_PAIR_SCATTER_MAX_POINTS = 1500 POSTERIOR_PAIR_MAX_DENSITY_SAMPLES = 4000 POSTERIOR_PAIR_MIN_DENSITY_SAMPLES = 800 @@ -192,6 +212,27 @@ def n_parameters(self) -> int: return len(self.parameter_names) +@dataclass(frozen=True) +class _CorrelationHeatmapContext: + """Inputs needed to build a correlation matrix plot.""" + + corr_df: pd.DataFrame + row_labels: list[str] + col_labels: list[str] + threshold: float | None + precision: int + + @property + def n_rows(self) -> int: + """Return the number of displayed rows.""" + return self.corr_df.shape[0] + + @property + def n_cols(self) -> int: + """Return the number of displayed columns.""" + return self.corr_df.shape[1] + + @dataclass(slots=True) class _PosteriorPairsLegendState: """Legend-visibility state for posterior pair plots.""" @@ -674,7 +715,7 @@ def plot_param_correlations( threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, precision: int = 2, *, - show_diagonal: bool = False, + show_diagonal: bool = True, ) -> None: """ Plot the parameter correlation matrix from the latest fit. @@ -683,10 +724,9 @@ def plot_param_correlations( the active engine is Plotly, an interactive heatmap is shown. Otherwise, a rounded correlation table is rendered. - By default only the lower triangle is shown (without the - diagonal), since the matrix is symmetric and diagonal values are - always ``1``. Set ``show_diagonal=True`` to keep blank diagonal - cells for a square lower-triangle layout. + By default the lower triangle is shown with blank diagonal cells + so the grid stays square, like posterior pair plots. Set + ``show_diagonal=False`` to trim the empty outer row and column. Parameters ---------- @@ -698,7 +738,7 @@ def plot_param_correlations( matrix. precision : int, default=2 Number of decimal places to show in the table fallback. - show_diagonal : bool, default=False + show_diagonal : bool, default=True Whether to retain blank diagonal cells in the displayed lower-triangle matrix. """ @@ -745,7 +785,7 @@ def plot_param_correlations( def plot_posterior_pairs( self, parameters: list[object] | None = None, - style: PosteriorPairPlotStyleEnum | str = PosteriorPairPlotStyleEnum.AUTO, + style: PosteriorPairPlotStyleEnum | str = 'auto', ) -> None: """ Plot posterior pair relationships for sampled parameters. @@ -756,9 +796,10 @@ def plot_posterior_pairs( Optional subset of sampled parameters to include. When ``None``, all sampled parameters are shown. style : PosteriorPairPlotStyleEnum | str, default='auto' - ``'auto'`` keeps contours for compact plots and disables - them for wide grids. ``'fast'`` always skips contours. - ``'full'`` always renders contours. + Pair-plot rendering mode. Defaults to ``'auto'``. ``'auto'`` + keeps contours for compact plots and disables them for wide + grids. ``'fast'`` always skips contours. ``'full'`` always + renders contours. """ plot = self._build_posterior_pairs_plot(parameters=parameters, style=style) if plot is None: @@ -1073,7 +1114,7 @@ def _build_posterior_pairs_plot( self, *, parameters: list[object] | None, - style: PosteriorPairPlotStyleEnum | str = PosteriorPairPlotStyleEnum.AUTO, + style: PosteriorPairPlotStyleEnum | str = 'auto', ) -> object | None: """ Build a Plotly posterior pair plot. @@ -1083,7 +1124,7 @@ def _build_posterior_pairs_plot( parameters : list[object] | None Optional subset of sampled parameters to include. style : PosteriorPairPlotStyleEnum | str, default='auto' - Posterior pair-plot rendering mode. + Posterior pair-plot rendering mode. Defaults to ``'auto'``. Returns ------- @@ -1131,7 +1172,7 @@ def _posterior_pairs_context( self, parameters: list[object] | None, *, - style: PosteriorPairPlotStyleEnum | str = PosteriorPairPlotStyleEnum.AUTO, + style: PosteriorPairPlotStyleEnum | str = 'auto', ) -> _PosteriorPairsContext | None: """Return the resolved inputs for a posterior pair plot.""" posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() @@ -1306,7 +1347,7 @@ def _add_posterior_pair_diagonal( x=density_values, nbinsx=40, histnorm='probability density', - marker={'color': 'rgb(99, 110, 250)'}, + marker={'color': POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR}, showlegend=False, hovertemplate='%{x:.4f}
density=%{y:.4f}', ), @@ -1315,6 +1356,7 @@ def _add_posterior_pair_diagonal( ) return + self._style_posterior_pair_marginal_density_trace(density_trace) density_trace.name = 'Marginal density' density_trace.legendgroup = 'posterior-marginal-density' density_trace.showlegend = legend_state.show_density @@ -1539,21 +1581,39 @@ def _collect_posterior_pair_panel_decorations( ]) @staticmethod - def _posterior_pair_title_annotation() -> dict[str, object]: - """Return the outer title annotation for the pair plot.""" + def _square_matrix_title_annotation( + title: str, + annotation_labels: list[str], + ) -> dict[str, object]: + """Return a top-left title annotation for matrix plots.""" return { 'x': 0.0, 'xref': 'paper', 'xanchor': 'left', + 'xshift': -Plotter._square_matrix_title_left_shift(annotation_labels), 'y': 1.0, 'yref': 'paper', 'yanchor': 'bottom', 'yshift': POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS, - 'text': 'Posterior pair plot', + 'text': title, 'font': {'size': POSTERIOR_PAIR_TITLE_FONT_SIZE}, 'showarrow': False, } + @staticmethod + def _posterior_pair_title_annotation(annotation_labels: list[str]) -> dict[str, object]: + """Return the outer title annotation for the pair plot.""" + return Plotter._square_matrix_title_annotation( + 'Posterior pair plot', + annotation_labels, + ) + + @staticmethod + def _square_matrix_title_left_shift(annotation_labels: list[str]) -> int: + """Return the title shift that cancels left margin.""" + extra_margin = Plotter._posterior_pair_extra_axis_title_margin(annotation_labels) + return POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + extra_margin + @staticmethod def _posterior_pair_layout_meta() -> dict[str, object]: """Return layout metadata used by the Plotly HTML wrapper.""" @@ -1577,7 +1637,7 @@ def _finalize_posterior_pairs_figure( margin=self._posterior_pair_layout_margin(context.annotation_labels), bargap=0.05, annotations=[ - self._posterior_pair_title_annotation(), + self._posterior_pair_title_annotation(context.annotation_labels), *subplot_title_annotations, ], shapes=subplot_border_shapes, @@ -1613,8 +1673,7 @@ def _posterior_pair_extra_axis_title_margin(annotation_labels: list[str]) -> int return 0 max_line_count = max( - Plotter._posterior_pair_axis_title_line_count(label) - for label in annotation_labels + Plotter._posterior_pair_axis_title_line_count(label) for label in annotation_labels ) return max(0, max_line_count - 1) * POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS @@ -1701,10 +1760,7 @@ def _validated_posterior_pair_plot_style( return PosteriorPairPlotStyleEnum(style) except ValueError as exc: supported_styles = ', '.join(item.value for item in PosteriorPairPlotStyleEnum) - msg = ( - 'style must be one of ' - f'{supported_styles} for posterior pair plots.' - ) + msg = f'style must be one of {supported_styles} for posterior pair plots.' raise ValueError(msg) from exc @staticmethod @@ -1762,6 +1818,10 @@ def _posterior_contour_traces( return None x_grid, y_grid, density = density_surface + fill_colorscale, line_colorscale = self._posterior_pair_contour_colorscales( + x_values, + y_values, + ) contour_start = float(np.max(density) * 0.20) contour_end = float(np.max(density) * 0.95) contour_size = float(np.max(density) * 0.15) @@ -1779,7 +1839,7 @@ def _posterior_contour_traces( 'end': contour_end, 'size': contour_size, }, - colorscale=POSTERIOR_CONTOUR_FILL_COLORSCALE, + colorscale=fill_colorscale, zmin=contour_start, zmax=contour_end, connectgaps=False, @@ -1799,7 +1859,7 @@ def _posterior_contour_traces( 'end': contour_end, 'size': contour_size, }, - colorscale=POSTERIOR_CONTOUR_LINE_COLORSCALE, + colorscale=line_colorscale, zmin=contour_start, zmax=contour_end, line={'width': 0.9}, @@ -2070,6 +2130,45 @@ def _show_plot_figure(self, figure: object) -> None: return figure.show() + @staticmethod + def _style_posterior_pair_marginal_density_trace(density_trace: object) -> None: + """Apply pair-plot-specific styling to a marginal KDE trace.""" + density_trace.line = { + 'color': POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR, + 'width': POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH, + } + density_trace.fillcolor = POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR + + @staticmethod + def _posterior_pair_correlation_value( + x_values: np.ndarray, + y_values: np.ndarray, + ) -> float | None: + """Return the sample correlation for one contour panel.""" + finite_mask = np.isfinite(x_values) & np.isfinite(y_values) + if np.count_nonzero(finite_mask) < MIN_POSTERIOR_SAMPLE_COUNT: + return None + + correlation_matrix = np.corrcoef(x_values[finite_mask], y_values[finite_mask]) + correlation_value = float(correlation_matrix[0, 1]) + if not np.isfinite(correlation_value): + return None + return correlation_value + + @staticmethod + def _posterior_pair_contour_colorscales( + x_values: np.ndarray, + y_values: np.ndarray, + ) -> tuple[list[list[float | str]], list[list[float | str]]]: + """Return sign-aware contour palettes for one panel.""" + correlation_value = Plotter._posterior_pair_correlation_value(x_values, y_values) + if correlation_value is not None and correlation_value < 0: + return ( + POSTERIOR_NEGATIVE_CONTOUR_FILL_COLORSCALE, + POSTERIOR_NEGATIVE_CONTOUR_LINE_COLORSCALE, + ) + return POSTERIOR_CONTOUR_FILL_COLORSCALE, POSTERIOR_CONTOUR_LINE_COLORSCALE + def _posterior_density_trace( self, *, @@ -3320,7 +3419,7 @@ def _plot_correlation_heatmap( precision: int, ) -> None: """ - Delegate correlation heatmap rendering to the backend. + Render a Plotly correlation matrix with pair-plot styling. Parameters ---------- @@ -3333,12 +3432,277 @@ def _plot_correlation_heatmap( precision : int Number of decimals to show in plot labels and hover text. """ - self._backend.plot_correlation_heatmap( + figure = self._build_correlation_heatmap_plot( corr_df, title, threshold=threshold, precision=precision, ) + self._show_plot_figure(figure) + + def _build_correlation_heatmap_plot( + self, + corr_df: pd.DataFrame, + title: str, + *, + threshold: float | None, + precision: int, + ) -> object: + """Build a Plotly correlation matrix with pair-plot geometry.""" + make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots + + context = _CorrelationHeatmapContext( + corr_df=corr_df, + row_labels=self._posterior_pair_axis_title_labels(corr_df.index.tolist()), + col_labels=self._posterior_pair_axis_title_labels(corr_df.columns.tolist()), + threshold=threshold, + precision=precision, + ) + subplot_title_annotations: list[dict[str, object]] = [] + subplot_border_shapes: list[dict[str, object]] = [] + fig = make_subplots( + rows=context.n_rows, + cols=context.n_cols, + shared_xaxes='columns', + shared_yaxes='rows', + horizontal_spacing=PAIR_PLOT_SUBPLOT_SPACING, + vertical_spacing=PAIR_PLOT_SUBPLOT_SPACING, + ) + + for row_index in range(context.n_rows): + for col_index in range(context.n_cols): + self._populate_correlation_heatmap_panel( + fig=fig, + context=context, + row_index=row_index, + col_index=col_index, + subplot_title_annotations=subplot_title_annotations, + subplot_border_shapes=subplot_border_shapes, + ) + + fig.update_layout( + autosize=True, + margin=self._posterior_pair_layout_margin([ + *context.row_labels, + *context.col_labels, + ]), + annotations=[ + self._square_matrix_title_annotation( + title, + [*context.row_labels, *context.col_labels], + ), + *subplot_title_annotations, + ], + shapes=subplot_border_shapes, + meta=self._posterior_pair_layout_meta(), + showlegend=False, + paper_bgcolor='white', + plot_bgcolor='white', + ) + return fig + + def _populate_correlation_heatmap_panel( + self, + *, + fig: object, + context: _CorrelationHeatmapContext, + row_index: int, + col_index: int, + subplot_title_annotations: list[dict[str, object]], + subplot_border_shapes: list[dict[str, object]], + ) -> None: + """Populate one panel in the correlation-matrix grid.""" + row = row_index + 1 + col = col_index + 1 + if col_index > row_index: + self._hide_posterior_pair_panel(fig=fig, row=row, col=col) + return + + value = context.corr_df.iat[row_index, col_index] + if not pd.isna(value): + self._add_correlation_heatmap_value_panel( + fig=fig, + context=context, + row_index=row_index, + col_index=col_index, + value=float(value), + ) + + self._configure_correlation_heatmap_panel_axes(fig=fig, row=row, col=col) + self._collect_correlation_heatmap_panel_decorations( + fig=fig, + context=context, + row_index=row_index, + col_index=col_index, + subplot_title_annotations=subplot_title_annotations, + subplot_border_shapes=subplot_border_shapes, + ) + + def _add_correlation_heatmap_value_panel( + self, + *, + fig: object, + context: _CorrelationHeatmapContext, + row_index: int, + col_index: int, + value: float, + ) -> None: + """Add one colored cell and optional text label.""" + go = __import__('plotly.graph_objects', fromlist=['Heatmap']) + row = row_index + 1 + col = col_index + 1 + hovertemplate = ( + f'x: {context.corr_df.columns[col_index]}
' + f'y: {context.corr_df.index[row_index]}
' + f'corr: %{{z:.{context.precision}f}}' + ) + fig.add_trace( + go.Heatmap( + z=[[value]], + x=[0.0, 1.0], + y=[0.0, 1.0], + zmin=-1.0, + zmax=1.0, + zmid=0.0, + colorscale=self._plot_correlation_colorscale(), + showscale=False, + hoverongaps=False, + hovertemplate=hovertemplate, + ), + row=row, + col=col, + ) + + if ( + context.threshold is not None + and context.threshold > 0 + and abs(value) < context.threshold + ): + return + + fig.add_trace( + go.Scatter( + x=[0.5], + y=[0.5], + mode='text', + text=[f'{value:.{context.precision}f}'], + textposition='middle center', + textfont={'color': PlotlyPlotter._correlation_label_color()}, + hoverinfo='skip', + showlegend=False, + ), + row=row, + col=col, + ) + + @staticmethod + def _configure_correlation_heatmap_panel_axes( + *, + fig: object, + row: int, + col: int, + ) -> None: + """Hide ticks and titles for one correlation-matrix panel.""" + fig.update_xaxes( + range=[0.0, 1.0], + showline=False, + mirror=False, + zeroline=False, + showgrid=False, + ticks='', + ticklen=0, + tickwidth=0, + showticklabels=False, + title_text=None, + layer='above traces', + row=row, + col=col, + ) + fig.update_yaxes( + range=[1.0, 0.0], + showline=False, + mirror=False, + zeroline=False, + showgrid=False, + ticks='', + ticklen=0, + tickwidth=0, + showticklabels=False, + title_text=None, + layer='above traces', + row=row, + col=col, + ) + + def _collect_correlation_heatmap_panel_decorations( + self, + *, + fig: object, + context: _CorrelationHeatmapContext, + row_index: int, + col_index: int, + subplot_title_annotations: list[dict[str, object]], + subplot_border_shapes: list[dict[str, object]], + ) -> None: + """Collect labels and frames for one correlation cell.""" + row = row_index + 1 + col = col_index + 1 + subplot = fig.get_subplot(row, col) + x_mid = 0.5 * (subplot.xaxis.domain[0] + subplot.xaxis.domain[1]) + y_mid = 0.5 * (subplot.yaxis.domain[0] + subplot.yaxis.domain[1]) + + if col_index == 0: + subplot_title_annotations.append({ + 'x': subplot.xaxis.domain[0], + 'xref': 'paper', + 'xanchor': 'right', + 'xshift': -POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS, + 'y': y_mid, + 'yref': 'paper', + 'yanchor': 'middle', + 'text': context.row_labels[row_index], + 'align': 'center', + 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + 'textangle': -90, + 'showarrow': False, + }) + if row_index == context.n_rows - 1: + subplot_title_annotations.append({ + 'x': x_mid, + 'xref': 'paper', + 'xanchor': 'center', + 'y': subplot.yaxis.domain[0], + 'yref': 'paper', + 'yanchor': 'top', + 'yshift': -POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS, + 'text': context.col_labels[col_index], + 'align': 'center', + 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + 'showarrow': False, + }) + + subplot_border_shapes.append({ + 'type': 'rect', + 'xref': 'paper', + 'yref': 'paper', + 'x0': subplot.xaxis.domain[0], + 'x1': subplot.xaxis.domain[1], + 'y0': subplot.yaxis.domain[0], + 'y1': subplot.yaxis.domain[1], + 'line': { + 'color': self._plot_axis_frame_color(), + 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, + }, + 'fillcolor': 'rgba(0, 0, 0, 0)', + 'layer': 'above', + }) + + def _plot_correlation_colorscale(self) -> list[tuple[float, str]]: + """Return the active correlation colorscale.""" + correlation_colorscale = getattr(self._backend, '_correlation_colorscale', None) + if callable(correlation_colorscale): + return correlation_colorscale() + return PlotlyPlotter._correlation_colorscale() @staticmethod def _format_correlation_table_dataframe( diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 1eb130b4..5afe289f 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -327,6 +327,9 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): 'broad_gauss_v', 'twotheta_offset', ] + assert figure.layout.annotations[0].xshift == -plotter._square_matrix_title_left_shift( + ['length_a', 'broad_gauss_u', 'broad_gauss_v', 'twotheta_offset'] + ) subplot = figure.get_subplot(1, 1) bottom_subplot = figure.get_subplot(4, 1) assert subplot.yaxis.showticklabels is False @@ -347,6 +350,44 @@ def test_build_posterior_pairs_plot_fast_mode_skips_contours(): assert all(trace.name != 'Posterior contours' for trace in figure.data) +def test_build_posterior_pairs_plot_sign_colors_contours_and_marginals(): + from easydiffraction.display.plotting import POSTERIOR_CONTOUR_FILL_COLORSCALE + from easydiffraction.display.plotting import POSTERIOR_CONTOUR_LINE_COLORSCALE + from easydiffraction.display.plotting import POSTERIOR_NEGATIVE_CONTOUR_FILL_COLORSCALE + from easydiffraction.display.plotting import POSTERIOR_NEGATIVE_CONTOUR_LINE_COLORSCALE + from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR + from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR + from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH + + plotter, _, _ = _make_bayesian_plotter_fixture() + + figure = plotter._build_posterior_pairs_plot(parameters=None) + + marginal_traces = [trace for trace in figure.data if trace.name == 'Marginal density'] + assert marginal_traces + assert all(trace.line.color == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR for trace in marginal_traces) + assert all(trace.line.width == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH for trace in marginal_traces) + assert all(trace.fillcolor == POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR for trace in marginal_traces) + + fill_contours = [ + trace + for trace in figure.data + if trace.type == 'contour' and trace.contours.coloring == 'fill' + ] + line_contours = [ + trace + for trace in figure.data + if trace.type == 'contour' and trace.contours.coloring == 'lines' + ] + fill_end_colors = {trace.colorscale[-1][1] for trace in fill_contours} + line_end_colors = {trace.colorscale[-1][1] for trace in line_contours} + + assert POSTERIOR_CONTOUR_FILL_COLORSCALE[-1][1] in fill_end_colors + assert POSTERIOR_NEGATIVE_CONTOUR_FILL_COLORSCALE[-1][1] in fill_end_colors + assert POSTERIOR_CONTOUR_LINE_COLORSCALE[-1][1] in line_end_colors + assert POSTERIOR_NEGATIVE_CONTOUR_LINE_COLORSCALE[-1][1] in line_end_colors + + def test_build_posterior_pairs_plot_formats_dotted_axis_titles_multiline(): from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_LEFT_MARGIN_PIXELS @@ -385,8 +426,12 @@ def test_posterior_pair_figure_height_shrinks_cells_for_many_parameters(): def test_posterior_pair_density_budget_scales_with_parameter_count(): from easydiffraction.display.plotting import Plotter - assert Plotter._posterior_pair_density_max_points(8) < Plotter._posterior_pair_density_max_points(4) - assert Plotter._posterior_pair_contour_grid_size(8) < Plotter._posterior_pair_contour_grid_size(4) + assert Plotter._posterior_pair_density_max_points( + 8 + ) < Plotter._posterior_pair_density_max_points(4) + assert Plotter._posterior_pair_contour_grid_size( + 8 + ) < Plotter._posterior_pair_contour_grid_size(4) def test_posterior_pairs_context_thins_kde_samples_and_preserves_axis_ranges(): @@ -1004,7 +1049,7 @@ class Project: p = Plotter() p.engine = 'asciichartpy' p._set_project(Project()) - p.plot_param_correlations(threshold=0.1, precision=3) + p.plot_param_correlations(threshold=0.1, precision=3, show_diagonal=False) df = captured['df'] assert [column.strip() for column in df.columns.get_level_values(0)] == [ @@ -1057,7 +1102,7 @@ class Project: p = Plotter() p.engine = 'plotly' p._set_project(Project()) - p.plot_param_correlations(threshold=0.1) + p.plot_param_correlations() fig = captured['fig'] assert len(fig.data) == 2 @@ -1066,10 +1111,11 @@ class Project: assert list(fig.data[0].y) == [0.0, 1.0] assert fig.data[0].xgap in (None, 0) assert fig.data[0].ygap in (None, 0) - assert fig.data[0].colorbar.lenmode == 'fraction' - assert fig.data[0].colorbar.len == 1.0 - assert fig.data[0].colorbar.title.text == '' - assert fig.data[0].hovertemplate == 'x: %{x}
y: %{y}
corr: %{z:.2f}' + assert fig.data[0].showscale is False + assert ( + fig.data[0].hovertemplate + == 'x: phase.scale
y: phase.cell.length_c
corr: %{z:.2f}' + ) assert pytest.approx(fig.data[0].z[0][0], rel=1e-9) == -0.5 assert fig.data[1].type == 'scatter' assert fig.data[1].mode == 'text' @@ -1078,23 +1124,32 @@ class Project: assert list(fig.data[1].text) == ['-0.50'] assert fig.data[1].textposition == 'middle center' assert fig.data[1].hoverinfo == 'skip' - assert fig.layout.xaxis.side == 'bottom' - assert fig.layout.xaxis.tickangle < 0 - assert list(fig.layout.xaxis.tickvals) == [0.5] - assert list(fig.layout.xaxis.ticktext) == ['phase.scale'] + assert [annotation.text for annotation in fig.layout.annotations] == [ + 'Refined parameter correlation matrix', + 'phase.
scale', + 'phase.
cell.
length_c', + 'phase.
scale', + 'phase.
cell.
length_c', + ] + assert fig.layout.annotations[0].xshift == -Plotter._square_matrix_title_left_shift( + ['phase.
scale', 'phase.
cell.
length_c'] + ) + assert fig.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] == '1 / 1' + assert fig.layout.xaxis.domain[1] < fig.layout.xaxis2.domain[0] assert fig.layout.xaxis.showline is False assert fig.layout.xaxis.mirror is False assert fig.layout.xaxis.layer == 'above traces' - assert list(fig.layout.yaxis.tickvals) == [0.5] - assert list(fig.layout.yaxis.ticktext) == ['phase.cell.length_c'] + assert fig.layout.xaxis.showticklabels is False + assert fig.layout.xaxis.title.text is None assert fig.layout.yaxis.showline is False assert fig.layout.yaxis.mirror is False assert fig.layout.yaxis.layer == 'above traces' - assert fig.layout.yaxis.ticklabelstandoff == 8 - assert len(fig.layout.shapes) == 1 - assert fig.layout.shapes[-1].type == 'rect' - assert fig.layout.shapes[-1].xref == 'paper' - assert fig.layout.shapes[-1].yref == 'paper' + assert fig.layout.yaxis.showticklabels is False + assert fig.layout.yaxis.title.text is None + assert len(fig.layout.shapes) == 3 + assert all(shape.type == 'rect' for shape in fig.layout.shapes) + assert all(shape.xref == 'paper' for shape in fig.layout.shapes) + assert all(shape.yref == 'paper' for shape in fig.layout.shapes) def test_plot_param_correlations_plotly_labels_respect_threshold(monkeypatch): @@ -1148,17 +1203,20 @@ class Project: p = Plotter() p.engine = 'plotly' p._set_project(Project()) - p.plot_param_correlations() + p.plot_param_correlations(threshold=0.7) fig = captured['fig'] - assert len(fig.data) == 2 - assert fig.data[0].type == 'heatmap' - assert fig.data[1].type == 'scatter' - assert fig.data[1].mode == 'text' - assert list(fig.data[1].text) == ['-0.91', '0.83', '-0.89', '0.82'] + heatmap_traces = [trace for trace in fig.data if trace.type == 'heatmap'] + text_traces = [ + trace + for trace in fig.data + if trace.type == 'scatter' and trace.mode == 'text' + ] + assert len(heatmap_traces) == 10 + assert [trace.text[0] for trace in text_traces] == ['-0.91', '0.83', '-0.89', '0.82'] -def test_plot_param_correlations_filters_by_default_threshold(monkeypatch): +def test_plot_param_correlations_shows_full_table_by_default(monkeypatch): from easydiffraction.display.plotting import Plotter from easydiffraction.display.tables import TableRenderer @@ -1212,12 +1270,22 @@ class Project: assert [column.strip() for column in df.columns.get_level_values(0)] == [ 'parameter', '1', + '2', + '3', ] - assert list(df.index) == [0, 1] + assert list(df.index) == [0, 1, 2] assert df.iloc[0, 0] == 'phase.scale' assert df.iloc[0, 1] == '' + assert df.iloc[0, 2] == '' + assert df.iloc[0, 3] == '' assert df.iloc[1, 0] == 'phase.cell.length_a' assert _strip_markup(df.iloc[1, 1]).strip() == '0.82' + assert df.iloc[1, 2] == '' + assert df.iloc[1, 3] == '' + assert df.iloc[2, 0] == 'phase.background' + assert _strip_markup(df.iloc[2, 1]).strip() == '0.25' + assert _strip_markup(df.iloc[2, 2]).strip() == '0.00' + assert df.iloc[2, 3] == '' def test_plot_param_correlations_hides_subthreshold_table_values(monkeypatch): @@ -1272,7 +1340,7 @@ class Project: p = Plotter() p.engine = 'asciichartpy' p._set_project(Project()) - p.plot_param_correlations() + p.plot_param_correlations(threshold=0.7, show_diagonal=False) df = captured['df'] assert [column.strip() for column in df.columns.get_level_values(0)] == [ From e97f04980f133d381f1c4db463e528c4277e3a04 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 22:35:33 +0200 Subject: [PATCH 060/106] Simplify tutorial parameter loops and bounds --- docs/docs/tutorials/ed-21.py | 42 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 543c3085..72eb8967 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -161,11 +161,11 @@ experiment.background.create(id='2', x=30, y=164.3357) experiment.background.create(id='3', x=50, y=166.8881) experiment.background.create(id='4', x=110, y=175.4006) -experiment.background.create(id='5', x=165, y=174.2813) +#experiment.background.create(id='5', x=165, y=174.2813) # %% -experiment.excluded_regions.create(id='1', start=0, end=30) -experiment.excluded_regions.create(id='2', start=70, end=180) +experiment.excluded_regions.create(id='1', start=0, end=10) +experiment.excluded_regions.create(id='2', start=100, end=180) # %% [markdown] # #### Link the Structural Phase to the Experiment @@ -189,6 +189,8 @@ # %% structure.cell.length_a.free = True + +experiment.linked_phases['lbco'].scale.free = True experiment.peak.broad_gauss_u.free = True experiment.peak.broad_gauss_v.free = True experiment.instrument.calib_twotheta_offset.free = True @@ -200,6 +202,8 @@ # %% project.analysis.fit.show_minimizer_types() + +# %% project.analysis.fit.minimizer_type = 'bumps (lm)' # %% @@ -233,15 +237,16 @@ # The helper method `set_fit_bounds_from_uncertainty` centers the bounds # on the current parameter value and expands them by a chosen multiple of # the reported uncertainty. +# +# Default multiplier is 8 to give a wide range for the sampler to +# explore, but here we use 3 to speed up the tutorial. # %% project.analysis.display.free_params() # %% -structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=4) -experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=4) -experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=4) -experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=4) +for param in project.free_parameters: + param.set_fit_bounds_from_uncertainty(multiplier=3) # %% [markdown] # Displaying the free parameters again is a convenient way to confirm @@ -258,9 +263,11 @@ # # The settings below are intentionally small so the tutorial runs # quickly. For production analysis you would usually increase the number -# of steps and often the burn-in as well. When needed, the DREAM API -# also lets you tune how chains are initialized through the `init` -# setting. +# of steps (`steps`) and often the burn-in (`burn`) as well. When +# needed, the DREAM API also lets you tune how chains are initialized +# through the `init` setting. Other sampler settings such as `thin` and +# `pop` can be adjusted as well, but here we keep them at their +# defaults. # %% project.analysis.fit.show_minimizer_types() @@ -269,10 +276,7 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' # %% -project.analysis.fit.minimizer.steps = 2000 # 1000 -project.analysis.fit.minimizer.burn = 400 # 200 -project.analysis.fit.minimizer.thin = 1 -project.analysis.fit.minimizer.pop = 4 +project.analysis.fit.minimizer.steps = 100 # 1000 # %% project.analysis.fit() @@ -296,7 +300,7 @@ # posterior contours off-diagonal. # %% -project.display.plotter.plot_param_correlations(show_diagonal=True) +project.display.plotter.plot_param_correlations(threshold=0, show_diagonal=True) # %% project.display.plotter.plot_posterior_pairs() @@ -307,10 +311,8 @@ # multimodality. # %% -project.display.plotter.plot_param_distribution(structure.cell.length_a) -project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_u) -project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_v) -project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) +for param in project.free_parameters: + project.display.plotter.plot_param_distribution(param) # %% [markdown] # Finally, the posterior predictive plot propagates the sampled parameter @@ -327,4 +329,4 @@ # after the Bayesian run. # %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) +project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=65, x_max=68) From ffbc0331aecff58ffd3d52e563e3ec97fb1db403 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 22:48:13 +0200 Subject: [PATCH 061/106] Improve hover template readability --- docs/docs/tutorials/ed-21.py | 6 +- .../display/plotters/plotly.py | 2 +- src/easydiffraction/display/plotting.py | 37 ++++++++--- .../easydiffraction/display/test_plotting.py | 65 ++++++++++++++----- 4 files changed, 82 insertions(+), 28 deletions(-) diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 72eb8967..364abeaf 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -161,7 +161,6 @@ experiment.background.create(id='2', x=30, y=164.3357) experiment.background.create(id='3', x=50, y=166.8881) experiment.background.create(id='4', x=110, y=175.4006) -#experiment.background.create(id='5', x=165, y=174.2813) # %% experiment.excluded_regions.create(id='1', start=0, end=10) @@ -190,6 +189,7 @@ # %% structure.cell.length_a.free = True +# %% experiment.linked_phases['lbco'].scale.free = True experiment.peak.broad_gauss_u.free = True experiment.peak.broad_gauss_v.free = True @@ -219,7 +219,7 @@ # region. # %% -project.display.plotter.plot_param_correlations(show_diagonal=True) +project.display.plotter.plot_param_correlations() # %% project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') @@ -300,7 +300,7 @@ # posterior contours off-diagonal. # %% -project.display.plotter.plot_param_correlations(threshold=0, show_diagonal=True) +project.display.plotter.plot_param_correlations() # %% project.display.plotter.plot_posterior_pairs() diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 9186b166..764c5a0f 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -220,7 +220,7 @@ def plot_correlation_heatmap( 'yanchor': 'middle', }, hoverongaps=False, - hovertemplate=f'x: %{{x}}
y: %{{y}}
corr: %{{z:.{precision}f}}', + hovertemplate=f'%{{x}}
%{{y}}
correlation: %{{z:.{precision}f}}', ) label_trace = self._get_correlation_label_trace( corr_df, diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 4f35e498..6242b404 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1349,7 +1349,9 @@ def _add_posterior_pair_diagonal( histnorm='probability density', marker={'color': POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR}, showlegend=False, - hovertemplate='%{x:.4f}
density=%{y:.4f}', + hovertemplate=self._posterior_pair_density_hovertemplate( + context.parameter_names[parameter_index] + ), ), row=row, col=col, @@ -1357,6 +1359,9 @@ def _add_posterior_pair_diagonal( return self._style_posterior_pair_marginal_density_trace(density_trace) + density_trace.hovertemplate = self._posterior_pair_density_hovertemplate( + context.parameter_names[parameter_index] + ) density_trace.name = 'Marginal density' density_trace.legendgroup = 'posterior-marginal-density' density_trace.showlegend = legend_state.show_density @@ -1393,9 +1398,9 @@ def _add_posterior_pair_off_diagonal( y_values=y_density_values, grid_size=context.contour_grid_size, ) - sample_hovertemplate = ( - f'{context.labels[col_index]}: %{{x:.4f}}
' - f'{context.labels[row_index]}: %{{y:.4f}}' + sample_hovertemplate = self._posterior_pair_scatter_hovertemplate( + x_parameter_name=context.parameter_names[col_index], + y_parameter_name=context.parameter_names[row_index], ) fig.add_trace( go.Scatter( @@ -2042,7 +2047,7 @@ def _add_posterior_distribution_histogram( }, opacity=0.82, name='Posterior histogram', - hovertemplate='sample=%{x:.4f}
density=%{y:.4f}', + hovertemplate='sample=%{x:.4f}
density: %{y:.2f}', ) ) @@ -2139,6 +2144,20 @@ def _style_posterior_pair_marginal_density_trace(density_trace: object) -> None: } density_trace.fillcolor = POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR + @staticmethod + def _posterior_pair_density_hovertemplate(parameter_name: str) -> str: + """Return the hover template for a marginal density trace.""" + return f'{parameter_name}: %{{x:.4f}}
density: %{{y:.4f}}' + + @staticmethod + def _posterior_pair_scatter_hovertemplate( + *, + x_parameter_name: str, + y_parameter_name: str, + ) -> str: + """Return the hover template for pair-plot sample points.""" + return f'{x_parameter_name}: %{{x:.4f}}
{y_parameter_name}: %{{y:.4f}}' + @staticmethod def _posterior_pair_correlation_value( x_values: np.ndarray, @@ -2202,7 +2221,7 @@ def _posterior_density_trace( fillcolor=POSTERIOR_DENSITY_FILL_COLOR, name=trace_name, showlegend=False, - hovertemplate='%{x:.4f}
density=%{y:.4f}', + hovertemplate='%{x:.4f}
density: %{y:.2f}', ) @staticmethod @@ -3552,9 +3571,9 @@ def _add_correlation_heatmap_value_panel( row = row_index + 1 col = col_index + 1 hovertemplate = ( - f'x: {context.corr_df.columns[col_index]}
' - f'y: {context.corr_df.index[row_index]}
' - f'corr: %{{z:.{context.precision}f}}' + f'{context.corr_df.columns[col_index]}
' + f'{context.corr_df.index[row_index]}
' + f'correlation: %{{z:.{context.precision}f}}' ) fig.add_trace( go.Heatmap( diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 5afe289f..bdadc9e8 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -327,9 +327,12 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): 'broad_gauss_v', 'twotheta_offset', ] - assert figure.layout.annotations[0].xshift == -plotter._square_matrix_title_left_shift( - ['length_a', 'broad_gauss_u', 'broad_gauss_v', 'twotheta_offset'] - ) + assert figure.layout.annotations[0].xshift == -plotter._square_matrix_title_left_shift([ + 'length_a', + 'broad_gauss_u', + 'broad_gauss_v', + 'twotheta_offset', + ]) subplot = figure.get_subplot(1, 1) bottom_subplot = figure.get_subplot(4, 1) assert subplot.yaxis.showticklabels is False @@ -365,9 +368,15 @@ def test_build_posterior_pairs_plot_sign_colors_contours_and_marginals(): marginal_traces = [trace for trace in figure.data if trace.name == 'Marginal density'] assert marginal_traces - assert all(trace.line.color == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR for trace in marginal_traces) - assert all(trace.line.width == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH for trace in marginal_traces) - assert all(trace.fillcolor == POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR for trace in marginal_traces) + assert all( + trace.line.color == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR for trace in marginal_traces + ) + assert all( + trace.line.width == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH for trace in marginal_traces + ) + assert all( + trace.fillcolor == POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR for trace in marginal_traces + ) fill_contours = [ trace @@ -414,6 +423,35 @@ def test_build_posterior_pairs_plot_formats_dotted_axis_titles_multiline(): assert figure.layout.margin.b > POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS +def test_build_posterior_pairs_plot_uses_full_names_in_hovertemplates(): + plotter, fit_results, _ = _make_bayesian_plotter_fixture() + dotted_parameter_names = [ + 'lbco.cell.length_a', + 'hrpt.peak.broad_gauss_u', + 'hrpt.peak.broad_gauss_v', + 'hrpt.instrument.twotheta_offset', + ] + fit_results.posterior_samples.parameter_names = dotted_parameter_names + for index, unique_name in enumerate(dotted_parameter_names): + fit_results.parameters[index].unique_name = unique_name + fit_results.posterior_parameter_summaries[index].unique_name = unique_name + + figure = plotter._build_posterior_pairs_plot(parameters=None) + + hovertemplates = { + trace.hovertemplate + for trace in figure.data + if getattr(trace, 'hovertemplate', None) is not None + } + + assert ( + 'lbco.cell.length_a: %{x:.4f}
hrpt.peak.broad_gauss_u: %{y:.4f}' + ) in hovertemplates + assert ( + 'hrpt.instrument.twotheta_offset: %{x:.4f}
density: %{y:.4f}' + ) in hovertemplates + + def test_posterior_pair_figure_height_shrinks_cells_for_many_parameters(): from easydiffraction.display.plotting import PAIR_PLOT_CELL_SIZE_PIXELS from easydiffraction.display.plotting import Plotter @@ -1114,7 +1152,7 @@ class Project: assert fig.data[0].showscale is False assert ( fig.data[0].hovertemplate - == 'x: phase.scale
y: phase.cell.length_c
corr: %{z:.2f}' + == 'phase.scale
phase.cell.length_c
correlation: %{z:.2f}' ) assert pytest.approx(fig.data[0].z[0][0], rel=1e-9) == -0.5 assert fig.data[1].type == 'scatter' @@ -1131,9 +1169,10 @@ class Project: 'phase.
scale', 'phase.
cell.
length_c', ] - assert fig.layout.annotations[0].xshift == -Plotter._square_matrix_title_left_shift( - ['phase.
scale', 'phase.
cell.
length_c'] - ) + assert fig.layout.annotations[0].xshift == -Plotter._square_matrix_title_left_shift([ + 'phase.
scale', + 'phase.
cell.
length_c', + ]) assert fig.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] == '1 / 1' assert fig.layout.xaxis.domain[1] < fig.layout.xaxis2.domain[0] assert fig.layout.xaxis.showline is False @@ -1207,11 +1246,7 @@ class Project: fig = captured['fig'] heatmap_traces = [trace for trace in fig.data if trace.type == 'heatmap'] - text_traces = [ - trace - for trace in fig.data - if trace.type == 'scatter' and trace.mode == 'text' - ] + text_traces = [trace for trace in fig.data if trace.type == 'scatter' and trace.mode == 'text'] assert len(heatmap_traces) == 10 assert [trace.text[0] for trace in text_traces] == ['-0.91', '0.83', '-0.89', '0.82'] From 78261ca928f87ae772b981844fc5c69bdefde509 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 23:04:46 +0200 Subject: [PATCH 062/106] Improve posterior plot binning and styling --- docs/dev/package-structure-full.md | 2 + src/easydiffraction/display/plotting.py | 107 +++++++++++++++++- .../easydiffraction/display/test_plotting.py | 15 ++- 3 files changed, 118 insertions(+), 6 deletions(-) diff --git a/docs/dev/package-structure-full.md b/docs/dev/package-structure-full.md index d1901351..8083f39b 100644 --- a/docs/dev/package-structure-full.md +++ b/docs/dev/package-structure-full.md @@ -376,10 +376,12 @@ β”‚ β”‚ └── 🏷️ class RendererFactoryBase β”‚ β”œβ”€β”€ πŸ“„ plotting.py β”‚ β”‚ β”œβ”€β”€ 🏷️ class PlotterEngineEnum +β”‚ β”‚ β”œβ”€β”€ 🏷️ class PosteriorPairPlotStyleEnum β”‚ β”‚ β”œβ”€β”€ 🏷️ class _MeasVsCalcPlotOptions β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PowderMeasVsCalcSeries β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PosteriorDistributionContext β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PosteriorPairsContext +β”‚ β”‚ β”œβ”€β”€ 🏷️ class _CorrelationHeatmapContext β”‚ β”‚ β”œβ”€β”€ 🏷️ class _PosteriorPairsLegendState β”‚ β”‚ β”œβ”€β”€ 🏷️ class Plotter β”‚ β”‚ └── 🏷️ class PlotterFactory diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 6242b404..59262e3a 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1903,15 +1903,27 @@ def _build_param_distribution_plot( title=context.title, label=context.label, ) + histogram_bin_edges = self._posterior_distribution_histogram_bin_edges(context.values) density_trace = self._posterior_density_trace( fit_results=context.fit_results, parameter_name=context.parameter_name, values=context.values, - trace_name='Posterior density', + trace_name='Marginal density', + ) + if density_trace is not None: + self._style_posterior_pair_marginal_density_trace(density_trace) + density_trace.hovertemplate = self._posterior_pair_density_hovertemplate( + context.parameter_name + ) + x_axis_range = self._posterior_distribution_x_axis_range( + values=context.values, + density_trace=density_trace, + histogram_bin_edges=histogram_bin_edges, ) y_axis_range = self._posterior_distribution_y_axis_range( values=context.values, density_trace=density_trace, + histogram_bin_edges=histogram_bin_edges, ) self._add_posterior_distribution_interval_traces( @@ -1923,6 +1935,7 @@ def _build_param_distribution_plot( fig=fig, go=go, values=context.values, + histogram_bin_edges=histogram_bin_edges, ) self._add_posterior_distribution_density_trace(fig=fig, density_trace=density_trace) self._add_posterior_distribution_reference_traces( @@ -1936,6 +1949,7 @@ def _build_param_distribution_plot( layout_factory=layout_factory, title=context.title, label=context.label, + x_axis_range=x_axis_range, y_axis_range=y_axis_range, ) return fig @@ -1990,14 +2004,82 @@ def _posterior_distribution_y_axis_range( *, values: np.ndarray, density_trace: object | None, + histogram_bin_edges: np.ndarray | None, ) -> tuple[float, float] | None: """Return the y-axis range for a posterior distribution plot.""" - histogram_density, _ = np.histogram(values, bins=50, density=True) - density_sources = [histogram_density] + density_sources = [] + histogram_density = self._posterior_distribution_histogram_density( + values, + histogram_bin_edges, + ) + if histogram_density is not None: + density_sources.append(histogram_density) if density_trace is not None: density_sources.append(np.asarray(density_trace.y, dtype=float)) + if not density_sources: + return None return self._posterior_density_axis_range(np.concatenate(density_sources)) + def _posterior_distribution_x_axis_range( + self, + *, + values: np.ndarray, + density_trace: object | None, + histogram_bin_edges: np.ndarray | None, + ) -> tuple[float, float] | None: + """Return the x-axis range for a posterior distribution plot.""" + if density_trace is not None: + return self._posterior_axis_bounds( + np.asarray(density_trace.x, dtype=float), + lower_bound=None, + upper_bound=None, + ) + + if histogram_bin_edges is not None: + return ( + float(histogram_bin_edges[0]), + float(histogram_bin_edges[-1]), + ) + + finite_values = np.asarray(values, dtype=float) + finite_values = finite_values[np.isfinite(finite_values)] + if finite_values.size == 0: + return None + return self._posterior_axis_bounds( + finite_values, + lower_bound=None, + upper_bound=None, + ) + + @staticmethod + def _posterior_distribution_histogram_bin_edges(values: np.ndarray) -> np.ndarray | None: + """Return histogram bin edges used by the distribution plot.""" + finite_values = np.asarray(values, dtype=float) + finite_values = finite_values[np.isfinite(finite_values)] + if finite_values.size == 0: + return None + + bin_edges = np.histogram_bin_edges(finite_values, bins='auto') + if bin_edges.size >= MIN_POSTERIOR_SAMPLE_COUNT: + return np.asarray(bin_edges, dtype=float) + return None + + @staticmethod + def _posterior_distribution_histogram_density( + values: np.ndarray, + histogram_bin_edges: np.ndarray | None, + ) -> np.ndarray | None: + """Return densities matching the rendered histogram bins.""" + if histogram_bin_edges is None: + return None + + histogram_density, _ = np.histogram( + np.asarray(values, dtype=float), + bins=histogram_bin_edges, + density=True, + ) + return np.asarray(histogram_density, dtype=float) + def _add_posterior_distribution_interval_traces( self, *, @@ -2034,12 +2116,23 @@ def _add_posterior_distribution_histogram( fig: object, go: object, values: np.ndarray, + histogram_bin_edges: np.ndarray | None, ) -> None: """Add the histogram trace for a posterior distribution plot.""" + histogram_kwargs: dict[str, object] = {} + if ( + histogram_bin_edges is not None + and histogram_bin_edges.size >= MIN_POSTERIOR_SAMPLE_COUNT + ): + histogram_kwargs['xbins'] = { + 'start': float(histogram_bin_edges[0]), + 'end': float(histogram_bin_edges[-1]), + 'size': float(histogram_bin_edges[1] - histogram_bin_edges[0]), + } + fig.add_trace( go.Histogram( x=values, - nbinsx=50, histnorm='probability density', marker={ 'color': POSTERIOR_HISTOGRAM_FILL_COLOR, @@ -2048,6 +2141,7 @@ def _add_posterior_distribution_histogram( opacity=0.82, name='Posterior histogram', hovertemplate='sample=%{x:.4f}
density: %{y:.2f}', + **histogram_kwargs, ) ) @@ -2061,7 +2155,7 @@ def _add_posterior_distribution_density_trace( if density_trace is None: return - density_trace.name = 'Posterior density' + density_trace.name = 'Marginal density' density_trace.showlegend = True fig.add_trace(density_trace) @@ -2106,6 +2200,7 @@ def _apply_posterior_distribution_layout( layout_factory: object | None, title: str, label: str, + x_axis_range: tuple[float, float] | None, y_axis_range: tuple[float, float] | None, ) -> None: """Apply layout settings to the distribution plot.""" @@ -2124,6 +2219,8 @@ def _apply_posterior_distribution_layout( 'y': 1.0, }, ) + if x_axis_range is not None: + fig.update_xaxes(range=list(x_axis_range)) if y_axis_range is not None: fig.update_yaxes(range=list(y_axis_range)) diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index bdadc9e8..047a05b6 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -532,6 +532,10 @@ def test_build_posterior_pairs_plot_rejects_unknown_style(): def test_build_param_distribution_plot_returns_plotly_figure(): + from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR + from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR + from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH + plotter, fit_results, _ = _make_bayesian_plotter_fixture() parameter = fit_results.parameters[0] @@ -540,12 +544,21 @@ def test_build_param_distribution_plot_returns_plotly_figure(): assert figure.layout.title.text == 'Posterior distribution: length_a' assert {trace.name for trace in figure.data} >= { 'Posterior histogram', - 'Posterior density', + 'Marginal density', '68% credible interval', '95% credible interval', 'Median', 'Max posterior', } + marginal_trace = next(trace for trace in figure.data if trace.name == 'Marginal density') + histogram_trace = next(trace for trace in figure.data if trace.name == 'Posterior histogram') + assert marginal_trace.line.color == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR + assert marginal_trace.line.width == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH + assert marginal_trace.fillcolor == POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR + assert marginal_trace.hovertemplate == 'length_a: %{x:.4f}
density: %{y:.4f}' + assert histogram_trace.xbins.size is not None + assert figure.layout.xaxis.range is not None + assert figure.layout.yaxis.range is not None def test_build_param_distribution_plot_accepts_unique_name_string(): From 0f79235948cc81d0b5738e56bdea9dc5f0990b41 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 23:06:34 +0200 Subject: [PATCH 063/106] Refactor posterior x-axis range to static method --- src/easydiffraction/display/plotting.py | 15 ++++----------- .../unit/easydiffraction/display/test_plotting.py | 1 + 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 59262e3a..0b3a2cb6 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -2020,8 +2020,8 @@ def _posterior_distribution_y_axis_range( return None return self._posterior_density_axis_range(np.concatenate(density_sources)) + @staticmethod def _posterior_distribution_x_axis_range( - self, *, values: np.ndarray, density_trace: object | None, @@ -2029,11 +2029,8 @@ def _posterior_distribution_x_axis_range( ) -> tuple[float, float] | None: """Return the x-axis range for a posterior distribution plot.""" if density_trace is not None: - return self._posterior_axis_bounds( - np.asarray(density_trace.x, dtype=float), - lower_bound=None, - upper_bound=None, - ) + density_x = np.asarray(density_trace.x, dtype=float) + return float(density_x[0]), float(density_x[-1]) if histogram_bin_edges is not None: return ( @@ -2045,11 +2042,7 @@ def _posterior_distribution_x_axis_range( finite_values = finite_values[np.isfinite(finite_values)] if finite_values.size == 0: return None - return self._posterior_axis_bounds( - finite_values, - lower_bound=None, - upper_bound=None, - ) + return float(np.min(finite_values)), float(np.max(finite_values)) @staticmethod def _posterior_distribution_histogram_bin_edges(values: np.ndarray) -> np.ndarray | None: diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 047a05b6..8f731513 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -558,6 +558,7 @@ def test_build_param_distribution_plot_returns_plotly_figure(): assert marginal_trace.hovertemplate == 'length_a: %{x:.4f}
density: %{y:.4f}' assert histogram_trace.xbins.size is not None assert figure.layout.xaxis.range is not None + assert tuple(figure.layout.xaxis.range) == (float(marginal_trace.x[0]), float(marginal_trace.x[-1])) assert figure.layout.yaxis.range is not None From dc38184ac8bb32ed7a3c808fa187bf47a9c4b0a0 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 23:44:06 +0200 Subject: [PATCH 064/106] Change posterior predictive default style to band --- src/easydiffraction/display/plotting.py | 4 +- .../easydiffraction/display/test_plotting.py | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 0b3a2cb6..c0a53092 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -828,7 +828,7 @@ def plot_param_distribution( def plot_posterior_predictive( self, expt_name: str, - style: str = 'band+draws', + style: str = 'band', x_min: float | None = None, x_max: float | None = None, *, @@ -842,7 +842,7 @@ def plot_posterior_predictive( ---------- expt_name : str Experiment name to plot. - style : str, default='band+draws' + style : str, default='band' ``'band'`` shows the 95% credible interval, ``'draws'`` shows sampled predictive curves, and ``'band+draws'`` shows both together. diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 8f731513..f90d6585 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -693,6 +693,56 @@ def fake_evaluate(self, *, sampled_parameters, values, experiment, expt_name, x_ assert [parameter.uncertainty for parameter in sampled_parameters] == [0.1, 0.2] +def test_plot_posterior_predictive_defaults_to_band_for_bragg(monkeypatch): + from easydiffraction.datablocks.experiment.item.enums import BeamModeEnum + from easydiffraction.datablocks.experiment.item.enums import SampleFormEnum + from easydiffraction.datablocks.experiment.item.enums import ScatteringTypeEnum + from easydiffraction.display.plotting import Plotter + + captured: dict[str, object] = {} + + class ExptType: + sample_form = type('SF', (), {'value': SampleFormEnum.POWDER})() + scattering_type = type('S', (), {'value': ScatteringTypeEnum.BRAGG})() + beam_mode = type('B', (), {'value': BeamModeEnum.CONSTANT_WAVELENGTH})() + + class Experiment: + type = ExptType() + + class Project: + experiments = {'hrpt': Experiment()} + + plotter = Plotter() + plotter.engine = 'plotly' + plotter._set_project(Project()) + + monkeypatch.setattr(Plotter, '_update_project_categories', lambda self, expt_name: None) + + def fake_plot_posterior_predictive_data( + self, + *, + experiment, + expt_name, + plot_options, + x_axis, + style, + ): + captured['experiment'] = experiment + captured['expt_name'] = expt_name + captured['style'] = style + captured['x_axis'] = x_axis + captured['show_residual'] = plot_options.show_residual + + monkeypatch.setattr(Plotter, '_plot_posterior_predictive_data', fake_plot_posterior_predictive_data) + + plotter.plot_posterior_predictive('hrpt') + + assert captured['experiment'] is Project.experiments['hrpt'] + assert captured['expt_name'] == 'hrpt' + assert captured['style'] == 'band' + assert captured['show_residual'] is None + + def test_extract_bragg_tick_sets_uses_derived_d_spacing_for_cwl_ticks(): import numpy as np From 6d8ce0f920d628ab7850807d5589ec2a8daa106d Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 23:44:33 +0200 Subject: [PATCH 065/106] Add separate caching for band summaries --- src/easydiffraction/display/plotting.py | 41 +++++-- .../easydiffraction/display/test_plotting.py | 114 +++++++++++++++++- 2 files changed, 143 insertions(+), 12 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index c0a53092..105976c6 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -849,7 +849,7 @@ def plot_posterior_predictive( x_min : float | None, default=None Lower bound for the x-axis range. x_max : float | None, default=None - Upper bound for the x-axis range. + include_draws=style in {'draws', 'band+draws'}, show_residual : bool | None, default=None Whether to include the residual row in the composite plot. x : object | None, default=None @@ -901,6 +901,7 @@ def plot_posterior_predictive( experiment=experiment, expt_name=expt_name, x_axis=x_axis, + include_draws=style in {'draws', 'band+draws'}, ) if summary is None: return @@ -2615,10 +2616,9 @@ def _get_or_build_posterior_predictive_summary( experiment: object, expt_name: str, x_axis: object, + include_draws: bool = True, ) -> object | None: - """ - Return a cached or newly built posterior predictive summary. - """ + """Return a cached or built predictive summary.""" fit_results = self._get_fit_result_for_correlation() if fit_results is None: return None @@ -2629,8 +2629,20 @@ def _get_or_build_posterior_predictive_summary( return None x_axis_name = getattr(x_axis, 'value', x_axis) - cache_key = self._posterior_predictive_key(expt_name, str(x_axis_name)) + draw_cache_key = self._posterior_predictive_key( + expt_name, + str(x_axis_name), + include_draws=True, + ) + band_cache_key = self._posterior_predictive_key( + expt_name, + str(x_axis_name), + include_draws=False, + ) + cache_key = draw_cache_key if include_draws else band_cache_key summary = posterior_predictive.get(cache_key) + if summary is None and not include_draws: + summary = posterior_predictive.get(draw_cache_key) if summary is not None: return summary @@ -2639,6 +2651,7 @@ def _get_or_build_posterior_predictive_summary( experiment=experiment, expt_name=expt_name, x_axis=x_axis, + include_draws=include_draws, ) if summary is None: return None @@ -2653,6 +2666,7 @@ def _build_posterior_predictive_summary( experiment: object, expt_name: str, x_axis: object, + include_draws: bool = True, ) -> object | None: """Build posterior predictive summaries from posterior draws.""" sampling_inputs = self._posterior_predictive_sampling_inputs(fit_results) @@ -2691,7 +2705,7 @@ def _build_posterior_predictive_summary( upper_95=np.asarray(upper_95, dtype=float), lower_68=np.asarray(lower_68, dtype=float), upper_68=np.asarray(upper_68, dtype=float), - draws=predictive_draw_array, + draws=predictive_draw_array if include_draws else None, ) @staticmethod @@ -2854,9 +2868,15 @@ def _posterior_predictive_draw_indices(n_draws: int) -> np.ndarray: ) @staticmethod - def _posterior_predictive_key(expt_name: str, x_axis_name: str) -> str: + def _posterior_predictive_key( + expt_name: str, + x_axis_name: str, + *, + include_draws: bool = True, + ) -> str: """Return the cache key for a posterior predictive summary.""" - return f'{expt_name}:{x_axis_name}' + key_suffix = 'draws' if include_draws else 'band' + return f'{expt_name}:{x_axis_name}:{key_suffix}' def _get_posterior_inference_data( self, @@ -3012,6 +3032,7 @@ def _plot_posterior_predictive_data( experiment=experiment, expt_name=expt_name, x_axis=x_axis, + include_draws=style in {'draws', 'band+draws'}, ) if summary is None: return @@ -3896,8 +3917,8 @@ def _plot_meas_data( 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 name for the title. *, + include_draws : bool, Experiment type with scattering/beam enums. x_min : object, default=None Optional minimum x-axis limit. diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index f90d6585..a26fb9ec 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -558,7 +558,10 @@ def test_build_param_distribution_plot_returns_plotly_figure(): assert marginal_trace.hovertemplate == 'length_a: %{x:.4f}
density: %{y:.4f}' assert histogram_trace.xbins.size is not None assert figure.layout.xaxis.range is not None - assert tuple(figure.layout.xaxis.range) == (float(marginal_trace.x[0]), float(marginal_trace.x[-1])) + assert tuple(figure.layout.xaxis.range) == ( + float(marginal_trace.x[0]), + float(marginal_trace.x[-1]), + ) assert figure.layout.yaxis.range is not None @@ -693,6 +696,111 @@ def fake_evaluate(self, *, sampled_parameters, values, experiment, expt_name, x_ assert [parameter.uncertainty for parameter in sampled_parameters] == [0.1, 0.2] +def test_build_posterior_predictive_summary_omits_draws_when_not_requested(monkeypatch): + from easydiffraction.display.plotting import Plotter + + class FakePredictiveParameter: + def __init__(self, unique_name, value, uncertainty): + self.unique_name = unique_name + self.value = value + self.uncertainty = uncertainty + + def _set_value_from_minimizer(self, value): + self.value = value + + sampled_parameters = [ + FakePredictiveParameter('a', 1.0, 0.1), + FakePredictiveParameter('b', 2.0, 0.2), + ] + posterior_samples = SimpleNamespace( + parameter_names=['a', 'b'], + flattened=lambda: np.array( + [ + [1.0, 2.0], + [1.1, 2.1], + [0.9, 1.9], + [1.2, 2.2], + ], + dtype=float, + ), + ) + fit_results = SimpleNamespace( + posterior_samples=posterior_samples, + parameters=sampled_parameters, + ) + plotter = Plotter() + + def fake_evaluate(self, *, sampled_parameters, values, experiment, expt_name, x_axis): + x = np.array([0.0, 1.0], dtype=float) + y = np.array([values[0] + values[1], values[0] - values[1]], dtype=float) + return y, x + + monkeypatch.setattr(Plotter, '_evaluate_posterior_predictive_state', fake_evaluate) + monkeypatch.setattr(Plotter, '_update_project_categories', lambda self, expt_name: None) + + summary = plotter._build_posterior_predictive_summary( + fit_results=fit_results, + experiment=object(), + expt_name='hrpt', + x_axis='two_theta', + include_draws=False, + ) + + assert summary is not None + assert summary.draws is None + np.testing.assert_allclose(summary.lower_95.shape, (2,)) + np.testing.assert_allclose(summary.upper_95.shape, (2,)) + + +def test_get_or_build_posterior_predictive_summary_rebuilds_draws_after_band_cache( + monkeypatch, +): + from easydiffraction.display.plotting import Plotter + + fit_results = SimpleNamespace( + posterior_predictive={}, + posterior_samples=object(), + ) + band_summary = SimpleNamespace(draws=None) + draw_summary = SimpleNamespace(draws=np.ones((2, 2), dtype=float)) + build_calls: list[bool] = [] + plotter = Plotter() + + monkeypatch.setattr(Plotter, '_get_fit_result_for_correlation', lambda self: fit_results) + + def fake_build( + self, + *, + fit_results, + experiment, + expt_name, + x_axis, + include_draws=True, + ): + del fit_results, experiment, expt_name, x_axis + build_calls.append(include_draws) + return draw_summary if include_draws else band_summary + + monkeypatch.setattr(Plotter, '_build_posterior_predictive_summary', fake_build) + + summary_band = plotter._get_or_build_posterior_predictive_summary( + experiment=object(), + expt_name='hrpt', + x_axis='two_theta', + include_draws=False, + ) + summary_draws = plotter._get_or_build_posterior_predictive_summary( + experiment=object(), + expt_name='hrpt', + x_axis='two_theta', + include_draws=True, + ) + + assert summary_band is band_summary + assert summary_draws is draw_summary + assert build_calls == [False, True] + + def test_plot_posterior_predictive_defaults_to_band_for_bragg(monkeypatch): from easydiffraction.datablocks.experiment.item.enums import BeamModeEnum from easydiffraction.datablocks.experiment.item.enums import SampleFormEnum @@ -733,7 +841,9 @@ def fake_plot_posterior_predictive_data( captured['x_axis'] = x_axis captured['show_residual'] = plot_options.show_residual - monkeypatch.setattr(Plotter, '_plot_posterior_predictive_data', fake_plot_posterior_predictive_data) + monkeypatch.setattr( + Plotter, '_plot_posterior_predictive_data', fake_plot_posterior_predictive_data + ) plotter.plot_posterior_predictive('hrpt') From 19815afaf184b6f53b21588f141a23209f5488d7 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 23:45:01 +0200 Subject: [PATCH 066/106] Reduce sampling steps and adjust plot ranges --- docs/docs/tutorials/ed-13.ipynb | 2 +- docs/docs/tutorials/ed-21.ipynb | 3677 +++++++++++++++++++++++++------ docs/docs/tutorials/ed-21.py | 14 +- 3 files changed, 3031 insertions(+), 662 deletions(-) diff --git a/docs/docs/tutorials/ed-13.ipynb b/docs/docs/tutorials/ed-13.ipynb index 69eae9aa..4d605962 100644 --- a/docs/docs/tutorials/ed-13.ipynb +++ b/docs/docs/tutorials/ed-13.ipynb @@ -2665,7 +2665,7 @@ ], "metadata": { "jupytext": { - "cell_metadata_filter": "title,tags,-all", + "cell_metadata_filter": "tags,title,-all", "main_language": "python", "notebook_metadata_filter": "-all" } diff --git a/docs/docs/tutorials/ed-21.ipynb b/docs/docs/tutorials/ed-21.ipynb index c9b1236e..2a938413 100644 --- a/docs/docs/tutorials/ed-21.ipynb +++ b/docs/docs/tutorials/ed-21.ipynb @@ -340,8 +340,7 @@ "experiment.background.create(id='1', x=10, y=168.5585)\n", "experiment.background.create(id='2', x=30, y=164.3357)\n", "experiment.background.create(id='3', x=50, y=166.8881)\n", - "experiment.background.create(id='4', x=110, y=175.4006)\n", - "experiment.background.create(id='5', x=165, y=174.2813)" + "experiment.background.create(id='4', x=110, y=175.4006)" ] }, { @@ -351,8 +350,8 @@ "metadata": {}, "outputs": [], "source": [ - "experiment.excluded_regions.create(id='1', start=0, end=30)\n", - "experiment.excluded_regions.create(id='2', start=70, end=180)" + "experiment.excluded_regions.create(id='1', start=0, end=10)\n", + "experiment.excluded_regions.create(id='2', start=100, end=180)" ] }, { @@ -399,7 +398,17 @@ "metadata": {}, "outputs": [], "source": [ - "structure.cell.length_a.free = True\n", + "structure.cell.length_a.free = True" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "29", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.linked_phases['lbco'].scale.free = True\n", "experiment.peak.broad_gauss_u.free = True\n", "experiment.peak.broad_gauss_v.free = True\n", "experiment.instrument.calib_twotheta_offset.free = True" @@ -407,7 +416,7 @@ }, { "cell_type": "markdown", - "id": "29", + "id": "30", "metadata": {}, "source": [ "We choose the BUMPS Levenberg-Marquardt minimizer as a fast local\n", @@ -417,8 +426,8 @@ }, { "cell_type": "code", - "execution_count": 18, - "id": "30", + "execution_count": 19, + "id": "31", "metadata": {}, "outputs": [ { @@ -432,124 +441,135 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 TypeDescriptionTypeDescription
1bumpsBumps library using the default Levenberg-Marquardt method1bumpsBumps library using the default Levenberg-Marquardt method
2bumps (amoeba)Bumps library with Nelder-Mead simplex method2bumps (amoeba)Bumps library with Nelder-Mead simplex method
3bumps (de)Bumps library with differential evolution method3bumps (de)Bumps library with differential evolution method
4bumps (dream)Bumps library with DREAM Bayesian sampling4bumps (dream)Bumps library with DREAM Bayesian sampling
5bumps (lm)Bumps library with Levenberg-Marquardt method5bumps (lm)Bumps library with Levenberg-Marquardt method
6dfolsDFO-LS library for derivative-free least-squares optimization6dfolsDFO-LS library for derivative-free least-squares optimization
7lmfitLMFIT library using the default Levenberg-Marquardt least squares method7lmfitLMFIT library using the default Levenberg-Marquardt least squares method
8lmfit (least_squares)LMFIT library with SciPy's trust region reflective algorithm8lmfit (least_squares)LMFIT library with SciPy's trust region reflective algorithm
9*lmfit (leastsq)LMFIT library with Levenberg-Marquardt least squares method9*lmfit (leastsq)LMFIT library with Levenberg-Marquardt least squares method
\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, "output_type": "display_data" - }, + } + ], + "source": [ + "project.analysis.fit.show_minimizer_types()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "32", + "metadata": {}, + "outputs": [ { "name": "stdout", "output_type": "stream", @@ -560,14 +580,13 @@ } ], "source": [ - "project.analysis.fit.show_minimizer_types()\n", "project.analysis.fit.minimizer_type = 'bumps (lm)'" ] }, { "cell_type": "code", - "execution_count": 19, - "id": "31", + "execution_count": 21, + "id": "33", "metadata": {}, "outputs": [ { @@ -584,154 +603,133 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 iterationtime (s)χ²change / statusiterationtime (s)χ²change / status
110.14736.04110.19377.51
270.25315.2257.2% ↓280.3756.3185.1% ↓
3120.3493.9770.2% ↓3140.5039.5429.8% ↓
4170.4340.3357.1% ↓4210.6637.664.7% ↓
5210.5139.063.1% ↓5260.7734.149.4% ↓
6220.5428.5027.0% ↓6270.8023.4731.3% ↓
7260.6124.6913.4% ↓7330.938.7462.7% ↓
8270.6316.2334.2% ↓8391.061.8578.9% ↓
9310.7114.779.0% ↓9451.191.3029.9% ↓
10320.732.7481.4% ↓
11370.821.4547.1% ↓
12420.911.375.6% ↓
13691.391.3710771.871.29
\n" @@ -747,7 +745,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "πŸ† Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m1.37\u001b[0m at iteration \u001b[1;36m68\u001b[0m\n", + "πŸ† Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m1.29\u001b[0m at iteration \u001b[1;36m76\u001b[0m\n", "βœ… Fitting complete.\n" ] } @@ -758,8 +756,8 @@ }, { "cell_type": "code", - "execution_count": 20, - "id": "32", + "execution_count": 22, + "id": "34", "metadata": {}, "outputs": [ { @@ -768,11 +766,11 @@ "text": [ "\u001b[1;34mFit results\u001b[0m\n", "βœ… Success: \u001b[3;92mTrue\u001b[0m\n", - "⏱️ Fitting time: \u001b[1;36m1.39\u001b[0m seconds\n", - "πŸ“ Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m1.37\u001b[0m\n", - "πŸ“ R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m5.27\u001b[0m%\n", - "πŸ“ R-factor squared \u001b[1m(\u001b[0mRfΒ²\u001b[1m)\u001b[0m: \u001b[1;36m4.42\u001b[0m%\n", - "πŸ“ Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m3.78\u001b[0m%\n", + "⏱️ Fitting time: \u001b[1;36m1.87\u001b[0m seconds\n", + "πŸ“ Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m1.29\u001b[0m\n", + "πŸ“ R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m5.65\u001b[0m%\n", + "πŸ“ R-factor squared \u001b[1m(\u001b[0mRfΒ²\u001b[1m)\u001b[0m: \u001b[1;36m4.92\u001b[0m%\n", + "πŸ“ Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m4.08\u001b[0m%\n", "πŸ“ˆ Fitted parameters:\n" ] }, @@ -780,140 +778,152 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 datablockcategoryentryparameterstartfitteduncertaintyunitschangedatablockcategoryentryparameterstartfitteduncertaintyunitschange
1lbcocelllength_a3.88003.89070.0002Γ…0.27 % ↑
2hrptpeakbroad_gauss_u0.10000.03330.0163degΒ²66.71 % ↓
3hrptpeakbroad_gauss_v-0.1000-0.09340.0091degΒ²6.57 % ↓
4hrptinstrumenttwotheta_offset0.00000.62210.0029degN/A1lbcocelllength_a3.88003.89130.0001Γ…0.29 % ↑
2hrptlinked_phaseslbcoscale9.13519.13290.03330.02 % ↓
3hrptpeakbroad_gauss_u0.10000.08170.0078degΒ²18.33 % ↓
4hrptpeakbroad_gauss_v-0.1000-0.11690.0057degΒ²16.91 % ↑
5hrptinstrumenttwotheta_offset0.00000.63060.0019degN/A
\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -926,7 +936,7 @@ }, { "cell_type": "markdown", - "id": "33", + "id": "35", "metadata": {}, "source": [ "The correlation plot shows how strongly the fitted parameters move\n", @@ -937,15 +947,35 @@ }, { "cell_type": "code", - "execution_count": 21, - "id": "34", + "execution_count": 23, + "id": "36", "metadata": {}, "outputs": [ { "data": { "text/html": [ + "\n", + "\n", + "
\n", "
\n", - "
" + "
\n", + "" ], "text/plain": [ "" @@ -956,22 +986,22 @@ } ], "source": [ - "project.display.plotter.plot_param_correlations(show_diagonal=True)" + "project.display.plotter.plot_param_correlations()" ] }, { "cell_type": "code", - "execution_count": 22, - "id": "35", + "execution_count": 24, + "id": "37", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", - "
\n", - "
\n", + "
\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.display.plotter.plot_param_correlations()" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "53", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "
\n", + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.display.plotter.plot_posterior_pairs()" + ] + }, + { + "cell_type": "markdown", + "id": "54", + "metadata": {}, + "source": [ + "The one-dimensional posterior distributions below make it easier to\n", + "inspect individual parameters in isolation, including asymmetry or\n", + "multimodality." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "55", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for param in project.free_parameters:\n", + " project.display.plotter.plot_param_distribution(param)" + ] + }, + { + "cell_type": "markdown", + "id": "56", + "metadata": {}, + "source": [ + "Finally, the posterior predictive plot propagates the sampled parameter\n", + "uncertainty into the calculated diffraction pattern. Comparing this to\n", + "the zoomed measured-vs-calculated view helps assess whether the sampled\n", + "model family explains the data in the region of interest." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "57", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.display.plotter.plot_posterior_predictive(expt_name='hrpt')" + ] + }, + { + "cell_type": "markdown", + "id": "58", + "metadata": {}, + "source": [ + "A final zoomed measured-vs-calculated plot is useful for checking how\n", + "the posterior-supported model behaves in a narrow region of the pattern\n", + "after the Bayesian run." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "59", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=45.4, x_max=46.3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "395b00f6-635c-43b9-9d86-aa00608a4b9b", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 364abeaf..1fadc54f 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -224,9 +224,6 @@ # %% project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') -# %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) - # %% [markdown] # ## Step 5: Prepare for Bayesian Sampling # @@ -238,7 +235,7 @@ # on the current parameter value and expands them by a chosen multiple of # the reported uncertainty. # -# Default multiplier is 8 to give a wide range for the sampler to +# Default `multiplier` is 8 to give a wide range for the sampler to # explore, but here we use 3 to speed up the tutorial. # %% @@ -268,6 +265,11 @@ # through the `init` setting. Other sampler settings such as `thin` and # `pop` can be adjusted as well, but here we keep them at their # defaults. +# +# Default `steps` is 1000, which is often need to be increased for a +# real analysis to ensure good convergence and sampling of the posterior +# distribution. Here we use much smaller value to speed up the tutorial, +# but this is not recommended for a real analysis. # %% project.analysis.fit.show_minimizer_types() @@ -276,7 +278,7 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' # %% -project.analysis.fit.minimizer.steps = 100 # 1000 +project.analysis.fit.minimizer.steps = 50 # 1000 # %% project.analysis.fit() @@ -329,4 +331,4 @@ # after the Bayesian run. # %% -project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=65, x_max=68) +project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=45.4, x_max=46.3) From 469ed50cd1e6d092f774e8d4c0c79ed52f948c57 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 23:57:59 +0200 Subject: [PATCH 067/106] Update posterior pair plot marker and background --- src/easydiffraction/display/plotting.py | 18 ++++++++++-------- .../easydiffraction/display/test_plotting.py | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 105976c6..733e54e6 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -158,6 +158,8 @@ class PosteriorPairPlotStyleEnum(StrEnum): POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 26 POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 42 POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS = 18 +POSTERIOR_PAIR_SAMPLE_MARKER_SIZE = 6 +POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE = 6 @dataclass(frozen=True) @@ -1408,7 +1410,10 @@ def _add_posterior_pair_off_diagonal( x=x_scatter_values, y=y_scatter_values, mode='markers', - marker={'color': POSTERIOR_SCATTER_MARKER_COLOR, 'size': 3}, + marker={ + 'color': POSTERIOR_SCATTER_MARKER_COLOR, + 'size': POSTERIOR_PAIR_SAMPLE_MARKER_SIZE, + }, name='Posterior samples', legendgroup='posterior-samples', showlegend=legend_state.show_scatter, @@ -1433,7 +1438,10 @@ def _add_posterior_pair_off_diagonal( x=x_scatter_values, y=y_scatter_values, mode='markers', - marker={'color': 'rgba(0, 0, 0, 0)', 'size': 6}, + marker={ + 'color': 'rgba(0, 0, 0, 0)', + 'size': POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE, + }, showlegend=False, hovertemplate=sample_hovertemplate, zorder=3, @@ -1656,8 +1664,6 @@ def _finalize_posterior_pairs_figure( 'y': 0.995, 'groupclick': 'togglegroup', }, - paper_bgcolor='white', - plot_bgcolor='white', ) @staticmethod @@ -3626,8 +3632,6 @@ def _build_correlation_heatmap_plot( shapes=subplot_border_shapes, meta=self._posterior_pair_layout_meta(), showlegend=False, - paper_bgcolor='white', - plot_bgcolor='white', ) return fig @@ -3918,8 +3922,6 @@ def _plot_meas_data( ``time_of_flight``, ``d_spacing``) and ``meas`` array. expt_name : str Experiment name for the title. *, - include_draws : bool, - Experiment type with scattering/beam enums. x_min : object, default=None Optional minimum x-axis limit. x_max : object, default=None diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index a26fb9ec..7ee026fa 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -307,6 +307,9 @@ def test_correlation_from_posterior_samples_returns_labeled_dataframe(): def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): + from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE + from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_MARKER_SIZE + plotter, _, _ = _make_bayesian_plotter_fixture() figure = plotter._build_posterior_pairs_plot(parameters=None) @@ -341,8 +344,19 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): assert subplot.yaxis.title.text is None assert bottom_subplot.xaxis.showticklabels is False assert bottom_subplot.xaxis.title.text is None + assert figure.layout.paper_bgcolor is None + assert figure.layout.plot_bgcolor is None assert len(figure.layout.shapes) == 30 assert any(trace.name == 'Posterior contours' for trace in figure.data) + sample_trace = next(trace for trace in figure.data if trace.name == 'Posterior samples') + hover_trace = next( + trace + for trace in figure.data + if getattr(trace, 'mode', None) == 'markers' + and getattr(trace.marker, 'color', None) == 'rgba(0, 0, 0, 0)' + ) + assert sample_trace.marker.size == POSTERIOR_PAIR_SAMPLE_MARKER_SIZE + assert hover_trace.marker.size == POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE def test_build_posterior_pairs_plot_fast_mode_skips_contours(): @@ -1359,6 +1373,8 @@ class Project: assert fig.layout.yaxis.layer == 'above traces' assert fig.layout.yaxis.showticklabels is False assert fig.layout.yaxis.title.text is None + assert fig.layout.paper_bgcolor is None + assert fig.layout.plot_bgcolor is None assert len(fig.layout.shapes) == 3 assert all(shape.type == 'rect' for shape in fig.layout.shapes) assert all(shape.xref == 'paper' for shape in fig.layout.shapes) From fcd9722904d93be48eaeb701f4379006b62ea314 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Sun, 10 May 2026 23:59:37 +0200 Subject: [PATCH 068/106] Update notebooks --- docs/docs/tutorials/ed-13.ipynb | 2 +- docs/docs/tutorials/ed-21.ipynb | 4092 +------------------------------ 2 files changed, 86 insertions(+), 4008 deletions(-) diff --git a/docs/docs/tutorials/ed-13.ipynb b/docs/docs/tutorials/ed-13.ipynb index 4d605962..69eae9aa 100644 --- a/docs/docs/tutorials/ed-13.ipynb +++ b/docs/docs/tutorials/ed-13.ipynb @@ -2665,7 +2665,7 @@ ], "metadata": { "jupytext": { - "cell_metadata_filter": "tags,title,-all", + "cell_metadata_filter": "title,tags,-all", "main_language": "python", "notebook_metadata_filter": "-all" } diff --git a/docs/docs/tutorials/ed-21.ipynb b/docs/docs/tutorials/ed-21.ipynb index 2a938413..0a198508 100644 --- a/docs/docs/tutorials/ed-21.ipynb +++ b/docs/docs/tutorials/ed-21.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "0", "metadata": { "tags": [ @@ -57,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3", "metadata": {}, "outputs": [], @@ -79,7 +79,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "5", "metadata": {}, "outputs": [], @@ -101,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "7", "metadata": {}, "outputs": [], @@ -111,7 +111,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "8", "metadata": {}, "outputs": [], @@ -121,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "9", "metadata": {}, "outputs": [], @@ -132,7 +132,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "10", "metadata": {}, "outputs": [], @@ -152,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "12", "metadata": {}, "outputs": [], @@ -223,20 +223,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "15", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mGetting data\u001b[0m\u001b[1;34m...\u001b[0m\n", - "Data #\u001b[1;36m3\u001b[0m: La0.5Ba0.5CoO3, HRPT \u001b[1m(\u001b[0mPSI\u001b[1m)\u001b[0m, \u001b[1;36m300\u001b[0m K\n", - "βœ… Data #\u001b[1;36m3\u001b[0m already present at \u001b[32m'data/ed-3.xye'\u001b[0m. Keeping existing file.\n" - ] - } - ], + "outputs": [], "source": [ "data_path = ed.download_data(id=3, destination='data')" ] @@ -251,19 +241,10 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "17", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mData loaded successfully\u001b[0m\n", - "Experiment πŸ”¬ \u001b[32m'hrpt'\u001b[0m. Number of data points: \u001b[1;36m3098\u001b[0m.\n" - ] - } - ], + "outputs": [], "source": [ "project.experiments.add_from_data_path(\n", " name='hrpt',\n", @@ -276,7 +257,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "18", "metadata": {}, "outputs": [], @@ -297,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "20", "metadata": {}, "outputs": [], @@ -308,7 +289,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "21", "metadata": {}, "outputs": [], @@ -332,7 +313,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "23", "metadata": {}, "outputs": [], @@ -345,7 +326,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "24", "metadata": {}, "outputs": [], @@ -364,7 +345,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "26", "metadata": {}, "outputs": [], @@ -393,7 +374,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "28", "metadata": {}, "outputs": [], @@ -403,7 +384,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "29", "metadata": {}, "outputs": [], @@ -426,510 +407,40 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "id": "31", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mMinimizer types\u001b[0m\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 TypeDescription
1bumpsBumps library using the default Levenberg-Marquardt method
2bumps (amoeba)Bumps library with Nelder-Mead simplex method
3bumps (de)Bumps library with differential evolution method
4bumps (dream)Bumps library with DREAM Bayesian sampling
5bumps (lm)Bumps library with Levenberg-Marquardt method
6dfolsDFO-LS library for derivative-free least-squares optimization
7lmfitLMFIT library using the default Levenberg-Marquardt least squares method
8lmfit (least_squares)LMFIT library with SciPy's trust region reflective algorithm
9*lmfit (leastsq)LMFIT library with Levenberg-Marquardt least squares method
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.analysis.fit.show_minimizer_types()" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "32", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mCurrent minimizer changed to\u001b[0m\n", - "bumps \u001b[1m(\u001b[0mlm\u001b[1m)\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ "project.analysis.fit.minimizer_type = 'bumps (lm)'" ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "33", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mStandard fitting\u001b[0m\n", - "πŸ“‹ Using experiment πŸ”¬ \u001b[32m'hrpt'\u001b[0m for \u001b[32m'single'\u001b[0m fitting\n", - "πŸš€ Starting fit process with \u001b[32m'bumps \u001b[0m\u001b[32m(\u001b[0m\u001b[32mlm\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n", - "πŸ“ˆ Goodness-of-fit progress:\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 iterationtime (s)χ²change / status
110.19377.51
280.3756.3185.1% ↓
3140.5039.5429.8% ↓
4210.6637.664.7% ↓
5260.7734.149.4% ↓
6270.8023.4731.3% ↓
7330.938.7462.7% ↓
8391.061.8578.9% ↓
9451.191.3029.9% ↓
10771.871.29
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "πŸ† Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m1.29\u001b[0m at iteration \u001b[1;36m76\u001b[0m\n", - "βœ… Fitting complete.\n" - ] - } - ], + "outputs": [], "source": [ "project.analysis.fit()" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "id": "34", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mFit results\u001b[0m\n", - "βœ… Success: \u001b[3;92mTrue\u001b[0m\n", - "⏱️ Fitting time: \u001b[1;36m1.87\u001b[0m seconds\n", - "πŸ“ Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m1.29\u001b[0m\n", - "πŸ“ R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m5.65\u001b[0m%\n", - "πŸ“ R-factor squared \u001b[1m(\u001b[0mRfΒ²\u001b[1m)\u001b[0m: \u001b[1;36m4.92\u001b[0m%\n", - "πŸ“ Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m4.08\u001b[0m%\n", - "πŸ“ˆ Fitted parameters:\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 datablockcategoryentryparameterstartfitteduncertaintyunitschange
1lbcocelllength_a3.88003.89130.0001Γ…0.29 % ↑
2hrptlinked_phaseslbcoscale9.13519.13290.03330.02 % ↓
3hrptpeakbroad_gauss_u0.10000.08170.0078degΒ²18.33 % ↓
4hrptpeakbroad_gauss_v-0.1000-0.11690.0057degΒ²16.91 % ↑
5hrptinstrumenttwotheta_offset0.00000.63060.0019degN/A
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.analysis.display.fit_results()" ] @@ -947,509 +458,27 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "id": "36", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - "
\n", - "
\n", - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.display.plotter.plot_param_correlations()" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "37", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.display.plotter.plot_meas_vs_calc(expt_name='hrpt')" ] }, - { - "cell_type": "code", - "execution_count": 25, - "id": "38", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68)" - ] - }, { "cell_type": "markdown", - "id": "39", + "id": "38", "metadata": {}, "source": [ "## Step 5: Prepare for Bayesian Sampling\n", @@ -1462,187 +491,24 @@ "on the current parameter value and expands them by a chosen multiple of\n", "the reported uncertainty.\n", "\n", - "Default multiplier is 8 to give a wide range for the sampler to\n", + "Default `multiplier` is 8 to give a wide range for the sampler to\n", "explore, but here we use 3 to speed up the tutorial." ] }, { "cell_type": "code", - "execution_count": 26, - "id": "40", + "execution_count": null, + "id": "39", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mFree parameters for both structures \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m🧩 data blocks\u001b[0m\u001b[1;34m)\u001b[0m\u001b[1;34m and experiments \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34mπŸ”¬ data blocks\u001b[0m\u001b[1;34m)\u001b[0m\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 datablockcategoryentryparametervalueuncertaintyminmaxunits
1lbcocelllength_a3.891340.00011-infinfΓ…
2hrptlinked_phaseslbcoscale9.132880.03329-infinf
3hrptpeakbroad_gauss_u0.081670.00783-infinfdegΒ²
4hrptpeakbroad_gauss_v-0.116910.00566-infinfdegΒ²
5hrptinstrumenttwotheta_offset0.630570.00191-infinfdeg
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.analysis.display.free_params()" ] }, { "cell_type": "code", - "execution_count": 27, - "id": "41", + "execution_count": null, + "id": "40", "metadata": {}, "outputs": [], "source": [ @@ -1652,7 +518,7 @@ }, { "cell_type": "markdown", - "id": "42", + "id": "41", "metadata": {}, "source": [ "Displaying the free parameters again is a convenient way to confirm\n", @@ -1662,180 +528,17 @@ }, { "cell_type": "code", - "execution_count": 28, - "id": "43", + "execution_count": null, + "id": "42", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mFree parameters for both structures \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m🧩 data blocks\u001b[0m\u001b[1;34m)\u001b[0m\u001b[1;34m and experiments \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34mπŸ”¬ data blocks\u001b[0m\u001b[1;34m)\u001b[0m\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 datablockcategoryentryparametervalueuncertaintyminmaxunits
1lbcocelllength_a3.891340.000113.891013.89166Γ…
2hrptlinked_phaseslbcoscale9.132880.033299.033029.23274
3hrptpeakbroad_gauss_u0.081670.007830.058170.10517degΒ²
4hrptpeakbroad_gauss_v-0.116910.00566-0.13389-0.09993degΒ²
5hrptinstrumenttwotheta_offset0.630570.001910.624830.63631deg
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.analysis.display.free_params()" ] }, { "cell_type": "markdown", - "id": "44", + "id": "43", "metadata": {}, "source": [ "## Step 6: Configure and Run DREAM\n", @@ -1848,486 +551,57 @@ "needed, the DREAM API also lets you tune how chains are initialized\n", "through the `init` setting. Other sampler settings such as `thin` and\n", "`pop` can be adjusted as well, but here we keep them at their\n", - "defaults." + "defaults.\n", + "\n", + "Default `steps` is 1000, which is often need to be increased for a\n", + "real analysis to ensure good convergence and sampling of the posterior\n", + "distribution. Here we use much smaller value to speed up the tutorial,\n", + "but this is not recommended for a real analysis." ] }, { "cell_type": "code", - "execution_count": 29, - "id": "45", + "execution_count": null, + "id": "44", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mMinimizer types\u001b[0m\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 TypeDescription
1bumpsBumps library using the default Levenberg-Marquardt method
2bumps (amoeba)Bumps library with Nelder-Mead simplex method
3bumps (de)Bumps library with differential evolution method
4bumps (dream)Bumps library with DREAM Bayesian sampling
5*bumps (lm)Bumps library with Levenberg-Marquardt method
6dfolsDFO-LS library for derivative-free least-squares optimization
7lmfitLMFIT library using the default Levenberg-Marquardt least squares method
8lmfit (least_squares)LMFIT library with SciPy's trust region reflective algorithm
9lmfit (leastsq)LMFIT library with Levenberg-Marquardt least squares method
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.analysis.fit.show_minimizer_types()" ] }, { "cell_type": "code", - "execution_count": 30, - "id": "46", + "execution_count": null, + "id": "45", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mCurrent minimizer changed to\u001b[0m\n", - "bumps \u001b[1m(\u001b[0mdream\u001b[1m)\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ "project.analysis.fit.minimizer_type = 'bumps (dream)'" ] }, { "cell_type": "code", - "execution_count": 31, - "id": "47", + "execution_count": null, + "id": "46", "metadata": {}, "outputs": [], "source": [ - "project.analysis.fit.minimizer.steps = 100 # 1000" + "project.analysis.fit.minimizer.steps = 50 # 1000" ] }, { "cell_type": "code", - "execution_count": 32, - "id": "48", + "execution_count": null, + "id": "47", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mStandard fitting\u001b[0m\n", - "πŸ“‹ Using experiment πŸ”¬ \u001b[32m'hrpt'\u001b[0m for \u001b[32m'single'\u001b[0m fitting\n", - "πŸš€ Starting fit process with \u001b[32m'bumps \u001b[0m\u001b[32m(\u001b[0m\u001b[32mdream\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n", - "πŸ“ˆ Bayesian sampling progress:\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 iterationprogresstime (s)log posteriorphase
11/1510.7%0.43-1157.01burn-in
213/1518.6%5.49-1157.54burn-in
326/15117.2%10.82-1158.21burn-in
438/15125.2%15.85-1159.61burn-in
550/15133.1%20.89-1159.52burn-in
651/15133.8%21.36-1159.49sampling
756/15137.1%23.41-1159.26sampling
862/15141.1%25.92-1159.52sampling
967/15144.4%27.96-1159.24sampling
1072/15147.7%30.23-1159.00sampling
1177/15151.0%32.42-1158.87sampling
1283/15155.0%34.90-1158.90sampling
1388/15158.3%36.91-1159.39sampling
1493/15161.6%39.10-1159.59sampling
1598/15164.9%41.21-1159.22sampling
16104/15168.9%43.71-1159.44sampling
17109/15172.2%45.72-1159.53sampling
18114/15175.5%47.82-1159.41sampling
19119/15178.8%49.95-1159.63sampling
20125/15182.8%52.50-1159.64sampling
21130/15186.1%54.61-1159.33sampling
22135/15189.4%56.70-1159.39sampling
23140/15192.7%58.78-1159.63sampling
24146/15196.7%61.23-1159.52sampling
25151/151100.0%63.47-1159.74sampling
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "⚠️ DREAM sampling completed, but convergence diagnostics indicate the posterior may be poorly mixed. \n", - "βœ… Bayesian sampling complete.\n" - ] - } - ], + "outputs": [], "source": [ "project.analysis.fit()" ] }, { "cell_type": "markdown", - "id": "49", + "id": "48", "metadata": {}, "source": [ "## Step 7: Inspect Bayesian Results\n", @@ -2339,386 +613,17 @@ }, { "cell_type": "code", - "execution_count": 33, - "id": "50", + "execution_count": null, + "id": "49", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;34mBayesian fit results\u001b[0m\n", - "βœ… Success: \u001b[3;92mTrue\u001b[0m\n", - "i Status: DREAM sampling completed\n", - "πŸ§ͺ Sampler: dream\n", - "🎯 Committed point estimate: Max posterior\n", - "πŸ” Sampler completed: \u001b[3;92mTrue\u001b[0m\n", - "⏱️ Fitting time: \u001b[1;36m63.47\u001b[0m seconds\n", - "πŸ“ Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m1.29\u001b[0m\n", - "πŸ“‰ Best log-posterior: \u001b[1;36m-1157.00\u001b[0m\n", - "βš™οΈ Sampler settings: random_seed=1708713996, steps=100, burn=50, thin=1, pop=4, samples=2000\n", - "πŸ“Š Convergence: converged=\u001b[31mfailed\u001b[0m, max_r_hat=\u001b[31m1.291\u001b[0m, min_ess_bulk=\u001b[31m56.4\u001b[0m, draws=100, chains=20\n", - "πŸ“ R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m5.65\u001b[0m%\n", - "πŸ“ R-factor squared \u001b[1m(\u001b[0mRfΒ²\u001b[1m)\u001b[0m: \u001b[1;36m4.92\u001b[0m%\n", - "πŸ“ Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m4.09\u001b[0m%\n", - "πŸ“ˆ Committed parameters:\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 datablockcategoryentryparameterstartmax posterioruncertaintyunitschange
1lbcocelllength_a3.89133.89130.0001Γ…0.00 % ↓
2hrptlinked_phaseslbcoscale9.13299.13360.03050.01 % ↑
3hrptpeakbroad_gauss_u0.08170.08170.0060degΒ²0.01 % ↓
4hrptpeakbroad_gauss_v-0.1169-0.11690.0044degΒ²0.01 % ↑
5hrptinstrumenttwotheta_offset0.63060.63030.0017deg0.05 % ↓
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "πŸ“Š Posterior parameter summaries:\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 datablockcategoryentryparametermedianstd68% interval95% intervalr_hatess_bulkunits
1lbcocelllength_a3.89130.0001[3.8912, 3.8914][3.8912, 3.8915]1.29156.4Γ…
2hrptlinked_phaseslbcoscale9.13410.0305[9.1029, 9.1650][9.0758, 9.1901]1.20878.6
3hrptpeakbroad_gauss_u0.08160.0060[0.0750, 0.0872][0.0684, 0.0928]1.23072.5degΒ²
4hrptpeakbroad_gauss_v-0.11670.0044[-0.1211, -0.1126][-0.1251, -0.1076]1.22672.6degΒ²
5hrptinstrumenttwotheta_offset0.63040.0017[0.6286, 0.6320][0.6271, 0.6337]1.28158.6deg
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "⚠️ \u001b[31mr_hat\u001b[0m: exceeds 1.01 (consider longer sampling, tighter bounds, or reparameterization). \n", - "⚠️ \u001b[31mess_bulk\u001b[0m: less than 400 (consider longer sampling, tighter bounds, or reparameterization). \n" - ] - } - ], + "outputs": [], "source": [ "project.analysis.display.fit_results()" ] }, { "cell_type": "markdown", - "id": "51", + "id": "50", "metadata": {}, "source": [ "The correlation and posterior-pair plots are complementary:\n", @@ -2731,300 +636,27 @@ }, { "cell_type": "code", - "execution_count": 34, - "id": "52", + "execution_count": null, + "id": "51", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - "
\n", - "
\n", - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.display.plotter.plot_param_correlations()" ] }, { "cell_type": "code", - "execution_count": 35, - "id": "53", + "execution_count": null, + "id": "52", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - "
\n", - "
\n", - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.display.plotter.plot_posterior_pairs()" ] }, { "cell_type": "markdown", - "id": "54", + "id": "53", "metadata": {}, "source": [ "The one-dimensional posterior distributions below make it easier to\n", @@ -3034,1101 +666,10 @@ }, { "cell_type": "code", - "execution_count": 36, - "id": "55", + "execution_count": null, + "id": "54", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "for param in project.free_parameters:\n", " project.display.plotter.plot_param_distribution(param)" @@ -4136,7 +677,7 @@ }, { "cell_type": "markdown", - "id": "56", + "id": "55", "metadata": {}, "source": [ "Finally, the posterior predictive plot propagates the sampled parameter\n", @@ -4147,236 +688,17 @@ }, { "cell_type": "code", - "execution_count": 37, - "id": "57", + "execution_count": null, + "id": "56", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.display.plotter.plot_posterior_predictive(expt_name='hrpt')" ] }, { "cell_type": "markdown", - "id": "58", + "id": "57", "metadata": {}, "source": [ "A final zoomed measured-vs-calculated plot is useful for checking how\n", @@ -4386,240 +708,13 @@ }, { "cell_type": "code", - "execution_count": 47, - "id": "59", + "execution_count": null, + "id": "58", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=45.4, x_max=46.3)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "395b00f6-635c-43b9-9d86-aa00608a4b9b", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -4627,23 +722,6 @@ "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.14.4" } }, "nbformat": 4, From f1039da1ae650f1cb45bf6bcc98079927dd042a8 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 00:00:31 +0200 Subject: [PATCH 069/106] Fix docstring errors in Plotter class --- src/easydiffraction/display/plotting.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 733e54e6..5567aca6 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -851,7 +851,7 @@ def plot_posterior_predictive( x_min : float | None, default=None Lower bound for the x-axis range. x_max : float | None, default=None - include_draws=style in {'draws', 'band+draws'}, + Upper bound for the x-axis range. show_residual : bool | None, default=None Whether to include the residual row in the composite plot. x : object | None, default=None @@ -3921,7 +3921,9 @@ def _plot_meas_data( Object with x-axis arrays (``two_theta``, ``time_of_flight``, ``d_spacing``) and ``meas`` array. expt_name : str - Experiment name for the title. *, + 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 From a79bd6600f00f9ee2a4617f8d2b717c774457229 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 08:49:59 +0200 Subject: [PATCH 070/106] Standardize axis title font size --- .../analysis/minimizers/bumps_dream.py | 3 +-- .../display/plotters/plotly.py | 26 ++++++++++++++++--- src/easydiffraction/display/plotting.py | 10 ++++--- .../display/plotters/test_plotly.py | 11 ++++++++ .../easydiffraction/display/test_plotting.py | 15 +++++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 7eab3f23..f7060d12 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -763,8 +763,7 @@ def _build_success_result( if not convergence_diagnostics.get('converged', True): log.warning( - 'DREAM sampling completed, but convergence diagnostics indicate ' - 'the posterior may be poorly mixed.' + 'Convergence diagnostics indicate the posterior may be poorly mixed.' ) return OptimizeResult( diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 764c5a0f..30164d10 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -65,6 +65,7 @@ COMPOSITE_MARGIN_RIGHT = 30 COMPOSITE_MARGIN_TOP = 40 COMPOSITE_MARGIN_BOTTOM = 45 +AXIS_TITLE_FONT_SIZE = 12 PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.26)' PREDICTIVE_BAND_EDGE_COLOR = 'rgba(214, 39, 40, 0.45)' PREDICTIVE_DRAW_COLOR = 'rgba(140, 140, 140, 0.18)' @@ -1005,14 +1006,20 @@ def _get_layout( 'y': 1.0, }, xaxis={ - 'title_text': axes_labels[0], + 'title': { + 'text': axes_labels[0], + 'font': {'size': AXIS_TITLE_FONT_SIZE}, + }, 'showline': True, 'linecolor': cls._axis_frame_color(), 'mirror': True, 'zeroline': False, }, yaxis={ - 'title_text': axes_labels[1], + 'title': { + 'text': axes_labels[1], + 'font': {'size': AXIS_TITLE_FONT_SIZE}, + }, 'showline': True, 'linecolor': cls._axis_frame_color(), 'mirror': True, @@ -1574,6 +1581,7 @@ def _configure_powder_composite_axes( fig.update_xaxes(showticklabels=(layout.row_count == 1), row=1, col=1) fig.update_yaxes( title_text=plot_spec.axes_labels[1], + title_font={'size': AXIS_TITLE_FONT_SIZE}, range=list(main_y_range), row=1, col=1, @@ -1591,7 +1599,12 @@ def _configure_powder_composite_axes( return terminal_row = layout.bragg_row if layout.bragg_row is not None else 1 - fig.update_xaxes(title_text=plot_spec.axes_labels[0], row=terminal_row, col=1) + fig.update_xaxes( + title_text=plot_spec.axes_labels[0], + title_font={'size': AXIS_TITLE_FONT_SIZE}, + row=terminal_row, + col=1, + ) def _configure_shared_composite_axes( self, @@ -1667,7 +1680,12 @@ def _configure_residual_axes( row=layout.residual_row, col=1, ) - fig.update_xaxes(title_text=plot_spec.axes_labels[0], row=layout.residual_row, col=1) + fig.update_xaxes( + title_text=plot_spec.axes_labels[0], + title_font={'size': AXIS_TITLE_FONT_SIZE}, + row=layout.residual_row, + col=1, + ) @staticmethod def _get_predictive_band_traces( diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 5567aca6..4da2f63b 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -146,7 +146,7 @@ class PosteriorPairPlotStyleEnum(StrEnum): PAIR_PLOT_SUBPLOT_SPACING = 0.01 POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE = 12 -POSTERIOR_PAIR_TITLE_FONT_SIZE = 16 +POSTERIOR_PAIR_TITLE_FONT_SIZE = POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 16 POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS = 10 POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS = 2 @@ -155,8 +155,8 @@ class PosteriorPairPlotStyleEnum(StrEnum): POSTERIOR_PAIR_FIXED_ASPECT_META_KEY = 'fixed_aspect_wrapper' POSTERIOR_PAIR_LEFT_MARGIN_PIXELS = 58 POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS = 10 -POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 26 -POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 42 +POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 40 +POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 24 POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS = 18 POSTERIOR_PAIR_SAMPLE_MARKER_SIZE = 6 POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE = 6 @@ -2219,6 +2219,8 @@ def _apply_posterior_distribution_layout( 'y': 1.0, }, ) + fig.update_xaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) + fig.update_yaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) if x_axis_range is not None: fig.update_xaxes(range=list(x_axis_range)) if y_axis_range is not None: @@ -3010,6 +3012,8 @@ def _plot_posterior_predictive_summary( xaxis_title=axes_labels[0], yaxis_title=axes_labels[1], ) + fig.update_xaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) + fig.update_yaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) fig.show() def _plot_posterior_predictive_data( diff --git a/tests/unit/easydiffraction/display/plotters/test_plotly.py b/tests/unit/easydiffraction/display/plotters/test_plotly.py index 54c2d5d6..bfb3105f 100644 --- a/tests/unit/easydiffraction/display/plotters/test_plotly.py +++ b/tests/unit/easydiffraction/display/plotters/test_plotly.py @@ -13,6 +13,15 @@ def test_module_import(): assert expected_module_name == actual_module_name +def test_get_layout_sets_axis_title_font_size(): + import easydiffraction.display.plotters.plotly as pp + + layout = pp.PlotlyPlotter._get_layout('Title', ['x axis', 'y axis']) + + assert layout.xaxis.title.font.size == pp.AXIS_TITLE_FONT_SIZE + assert layout.yaxis.title.font.size == pp.AXIS_TITLE_FONT_SIZE + + def test_get_trace_and_plot(monkeypatch): import easydiffraction.display.plotters.plotly as pp @@ -775,6 +784,8 @@ def fake_show_figure(self, fig): assert fig.layout.xaxis2.matches == 'x' assert fig.layout.yaxis2.title.text is None assert fig.layout.xaxis2.title.text == '2ΞΈ (degree)' + assert fig.layout.yaxis.title.font.size == pp.AXIS_TITLE_FONT_SIZE + assert fig.layout.xaxis2.title.font.size == pp.AXIS_TITLE_FONT_SIZE assert [trace.name for trace in fig.data] == [ 'Measured (Imeas)', 'Total calculated (Icalc)', diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 7ee026fa..09ccf6f6 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -307,8 +307,11 @@ def test_correlation_from_posterior_samples_returns_labeled_dataframe(): def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): + from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_MARKER_SIZE + from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_FONT_SIZE + from easydiffraction.display.plotting import POSTERIOR_PAIR_TOP_MARGIN_PIXELS plotter, _, _ = _make_bayesian_plotter_fixture() @@ -330,12 +333,15 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): 'broad_gauss_v', 'twotheta_offset', ] + assert figure.layout.annotations[0].font.size == POSTERIOR_PAIR_TITLE_FONT_SIZE assert figure.layout.annotations[0].xshift == -plotter._square_matrix_title_left_shift([ 'length_a', 'broad_gauss_u', 'broad_gauss_v', 'twotheta_offset', ]) + assert figure.layout.margin.t == POSTERIOR_PAIR_TOP_MARGIN_PIXELS + assert figure.layout.margin.b == POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS subplot = figure.get_subplot(1, 1) bottom_subplot = figure.get_subplot(4, 1) assert subplot.yaxis.showticklabels is False @@ -1294,6 +1300,10 @@ def test_plot_param_correlations_renders_plotly_heatmap(monkeypatch): import numpy as np import easydiffraction.display.plotters.plotly as plotly_mod + from easydiffraction.display.plotting import POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS + from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_FONT_SIZE + from easydiffraction.display.plotting import POSTERIOR_PAIR_TOP_MARGIN_PIXELS from easydiffraction.display.plotting import Plotter captured = {} @@ -1357,10 +1367,15 @@ class Project: 'phase.
scale', 'phase.
cell.
length_c', ] + assert fig.layout.annotations[0].font.size == POSTERIOR_PAIR_TITLE_FONT_SIZE assert fig.layout.annotations[0].xshift == -Plotter._square_matrix_title_left_shift([ 'phase.
scale', 'phase.
cell.
length_c', ]) + assert fig.layout.margin.t == POSTERIOR_PAIR_TOP_MARGIN_PIXELS + assert fig.layout.margin.b == ( + POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + 2 * POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS + ) assert fig.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] == '1 / 1' assert fig.layout.xaxis.domain[1] < fig.layout.xaxis2.domain[0] assert fig.layout.xaxis.showline is False From 9731a7aa4f6d5de23a3c1c231e36695e41575551 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 08:50:48 +0200 Subject: [PATCH 071/106] Improve Bayesian fit summary display --- .../analysis/fit_helpers/bayesian.py | 44 +++++++++++++------ .../display/plotters/plotly.py | 7 ++- src/easydiffraction/display/plotting.py | 29 +++++++++--- .../analysis/fit_helpers/test_bayesian.py | 44 +++++++++++++++++++ .../display/plotters/test_plotly.py | 4 +- .../easydiffraction/display/test_plotting.py | 4 ++ 6 files changed, 110 insertions(+), 22 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 243ce872..7e455893 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -330,19 +330,24 @@ def _print_table_notes(self) -> None: def _display_summary_header(self) -> None: """Render the high-level Bayesian fit summary.""" - status_icon = 'βœ…' if self.success else '❌' + status_icon, overall_status = _format_bayesian_overall_status( + success=self.success, + sampler_completed=self.sampler_completed, + convergence_diagnostics=self.convergence_diagnostics, + ) fitting_time = _format_optional_float(self.fitting_time, suffix=' seconds') goodness_of_fit = _format_optional_float(self.reduced_chi_square) console.paragraph('Bayesian fit results') - console.print(f'{status_icon} Success: {self.success}') + console.print(f'{status_icon} Overall status: {overall_status}') if self.message: - console.print(f'i Status: {self.message}') + console.print(f'πŸ’¬ Sampler status: {self.message}') console.print(f'πŸ§ͺ Sampler: {self.sampler_name}') console.print( f'🎯 Committed point estimate: {_format_point_estimate_name(self.point_estimate_name)}' ) - console.print(f'πŸ” Sampler completed: {self.sampler_completed}') + sampler_completed = 'yes' if self.sampler_completed else 'no' + console.print(f'πŸ” Sampler completed: {sampler_completed}') console.print(f'⏱️ Fitting time: {fitting_time}') console.print(f'πŸ“ Goodness-of-fit (reduced χ²): {goodness_of_fit}') if self.best_log_posterior is not None: @@ -566,6 +571,24 @@ def _format_point_estimate_name(point_estimate_name: str) -> str: return point_estimate_name.replace('_', ' ').title() +def _format_bayesian_overall_status( + *, + success: bool, + sampler_completed: bool, + convergence_diagnostics: dict[str, object], +) -> tuple[str, str]: + """Return icon and text for Bayesian run status.""" + if not success: + return '❌', 'failed' + + converged = convergence_diagnostics.get('converged') + if converged is False: + return '⚠️', 'completed with warnings' + if sampler_completed: + return 'βœ…', 'completed' + return 'βœ…', 'posterior available' + + def _format_convergence_summary(convergence_diagnostics: dict[str, object]) -> str | None: if not convergence_diagnostics: return None @@ -573,8 +596,8 @@ def _format_convergence_summary(convergence_diagnostics: dict[str, object]) -> s parts: list[str] = [] converged = convergence_diagnostics.get('converged') if converged is not None: - status = 'yes' if converged else '[red]failed[/red]' - parts.append(f'converged={status}') + status = 'passed' if converged else '[red]failed[/red]' + parts.append(f'status={status}') max_r_hat = _maybe_scalar(convergence_diagnostics.get('max_r_hat')) if max_r_hat is not None: @@ -639,8 +662,6 @@ def _render_posterior_summary_table( 'entry', 'parameter', 'median', - 'std', - '68% interval', '95% interval', 'r_hat', 'ess_bulk', @@ -655,8 +676,6 @@ def _render_posterior_summary_table( 'right', 'right', 'right', - 'right', - 'right', 'left', ] rows = [ @@ -679,16 +698,15 @@ def _build_posterior_summary_row( datablock = getattr(identity, 'datablock_entry_name', 'N/A') category = getattr(identity, 'category_code', 'N/A') entry = getattr(identity, 'category_entry_name', '') or '' + parameter_name = getattr(parameter, 'name', summary.display_name) units = getattr(parameter, 'units', 'N/A') return [ datablock, category, entry, - summary.display_name, + parameter_name, f'{summary.median:.4f}', - f'{summary.standard_deviation:.4f}', - _format_interval(summary.interval_68), _format_interval(summary.interval_95), _format_r_hat(summary.r_hat), _format_ess_bulk(summary.ess_bulk), diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 30164d10..0366e961 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -65,6 +65,7 @@ COMPOSITE_MARGIN_RIGHT = 30 COMPOSITE_MARGIN_TOP = 40 COMPOSITE_MARGIN_BOTTOM = 45 +TITLE_FONT_SIZE = 14 AXIS_TITLE_FONT_SIZE = 12 PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.26)' PREDICTIVE_BAND_EDGE_COLOR = 'rgba(214, 39, 40, 0.45)' @@ -997,6 +998,7 @@ def _get_layout( }, title={ 'text': title, + 'font': {'size': TITLE_FONT_SIZE}, }, legend={ 'bgcolor': cls._legend_background_color(), @@ -1552,7 +1554,10 @@ def _configure_powder_composite_layout( 't': COMPOSITE_MARGIN_TOP, 'b': COMPOSITE_MARGIN_BOTTOM, }, - title={'text': plot_spec.title}, + title={ + 'text': plot_spec.title, + 'font': {'size': TITLE_FONT_SIZE}, + }, legend={ 'bgcolor': self._legend_background_color(), 'xanchor': 'right', diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 4da2f63b..c9e8be42 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -31,6 +31,10 @@ from easydiffraction.display.plotters.base import BraggTickSet from easydiffraction.display.plotters.base import PowderMeasVsCalcSpec from easydiffraction.display.plotters.base import XAxisType +from easydiffraction.display.plotters.plotly import ( + AXIS_TITLE_FONT_SIZE as PLOTLY_AXIS_TITLE_FONT_SIZE, +) +from easydiffraction.display.plotters.plotly import TITLE_FONT_SIZE as PLOTLY_TITLE_FONT_SIZE from easydiffraction.display.plotters.plotly import PlotlyPlotter from easydiffraction.display.tables import TableRenderer from easydiffraction.utils.environment import in_jupyter @@ -145,17 +149,17 @@ class PosteriorPairPlotStyleEnum(StrEnum): PAIR_PLOT_ESTIMATED_CONTAINER_WIDTH_PIXELS = 980 PAIR_PLOT_SUBPLOT_SPACING = 0.01 POSTERIOR_PAIR_AXIS_LINE_WIDTH = 1.2 -POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE = 12 -POSTERIOR_PAIR_TITLE_FONT_SIZE = POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE +POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE = PLOTLY_AXIS_TITLE_FONT_SIZE +POSTERIOR_PAIR_TITLE_FONT_SIZE = PLOTLY_TITLE_FONT_SIZE POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 16 POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS = 10 -POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS = 2 +POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS = 8 POSTERIOR_PAIR_GUIDE_LINE_COLOR = 'rgba(125, 140, 173, 0.18)' POSTERIOR_PAIR_FIXED_ASPECT_RATIO = '1 / 1' POSTERIOR_PAIR_FIXED_ASPECT_META_KEY = 'fixed_aspect_wrapper' POSTERIOR_PAIR_LEFT_MARGIN_PIXELS = 58 POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS = 10 -POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 40 +POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 26 POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 24 POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS = 18 POSTERIOR_PAIR_SAMPLE_MARKER_SIZE = 6 @@ -2205,10 +2209,18 @@ def _apply_posterior_distribution_layout( ) -> None: """Apply layout settings to the distribution plot.""" if callable(layout_factory): - fig.update_layout(title={'text': title}) + fig.update_layout( + title={ + 'text': title, + 'font': {'size': POSTERIOR_PAIR_TITLE_FONT_SIZE}, + } + ) else: fig.update_layout( - title=title, + title={ + 'text': title, + 'font': {'size': POSTERIOR_PAIR_TITLE_FONT_SIZE}, + }, xaxis_title=label, yaxis_title='Probability density', legend={ @@ -3008,7 +3020,10 @@ def _plot_posterior_predictive_summary( ) ) fig.update_layout( - title=f"Posterior predictive for experiment πŸ”¬ '{expt_name}'", + title={ + 'text': f"Posterior predictive for experiment πŸ”¬ '{expt_name}'", + 'font': {'size': POSTERIOR_PAIR_TITLE_FONT_SIZE}, + }, xaxis_title=axes_labels[0], yaxis_title=axes_labels[1], ) diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py index 58fee092..708d8a6f 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py @@ -150,21 +150,65 @@ def test_bayesian_fit_results_display_results_prints_sampler_and_convergence(cap ], best_log_posterior=-12.34, ) + results.message = 'DREAM sampling completed' results.display_results(y_obs=[10.0, 20.0], y_calc=[9.5, 19.5]) out = capsys.readouterr().out assert 'Bayesian fit results' in out + assert 'Overall status: completed with warnings' in out + assert 'Sampler status: DREAM sampling completed' in out assert 'Sampler: dream' in out + assert 'Sampler completed: yes' in out assert 'random_seed=1313900679' in out assert 'steps=200' in out + assert 'status=failed' in out assert 'max_r_hat=1.107' in out assert 'min_ess_bulk=125.9' in out assert 'Posterior parameter summaries:' in out + assert 'Success: True' not in out + assert 'datablock' in out + assert 'category' in out + assert 'entry' in out + assert '95% interval' in out + assert '68% interval' not in out + assert 'std' not in out monkeypatch.setattr(Logger, '_reaction', Logger.Reaction.RAISE, raising=True) +def test_build_posterior_summary_row_restores_identifier_columns(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import _build_posterior_summary_row + + parameter = Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05) + summary = PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.2, + median=1.15, + standard_deviation=0.05, + interval_68=(1.1, 1.2), + interval_95=(1.0, 1.3), + r_hat=1.107, + ess_bulk=125.9, + ) + + row = _build_posterior_summary_row(summary, {'a': parameter}) + + assert row == [ + 'db', + 'cat', + 'entry', + 'a', + '1.1500', + '[1.0000, 1.3000]', + '[red]1.107[/red]', + '[red]125.9[/red]', + 'arb', + ] + + def test_posterior_table_notes_split_failed_diagnostics(): from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary from easydiffraction.analysis.fit_helpers.bayesian import _posterior_table_notes diff --git a/tests/unit/easydiffraction/display/plotters/test_plotly.py b/tests/unit/easydiffraction/display/plotters/test_plotly.py index bfb3105f..cb81844e 100644 --- a/tests/unit/easydiffraction/display/plotters/test_plotly.py +++ b/tests/unit/easydiffraction/display/plotters/test_plotly.py @@ -13,11 +13,12 @@ def test_module_import(): assert expected_module_name == actual_module_name -def test_get_layout_sets_axis_title_font_size(): +def test_get_layout_sets_title_and_axis_title_font_sizes(): import easydiffraction.display.plotters.plotly as pp layout = pp.PlotlyPlotter._get_layout('Title', ['x axis', 'y axis']) + assert layout.title.font.size == pp.TITLE_FONT_SIZE assert layout.xaxis.title.font.size == pp.AXIS_TITLE_FONT_SIZE assert layout.yaxis.title.font.size == pp.AXIS_TITLE_FONT_SIZE @@ -784,6 +785,7 @@ def fake_show_figure(self, fig): assert fig.layout.xaxis2.matches == 'x' assert fig.layout.yaxis2.title.text is None assert fig.layout.xaxis2.title.text == '2ΞΈ (degree)' + assert fig.layout.title.font.size == pp.TITLE_FONT_SIZE assert fig.layout.yaxis.title.font.size == pp.AXIS_TITLE_FONT_SIZE assert fig.layout.xaxis2.title.font.size == pp.AXIS_TITLE_FONT_SIZE assert [trace.name for trace in fig.data] == [ diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 09ccf6f6..acc1c9d6 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -311,6 +311,7 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_MARKER_SIZE from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_FONT_SIZE + from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_TOP_MARGIN_PIXELS plotter, _, _ = _make_bayesian_plotter_fixture() @@ -334,6 +335,7 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): 'twotheta_offset', ] assert figure.layout.annotations[0].font.size == POSTERIOR_PAIR_TITLE_FONT_SIZE + assert figure.layout.annotations[0].yshift == POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS assert figure.layout.annotations[0].xshift == -plotter._square_matrix_title_left_shift([ 'length_a', 'broad_gauss_u', @@ -1303,6 +1305,7 @@ def test_plot_param_correlations_renders_plotly_heatmap(monkeypatch): from easydiffraction.display.plotting import POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_FONT_SIZE + from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_TOP_MARGIN_PIXELS from easydiffraction.display.plotting import Plotter @@ -1368,6 +1371,7 @@ class Project: 'phase.
cell.
length_c', ] assert fig.layout.annotations[0].font.size == POSTERIOR_PAIR_TITLE_FONT_SIZE + assert fig.layout.annotations[0].yshift == POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS assert fig.layout.annotations[0].xshift == -Plotter._square_matrix_title_left_shift([ 'phase.
scale', 'phase.
cell.
length_c', From 511a5e5c4053fa4ae334c93cca75173d455caf4c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 09:58:27 +0200 Subject: [PATCH 072/106] Improve Bayesian fit result display --- docs/docs/tutorials/ed-21.py | 4 +- .../analysis/fit_helpers/bayesian.py | 14 +-- .../analysis/fit_helpers/reporting.py | 6 +- src/easydiffraction/display/plotters/base.py | 1 + .../display/plotters/plotly.py | 5 +- src/easydiffraction/display/plotting.py | 28 +++-- .../analysis/fit_helpers/test_bayesian.py | 116 ++++++++++++++++++ .../analysis/fit_helpers/test_reporting.py | 64 ++++++++++ .../display/plotters/test_plotly.py | 43 +++++++ .../easydiffraction/display/test_plotting.py | 104 ++++++++++++++++ 10 files changed, 365 insertions(+), 20 deletions(-) diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 1fadc54f..4bdbc0cf 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -331,4 +331,6 @@ # after the Bayesian run. # %% -project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=45.4, x_max=46.3) +project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=92, x_max=93) + +# %% diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 7e455893..78fa637b 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -621,10 +621,10 @@ def _render_committed_parameter_table(parameters: list[object]) -> None: 'category', 'entry', 'parameter', + 'units', 'start', 'max posterior', 'uncertainty', - 'units', 'change', ] alignments = [ @@ -632,10 +632,10 @@ def _render_committed_parameter_table(parameters: list[object]) -> None: 'left', 'left', 'left', + 'left', 'right', 'right', 'right', - 'left', 'right', ] rows = [_build_parameter_row(parameter) for parameter in parameters] @@ -661,22 +661,22 @@ def _render_posterior_summary_table( 'category', 'entry', 'parameter', + 'units', 'median', '95% interval', - 'r_hat', - 'ess_bulk', - 'units', + 'r-hat', + 'ess bulk', ] alignments = [ 'left', 'left', 'left', 'left', + 'left', 'right', 'right', 'right', 'right', - 'left', ] rows = [ _build_posterior_summary_row(summary, parameters_by_name) @@ -706,11 +706,11 @@ def _build_posterior_summary_row( category, entry, parameter_name, + units, f'{summary.median:.4f}', _format_interval(summary.interval_95), _format_r_hat(summary.r_hat), _format_ess_bulk(summary.ess_bulk), - units, ] diff --git a/src/easydiffraction/analysis/fit_helpers/reporting.py b/src/easydiffraction/analysis/fit_helpers/reporting.py index 0e867156..aefad27b 100644 --- a/src/easydiffraction/analysis/fit_helpers/reporting.py +++ b/src/easydiffraction/analysis/fit_helpers/reporting.py @@ -127,10 +127,10 @@ def display_results( 'category', 'entry', 'parameter', + 'units', 'start', 'fitted', 'uncertainty', - 'units', 'change', ] alignments = [ @@ -138,10 +138,10 @@ def display_results( 'left', 'left', 'left', + 'left', 'right', 'right', 'right', - 'left', 'right', ] @@ -223,10 +223,10 @@ def _build_parameter_row(param: object) -> list[str]: param._identity.category_code, param._identity.category_entry_name or '', name, + units, start, fitted, uncertainty, - units, relative_change, ] diff --git a/src/easydiffraction/display/plotters/base.py b/src/easydiffraction/display/plotters/base.py index 6f041161..d4be0d67 100644 --- a/src/easydiffraction/display/plotters/base.py +++ b/src/easydiffraction/display/plotters/base.py @@ -64,6 +64,7 @@ class PowderMeasVsCalcSpec: predictive_upper_95: np.ndarray | None = None predictive_draws: np.ndarray | None = None y_calc_name: str | None = None + y_calc_line_dash: str | None = None class XAxisType(StrEnum): diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 0366e961..16383473 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -1461,6 +1461,8 @@ def _add_main_intensity_traces( ) if plot_spec.y_calc_name is not None: calc_trace.name = plot_spec.y_calc_name + if plot_spec.y_calc_line_dash is not None: + calc_trace.line.dash = plot_spec.y_calc_line_dash fig.add_trace(calc_trace, row=1, col=1) def _add_predictive_draw_traces( @@ -1718,9 +1720,10 @@ def _get_predictive_band_traces( line={'color': PREDICTIVE_BAND_EDGE_COLOR, 'width': 1}, fill='tonexty', fillcolor=PREDICTIVE_BAND_COLOR, - name='Posterior predictive 95% CI', + name='95% interval', hoverinfo='skip', legendgroup='predictive_band', + legendrank=35, ) return lower_trace, upper_trace diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index c9e8be42..375787a6 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -94,10 +94,13 @@ class PosteriorPairPlotStyleEnum(StrEnum): POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH = 1 POSTERIOR_HISTOGRAM_FILL_COLOR = 'rgba(120, 120, 120, 0.38)' POSTERIOR_HISTOGRAM_LINE_COLOR = 'rgba(120, 120, 120, 0.24)' -POSTERIOR_INTERVAL_95_FILL_COLOR = 'rgba(140, 140, 140, 0.08)' +POSTERIOR_INTERVAL_95_FILL_COLOR = 'rgba(214, 39, 40, 0.26)' POSTERIOR_INTERVAL_68_FILL_COLOR = 'rgba(140, 140, 140, 0.16)' POSTERIOR_MEDIAN_LINE_COLOR = 'rgb(80, 80, 80)' POSTERIOR_POINT_ESTIMATE_LINE_COLOR = 'rgb(214, 39, 40)' +POSTERIOR_POINT_ESTIMATE_TRACE_NAME = 'Max posterior' +POSTERIOR_POINT_ESTIMATE_LINE_DASH = 'dot' +POSTERIOR_PREDICTIVE_INTERVAL_TRACE_NAME = '95% interval' POSTERIOR_DRAW_LINE_COLOR = 'rgba(140, 140, 140, 0.18)' POSTERIOR_SCATTER_MARKER_COLOR = 'rgba(140, 140, 140, 0.20)' POSTERIOR_CONTOUR_FILL_COLORSCALE = [ @@ -2191,9 +2194,9 @@ def _add_posterior_distribution_reference_traces( self._posterior_reference_line_trace( x_value=summary.map_value, y_axis_range=y_axis_range, - trace_name='Max posterior', + trace_name=POSTERIOR_POINT_ESTIMATE_TRACE_NAME, color=POSTERIOR_POINT_ESTIMATE_LINE_COLOR, - dash='dot', + dash=POSTERIOR_POINT_ESTIMATE_LINE_DASH, ) ) @@ -2976,9 +2979,10 @@ def _plot_posterior_predictive_summary( mode='lines', line={'color': 'rgba(0, 0, 0, 0)'}, fill='tonexty', - fillcolor='rgba(214, 39, 40, 0.18)', - name='Posterior predictive 95% CI', + fillcolor=POSTERIOR_INTERVAL_95_FILL_COLOR, + name=POSTERIOR_PREDICTIVE_INTERVAL_TRACE_NAME, hoverinfo='skip', + legendrank=30, ) ) @@ -2998,6 +3002,7 @@ def _plot_posterior_predictive_summary( line={'color': POSTERIOR_DRAW_LINE_COLOR, 'width': 1}, name='Posterior draw' if index == 0 else None, showlegend=index == 0, + legendrank=40, ) ) @@ -3008,6 +3013,7 @@ def _plot_posterior_predictive_summary( mode='lines+markers', line={'color': 'rgb(31, 119, 180)', 'width': 1.5}, name='Measured', + legendrank=10, ) ) fig.add_trace( @@ -3015,8 +3021,13 @@ def _plot_posterior_predictive_summary( x=summary.x, y=summary.map_prediction, mode='lines', - line={'color': POSTERIOR_POINT_ESTIMATE_LINE_COLOR, 'width': 2}, - name='Max posterior prediction', + line={ + 'color': POSTERIOR_POINT_ESTIMATE_LINE_COLOR, + 'width': 2, + 'dash': POSTERIOR_POINT_ESTIMATE_LINE_DASH, + }, + name=POSTERIOR_POINT_ESTIMATE_TRACE_NAME, + legendrank=20, ) ) fig.update_layout( @@ -3136,7 +3147,8 @@ def _plot_posterior_predictive_data( predictive_lower_95=predictive_lower_95, predictive_upper_95=predictive_upper_95, predictive_draws=predictive_draws, - y_calc_name='Max posterior prediction', + y_calc_name=POSTERIOR_POINT_ESTIMATE_TRACE_NAME, + y_calc_line_dash=POSTERIOR_POINT_ESTIMATE_LINE_DASH, ) self._backend.plot_powder_meas_vs_calc(plot_spec=plot_spec) diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py index 708d8a6f..55d8dacc 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py @@ -201,12 +201,128 @@ def test_build_posterior_summary_row_restores_identifier_columns(): 'cat', 'entry', 'a', + 'arb', '1.1500', '[1.0000, 1.3000]', '[red]1.107[/red]', '[red]125.9[/red]', + ] + + +def test_render_committed_parameter_table_places_units_after_parameter(monkeypatch): + from easydiffraction.analysis.fit_helpers import bayesian + + captured: dict[str, object] = {} + + def fake_render_table(*, columns_headers, columns_alignment, columns_data): + captured['columns_headers'] = columns_headers + captured['columns_alignment'] = columns_alignment + captured['columns_data'] = columns_data + + monkeypatch.setattr(bayesian, 'render_table', fake_render_table) + + bayesian._render_committed_parameter_table([ + Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05) + ]) + + assert captured['columns_headers'] == [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'units', + 'start', + 'max posterior', + 'uncertainty', + 'change', + ] + assert captured['columns_alignment'] == [ + 'left', + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'right', + ] + assert captured['columns_data'] == [[ + 'db', + 'cat', + 'entry', + 'a', 'arb', + '1.0000', + '1.2000', + '0.0500', + '20.00 % ↑', + ]] + + +def test_render_posterior_summary_table_places_units_after_parameter(monkeypatch): + from easydiffraction.analysis.fit_helpers import bayesian + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + + captured: dict[str, object] = {} + + def fake_render_table(*, columns_headers, columns_alignment, columns_data): + captured['columns_headers'] = columns_headers + captured['columns_alignment'] = columns_alignment + captured['columns_data'] = columns_data + + monkeypatch.setattr(bayesian, 'render_table', fake_render_table) + + bayesian._render_posterior_summary_table( + parameters=[Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05)], + posterior_parameter_summaries=[ + PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.2, + median=1.15, + standard_deviation=0.05, + interval_68=(1.1, 1.2), + interval_95=(1.0, 1.3), + r_hat=1.107, + ess_bulk=125.9, + ) + ], + ) + + assert captured['columns_headers'] == [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'units', + 'median', + '95% interval', + 'r-hat', + 'ess bulk', + ] + assert captured['columns_alignment'] == [ + 'left', + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'right', ] + assert captured['columns_data'] == [[ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.1500', + '[1.0000, 1.3000]', + '[red]1.107[/red]', + '[red]125.9[/red]', + ]] def test_posterior_table_notes_split_failed_diagnostics(): diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py index ee8014f2..d46f267b 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py @@ -59,3 +59,67 @@ def __init__(self, start, value, uncertainty, name='p', units='u'): assert 'Fitted parameters:' in out # Table border: accept common border glyphs from Rich/tabulate assert any(ch in out for ch in ('β•’', 'β”Œ', '+', '─')) + + +def test_fitresults_display_results_places_units_after_parameter(monkeypatch): + class Identity: + def __init__(self): + self.datablock_entry_name = 'db' + self.category_code = 'cat' + self.category_entry_name = 'entry' + + class Param: + def __init__(self): + self._identity = Identity() + self._fit_start_value = 1.0 + self.value = 1.2 + self.uncertainty = 0.05 + self.name = 'a' + self.units = 'arb' + + from easydiffraction.analysis.fit_helpers import reporting + + captured: dict[str, object] = {} + + def fake_render_table(*, columns_headers, columns_alignment, columns_data): + captured['columns_headers'] = columns_headers + captured['columns_alignment'] = columns_alignment + captured['columns_data'] = columns_data + + monkeypatch.setattr(reporting, 'render_table', fake_render_table) + + reporting.FitResults(success=True, parameters=[Param()]).display_results() + + assert captured['columns_headers'] == [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'units', + 'start', + 'fitted', + 'uncertainty', + 'change', + ] + assert captured['columns_alignment'] == [ + 'left', + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'right', + ] + assert captured['columns_data'] == [[ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.0000', + '1.2000', + '0.0500', + '20.00 % ↑', + ]] diff --git a/tests/unit/easydiffraction/display/plotters/test_plotly.py b/tests/unit/easydiffraction/display/plotters/test_plotly.py index cb81844e..5c3c8dd5 100644 --- a/tests/unit/easydiffraction/display/plotters/test_plotly.py +++ b/tests/unit/easydiffraction/display/plotters/test_plotly.py @@ -795,6 +795,49 @@ def fake_show_figure(self, fig): ] +def test_plot_powder_meas_vs_calc_styles_predictive_max_posterior_and_band(monkeypatch): + import easydiffraction.display.plotters.plotly as pp + + from easydiffraction.display.plotters.base import PowderMeasVsCalcSpec + + captured = {} + + def fake_show_figure(self, fig): + captured['fig'] = fig + + monkeypatch.setattr(pp.PlotlyPlotter, '_show_figure', fake_show_figure) + + plotter = pp.PlotlyPlotter() + plotter.plot_powder_meas_vs_calc( + plot_spec=PowderMeasVsCalcSpec( + x=np.array([1.0, 2.0, 3.0]), + y_meas=np.array([10.0, 12.0, 11.0]), + y_calc=np.array([9.0, 11.0, 10.5]), + y_resid=np.array([1.0, 1.0, 0.5]), + bragg_tick_sets=(), + axes_labels=['2ΞΈ (degree)', 'Intensity (arb. units)'], + title='Powder', + residual_height_fraction=0.25, + bragg_peaks_height_fraction=0.15, + height=None, + predictive_lower_95=np.array([8.0, 9.0, 10.0]), + predictive_upper_95=np.array([10.0, 11.0, 12.0]), + y_calc_name='Max posterior', + y_calc_line_dash='dot', + ), + ) + + fig = captured['fig'] + predictive_band_trace = next(trace for trace in fig.data if trace.name == '95% interval') + max_posterior_trace = next(trace for trace in fig.data if trace.name == 'Max posterior') + residual_trace = next(trace for trace in fig.data if trace.name == 'Residual (Imeas - Icalc)') + + assert predictive_band_trace.fillcolor == pp.PREDICTIVE_BAND_COLOR + assert predictive_band_trace.legendrank == 35 + assert max_posterior_trace.line.dash == 'dot' + assert predictive_band_trace.legendrank < residual_trace.legendrank + + def test_plot_powder_meas_vs_calc_keeps_exact_residual_scale_match(monkeypatch): import easydiffraction.display.plotters.plotly as pp diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index acc1c9d6..0a8b45cb 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -557,6 +557,8 @@ def test_build_param_distribution_plot_returns_plotly_figure(): from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH + from easydiffraction.display.plotting import POSTERIOR_INTERVAL_95_FILL_COLOR + from easydiffraction.display.plotting import POSTERIOR_POINT_ESTIMATE_LINE_DASH plotter, fit_results, _ = _make_bayesian_plotter_fixture() parameter = fit_results.parameters[0] @@ -574,11 +576,15 @@ def test_build_param_distribution_plot_returns_plotly_figure(): } marginal_trace = next(trace for trace in figure.data if trace.name == 'Marginal density') histogram_trace = next(trace for trace in figure.data if trace.name == 'Posterior histogram') + interval_trace = next(trace for trace in figure.data if trace.name == '95% credible interval') + max_posterior_trace = next(trace for trace in figure.data if trace.name == 'Max posterior') assert marginal_trace.line.color == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR assert marginal_trace.line.width == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH assert marginal_trace.fillcolor == POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR assert marginal_trace.hovertemplate == 'length_a: %{x:.4f}
density: %{y:.4f}' assert histogram_trace.xbins.size is not None + assert interval_trace.fillcolor == POSTERIOR_INTERVAL_95_FILL_COLOR + assert max_posterior_trace.line.dash == POSTERIOR_POINT_ESTIMATE_LINE_DASH assert figure.layout.xaxis.range is not None assert tuple(figure.layout.xaxis.range) == ( float(marginal_trace.x[0]), @@ -587,6 +593,104 @@ def test_build_param_distribution_plot_returns_plotly_figure(): assert figure.layout.yaxis.range is not None +def test_plot_posterior_predictive_summary_uses_consistent_labels_and_styles(monkeypatch): + from types import SimpleNamespace + + from easydiffraction.display.plotting import POSTERIOR_INTERVAL_95_FILL_COLOR + from easydiffraction.display.plotting import POSTERIOR_POINT_ESTIMATE_LINE_DASH + from easydiffraction.display.plotting import Plotter + + captured: dict[str, object] = {} + + def fake_show(self): + captured['fig'] = self + + monkeypatch.setattr('plotly.graph_objects.Figure.show', fake_show) + + Plotter._plot_posterior_predictive_summary( + expt_name='hrpt', + summary=SimpleNamespace( + x=np.array([1.0, 2.0, 3.0]), + lower_95=np.array([8.0, 9.0, 10.0]), + upper_95=np.array([10.0, 11.0, 12.0]), + map_prediction=np.array([9.0, 10.0, 11.0]), + ), + y_meas=np.array([9.5, 10.5, 11.5]), + axes_labels=['2ΞΈ (degree)', 'Intensity (arb. units)'], + show_band=True, + show_draws=False, + ) + + fig = captured['fig'] + upper_band_trace = fig.data[1] + measured_trace = next(trace for trace in fig.data if trace.name == 'Measured') + max_posterior_trace = next(trace for trace in fig.data if trace.name == 'Max posterior') + + assert upper_band_trace.name == '95% interval' + assert upper_band_trace.fillcolor == POSTERIOR_INTERVAL_95_FILL_COLOR + assert upper_band_trace.legendrank == 30 + assert measured_trace.legendrank == 10 + assert max_posterior_trace.legendrank == 20 + assert max_posterior_trace.line.dash == POSTERIOR_POINT_ESTIMATE_LINE_DASH + + +def test_plot_posterior_predictive_data_uses_max_posterior_label_and_dash(monkeypatch): + from types import SimpleNamespace + + from easydiffraction.datablocks.experiment.item.enums import BeamModeEnum + from easydiffraction.datablocks.experiment.item.enums import SampleFormEnum + from easydiffraction.datablocks.experiment.item.enums import ScatteringTypeEnum + from easydiffraction.display.plotting import Plotter + from easydiffraction.display.plotting import XAxisType + + captured: dict[str, object] = {} + + class ExptType: + sample_form = type('SF', (), {'value': SampleFormEnum.POWDER})() + scattering_type = type('S', (), {'value': ScatteringTypeEnum.BRAGG})() + beam_mode = type('B', (), {'value': BeamModeEnum.CONSTANT_WAVELENGTH})() + + class Pattern: + two_theta = np.array([1.0, 2.0, 3.0]) + intensity_meas = np.array([10.0, 12.0, 11.0]) + intensity_bkg = np.array([1.0, 1.0, 1.0]) + + class Experiment: + type = ExptType() + data = Pattern() + + plotter = Plotter() + plotter.engine = 'plotly' + plotter._backend = SimpleNamespace( + plot_powder_meas_vs_calc=lambda *, plot_spec: captured.setdefault('plot_spec', plot_spec) + ) + + monkeypatch.setattr( + Plotter, + '_get_or_build_posterior_predictive_summary', + lambda self, **kwargs: SimpleNamespace( + x=np.array([1.0, 2.0, 3.0]), + lower_95=np.array([8.0, 9.0, 10.0]), + upper_95=np.array([10.0, 11.0, 12.0]), + map_prediction=np.array([9.0, 11.0, 10.5]), + draws=None, + ), + ) + monkeypatch.setattr(Plotter, '_extract_bragg_tick_sets', lambda self, **kwargs: ()) + + plotter._plot_posterior_predictive_data( + experiment=Experiment(), + expt_name='hrpt', + plot_options=SimpleNamespace(x_min=None, x_max=None, show_residual=None, x=None), + x_axis=XAxisType.TWO_THETA, + style='band', + ) + + plot_spec = captured['plot_spec'] + assert plot_spec.y_calc_name == 'Max posterior' + assert plot_spec.y_calc_line_dash == 'dot' + + def test_build_param_distribution_plot_accepts_unique_name_string(): plotter, _, _ = _make_bayesian_plotter_fixture() From 46791e27c5b6404e037770df2a2075590f5348eb Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 09:59:01 +0200 Subject: [PATCH 073/106] Adjust posterior and band fill transparency --- src/easydiffraction/display/plotters/plotly.py | 2 +- src/easydiffraction/display/plotting.py | 4 ++-- tests/unit/easydiffraction/display/test_plotting.py | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/easydiffraction/display/plotters/plotly.py b/src/easydiffraction/display/plotters/plotly.py index 16383473..cb4914c3 100644 --- a/src/easydiffraction/display/plotters/plotly.py +++ b/src/easydiffraction/display/plotters/plotly.py @@ -67,7 +67,7 @@ COMPOSITE_MARGIN_BOTTOM = 45 TITLE_FONT_SIZE = 14 AXIS_TITLE_FONT_SIZE = 12 -PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.26)' +PREDICTIVE_BAND_COLOR = 'rgba(214, 39, 40, 0.14)' PREDICTIVE_BAND_EDGE_COLOR = 'rgba(214, 39, 40, 0.45)' PREDICTIVE_DRAW_COLOR = 'rgba(140, 140, 140, 0.18)' PREDICTIVE_DRAW_PLOT_CAP = 50 diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 375787a6..a3076463 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -94,8 +94,8 @@ class PosteriorPairPlotStyleEnum(StrEnum): POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH = 1 POSTERIOR_HISTOGRAM_FILL_COLOR = 'rgba(120, 120, 120, 0.38)' POSTERIOR_HISTOGRAM_LINE_COLOR = 'rgba(120, 120, 120, 0.24)' -POSTERIOR_INTERVAL_95_FILL_COLOR = 'rgba(214, 39, 40, 0.26)' -POSTERIOR_INTERVAL_68_FILL_COLOR = 'rgba(140, 140, 140, 0.16)' +POSTERIOR_INTERVAL_95_FILL_COLOR = 'rgba(214, 39, 40, 0.14)' +POSTERIOR_INTERVAL_68_FILL_COLOR = 'rgba(214, 39, 40, 0.26)' POSTERIOR_MEDIAN_LINE_COLOR = 'rgb(80, 80, 80)' POSTERIOR_POINT_ESTIMATE_LINE_COLOR = 'rgb(214, 39, 40)' POSTERIOR_POINT_ESTIMATE_TRACE_NAME = 'Max posterior' diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 0a8b45cb..4870d299 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -554,6 +554,7 @@ def test_build_posterior_pairs_plot_rejects_unknown_style(): def test_build_param_distribution_plot_returns_plotly_figure(): + from easydiffraction.display.plotting import POSTERIOR_INTERVAL_68_FILL_COLOR from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR from easydiffraction.display.plotting import POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_WIDTH @@ -576,6 +577,7 @@ def test_build_param_distribution_plot_returns_plotly_figure(): } marginal_trace = next(trace for trace in figure.data if trace.name == 'Marginal density') histogram_trace = next(trace for trace in figure.data if trace.name == 'Posterior histogram') + interval_68_trace = next(trace for trace in figure.data if trace.name == '68% credible interval') interval_trace = next(trace for trace in figure.data if trace.name == '95% credible interval') max_posterior_trace = next(trace for trace in figure.data if trace.name == 'Max posterior') assert marginal_trace.line.color == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR @@ -583,6 +585,7 @@ def test_build_param_distribution_plot_returns_plotly_figure(): assert marginal_trace.fillcolor == POSTERIOR_PAIR_MARGINAL_DENSITY_FILL_COLOR assert marginal_trace.hovertemplate == 'length_a: %{x:.4f}
density: %{y:.4f}' assert histogram_trace.xbins.size is not None + assert interval_68_trace.fillcolor == POSTERIOR_INTERVAL_68_FILL_COLOR assert interval_trace.fillcolor == POSTERIOR_INTERVAL_95_FILL_COLOR assert max_posterior_trace.line.dash == POSTERIOR_POINT_ESTIMATE_LINE_DASH assert figure.layout.xaxis.range is not None From f3f5accbd01bb3aab00b169435ada0f654932c38 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 10:17:53 +0200 Subject: [PATCH 074/106] Update fit bounds and plot range in ed-21 --- docs/docs/tutorials/ed-21.ipynb | 4 ++-- docs/docs/tutorials/ed-21.py | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/docs/tutorials/ed-21.ipynb b/docs/docs/tutorials/ed-21.ipynb index 0a198508..305ece8d 100644 --- a/docs/docs/tutorials/ed-21.ipynb +++ b/docs/docs/tutorials/ed-21.ipynb @@ -513,7 +513,7 @@ "outputs": [], "source": [ "for param in project.free_parameters:\n", - " param.set_fit_bounds_from_uncertainty(multiplier=3)" + " param.set_fit_bounds_from_uncertainty(multiplier=3.5)" ] }, { @@ -713,7 +713,7 @@ "metadata": {}, "outputs": [], "source": [ - "project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=45.4, x_max=46.3)" + "project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=92, x_max=93)" ] } ], diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 4bdbc0cf..5cb44557 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -243,7 +243,7 @@ # %% for param in project.free_parameters: - param.set_fit_bounds_from_uncertainty(multiplier=3) + param.set_fit_bounds_from_uncertainty(multiplier=3.5) # %% [markdown] # Displaying the free parameters again is a convenient way to confirm @@ -332,5 +332,3 @@ # %% project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=92, x_max=93) - -# %% From 1f3e1ae6cd609069636a87c846147edc0c56504f Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 10:39:21 +0200 Subject: [PATCH 075/106] Improve posterior table diagnostic notes --- .../analysis/fit_helpers/bayesian.py | 8 ++-- .../analysis/minimizers/bumps_dream.py | 4 +- .../analysis/fit_helpers/test_bayesian.py | 48 ++++++++++--------- .../analysis/fit_helpers/test_reporting.py | 24 +++++----- .../easydiffraction/display/test_plotting.py | 4 +- 5 files changed, 47 insertions(+), 41 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 78fa637b..db3bd220 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -758,12 +758,12 @@ def _posterior_table_notes( notes: list[str] = [] if has_failed_r_hat: notes.append( - f'[red]r_hat[/red]: exceeds {R_HAT_CONVERGENCE_THRESHOLD:.2f} ' - '(consider longer sampling, tighter bounds, or reparameterization).' + f'[red]r-hat[/red]: exceeds {R_HAT_CONVERGENCE_THRESHOLD:.2f} ' + 'Consider longer sampling, better initialization, or reparameterization.' ) if has_failed_ess_bulk: notes.append( - f'[red]ess_bulk[/red]: less than {ESS_BULK_CONVERGENCE_THRESHOLD:.0f} ' - '(consider longer sampling, tighter bounds, or reparameterization).' + f'[red]ess bulk[/red]: less than {ESS_BULK_CONVERGENCE_THRESHOLD:.0f} ' + 'Consider longer sampling or reparameterization.' ) return notes diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index f7060d12..82226547 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -762,9 +762,7 @@ def _build_success_result( ) if not convergence_diagnostics.get('converged', True): - log.warning( - 'Convergence diagnostics indicate the posterior may be poorly mixed.' - ) + log.warning('Convergence diagnostics indicate the posterior may be poorly mixed.') return OptimizeResult( x=map_values, diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py index 55d8dacc..020b87fe 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py @@ -247,17 +247,19 @@ def fake_render_table(*, columns_headers, columns_alignment, columns_data): 'right', 'right', ] - assert captured['columns_data'] == [[ - 'db', - 'cat', - 'entry', - 'a', - 'arb', - '1.0000', - '1.2000', - '0.0500', - '20.00 % ↑', - ]] + assert captured['columns_data'] == [ + [ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.0000', + '1.2000', + '0.0500', + '20.00 % ↑', + ] + ] def test_render_posterior_summary_table_places_units_after_parameter(monkeypatch): @@ -312,17 +314,19 @@ def fake_render_table(*, columns_headers, columns_alignment, columns_data): 'right', 'right', ] - assert captured['columns_data'] == [[ - 'db', - 'cat', - 'entry', - 'a', - 'arb', - '1.1500', - '[1.0000, 1.3000]', - '[red]1.107[/red]', - '[red]125.9[/red]', - ]] + assert captured['columns_data'] == [ + [ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.1500', + '[1.0000, 1.3000]', + '[red]1.107[/red]', + '[red]125.9[/red]', + ] + ] def test_posterior_table_notes_split_failed_diagnostics(): diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py index d46f267b..bb824f82 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_reporting.py @@ -112,14 +112,16 @@ def fake_render_table(*, columns_headers, columns_alignment, columns_data): 'right', 'right', ] - assert captured['columns_data'] == [[ - 'db', - 'cat', - 'entry', - 'a', - 'arb', - '1.0000', - '1.2000', - '0.0500', - '20.00 % ↑', - ]] + assert captured['columns_data'] == [ + [ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.0000', + '1.2000', + '0.0500', + '20.00 % ↑', + ] + ] diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 4870d299..66fee2a1 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -577,7 +577,9 @@ def test_build_param_distribution_plot_returns_plotly_figure(): } marginal_trace = next(trace for trace in figure.data if trace.name == 'Marginal density') histogram_trace = next(trace for trace in figure.data if trace.name == 'Posterior histogram') - interval_68_trace = next(trace for trace in figure.data if trace.name == '68% credible interval') + interval_68_trace = next( + trace for trace in figure.data if trace.name == '68% credible interval' + ) interval_trace = next(trace for trace in figure.data if trace.name == '95% credible interval') max_posterior_trace = next(trace for trace in figure.data if trace.name == 'Max posterior') assert marginal_trace.line.color == POSTERIOR_PAIR_MARGINAL_DENSITY_LINE_COLOR From 01dc0057fd0fdabc015a23207553f0ad2055b89b Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 10:59:37 +0200 Subject: [PATCH 076/106] Add parallel DREAM sampling --- docs/docs/tutorials/ed-21.ipynb | 2 +- docs/docs/tutorials/ed-21.py | 2 +- .../analysis/fit_helpers/bayesian.py | 4 +- .../analysis/minimizers/bumps_dream.py | 50 ++++++++++++++----- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/docs/docs/tutorials/ed-21.ipynb b/docs/docs/tutorials/ed-21.ipynb index 305ece8d..82aa0c0e 100644 --- a/docs/docs/tutorials/ed-21.ipynb +++ b/docs/docs/tutorials/ed-21.ipynb @@ -586,7 +586,7 @@ "metadata": {}, "outputs": [], "source": [ - "project.analysis.fit.minimizer.steps = 50 # 1000" + "project.analysis.fit.minimizer.steps = 100 # 1000" ] }, { diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 5cb44557..1d59516f 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -278,7 +278,7 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' # %% -project.analysis.fit.minimizer.steps = 50 # 1000 +project.analysis.fit.minimizer.steps = 100 # 1000 # %% project.analysis.fit() diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index db3bd220..907cb53f 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -758,12 +758,12 @@ def _posterior_table_notes( notes: list[str] = [] if has_failed_r_hat: notes.append( - f'[red]r-hat[/red]: exceeds {R_HAT_CONVERGENCE_THRESHOLD:.2f} ' + f'[red]r-hat > {R_HAT_CONVERGENCE_THRESHOLD:.2f}[/red]: ' 'Consider longer sampling, better initialization, or reparameterization.' ) if has_failed_ess_bulk: notes.append( - f'[red]ess bulk[/red]: less than {ESS_BULK_CONVERGENCE_THRESHOLD:.0f} ' + f'[red]ess bulk < {ESS_BULK_CONVERGENCE_THRESHOLD:.0f}[/red]: ' 'Consider longer sampling or reparameterization.' ) return notes diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 82226547..c23d923c 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -12,6 +12,8 @@ from bumps.fitters import FITTERS from bumps.fitters import FitDriver from bumps.fitters import monitor as bumps_monitor +from bumps.mapper import MPMapper +from bumps.mapper import can_pickle from scipy.optimize import OptimizeResult from easydiffraction.analysis.fit_helpers.bayesian import BayesianFitResults @@ -34,6 +36,7 @@ DEFAULT_MIN_BURN = 50 DEFAULT_THIN = 1 DEFAULT_POP = 4 +DEFAULT_PARALLEL = 0 DEFAULT_INIT = DreamPopulationInitializationEnum.EPS DEFAULT_ALPHA = 0.0 DEFAULT_OUTLIER_TEST = 'none' @@ -264,6 +267,7 @@ def __init__( self._burn: int | None = None self._thin: int = DEFAULT_THIN self._pop: int = DEFAULT_POP + self._parallel: int = DEFAULT_PARALLEL self._init: DreamPopulationInitializationEnum = DEFAULT_INIT @property @@ -305,6 +309,15 @@ def pop(self) -> int: def pop(self, value: int) -> None: self._pop = self._validated_positive_integer('pop', value) + @property + def parallel(self) -> int: + """DREAM parallel worker count; ``0`` uses all CPUs.""" + return self._parallel + + @parallel.setter + def parallel(self, value: int) -> None: + self._parallel = self._validated_non_negative_integer('parallel', value) + @property def init(self) -> DreamPopulationInitializationEnum: """DREAM population initializer.""" @@ -495,26 +508,24 @@ def _resolved_burn(self, steps: int) -> int: raise ValueError(msg) return burn - @staticmethod def _sampler_settings( + self, *, random_seed: int, steps: int, burn: int, - thin: int, - pop: int, - init: DreamPopulationInitializationEnum, n_parameters: int, ) -> dict[str, object]: """Build the sampler settings dictionary recorded in results.""" - samples = steps * pop * n_parameters + samples = steps * self.pop * n_parameters return { 'random_seed': int(random_seed), 'steps': int(steps), 'burn': int(burn), - 'thin': int(thin), - 'pop': int(pop), - 'init': init.value, + 'thin': int(self.thin), + 'pop': int(self.pop), + 'parallel': int(self.parallel), + 'init': self.init.value, 'samples': int(samples), 'alpha': float(DEFAULT_ALPHA), 'outliers': DEFAULT_OUTLIER_TEST, @@ -591,9 +602,6 @@ def _prepare_run_context( random_seed=random_seed, steps=steps, burn=burn, - thin=self.thin, - pop=self.pop, - init=init, n_parameters=len(bumps_params), ) driver = self._build_driver( @@ -634,6 +642,7 @@ def _build_driver( ) -> FitDriver: """Build and clip the BUMPS DREAM driver.""" total_generations = int(steps + burn + 1) + problem = FitProblem(fitness) progress_monitor = _DreamProgressMonitor( tracker=self.tracker, n_points=fitness.numpoints(), @@ -641,10 +650,12 @@ def _build_driver( total_generations=total_generations, burn_steps=int(burn), ) + mapper = self._build_mapper(problem) driver = FitDriver( fitclass=fitclass, - problem=FitProblem(fitness), + problem=problem, monitors=[progress_monitor], + mapper=mapper, steps=steps, burn=burn, thin=self.thin, @@ -658,6 +669,20 @@ def _build_driver( driver.clip() return driver + def _build_mapper(self, problem: FitProblem) -> object | None: + """Return a DREAM mapper for the configured parallel setting.""" + if self.parallel == 1: + return None + + if not can_pickle(problem): + log.warning( + 'DREAM parallel evaluation requires a picklable ' + 'problem; falling back to serial execution.' + ) + return None + + return MPMapper.start_mapper(problem, [], cpus=self.parallel) + @staticmethod def _execute_driver(*, driver: FitDriver, random_seed: int) -> _DreamDriverResult: """ @@ -678,6 +703,7 @@ def _execute_driver(*, driver: FitDriver, random_seed: int) -> _DreamDriverResul error=error, ) finally: + MPMapper.stop_mapper() numpy_rng.set_state(numpy_state) random.setstate(python_state) From 83ef1534009d9513a0129f090041547a783bd42e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 11:06:25 +0200 Subject: [PATCH 077/106] Add parallel=0 description to DREAM tutorial --- docs/docs/tutorials/ed-21.ipynb | 15 ++++++++------- docs/docs/tutorials/ed-21.py | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/docs/tutorials/ed-21.ipynb b/docs/docs/tutorials/ed-21.ipynb index 82aa0c0e..d2a23c71 100644 --- a/docs/docs/tutorials/ed-21.ipynb +++ b/docs/docs/tutorials/ed-21.ipynb @@ -550,13 +550,14 @@ "of steps (`steps`) and often the burn-in (`burn`) as well. When\n", "needed, the DREAM API also lets you tune how chains are initialized\n", "through the `init` setting. Other sampler settings such as `thin` and\n", - "`pop` can be adjusted as well, but here we keep them at their\n", - "defaults.\n", + "`pop` can be adjusted as well. The current EasyDiffraction default\n", + "also uses `parallel=0`, which tells BUMPS DREAM to use all available\n", + "CPUs for population evaluations.\n", "\n", - "Default `steps` is 1000, which is often need to be increased for a\n", - "real analysis to ensure good convergence and sampling of the posterior\n", - "distribution. Here we use much smaller value to speed up the tutorial,\n", - "but this is not recommended for a real analysis." + "The default `steps` value is 1000, and real analyses often need more\n", + "to achieve good convergence and posterior sampling. Here we use a much\n", + "smaller value to keep the tutorial fast, but this is not recommended\n", + "for production analysis." ] }, { @@ -586,7 +587,7 @@ "metadata": {}, "outputs": [], "source": [ - "project.analysis.fit.minimizer.steps = 100 # 1000" + "project.analysis.fit.minimizer.steps = 100 # lower than the default 1000" ] }, { diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index 1d59516f..ccfdb965 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -263,13 +263,14 @@ # of steps (`steps`) and often the burn-in (`burn`) as well. When # needed, the DREAM API also lets you tune how chains are initialized # through the `init` setting. Other sampler settings such as `thin` and -# `pop` can be adjusted as well, but here we keep them at their -# defaults. +# `pop` can be adjusted as well. The current EasyDiffraction default +# also uses `parallel=0`, which tells BUMPS DREAM to use all available +# CPUs for population evaluations. # -# Default `steps` is 1000, which is often need to be increased for a -# real analysis to ensure good convergence and sampling of the posterior -# distribution. Here we use much smaller value to speed up the tutorial, -# but this is not recommended for a real analysis. +# The default `steps` value is 1000, and real analyses often need more +# to achieve good convergence and posterior sampling. Here we use a much +# smaller value to keep the tutorial fast, but this is not recommended +# for production analysis. # %% project.analysis.fit.show_minimizer_types() @@ -278,7 +279,7 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' # %% -project.analysis.fit.minimizer.steps = 100 # 1000 +project.analysis.fit.minimizer.steps = 100 # lower than the default 1000 # %% project.analysis.fit() From b2ac66af6fd1e4a7df5e700c80966c683a2f7708 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 11:09:12 +0200 Subject: [PATCH 078/106] Fix test expectations for r-hat and parallel=0 --- .../analysis/fit_helpers/test_bayesian.py | 4 +- .../analysis/minimizers/test_bumps_dream.py | 8 +- tmp/bumps_dream/ed-2-bayesian-new-API.py | 333 ------------------ 3 files changed, 7 insertions(+), 338 deletions(-) delete mode 100644 tmp/bumps_dream/ed-2-bayesian-new-API.py diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py index 020b87fe..278a48ce 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py @@ -348,5 +348,5 @@ def test_posterior_table_notes_split_failed_diagnostics(): ]) assert len(notes) == 2 - assert 'r_hat' in notes[0] - assert 'ess_bulk' in notes[1] + assert 'r-hat' in notes[0] + assert 'ess bulk' in notes[1] diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py index 9fa85263..8e800cb4 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py @@ -110,17 +110,19 @@ def test_sampler_settings_include_init_and_sample_count(): from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum minimizer = BumpsDreamMinimizer() + minimizer.thin = 1 + minimizer.pop = 4 + minimizer.init = DreamPopulationInitializationEnum.LHS + settings = minimizer._sampler_settings( random_seed=7, steps=10, burn=2, - thin=1, - pop=4, - init=DreamPopulationInitializationEnum.LHS, n_parameters=3, ) assert settings['random_seed'] == 7 + assert settings['parallel'] == 0 assert settings['init'] == 'lhs' assert settings['samples'] == 120 diff --git a/tmp/bumps_dream/ed-2-bayesian-new-API.py b/tmp/bumps_dream/ed-2-bayesian-new-API.py deleted file mode 100644 index 571cd01f..00000000 --- a/tmp/bumps_dream/ed-2-bayesian-new-API.py +++ /dev/null @@ -1,333 +0,0 @@ -# %% [markdown] -# # Deterministic and Bayesian Refinement: LBCO, HRPT -# -# This tutorial demonstrates a practical two-stage workflow for powder -# diffraction analysis with EasyDiffraction. -# -# In the first stage, we run a fast local refinement to obtain a sensible -# point estimate and parameter uncertainties. In the second stage, we use -# these refined values to define fit bounds and then sample the posterior -# distribution with DREAM. -# -# The example uses constant-wavelength neutron powder diffraction data -# for La0.5Ba0.5CoO3 measured on HRPT at PSI. -# -# The goal is not only to obtain a good fit, but also to answer Bayesian -# questions such as: -# -# - Which parameter values are most probable? -# - How broad are the credible intervals? -# - Which parameters are strongly correlated? -# - How much uncertainty propagates into the calculated diffraction -# pattern? - -# %% [markdown] -# ## Import Library - -# %% -import easydiffraction as ed - -# %% [markdown] -# ## Step 1: Create a Project Container -# -# The project object keeps structures, experiments, fit settings, and -# plotting utilities together in a single place. We will build the full -# workflow inside this object. - -# %% -project = ed.Project() - -# %% [markdown] -# ## Step 2: Build the Structural Model -# -# We define a simple cubic perovskite model for LBCO. La and Ba share the -# same crystallographic site with equal occupancy, while Co and O occupy -# the remaining ideal perovskite positions. - -# %% -project.structures.create(name='lbco') - -# %% -structure = project.structures['lbco'] - -# %% -structure.space_group.name_h_m = 'P m -3 m' -structure.space_group.it_coordinate_system_code = '1' - -# %% -structure.cell.length_a = 3.88 - -# %% [markdown] -# The atom-site definitions below form the starting structural model. The -# parameters are intentionally reasonable rather than fully optimized, -# because the refinement step will improve them. - -# %% -structure.atom_sites.create( - label='La', - type_symbol='La', - fract_x=0, - fract_y=0, - fract_z=0, - wyckoff_letter='a', - adp_type='Biso', - adp_iso=0.5151, - occupancy=0.5, -) -structure.atom_sites.create( - label='Ba', - type_symbol='Ba', - fract_x=0, - fract_y=0, - fract_z=0, - wyckoff_letter='a', - adp_type='Biso', - adp_iso=0.5151, - occupancy=0.5, -) -structure.atom_sites.create( - label='Co', - type_symbol='Co', - fract_x=0.5, - fract_y=0.5, - fract_z=0.5, - wyckoff_letter='b', - adp_type='Biso', - adp_iso=0.2190, -) -structure.atom_sites.create( - label='O', - type_symbol='O', - fract_x=0, - fract_y=0.5, - fract_z=0.5, - wyckoff_letter='c', - adp_type='Biso', - adp_iso=1.3916, -) - -# %% [markdown] -# ## Step 3: Define the Diffraction Experiment -# -# Next we download the measured powder pattern, create a neutron powder -# experiment, and configure the instrument, profile, background, and -# excluded regions. - -# %% [markdown] -# #### Download the Measured Data - -# %% -data_path = ed.download_data(id=3, destination='data') - -# %% [markdown] -# #### Create the Experiment Object - -# %% -project.experiments.add_from_data_path( - name='hrpt', - data_path=data_path, - sample_form='powder', - beam_mode='constant wavelength', - radiation_probe='neutron', -) - -# %% -experiment = project.experiments['hrpt'] - -# %% [markdown] -# #### Set Instrument and Peak-Profile Parameters -# -# These values provide the initial instrument description for the local -# refinement. Later, a subset of them will be refined. - -# %% -experiment.instrument.setup_wavelength = 1.494 -experiment.instrument.calib_twotheta_offset = 0.0 - -# %% -experiment.peak.broad_gauss_u = 0.1 -experiment.peak.broad_gauss_v = -0.1 -experiment.peak.broad_gauss_w = 0.1204 -experiment.peak.broad_lorentz_y = 0.0844 - -# %% [markdown] -# #### Add Background Points and Excluded Regions -# -# The line-segment background is defined by a few anchor points. We also -# exclude regions that are not intended to contribute to the fit. - -# %% -experiment.background.create(id='1', x=10, y=168.5585) -experiment.background.create(id='2', x=30, y=164.3357) -experiment.background.create(id='3', x=50, y=166.8881) -experiment.background.create(id='4', x=110, y=175.4006) -experiment.background.create(id='5', x=165, y=174.2813) - -# %% -experiment.excluded_regions.create(id='1', start=0, end=30) -experiment.excluded_regions.create(id='2', start=70, end=180) - -# %% [markdown] -# #### Link the Structural Phase to the Experiment - -# %% -experiment.linked_phases.create(id='lbco', scale=9.1351) - -# %% [markdown] -# ## Step 4: Run an Initial Local Refinement -# -# Before Bayesian sampling, it is useful to run a deterministic fit. This -# gives us: -# -# - a good point estimate near the best-fit region, -# - uncertainties from the local optimizer, -# - a quick check that the model and experiment are configured -# sensibly. -# -# In this tutorial we refine only a small set of parameters that are easy -# to interpret in the later Bayesian stage. - -# %% -structure.cell.length_a.free = True -experiment.peak.broad_gauss_u.free = True -experiment.peak.broad_gauss_v.free = True -experiment.peak.broad_gauss_w.free = True -experiment.instrument.calib_twotheta_offset.free = True - -# %% [markdown] -# We choose the BUMPS Levenberg-Marquardt minimizer as a fast local -# optimizer. Its main purpose here is to provide a stable starting point -# and uncertainty estimates for the Bayesian run. - -# %% -project.analysis.fit.show_minimizer_types() -project.analysis.fit.minimizer_type = 'bumps (lm)' - -# %% -project.analysis.fit() - -# %% -project.analysis.display.fit_results() - -# %% [markdown] -# The correlation plot shows how strongly the fitted parameters move -# together in the local refinement. The measured-vs-calculated plots show -# how well the refined model reproduces the data globally and in a zoomed -# region. - -# %% -project.display.plotter.plot_param_correlations(show_diagonal=True) - -# %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') - -# %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) - -# %% [markdown] -# ## Step 5: Prepare for Bayesian Sampling -# -# DREAM requires finite bounds for the free parameters. Instead of -# setting them manually, we derive them from the uncertainties estimated -# in the local refinement. -# -# The helper method `set_fit_bounds_from_uncertainty` centers the bounds -# on the current parameter value and expands them by a chosen multiple of -# the reported uncertainty. - -# %% -project.analysis.display.free_params() - -# %% -structure.cell.length_a.set_fit_bounds_from_uncertainty(multiplier=4) -experiment.peak.broad_gauss_u.set_fit_bounds_from_uncertainty(multiplier=4) -experiment.peak.broad_gauss_v.set_fit_bounds_from_uncertainty(multiplier=4) -experiment.peak.broad_gauss_w.set_fit_bounds_from_uncertainty(multiplier=4) -experiment.instrument.calib_twotheta_offset.set_fit_bounds_from_uncertainty(multiplier=4) - -# %% [markdown] -# Displaying the free parameters again is a convenient way to confirm -# that the fit bounds have been assigned as expected before launching the -# sampler. - -# %% -project.analysis.display.free_params() - -# %% [markdown] -# ## Step 6: Configure and Run DREAM -# -# We now switch from the local minimizer to the Bayesian DREAM sampler. -# -# The settings below are intentionally small so the tutorial runs -# quickly. For production analysis you would usually increase the number -# of steps and often the burn-in as well. When needed, the DREAM API -# also lets you tune how chains are initialized through the `init` -# setting. - -# %% -project.analysis.fit.show_minimizer_types() - -# %% -project.analysis.fit.minimizer_type = 'bumps (dream)' - -# %% -project.analysis.fit.minimizer.steps = 200 #1000 -project.analysis.fit.minimizer.burn = 40 #200 -project.analysis.fit.minimizer.thin = 1 -project.analysis.fit.minimizer.pop = 4 - -# %% -project.analysis.fit() - -# %% [markdown] -# ## Step 7: Inspect Bayesian Results -# -# The fit-results display now includes sampler settings, convergence -# diagnostics, committed parameter values, and posterior summary -# statistics. - -# %% -project.analysis.display.fit_results() - -# %% [markdown] -# The correlation and posterior-pair plots are complementary: -# -# - `plot_param_correlations` summarizes pairwise structure in a compact -# matrix. -# - `plot_posterior_pairs` shows marginal densities on the diagonal and -# posterior contours off-diagonal. - -# %% -project.display.plotter.plot_param_correlations(show_diagonal=True) - -# %% -project.display.plotter.plot_posterior_pairs() - -# %% [markdown] -# The one-dimensional posterior distributions below make it easier to -# inspect individual parameters in isolation, including asymmetry or -# multimodality. - -# %% -project.display.plotter.plot_param_distribution(structure.cell.length_a) -project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_u) -project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_v) -project.display.plotter.plot_param_distribution(experiment.peak.broad_gauss_w) -project.display.plotter.plot_param_distribution(experiment.instrument.calib_twotheta_offset) - -# %% [markdown] -# Finally, the posterior predictive plot propagates the sampled parameter -# uncertainty into the calculated diffraction pattern. Comparing this to -# the zoomed measured-vs-calculated view helps assess whether the sampled -# model family explains the data in the region of interest. - -# %% -project.display.plotter.plot_posterior_predictive(expt_name='hrpt') - -# %% [markdown] -# A final zoomed measured-vs-calculated plot is useful for checking how -# the posterior-supported model behaves in a narrow region of the pattern -# after the Bayesian run. - -# %% -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', x_min=65, x_max=68) From 72093d739c24194b8879aee0da42c46a81a41bf3 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 11:14:50 +0200 Subject: [PATCH 079/106] Add Bayesian DREAM to architecture --- docs/dev/architecture.md | 58 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index 8c30e378..48a41161 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md @@ -826,14 +826,45 @@ workflow: only `single`; >1 β†’ all three). - Joint-fit weights: `joint_fit_experiments` (`CategoryCollection` of per-experiment weight entries); sibling of `fit`, not a child. +- Fit results: `analysis.fit_results` stores the latest runtime result + object. This is `FitResults` for deterministic fits and + `BayesianFitResults` for Bayesian DREAM runs. - Parameter tables: `show_all_params()`, `show_fittable_params()`, `show_free_params()`, `how_to_access_parameters()` - Fitting: `fit()` dispatches single/joint through the callable `fit` category; `fit_sequential()` handles sequential mode (sets `fit.mode` - to `'sequential'` internally). `display.fit_results()` shows results. + to `'sequential'` internally). `fit()` accepts optional `random_seed` + for stochastic minimizers; deterministic minimizers reject non-`None` + seeds. `display.fit_results()` dispatches through the active runtime + result object. - Aliases and constraints (single-type categories; no public `_type` getter or setter) +#### 6.4.1 Bayesian DREAM Runtime Results + +Bayesian sampling is integrated as a normal minimizer selection with tag +`'bumps (dream)'`. It does not create a parallel `Analysis` stack or a +new persisted results category. + +- `BayesianFitResults` extends `FitResults` with runtime-only posterior + state such as `posterior_samples`, `posterior_parameter_summaries`, + `posterior_predictive`, `diagnostics`, and `sampler_settings`. +- Posterior arrays and predictive caches remain runtime-only; they are + not serialized into CIF or project directories. +- `sampler_settings` records the resolved stochastic settings actually + used for the run, including `random_seed`, `steps`, `burn`, `thin`, + `pop`, and `parallel`. +- The current user-facing DREAM controls live on the active minimizer + object, for example `project.analysis.fit.minimizer.steps`, `burn`, + `thin`, `pop`, `parallel`, and `init`. +- `plot_param_correlations()` uses posterior samples when available and + otherwise falls back to deterministic covariance or engine-derived + correlations. +- Bayesian-only plotting methods are exposed explicitly rather than by + overloading deterministic plot calls: `plot_posterior_pairs()`, + `plot_param_distribution(param)`, and + `plot_posterior_predictive(expt_name, ...)`. + --- ## 7. Project β€” The Top-Level FaΓ§ade @@ -895,7 +926,9 @@ project_dir/ saved project re-opens with the same display backends. Per-experiment calculator selection (`_calculation.calculator_type`) lives in each experiment file, and fit configuration (`_fit.minimizer_type`, -`_fit.mode`) lives in `analysis/analysis.cif`. +`_fit.mode`) lives in `analysis/analysis.cif`. Runtime fit outputs, +including `analysis.fit_results`, posterior chains, posterior predictive +summaries, and convergence diagnostics, are not serialized. ### 7.3 Verbosity @@ -1053,6 +1086,27 @@ project.display.plotter.plot_meas_vs_calc(expt_name='hrpt', show_residual=True) project.save() ``` +### 8.4.1 Bayesian Refinement + +```python +# Deterministic pre-fit remains explicit +project.analysis.fit.minimizer_type = 'bumps (lm)' +project.analysis.fit() + +# Switch to Bayesian sampling using the same entry point +project.analysis.fit.minimizer_type = 'bumps (dream)' +project.analysis.fit.minimizer.steps = 1000 +project.analysis.fit.minimizer.parallel = 0 +project.analysis.fit(random_seed=11) + +# Runtime-only Bayesian summaries and plots +project.analysis.display.fit_results() +project.display.plotter.plot_param_correlations() +project.display.plotter.plot_posterior_pairs() +project.display.plotter.plot_param_distribution(param) +project.display.plotter.plot_posterior_predictive(expt_name='hrpt') +``` + ### 8.5 TOF Experiment (tutorial ed-7) ```python From d901adcbe2448cfe9a65c87b450a66cc665489ff Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 11:16:27 +0200 Subject: [PATCH 080/106] Clean up --- docs/dev/bayesian-analysis-design.md | 738 --------------------------- docs/dev/plan_bayesian-analysis.md | 334 ------------ 2 files changed, 1072 deletions(-) delete mode 100644 docs/dev/bayesian-analysis-design.md delete mode 100644 docs/dev/plan_bayesian-analysis.md diff --git a/docs/dev/bayesian-analysis-design.md b/docs/dev/bayesian-analysis-design.md deleted file mode 100644 index 1ca66fdb..00000000 --- a/docs/dev/bayesian-analysis-design.md +++ /dev/null @@ -1,738 +0,0 @@ -# Bayesian Analysis Design - -**Status:** Design proposal **Date:** 2026-05-07 - -## Goal - -Add Bayesian analysis to the existing fitting workflow with the smallest -user-facing API change possible. The first implementation target is the -BUMPS DREAM sampler for diffraction refinement, with sampled parameters -bounded by each parameter's `fit_min` and `fit_max` attributes. - -The word `DREAM` in this document means the BUMPS Markov-chain Monte -Carlo sampler. It does not refer to the ESS DREAM instrument. - -## Design Principles - -- Keep `project.analysis.fit()` as the single execution entry point. -- Add `'bumps (dream)'` as a normal minimizer tag. -- Store large posterior outputs in runtime result objects, not in CIF - categories. -- Commit one coherent sampled parameter vector back to the project after - sampling. -- Keep deterministic fitting and Bayesian sampling behavior explicit. -- Add Bayesian display and plotting behavior without changing existing - deterministic semantics. - -## Current Code Anchors - -The design should extend the existing seams instead of adding a parallel -analysis stack: - -- `src/easydiffraction/analysis/categories/fit/default.py` owns - `fit.minimizer_type` and `fit.mode`. -- `src/easydiffraction/analysis/fitting.py` collects free parameters, - builds the residual objective, and calls `MinimizerBase.fit()`. -- `src/easydiffraction/analysis/minimizers/base.py` defines the - minimizer lifecycle and returns a `FitResults` instance. -- `src/easydiffraction/analysis/minimizers/bumps.py` already adapts an - EasyDiffraction residual function into BUMPS through - `_EasyDiffractionFitness`. -- `src/easydiffraction/analysis/fit_helpers/reporting.py` owns - `FitResults` display behavior. -- `src/easydiffraction/display/plotting.py` currently builds parameter - correlations from `analysis.fit_results.engine_result`. -- `pyproject.toml` already declares `arviz`, so Bayesian plotting does - not need a new dependency decision. - -## User-Facing API - -The intended workflow stays aligned with the current fitting API: - -```python -project.analysis.fit.minimizer_type = 'bumps (lm)' -project.analysis.fit() - -project.analysis.fit.minimizer_type = 'bumps (dream)' -project.analysis.fit() - -project.analysis.display.fit_results() -project.display.plotter.plot_meas_vs_calc(expt_name='hrpt') -project.display.plotter.plot_param_correlations() -``` - -Additional Bayesian-specific plotting methods should be added rather -than forcing every existing plotting method to accept Bayesian-specific -options: - -```python -project.display.plotter.plot_posterior_pairs() -project.display.plotter.plot_param_distribution(param) -project.display.plotter.plot_posterior_predictive(expt_name='hrpt') -``` - -### Explicit Two-Step Workflow - -`'bumps (dream)'` must not implicitly run a deterministic -Levenberg-Marquardt pre-fit. Users should call `'bumps (lm)'` first when -they want a better starting point. - -Reasons: - -- `fit()` stays explicit and predictable. -- Hidden pre-fitting can add significant runtime. -- Deterministic failures stay separate from sampling failures. -- The behavior matches the existing minimizer-selection model. - -## Scope - -### In Scope For The First Implementation - -- Register `MinimizerTypeEnum.BUMPS_DREAM` with tag `'bumps (dream)'`. -- Add `BumpsDreamMinimizer`. -- Add `BayesianFitResults` and small posterior value objects. -- Require finite bounds for every sampled free parameter. -- Use bounded uniform priors implied by `fit_min` and `fit_max`. -- Use the existing residual objective and BUMPS likelihood convention. -- Store posterior chains runtime-only in `analysis.fit_results`. -- Display posterior summaries from `analysis.display.fit_results()`. -- Add posterior correlation support to `plot_param_correlations()`. -- Add posterior marginal and posterior pair plots. -- Add posterior predictive plotting with capped draw evaluation. - -### Out Of Scope Initially - -- Automatic deterministic pre-fitting. -- Persistent Bayesian configuration categories. -- CIF serialization of posterior chains. -- Export of posterior chains. -- Model comparison across multiple Bayesian fits. -- User-facing DREAM hyperparameter controls. -- Unbounded posterior predictive storage for every draw and every - experiment. -- Sequential Bayesian fitting. - -## Resolved Design Decisions - -- `plot_posterior_predictive(...)` is required for the first useful - Bayesian implementation. -- Posterior chains remain runtime-only and do not need an export API in - phase 1. -- `project.analysis.fit(random_seed=...)` should be supported for - `'bumps (dream)'` because stochastic scientific workflows need - reproducibility. If omitted, the minimizer should generate a seed and - record it in `BayesianFitResults.sampler_settings`. -- Deterministic minimizers should reject a non-`None` `random_seed` with - a clear error rather than silently ignoring it. -- `BayesianFitResults.success` should mean that DREAM completed and - produced usable posterior samples. Convergence quality should be - stored separately in diagnostics, displayed prominently, and warned on - when poor. It should set `success=False` only when there are no usable - samples or the sampler itself fails. -- Posterior predictive plots should evaluate a capped subset of - posterior draws. Start with an internal default cap of 200 draws, - record the effective draw count in the result, and expose the cap only - later if users need control. - -## Statistical Semantics - -The existing residual objective returns the residual vector consumed by -deterministic minimizers. The first Bayesian implementation should treat -the BUMPS negative log likelihood as: - -```python -nllf = 0.5 * sum(residuals**2) -``` - -This assumes residuals are already scaled consistently with the -experimental uncertainty model. If an experiment does not provide valid -uncertainties, the posterior is only as meaningful as the residual -weighting currently used by deterministic fitting. - -Initial priors are uniform inside finite `fit_min` and `fit_max` bounds -and zero outside those bounds. No Gaussian, log-normal, or -domain-specific priors are part of the first implementation. - -## Core Architectural Decision - -### Keep Full Results In `analysis.fit_results` - -Bayesian results should be stored in a new runtime result object, not in -a new heavy `Analysis` category. - -Recommended model: - -- `FitResults` remains the base deterministic result container. -- `BayesianFitResults` extends `FitResults` for posterior-specific data. -- `analysis.fit_results` stores either `FitResults` or - `BayesianFitResults`. - -This keeps the existing public access pattern unchanged: - -```python -project.analysis.fit_results -``` - -### Why Not A New Results Category Under `Analysis` - -Current `Analysis` categories are lightweight, structured, project-owned -configuration or control objects: - -- `fit` -- `aliases` -- `constraints` -- `joint_fit_experiments` - -These are serialized with the project. Full Bayesian results are a poor -fit for this category model because they are: - -- runtime products rather than project configuration -- potentially large arrays -- not natural CIF content -- often disposable or recomputable - -Posterior chains, posterior predictive draws, and pair-plot inputs -should therefore remain runtime-only objects attached to -`BayesianFitResults`. - -## Optional Future Category - -A small `Analysis` category may still be useful later, but only for -Bayesian configuration, not for heavy result storage. - -Possible future category name: - -- `analysis.sampling` -- `analysis.bayesian` - -Possible responsibilities: - -- sampler type -- point estimate policy -- default highest-density interval levels -- default posterior predictive draw cap -- public DREAM hyperparameters -- persistent default random seed policy, if users need saved sampling - preferences later - -This category should stay lightweight and serializable. It must not -store raw chains. - -## Runtime Type Contracts - -### `BumpsDreamMinimizer` - -Add a new minimizer implementation registered through `MinimizerFactory` -with tag: - -```python -'bumps (dream)' -``` - -Responsibilities: - -- Reuse `_EasyDiffractionFitness` or a small subclass of it. -- Build bounded BUMPS parameters from EasyDiffraction parameters. -- Preserve parameter order from `Fitter.fit()` through all arrays. -- Validate finite bounds before starting the sampler. -- Run DREAM with internal defaults. -- Collect posterior samples, log likelihood values, and sampler - diagnostics where BUMPS exposes them. -- Choose and commit the MAP or best posterior sample after sampling. -- Build `BayesianFitResults`. - -The existing `BumpsMinimizer` handles BUMPS parameter ordering carefully -because `FitProblem` can sort parameters internally. DREAM must preserve -the same guarantee: result arrays and summaries must be mapped back to -the original EasyDiffraction parameter order. - -### `BayesianFitResults` - -Subclass `FitResults` and add Bayesian-specific fields. Inherited fields -should keep deterministic-compatible meanings: - -- `success`: sampler completed and produced usable posterior samples -- `parameters`: EasyDiffraction parameters updated to the committed MAP - vector -- `starting_parameters`: an immutable snapshot of starting values, not - the same mutable parameter objects after fitting -- `reduced_chi_square`: reduced chi-square at the committed MAP vector, - when available -- `engine_result`: raw or lightly wrapped BUMPS DREAM result -- `fitting_time`: elapsed sampling time - -Recommended Bayesian fields: - -- `sampler_name` -- `point_estimate_name` -- `posterior_samples` -- `posterior_parameter_summaries` -- `posterior_predictive` -- `credible_interval_levels` -- `diagnostics` -- `sampler_settings` - -`sampler_settings` should record the internal defaults actually used. -That keeps a runtime audit trail even before the settings are public -configuration. - -For DREAM, `sampler_settings` must include `random_seed`, whether the -seed was user-provided or generated, and the posterior predictive draw -cap used for summaries. - -### `PosteriorSamples` - -Recommended fields: - -- `parameter_names`: minimizer-safe names, matching sampled array order -- `parameter_labels`: user-facing labels for tables and plots -- `values`: NumPy array shaped `(chain, draw, parameter)` -- `flat_values`: optional cached array shaped `(sample, parameter)` -- `log_likelihood`: optional NumPy array shaped `(chain, draw)` -- `log_posterior`: optional NumPy array shaped `(chain, draw)` -- `bounds`: mapping from parameter name to `(fit_min, fit_max)` -- `start_values`: starting values in parameter order -- `map_values`: committed MAP values in parameter order -- `map_chain`: chain index of the MAP sample, if known -- `map_draw`: draw index of the MAP sample, if known - -The object should provide one conversion helper: - -```python -posterior_samples.to_arviz() -``` - -This keeps public EasyDiffraction methods independent of ArviZ while -letting plotting and summaries use ArviZ internally. - -### `PosteriorParameterSummary` - -Recommended fields: - -- `parameter_name` -- `parameter_label` -- `datablock` -- `category` -- `entry` -- `parameter` -- `start` -- `map` -- `mean` -- `median` -- `std` -- `hdi` -- `fit_min` -- `fit_max` -- `units` - -`hdi` should be a mapping keyed by interval probability, for example: - -```python -{ - 0.68: (lower_68, upper_68), - 0.95: (lower_95, upper_95), -} -``` - -### `PosteriorPredictiveSummary` - -Posterior predictive data can be expensive for diffraction patterns, so -the first implementation should store summaries rather than every draw. - -Recommended fields: - -- `experiment_name` -- `x` -- `y_observed` -- `y_map` -- `intervals` -- `draw_count` - -`intervals` should be keyed by interval probability: - -```python -{ - 0.95: (lower_y, upper_y), -} -``` - -Posterior predictive summaries are required for -`plot_posterior_predictive(...)`, but they should be based on a capped -subset of posterior draws. The default cap is an internal implementation -constant, initially 200 draws. - -## Point Estimate Policy - -After a DREAM run, project parameters should be updated to the MAP or -best posterior sample, not to independent marginal medians. - -Reasons: - -- Per-parameter medians can produce a parameter vector that was never - sampled jointly. -- MAP corresponds to one coherent sampled state. -- The calculated profile shown after Bayesian fitting should correspond - to one actual parameter set. - -Posterior tables should still report mean, median, standard deviation, -and HDIs. - -If the sampler fails before producing usable samples, the minimizer -should restore starting parameter values instead of leaving the project -at an arbitrary last sampled state. - -## Parameter Bounds - -DREAM should require finite bounds for every sampled free parameter. - -Validation rules: - -- Use `fit_min` and `fit_max`. -- Bounds must be finite. -- `fit_min` must be strictly less than `fit_max`. -- The starting value must be inside the bounds. -- Validate only sampled parameters: free, unconstrained parameters - collected by `Fitter.fit()`. - -Failure behavior: - -- Stop before running BUMPS. -- Raise a clear `ValueError`. -- List every offending parameter and the specific problem. - -This is stricter than some deterministic minimizers, but appropriate for -bounded posterior sampling. - -### Interaction With Physical Limits - -`Analysis.fit(use_physical_limits=True)` currently allows deterministic -minimizers to fill unbounded `fit_min` and `fit_max` from parameter -value spec physical limits. DREAM should use the same pre-processing -path. - -If `use_physical_limits=True` still leaves any sampled parameter -unbounded, DREAM must fail with the same finite-bound error. - -## DREAM Defaults And Reproducibility - -For the first implementation, sampling parameters should stay internal -and use library defaults or small wrapper constants in `bumps_dream.py`. - -Examples: - -- `n_steps` -- `n_burn` -- `thin` -- `pop` -- `alpha` - -These should not be user-facing API initially. They should be recorded -in `BayesianFitResults.sampler_settings` so users can inspect how a -runtime result was produced. - -The exception is `random_seed`, which should be accepted as an optional -keyword by `project.analysis.fit(...)` when the active minimizer is -`'bumps (dream)'`. This keeps stochastic results reproducible without -creating a persistent sampling category in phase 1. - -Tests may monkeypatch the internal defaults to keep unit and integration -tests fast. That test hook should not become public API. - -## Display Behavior - -### `project.analysis.display.fit_results()` - -Keep the existing entry point and dispatch by result type. - -Deterministic fit: - -- keep the current summary -- keep the current fitted-parameter table - -Bayesian fit: - -- show a sampling summary section -- show sampler settings that materially affect the result -- show diagnostics when available -- show posterior parameter summaries instead of only fitted values and - covariance-derived uncertainties - -Recommended Bayesian table columns: - -- datablock -- category -- entry -- parameter -- start -- MAP -- mean -- median -- posterior std -- 68% HDI -- 95% HDI -- units - -Display code should not require ArviZ at render time if summaries were -already computed by the minimizer. - -## Plotting Behavior - -### `plot_meas_vs_calc(expt_name=...)` - -Keep the existing method name. - -Deterministic fit: - -- current measured vs calculated behavior unchanged - -Bayesian fit: - -- measured pattern -- MAP calculated line -- one shaded 95% credible interval band when `posterior_predictive` is - available - -If predictive intervals are unavailable, the method should plot the MAP -calculated line and warn that posterior predictive intervals were not -computed. - -This is the clearest default for diffraction patterns. A full posterior -predictive distribution at every x value is useful but visually denser, -so it should not be the default first view. - -### `plot_param_correlations()` - -Keep the current method name and purpose. - -Deterministic fit: - -- covariance- or engine-derived correlation matrix - -Bayesian fit: - -- posterior-sample correlation matrix computed from flattened posterior - samples - -Implementation detail: - -- Check for `BayesianFitResults.posterior_samples` first. -- Fall back to the existing covariance path for deterministic results. -- Keep the current thresholding and lower-triangle display behavior. - -This preserves the meaning of the method while making it work for -posterior samples. - -### New `plot_posterior_pairs()` - -Add a Bayesian-specific method for pairwise posterior exploration. - -Intended behavior: - -- ArviZ-backed implementation first -- Plotly backend where practical -- pairwise scatter or density panels -- marginal distributions on the diagonal -- optional parameter subset support - -This method should serve the role of an interactive corner or pair plot. -When the active result is deterministic, it should log a clear warning -instead of trying to infer a posterior from covariance. - -### New `plot_param_distribution(param)` - -Add a one-dimensional marginal posterior plot for a selected parameter. - -Intended behavior: - -- ArviZ-backed implementation first -- posterior histogram or density -- MAP marker -- median marker -- HDI overlay - -Parameter selection should accept the same identifiers users see in -fit-result tables where possible: - -- parameter object -- unique parameter name -- user-facing label - -Ambiguous string matches should fail with a clear error listing matching -parameters. - -### New `plot_posterior_predictive(...)` - -Add a dedicated method for posterior predictive views. This is required -for phase 1 because `plot_meas_vs_calc(...)` should stay a concise -measured-versus-current-calculation view. - -Initial API: - -```python -project.display.plotter.plot_posterior_predictive( - expt_name='hrpt', - style='band', -) -``` - -Possible styles: - -- `band` -- `draws` -- `distribution` - -Initial behavior: - -- default to `style='band'` -- show measured pattern -- show MAP calculated line -- show a 95% posterior predictive band by default -- support capped individual posterior predictive draws with - `style='draws'` - -For the first implementation, richer views may be delegated to ArviZ -where practical, but diffraction-specific x/y plotting should remain -clear and domain-oriented. - -## Data Ownership - -Experiment `data` categories should remain responsible for: - -- measured pattern -- current calculated pattern -- current background pattern - -Posterior-specific data should remain analysis-owned through -`BayesianFitResults`, because it is: - -- fit-result scoped -- potentially joint across experiments -- used mainly for reporting and plotting - -When the MAP vector is committed, normal category update behavior should -make the current calculated pattern correspond to the MAP values. -Posterior predictive summaries should not mutate experiment data -categories for every posterior draw. - -## Persistence And Serialization - -For the first implementation: - -- Do not serialize full posterior chains to CIF. -- Do not force posterior arrays into project save files. -- Let project auto-save persist the current MAP parameter values and - `fit.minimizer_type`, as it already does for deterministic fitting. -- Treat `analysis.fit_results` as runtime-only. - -Possible future export surfaces: - -- explicit posterior export methods -- CSV summaries -- ArviZ NetCDF export -- NumPy archive export - -## Failure And Warning Policy - -Hard failures should stop before expensive sampling when possible: - -- missing finite bounds -- invalid bound order -- start value outside bounds -- no sampled parameters -- BUMPS DREAM backend unavailable - -Soft warnings should allow a result to be returned: - -- convergence diagnostics unavailable -- convergence diagnostics outside recommended thresholds -- posterior predictive intervals not computed -- MAP value close to a fit bound - -`success` should mean that the sampler completed and usable posterior -samples were produced. Convergence diagnostics should be shown and -stored separately. Poor convergence should set a diagnostic flag and log -a warning, but it should not turn the result into a hard failure unless -there are no usable samples. - -## Testing Requirements - -Unit tests should cover: - -- `MinimizerTypeEnum.BUMPS_DREAM` and factory registration. -- Finite-bound validation with all offending parameters reported. -- Start-value-inside-bounds validation. -- `random_seed` threading and recording for DREAM. -- Non-`None` `random_seed` rejection for deterministic minimizers. -- Preservation of parameter order between EasyDiffraction parameters, - BUMPS parameters, posterior arrays, and summaries. -- MAP commit behavior. -- Restore-start-values behavior on sampler failure. -- `BayesianFitResults.display_results()` table content. -- Posterior correlation calculation from flattened posterior samples. -- Posterior predictive summary generation with capped draw evaluation. -- Deterministic correlation behavior remaining unchanged. -- Project serialization not including posterior arrays. - -Integration tests should cover: - -- A small bounded synthetic refinement with `'bumps (dream)'`. -- Optional deterministic pre-fit followed by DREAM as two explicit - `fit()` calls. -- `analysis.display.fit_results()` after DREAM. -- `plot_posterior_predictive(...)` after DREAM. -- Bayesian plotting smoke tests using a small posterior fixture. - -## Implementation Plan - -The detailed implementation plan is -`docs/dev/plan_bayesian-analysis.md`. It follows -`.github/copilot-instructions.md`: phase 1 is implementation only, phase -2 is verification, and every completed phase 1 implementation step must -be staged with explicit paths and committed locally before the next step -starts. - -High-level implementation order: - -- register the DREAM minimizer -- add Bayesian result models -- thread optional `random_seed` through fitting -- implement DREAM sampling and MAP commit behavior -- add Bayesian result display -- add posterior correlations -- add posterior distribution plots -- add posterior predictive summaries and plots - -## Acceptance Criteria - -The first useful implementation is complete when: - -- `project.analysis.fit.show_minimizer_types()` lists `'bumps (dream)'`. -- `project.analysis.fit.minimizer_type = 'bumps (dream)'` runs through - the same `project.analysis.fit()` path as other minimizers. -- Missing finite bounds fail before sampling with a clear parameter - list. -- Successful sampling stores `BayesianFitResults` in - `project.analysis.fit_results`. -- Project parameters are left at the MAP sample after a successful run. -- `project.analysis.display.fit_results()` renders posterior summaries. -- `plot_param_correlations()` works from posterior samples. -- `plot_posterior_predictive(expt_name=...)` shows measured data, MAP - calculation, and a posterior predictive band. -- Saving a project does not serialize posterior chains. - -## Implementation Discovery - -During implementation, inspect which BUMPS DREAM result object fields -are stable enough to store directly in `engine_result`. Normalize -posterior samples, log-likelihood values, diagnostics, and summaries -into EasyDiffraction-owned value objects first; keep `engine_result` as -an opaque backend escape hatch. - -## Summary - -The recommended design is to add `'bumps (dream)'` as a normal minimizer -type, keep Bayesian analysis inside the existing `fit()` workflow, store -heavy posterior data in `BayesianFitResults`, and keep -`analysis.fit_results` as the main public result entry point. A -lightweight serialized `Analysis` category can be added later if -Bayesian settings need to become persistent and user-configurable. diff --git a/docs/dev/plan_bayesian-analysis.md b/docs/dev/plan_bayesian-analysis.md deleted file mode 100644 index 4a5697b8..00000000 --- a/docs/dev/plan_bayesian-analysis.md +++ /dev/null @@ -1,334 +0,0 @@ -# Bayesian Analysis Implementation Plan - -**Status:** Planned **Feature name:** `bayesian-analysis` **Suggested -branch:** `feature/bayesian-analysis` **Design doc:** -`docs/dev/bayesian-analysis-design.md` - -## Context - -This plan follows `.github/copilot-instructions.md`. The instructions -refer to `docs/dev/architecture.md`, but this checkout does not contain -that file. The matching living architecture document used for this plan -is `docs/dev/architecture.md`. - -Relevant current seams: - -- `src/easydiffraction/analysis/categories/fit/default.py` -- `src/easydiffraction/analysis/analysis.py` -- `src/easydiffraction/analysis/fitting.py` -- `src/easydiffraction/analysis/minimizers/base.py` -- `src/easydiffraction/analysis/minimizers/bumps.py` -- `src/easydiffraction/analysis/minimizers/enums.py` -- `src/easydiffraction/analysis/minimizers/factory.py` -- `src/easydiffraction/analysis/minimizers/__init__.py` -- `src/easydiffraction/analysis/fit_helpers/reporting.py` -- `src/easydiffraction/display/plotting.py` - -## Decisions - -- Add Bayesian sampling as a normal minimizer tag: `'bumps (dream)'`. -- Keep `project.analysis.fit()` as the execution entry point. -- Keep posterior chains runtime-only in `BayesianFitResults`. -- Do not add posterior chain export in phase 1. -- Add `plot_posterior_predictive(...)` in phase 1. -- Add optional `random_seed` support for `'bumps (dream)'`. -- Generate and record a seed when the user does not provide one. -- Reject non-`None` `random_seed` for deterministic minimizers. -- Treat sampler completion and convergence quality separately. -- Use `success=False` only when DREAM fails or no usable posterior - samples exist. -- Store and display convergence diagnostics; warn on poor convergence. -- Start with an internal posterior predictive draw cap of 200. - -## Scope - -Phase 1 delivers implementation only. Do not add or run tests in phase 1 -unless the user explicitly asks. Stop after phase 1 and request review. - -Phase 2 delivers verification only. Add/update tests, then run the -commands listed in this plan. - -## Agent Execution Rule - -When an AI agent follows this plan, every completed phase 1 -implementation step must be staged with explicit paths and committed -locally before moving to the next implementation step or the phase 1 -review gate. Commits must be atomic, single-purpose, and aligned with -the step just completed. - -If implementation uncovers a serious requirement, risk, design issue, or -scope change not covered by this plan, stop and ask for clarification or -approval before proceeding. - -## Status Checklist - -- [x] Repository context gathered. -- [x] Design decisions recorded. -- [ ] Phase 1 implementation complete. -- [ ] Phase 1 review approved. -- [ ] Phase 2 tests added. -- [ ] Phase 2 verification commands completed. - -## Phase 1: Implementation - -### Step 1: Register The DREAM Minimizer - -- [ ] Add `BUMPS_DREAM = 'bumps (dream)'` to `MinimizerTypeEnum`. -- [ ] Add a human-readable enum description. -- [ ] Add `src/easydiffraction/analysis/minimizers/bumps_dream.py`. -- [ ] Register `BumpsDreamMinimizer` with `MinimizerFactory`. -- [ ] Import `BumpsDreamMinimizer` from - `src/easydiffraction/analysis/minimizers/__init__.py`. -- [ ] Update `docs/dev/architecture.md` minimizer tag tables if the - implementation changes the documented supported tags. - -Likely files: - -- `src/easydiffraction/analysis/minimizers/enums.py` -- `src/easydiffraction/analysis/minimizers/bumps_dream.py` -- `src/easydiffraction/analysis/minimizers/__init__.py` -- `docs/dev/architecture.md` - -Suggested commit message: - -```text -Register BUMPS DREAM minimizer -``` - -### Step 2: Add Bayesian Result Models - -- [ ] Add `BayesianFitResults`. -- [ ] Add `PosteriorSamples`. -- [ ] Add `PosteriorParameterSummary`. -- [ ] Add `PosteriorPredictiveSummary`. -- [ ] Keep public constructors explicit; do not use `**kwargs`. -- [ ] Add NumPy-style docstrings for public classes and methods. -- [ ] Provide `PosteriorSamples.to_arviz()` for plotting integration. - -Likely files: - -- `src/easydiffraction/analysis/fit_helpers/bayesian.py` -- `src/easydiffraction/analysis/fit_helpers/reporting.py` -- `src/easydiffraction/analysis/fit_helpers/__init__.py` - -Suggested commit message: - -```text -Add Bayesian fit result models -``` - -### Step 3: Thread Random Seed Through Fit Execution - -- [ ] Add optional `random_seed: int | None = None` to `Fit.run(...)` - and `Fit.__call__(...)`. -- [ ] Thread `random_seed` through `Analysis._run_fit(...)`, - `_fit_single(...)`, `_fit_joint(...)`, and `Fitter.fit(...)`. -- [ ] Thread `random_seed` through `MinimizerBase.fit(...)`. -- [ ] Reject non-`None` `random_seed` in deterministic minimizers with a - clear `ValueError`. -- [ ] Let `BumpsDreamMinimizer` generate a seed when `random_seed` is - `None`. -- [ ] Record the user-provided or generated seed in - `BayesianFitResults.sampler_settings`. - -Likely files: - -- `src/easydiffraction/analysis/categories/fit/default.py` -- `src/easydiffraction/analysis/analysis.py` -- `src/easydiffraction/analysis/fitting.py` -- `src/easydiffraction/analysis/minimizers/base.py` -- `src/easydiffraction/analysis/minimizers/bumps_dream.py` - -Suggested commit message: - -```text -Thread random seed through fitting -``` - -### Step 4: Implement DREAM Sampling - -- [ ] Reuse `_EasyDiffractionFitness` or extract a shared BUMPS helper - only if needed. -- [ ] Build BUMPS parameters from sampled EasyDiffraction parameters. -- [ ] Validate finite bounds, bound ordering, and start values before - sampling. -- [ ] Preserve parameter order across BUMPS parameters, posterior - arrays, summaries, and MAP commit. -- [ ] Run BUMPS DREAM with internal defaults. -- [ ] Commit the MAP or best posterior sample to project parameters. -- [ ] Restore starting values if the sampler fails before producing - usable samples. -- [ ] Store raw BUMPS output as `engine_result` only after stable fields - have been normalized into EasyDiffraction-owned result objects. - -Likely files: - -- `src/easydiffraction/analysis/minimizers/bumps.py` -- `src/easydiffraction/analysis/minimizers/bumps_dream.py` -- `src/easydiffraction/analysis/fit_helpers/bayesian.py` - -Suggested commit message: - -```text -Implement BUMPS DREAM sampling -``` - -### Step 5: Add Bayesian Display - -- [ ] Make `BayesianFitResults.display_results(...)` render sampler - status, diagnostics, settings, and posterior parameter summaries. -- [ ] Keep deterministic `FitResults.display_results(...)` unchanged. -- [ ] Ensure `analysis.display.fit_results()` continues to dispatch - through the active result object. -- [ ] Display poor convergence prominently without hiding usable - posterior summaries. - -Likely files: - -- `src/easydiffraction/analysis/fit_helpers/bayesian.py` -- `src/easydiffraction/analysis/fit_helpers/reporting.py` - -Suggested commit message: - -```text -Display Bayesian fit summaries -``` - -### Step 6: Add Posterior Correlations - -- [ ] Extend `plot_param_correlations()` to detect - `BayesianFitResults.posterior_samples`. -- [ ] Compute the correlation matrix from flattened posterior samples. -- [ ] Preserve deterministic covariance and engine-derived behavior. -- [ ] Preserve current thresholding and lower-triangle display behavior. - -Likely files: - -- `src/easydiffraction/display/plotting.py` -- `src/easydiffraction/analysis/fit_helpers/bayesian.py` - -Suggested commit message: - -```text -Plot posterior parameter correlations -``` - -### Step 7: Add Bayesian Posterior Plots - -- [ ] Add `plot_posterior_pairs(...)`. -- [ ] Add `plot_param_distribution(param, ...)`. -- [ ] Use `PosteriorSamples.to_arviz()` internally where practical. -- [ ] Accept parameter objects, unique names, and user-facing labels for - one-parameter selection. -- [ ] Fail ambiguous string matches with a clear list of matches. -- [ ] Warn clearly when Bayesian-only plots are called on deterministic - results. - -Likely files: - -- `src/easydiffraction/display/plotting.py` -- `src/easydiffraction/analysis/fit_helpers/bayesian.py` - -Suggested commit message: - -```text -Add posterior distribution plots -``` - -### Step 8: Add Posterior Predictive Plots - -- [ ] Generate posterior predictive summaries from a capped subset of - posterior draws. -- [ ] Store summaries in `BayesianFitResults.posterior_predictive`. -- [ ] Add `plot_posterior_predictive(expt_name, style='band', ...)`. -- [ ] Support `style='band'` and `style='draws'` initially. -- [ ] Extend `plot_meas_vs_calc(...)` to show a 95% credible band when - posterior predictive summaries are available. -- [ ] Keep experiment data categories responsible only for measured, - current calculated, and current background patterns. - -Likely files: - -- `src/easydiffraction/display/plotting.py` -- `src/easydiffraction/analysis/minimizers/bumps_dream.py` -- `src/easydiffraction/analysis/fit_helpers/bayesian.py` - -Suggested commit message: - -```text -Add posterior predictive plotting -``` - -## Phase 1 Review Gate - -- [ ] Inspect `git status --short`. -- [ ] Inspect the diff for unrelated changes. -- [ ] Confirm every phase 1 step has an atomic local commit. -- [ ] Present the implementation summary for review. -- [ ] Do not start phase 2 until the user approves verification work. - -## Phase 2: Verification - -### Test Additions - -- [ ] Add unit tests for enum and factory registration. -- [ ] Add unit tests for finite-bound validation. -- [ ] Add unit tests for start-value-inside-bounds validation. -- [ ] Add unit tests for `random_seed` behavior. -- [ ] Add unit tests for deterministic minimizer seed rejection. -- [ ] Add unit tests for parameter order preservation. -- [ ] Add unit tests for MAP commit and restore-on-failure behavior. -- [ ] Add unit tests for Bayesian display output. -- [ ] Add unit tests for posterior sample correlation calculation. -- [ ] Add unit tests for posterior predictive summary generation. -- [ ] Add plotting smoke tests using small posterior fixtures. -- [ ] Add integration coverage for a small bounded DREAM refinement. -- [ ] Add integration coverage for explicit LM pre-fit followed by - DREAM. -- [ ] Add serialization coverage proving posterior chains are not saved. - -Likely test files: - -- `tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py` -- `tests/unit/easydiffraction/analysis/minimizers/test_enums.py` -- `tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py` -- `tests/unit/easydiffraction/display/test_plotting.py` -- `tests/integration/fitting/test_bayesian_dream.py` -- `tests/integration/fitting/test_project_load.py` - -Suggested commit message: - -```text -Test Bayesian DREAM workflow -``` - -### Verification Commands - -- [ ] `pixi run test-structure-check` -- [ ] `pixi run fix` -- [ ] `pixi run check` -- [ ] `pixi run unit-tests` -- [ ] `pixi run integration-tests` -- [ ] `pixi run script-tests` - -If `pixi run fix` regenerates package-structure docs, accept the -generated changes and include them only in the verification commit where -they were produced. - -## Non-Blocking Implementation Discovery - -The BUMPS DREAM return object must be inspected during implementation. -If the stable public fields are insufficient for posterior samples, -log-likelihood values, or diagnostics, normalize the available fields -into EasyDiffraction-owned value objects and keep `engine_result` -opaque. If this prevents a required feature, stop and ask before -changing scope. - -## Suggested Pull Request - -**Title:** Add Bayesian DREAM sampling and posterior plots - -**Description:** Adds Bayesian refinement through the BUMPS DREAM -sampler, including reproducible runs, posterior parameter summaries, and -posterior predictive plots so users can inspect uncertainty in fitted -diffraction models. From c7f3a6d11497befd08190352ff358c74cd35f1d5 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 11:56:22 +0200 Subject: [PATCH 081/106] Fix Bayesian diagnostics and DREAM cleanup edge cases --- .../analysis/fit_helpers/bayesian.py | 26 ++-- .../analysis/minimizers/base.py | 13 +- .../analysis/minimizers/bumps_dream.py | 62 +++++--- src/easydiffraction/display/plotting.py | 146 ++++++++++++++++-- .../analysis/fit_helpers/test_bayesian.py | 31 ++++ .../analysis/minimizers/test_base.py | 39 +++++ .../analysis/minimizers/test_bumps_dream.py | 53 +++++++ .../easydiffraction/display/test_plotting.py | 118 +++++++++++++- 8 files changed, 433 insertions(+), 55 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index 907cb53f..aa087fcb 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -383,10 +383,15 @@ def compute_convergence_diagnostics(posterior_samples: PosteriorSamples) -> dict r_hat_by_parameter = _dataset_to_scalar_dict(rhat_dataset) ess_bulk_by_parameter = _dataset_to_scalar_dict(ess_dataset) - max_r_hat = max(r_hat_by_parameter.values(), default=None) - min_ess_bulk = min(ess_bulk_by_parameter.values(), default=None) + finite_r_hat = [value for value in r_hat_by_parameter.values() if value is not None] + finite_ess_bulk = [value for value in ess_bulk_by_parameter.values() if value is not None] - converged = True + max_r_hat = max(finite_r_hat, default=None) + min_ess_bulk = min(finite_ess_bulk, default=None) + + converged = len(finite_r_hat) == len(r_hat_by_parameter) and len(finite_ess_bulk) == len( + ess_bulk_by_parameter + ) if max_r_hat is not None and max_r_hat > R_HAT_CONVERGENCE_THRESHOLD: converged = False if min_ess_bulk is not None and min_ess_bulk < ESS_BULK_CONVERGENCE_THRESHOLD: @@ -500,17 +505,20 @@ def standard_deviations_from_summaries( return np.array([summary.standard_deviation for summary in summaries], dtype=float) -def _dataset_to_scalar_dict(dataset: object) -> dict[str, float]: - values: dict[str, float] = {} +def _dataset_to_scalar_dict(dataset: object) -> dict[str, float | None]: + values: dict[str, float | None] = {} for name, data_array in dataset.data_vars.items(): - values[name] = float(np.asarray(data_array).reshape(-1)[0]) + values[name] = _maybe_scalar(np.asarray(data_array).reshape(-1)[0]) return values def _maybe_scalar(value: object) -> float | None: if value is None: return None - return float(value) + scalar = float(value) + if not np.isfinite(scalar): + return None + return scalar def _format_sampler_settings(sampler_settings: dict[str, object]) -> str | None: @@ -719,7 +727,7 @@ def _format_interval(interval: tuple[float, float]) -> str: def _format_r_hat(value: float | None) -> str: - if value is None: + if value is None or not np.isfinite(value): return 'N/A' formatted = f'{value:.3f}' if value > R_HAT_CONVERGENCE_THRESHOLD: @@ -728,7 +736,7 @@ def _format_r_hat(value: float | None) -> str: def _format_ess_bulk(value: float | None) -> str: - if value is None: + if value is None or not np.isfinite(value): return 'N/A' formatted = f'{value:.1f}' if value < ESS_BULK_CONVERGENCE_THRESHOLD: diff --git a/src/easydiffraction/analysis/minimizers/base.py b/src/easydiffraction/analysis/minimizers/base.py index 142ed569..bbc639f1 100644 --- a/src/easydiffraction/analysis/minimizers/base.py +++ b/src/easydiffraction/analysis/minimizers/base.py @@ -338,12 +338,13 @@ def fit( self._start_tracking(minimizer_name, verbosity=verbosity) - solver_args = self._prepare_solver_args(parameters) - if resolved_random_seed is not None: - solver_args['random_seed'] = resolved_random_seed - raw_result = self._run_solver(objective_function, **solver_args) - - self._stop_tracking() + try: + solver_args = self._prepare_solver_args(parameters) + if resolved_random_seed is not None: + solver_args['random_seed'] = resolved_random_seed + raw_result = self._run_solver(objective_function, **solver_args) + finally: + self._stop_tracking() return self._finalize_fit(parameters, raw_result) diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index c23d923c..cc141d32 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -41,6 +41,7 @@ DEFAULT_ALPHA = 0.0 DEFAULT_OUTLIER_TEST = 'none' DEFAULT_TRIM = False +MAX_RANDOM_SEED = int(np.iinfo(np.uint32).max) BURN_IN_PROGRESS_POINTS = 5 SAMPLING_PROGRESS_POINTS = 20 DREAM_SAMPLE_ARRAY_NDIM = 3 @@ -345,9 +346,24 @@ def _resolve_random_seed(self, random_seed: int | None) -> int: generator = np.random.default_rng() random_seed = int(generator.integers(0, np.iinfo(np.int32).max)) - self._resolved_random_seed = int(random_seed) + integer_seed = self._validated_random_seed_value(random_seed) + + self._resolved_random_seed = integer_seed return self._resolved_random_seed + @staticmethod + def _validated_random_seed_value(random_seed: object) -> int: + """Validate and normalize a DREAM random seed.""" + if isinstance(random_seed, bool): + msg = f'DREAM random_seed must be an integer between 0 and {MAX_RANDOM_SEED}.' + raise TypeError(msg) + + integer_seed = int(random_seed) + if integer_seed != random_seed or integer_seed < 0 or integer_seed > MAX_RANDOM_SEED: + msg = f'DREAM random_seed must be an integer between 0 and {MAX_RANDOM_SEED}.' + raise ValueError(msg) + return integer_seed + @staticmethod def _tracking_mode() -> str: """Use sampler-style progress reporting for DREAM runs.""" @@ -651,23 +667,28 @@ def _build_driver( burn_steps=int(burn), ) mapper = self._build_mapper(problem) - driver = FitDriver( - fitclass=fitclass, - problem=problem, - monitors=[progress_monitor], - mapper=mapper, - steps=steps, - burn=burn, - thin=self.thin, - pop=self.pop, - init=init.value, - samples=sampler_settings['samples'], - alpha=DEFAULT_ALPHA, - outliers=DEFAULT_OUTLIER_TEST, - trim=DEFAULT_TRIM, - ) - driver.clip() - return driver + try: + driver = FitDriver( + fitclass=fitclass, + problem=problem, + monitors=[progress_monitor], + mapper=mapper, + steps=steps, + burn=burn, + thin=self.thin, + pop=self.pop, + init=init.value, + samples=sampler_settings['samples'], + alpha=DEFAULT_ALPHA, + outliers=DEFAULT_OUTLIER_TEST, + trim=DEFAULT_TRIM, + ) + driver.clip() + except Exception: + MPMapper.stop_mapper() + raise + else: + return driver def _build_mapper(self, problem: FitProblem) -> object | None: """Return a DREAM mapper for the configured parallel setting.""" @@ -691,9 +712,10 @@ def _execute_driver(*, driver: FitDriver, random_seed: int) -> _DreamDriverResul numpy_rng = np.random.mtrand._rand numpy_state = numpy_rng.get_state() python_state = random.getstate() - numpy_rng.seed(random_seed) - random.seed(random_seed) try: + validated_seed = BumpsDreamMinimizer._validated_random_seed_value(random_seed) + numpy_rng.seed(validated_seed) + random.seed(validated_seed) best_values, best_nllf = driver.fit() except DREAM_DRIVER_FAILURES as error: # pragma: no cover - backend-specific return _DreamDriverResult( diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index a3076463..6998640d 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -84,6 +84,7 @@ class PosteriorPairPlotStyleEnum(StrEnum): DEFAULT_BRAGG_ROW = DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION DEFAULT_POSTERIOR_PREDICTIVE_DRAWS = 200 DEFAULT_POSTERIOR_PREDICTIVE_DRAW_PLOT_CAP = 50 +FULL_POSTERIOR_PAIR_COVARIANCE_RANK = 2 POSTERIOR_FLATTENED_SAMPLE_NDIM = 2 MIN_POSTERIOR_PARAMETER_COUNT = 2 MIN_POSTERIOR_SAMPLE_COUNT = 2 @@ -906,26 +907,85 @@ def plot_posterior_predictive( ) return - summary = self._get_or_build_posterior_predictive_summary( + self._plot_non_bragg_posterior_predictive( experiment=experiment, expt_name=expt_name, + plot_options=plot_options, x_axis=x_axis, - include_draws=style in {'draws', 'band+draws'}, + sample_form=sample_form, + scattering_type=scattering_type, + style=style, ) - if summary is None: - return + def _plot_non_bragg_posterior_predictive( + self, + *, + experiment: object, + expt_name: str, + plot_options: _MeasVsCalcPlotOptions, + x_axis: object, + sample_form: object, + scattering_type: object, + style: str, + ) -> None: + """Render non-Bragg posterior predictive summaries.""" pattern = intensity_category_for(experiment) y_meas = getattr(pattern, 'intensity_meas', None) if y_meas is None: log.warning(f'No measured data available for experiment {expt_name}.') return + ctx = self._prepare_powder_context( + pattern, + expt_name, + experiment.type, + plot_options.x_min, + plot_options.x_max, + plot_options.x, + ) + if ctx is None: + return + + if plot_options.show_residual: + log.warning( + 'Posterior predictive residuals are unavailable for non-Bragg ' + 'summary plots; ignoring show_residual=True.' + ) + + summary = self._get_or_build_posterior_predictive_summary( + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + include_draws=style in {'draws', 'band+draws'}, + ) + if summary is None: + return + + filtered_summary = self._filtered_posterior_predictive_summary( + summary=summary, + x_min=ctx['x_min'], + x_max=ctx['x_max'], + include_draws=style in {'draws', 'band+draws'}, + ) + if filtered_summary is None: + log.warning( + f'No posterior predictive data available within the requested x-range ' + f'for experiment {expt_name}.' + ) + return + + filtered_y_meas = self._filtered_y_array( + y_meas, + ctx['x_array'], + ctx['x_min'], + ctx['x_max'], + ) + axes_labels = self._get_axes_labels(sample_form, scattering_type, x_axis) self._plot_posterior_predictive_summary( expt_name=expt_name, - summary=summary, - y_meas=np.asarray(y_meas, dtype=float), + summary=filtered_summary, + y_meas=filtered_y_meas, axes_labels=axes_labels, show_band=style in {'band', 'band+draws'}, show_draws=style in {'draws', 'band+draws'}, @@ -2557,16 +2617,24 @@ def _posterior_pair_density_surface( if np.allclose(x_data, x_data[0]) and np.allclose(y_data, y_data[0]): return None + pair_data = np.vstack([x_data, y_data]) + covariance = np.cov(pair_data) + if np.linalg.matrix_rank(covariance) < FULL_POSTERIOR_PAIR_COVARIANCE_RANK: + return None + x_grid = np.linspace(x_bounds[0], x_bounds[1], num=grid_size) y_grid = np.linspace(y_bounds[0], y_bounds[1], num=grid_size) mesh_x, mesh_y = np.meshgrid(x_grid, y_grid) - density = cls._evaluate_reflected_2d_kde( - gaussian_kde(np.vstack([x_data, y_data])), - mesh_x=mesh_x, - mesh_y=mesh_y, - x_bounds=x_bounds, - y_bounds=y_bounds, - ) + try: + density = cls._evaluate_reflected_2d_kde( + gaussian_kde(pair_data), + mesh_x=mesh_x, + mesh_y=mesh_y, + x_bounds=x_bounds, + y_bounds=y_bounds, + ) + except (np.linalg.LinAlgError, ValueError): + return None if not np.any(np.isfinite(density)): return None return x_grid, y_grid, density @@ -2947,8 +3015,8 @@ def _get_posterior_samples_and_fit_results( return posterior_samples, fit_results - @staticmethod def _plot_posterior_predictive_summary( + self, *, expt_name: str, summary: object, @@ -3040,7 +3108,55 @@ def _plot_posterior_predictive_summary( ) fig.update_xaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) fig.update_yaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) - fig.show() + self._show_plot_figure(fig) + + def _filtered_posterior_predictive_summary( + self, + *, + summary: PosteriorPredictiveSummary, + x_min: float, + x_max: float, + include_draws: bool, + ) -> PosteriorPredictiveSummary | None: + """Return a predictive summary filtered to an x-range.""" + x_filtered = self._filtered_y_array(summary.x, summary.x, x_min, x_max) + if np.asarray(x_filtered).size == 0: + return None + + draws = None + if include_draws and summary.draws is not None: + draws = np.asarray( + [self._filtered_y_array(draw, summary.x, x_min, x_max) for draw in summary.draws], + dtype=float, + ) + + return PosteriorPredictiveSummary( + experiment_name=summary.experiment_name, + x_axis_name=summary.x_axis_name, + x=x_filtered, + map_prediction=self._filtered_y_array(summary.map_prediction, summary.x, x_min, x_max), + lower_95=( + None + if summary.lower_95 is None + else self._filtered_y_array(summary.lower_95, summary.x, x_min, x_max) + ), + upper_95=( + None + if summary.upper_95 is None + else self._filtered_y_array(summary.upper_95, summary.x, x_min, x_max) + ), + lower_68=( + None + if summary.lower_68 is None + else self._filtered_y_array(summary.lower_68, summary.x, x_min, x_max) + ), + upper_68=( + None + if summary.upper_68 is None + else self._filtered_y_array(summary.upper_68, summary.x, x_min, x_max) + ), + draws=draws, + ) def _plot_posterior_predictive_data( self, diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py index 278a48ce..5fcfbf1a 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py @@ -72,6 +72,37 @@ def test_posterior_samples_to_arviz_validates_shapes(): posterior_samples.to_arviz() +def test_compute_convergence_diagnostics_treats_non_finite_values_as_not_converged(monkeypatch): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.analysis.fit_helpers.bayesian import compute_convergence_diagnostics + + posterior_samples = PosteriorSamples( + parameter_names=['a'], + parameter_samples=np.ones((4, 2, 1), dtype=float), + ) + + fake_dataset = type('FakeDataset', (), {'data_vars': {'a': np.array([np.nan], dtype=float)}}) + + monkeypatch.setattr( + 'easydiffraction.analysis.fit_helpers.bayesian.az.rhat', + lambda inference_data: fake_dataset, + ) + monkeypatch.setattr( + 'easydiffraction.analysis.fit_helpers.bayesian.az.ess', + lambda inference_data, method='bulk': type( + 'FakeDataset', (), {'data_vars': {'a': np.array([4000.0], dtype=float)}} + ), + ) + + diagnostics = compute_convergence_diagnostics(posterior_samples) + + assert diagnostics['converged'] is False + assert diagnostics['r_hat_by_parameter'] == {'a': None} + assert diagnostics['ess_bulk_by_parameter'] == {'a': 4000.0} + assert diagnostics['max_r_hat'] is None + assert diagnostics['min_ess_bulk'] == pytest.approx(4000.0) + + def test_summarize_posterior_parameters_preserves_order_and_display_names(): from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples from easydiffraction.analysis.fit_helpers.bayesian import summarize_posterior_parameters diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_base.py b/tests/unit/easydiffraction/analysis/minimizers/test_base.py index 23d385e7..0ad0ca12 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_base.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_base.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: BSD-3-Clause import numpy as np +import pytest class _DummyParam: @@ -119,3 +120,41 @@ def _compute_residuals( ) out = f({}) assert np.allclose(out, np.array([1.0, 2.0, 3.0])) + + +def test_minimizer_base_fit_stops_tracking_when_solver_prep_fails(): + from easydiffraction.analysis.minimizers.base import MinimizerBase + + class M(MinimizerBase): + def __init__(self): + super().__init__(name='dummy', method='m', max_iterations=5) + self.started = False + self.stopped = False + + def _start_tracking(self, minimizer_name, verbosity=None): + self.started = True + + def _stop_tracking(self): + self.stopped = True + + def _prepare_solver_args(self, parameters): + msg = 'prep failed' + raise ValueError(msg) + + def _run_solver(self, objective_function, **kwargs): + msg = 'should not run solver' + raise AssertionError(msg) + + def _sync_result_to_parameters(self, parameters, raw_result): + pass + + def _check_success(self, raw_result): + return True + + minimizer = M() + + with pytest.raises(ValueError, match='prep failed'): + minimizer.fit(parameters=[_DummyParam(1.0)], objective_function=lambda _: np.array([0.0])) + + assert minimizer.started is True + assert minimizer.stopped is True diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py index 8e800cb4..6ee5e1f4 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py @@ -87,6 +87,19 @@ def test_resolve_random_seed_returns_provided_or_generated(monkeypatch): assert minimizer._resolved_random_seed == 123456 +@pytest.mark.parametrize('seed', [-1, np.iinfo(np.uint32).max + 1]) +def test_resolve_random_seed_rejects_out_of_range_values(seed): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + with pytest.raises( + ValueError, + match=r'DREAM random_seed must be an integer between 0 and 4294967295\.', + ): + minimizer._resolve_random_seed(seed) + + def test_resolved_burn_uses_auto_or_explicit_and_validates(): from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer @@ -286,3 +299,43 @@ def best(self): assert result.sampler_settings['init'] == 'lhs' assert result.sampler_settings['random_seed'] == 17 assert summarize_mock.call_args.kwargs['parameter_names'] == ['beta', 'alpha'] + + +def test_build_driver_stops_mapper_when_driver_clip_fails(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + with ( + patch.object(minimizer, '_build_mapper', return_value='mapper'), + patch('easydiffraction.analysis.minimizers.bumps_dream.FitProblem', return_value='problem'), + patch('easydiffraction.analysis.minimizers.bumps_dream.FitDriver') as mock_driver_cls, + patch('easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper') as stop_mapper, + ): + mock_driver_cls.return_value.clip.side_effect = RuntimeError('clip failed') + + with pytest.raises(RuntimeError, match='clip failed'): + minimizer._build_driver( + fitclass=object(), + fitness=SimpleNamespace(numpoints=lambda: 10), + steps=10, + burn=2, + init=minimizer.init, + sampler_settings={'samples': 40}, + n_parameters=1, + ) + + stop_mapper.assert_called_once() + + +def test_execute_driver_stops_mapper_when_seed_is_invalid(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + driver = SimpleNamespace(fit=MagicMock(), fitter=SimpleNamespace(state=None)) + + with patch('easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper') as stop_mapper: + result = BumpsDreamMinimizer._execute_driver(driver=driver, random_seed=-1) + + assert isinstance(result.error, ValueError) + driver.fit.assert_not_called() + stop_mapper.assert_called_once() diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 66fee2a1..0b21b53d 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -607,12 +607,10 @@ def test_plot_posterior_predictive_summary_uses_consistent_labels_and_styles(mon captured: dict[str, object] = {} - def fake_show(self): - captured['fig'] = self - - monkeypatch.setattr('plotly.graph_objects.Figure.show', fake_show) + plotter = Plotter() + plotter._backend = SimpleNamespace(_show_figure=lambda figure: captured.setdefault('fig', figure)) - Plotter._plot_posterior_predictive_summary( + plotter._plot_posterior_predictive_summary( expt_name='hrpt', summary=SimpleNamespace( x=np.array([1.0, 2.0, 3.0]), @@ -639,6 +637,36 @@ def fake_show(self): assert max_posterior_trace.line.dash == POSTERIOR_POINT_ESTIMATE_LINE_DASH +@pytest.mark.parametrize( + ('x_values', 'y_values', 'x_bounds', 'y_bounds'), + [ + (np.ones(8), np.arange(8, dtype=float), (0.5, 1.5), (0.0, 7.0)), + ( + np.arange(8, dtype=float), + 2.0 * np.arange(8, dtype=float) + 1.0, + (0.0, 7.0), + (1.0, 15.0), + ), + ], +) +def test_posterior_pair_density_surface_returns_none_for_rank_deficient_samples( + x_values, + y_values, + x_bounds, + y_bounds, +): + from easydiffraction.display.plotting import Plotter + + surface = Plotter._posterior_pair_density_surface( + x_values=np.asarray(x_values, dtype=float), + y_values=np.asarray(y_values, dtype=float), + x_bounds=x_bounds, + y_bounds=y_bounds, + ) + + assert surface is None + + def test_plot_posterior_predictive_data_uses_max_posterior_label_and_dash(monkeypatch): from types import SimpleNamespace @@ -984,6 +1012,86 @@ def fake_plot_posterior_predictive_data( assert captured['show_residual'] is None +def test_plot_posterior_predictive_non_bragg_filters_x_range_and_warns_for_residual( + monkeypatch, +): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorPredictiveSummary + from easydiffraction.datablocks.experiment.item.enums import BeamModeEnum + from easydiffraction.datablocks.experiment.item.enums import SampleFormEnum + from easydiffraction.datablocks.experiment.item.enums import ScatteringTypeEnum + from easydiffraction.display.plotting import Plotter + + captured: dict[str, object] = {} + warnings: list[str] = [] + + class ExptType: + sample_form = type('SF', (), {'value': SampleFormEnum.POWDER})() + scattering_type = type('S', (), {'value': ScatteringTypeEnum.TOTAL})() + beam_mode = type('B', (), {'value': BeamModeEnum.CONSTANT_WAVELENGTH})() + + class Pattern: + x = np.array([1.0, 2.0, 3.0]) + two_theta = np.array([1.0, 2.0, 3.0]) + intensity_meas = np.array([10.0, 20.0, 30.0]) + + class Experiment: + type = ExptType() + data = Pattern() + + class Project: + experiments = {'pdf': Experiment()} + + plotter = Plotter() + plotter.engine = 'plotly' + plotter._set_project(Project()) + + monkeypatch.setattr(Plotter, '_update_project_categories', lambda self, expt_name: None) + monkeypatch.setattr( + Plotter, + '_get_or_build_posterior_predictive_summary', + lambda self, **kwargs: PosteriorPredictiveSummary( + experiment_name='pdf', + x_axis_name='two_theta', + x=np.array([1.0, 2.0, 3.0]), + map_prediction=np.array([9.0, 19.0, 29.0]), + lower_95=np.array([8.0, 18.0, 28.0]), + upper_95=np.array([10.0, 20.0, 30.0]), + ), + ) + monkeypatch.setattr('easydiffraction.display.plotting.log.warning', warnings.append) + + def fake_plot_summary( + self, + *, + expt_name, + summary, + y_meas, + axes_labels, + show_band, + show_draws, + ): + captured['expt_name'] = expt_name + captured['summary'] = summary + captured['y_meas'] = y_meas + captured['axes_labels'] = axes_labels + captured['show_band'] = show_band + captured['show_draws'] = show_draws + + monkeypatch.setattr(Plotter, '_plot_posterior_predictive_summary', fake_plot_summary) + + plotter.plot_posterior_predictive('pdf', x_min=1.5, x_max=2.5, show_residual=True) + + assert captured['expt_name'] == 'pdf' + np.testing.assert_allclose(captured['summary'].x, np.array([2.0])) + np.testing.assert_allclose(captured['summary'].map_prediction, np.array([19.0])) + np.testing.assert_allclose(captured['summary'].lower_95, np.array([18.0])) + np.testing.assert_allclose(captured['summary'].upper_95, np.array([20.0])) + np.testing.assert_allclose(captured['y_meas'], np.array([20.0])) + assert captured['show_band'] is True + assert captured['show_draws'] is False + assert any('ignoring show_residual=True' in warning for warning in warnings) + + def test_extract_bragg_tick_sets_uses_derived_d_spacing_for_cwl_ticks(): import numpy as np From 798b0bc9a1136aea8ee68518e8b0b520dacb34d3 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 13:03:20 +0200 Subject: [PATCH 082/106] Fix square matrix plot spacing and aspect ratio --- src/easydiffraction/display/plotting.py | 340 +++++++++++++++--- .../analysis/minimizers/test_bumps_dream.py | 12 +- .../easydiffraction/display/test_plotting.py | 182 ++++++++-- 3 files changed, 454 insertions(+), 80 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 6998640d..7e351abb 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -76,7 +76,8 @@ class PosteriorPairPlotStyleEnum(StrEnum): FULL = 'full' -DEFAULT_CORRELATION_THRESHOLD = 0.0 +DEFAULT_CORRELATION_THRESHOLD: float | None = None +DEFAULT_CORRELATION_MAX_PARAMETERS = 5 EXPECTED_COVAR_NDIM = 2 DEFAULT_RESIDUAL_HEIGHT_FRACTION = 0.25 DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION = 0.10 @@ -742,9 +743,9 @@ def plot_param_correlations( ---------- threshold : float | None, default=DEFAULT_CORRELATION_THRESHOLD Minimum absolute off-diagonal correlation required for a - parameter to be shown. Parameters are kept only if they - participate in at least one pair with ``abs(correlation) >= - threshold``. Set to ``None`` or ``0`` to show the full + parameter to be shown. When omitted, an automatic cutoff is + chosen so the displayed matrix stays at or below ``5 x 5`` + parameters when possible. Set to ``0`` to show the full matrix. precision : int, default=2 Number of decimal places to show in the table fallback. @@ -756,14 +757,17 @@ def plot_param_correlations( if corr_df is None: return - corr_df = self._filter_correlation_dataframe(corr_df, threshold=threshold) + corr_df, resolved_threshold = self._resolve_correlation_filter( + corr_df, + threshold=threshold, + ) if corr_df is None: return corr_df = self._mask_correlation_lower_triangle(corr_df) title = 'Refined parameter correlation matrix' - if threshold is not None and threshold > 0: - title += f' with |correlation| >= {threshold:.2f}' + if resolved_threshold > 0: + title += f' with |correlation| >= {resolved_threshold:.2f}' is_graphical = self._backend._supports_graphical_heatmap display_corr_df, row_numbers, col_numbers = self._trim_correlation_display_dataframe( @@ -776,7 +780,7 @@ def plot_param_correlations( self._plot_correlation_heatmap( display_corr_df, title, - threshold=threshold, + threshold=resolved_threshold, precision=precision, ) return @@ -787,11 +791,55 @@ def plot_param_correlations( display_corr_df, row_numbers=row_numbers, col_numbers=col_numbers, - threshold=threshold, + threshold=resolved_threshold, precision=precision, ) ) + @classmethod + def _resolve_correlation_filter( + cls, + corr_df: pd.DataFrame, + *, + threshold: float | None, + ) -> tuple[pd.DataFrame | None, float]: + """Return a filtered matrix and effective threshold.""" + if threshold is not None: + filtered_corr_df = cls._filter_correlation_dataframe(corr_df, threshold=threshold) + return filtered_corr_df, float(threshold) + return cls._auto_filtered_correlation_dataframe( + corr_df, + max_parameters=DEFAULT_CORRELATION_MAX_PARAMETERS, + ) + + @staticmethod + def _auto_filtered_correlation_dataframe( + corr_df: pd.DataFrame, + *, + max_parameters: int, + ) -> tuple[pd.DataFrame, float]: + """Return an auto-limited matrix for default display.""" + if corr_df.shape[0] <= max_parameters: + return corr_df, 0.0 + + abs_corr = np.abs(corr_df.to_numpy(copy=True)) + np.fill_diagonal(abs_corr, 0.0) + positive_values = np.unique(abs_corr[abs_corr > 0.0]) + for candidate in np.sort(positive_values): + keep_mask = (abs_corr >= candidate).any(axis=0) + if 0 < int(keep_mask.sum()) <= max_parameters: + labels = corr_df.index[keep_mask] + return corr_df.loc[labels, labels], float(candidate) + + if positive_values.size == 0: + return corr_df.iloc[:max_parameters, :max_parameters], 0.0 + + parameter_strength = np.max(abs_corr, axis=0) + top_indices = np.argsort(-parameter_strength, kind='stable')[:max_parameters] + top_indices.sort() + labels = corr_df.index[top_indices] + return corr_df.loc[labels, labels], 0.0 + def plot_posterior_pairs( self, parameters: list[object] | None = None, @@ -1696,11 +1744,46 @@ def _square_matrix_title_left_shift(annotation_labels: list[str]) -> int: return POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + extra_margin @staticmethod - def _posterior_pair_layout_meta() -> dict[str, object]: - """Return layout metadata used by the Plotly HTML wrapper.""" + def _square_matrix_gap_data_width(n_parameters: int) -> float: + """Return the gap width matching pair-plot spacing.""" + if n_parameters <= 1: + return 0.0 + + denominator = 1.0 - PAIR_PLOT_SUBPLOT_SPACING * (n_parameters - 1) + if denominator <= 0: + return 0.0 + return PAIR_PLOT_SUBPLOT_SPACING * n_parameters / denominator + + @classmethod + def _square_matrix_plot_extent(cls, n_parameters: int) -> float: + """Return the inner plot extent for one square matrix plot.""" + gap_width = cls._square_matrix_gap_data_width(n_parameters) + return float(n_parameters + max(0, n_parameters - 1) * gap_width) + + @classmethod + def _square_matrix_target_plot_size_pixels(cls, n_parameters: int) -> float: + """Return the target inner size for one square matrix plot.""" + cell_size = cls._posterior_pair_cell_size_pixels( + n_parameters, + available_width_pixels=PAIR_PLOT_ESTIMATED_CONTAINER_WIDTH_PIXELS, + ) + return cell_size * cls._square_matrix_plot_extent(n_parameters) + + @classmethod + def _square_matrix_layout_meta( + cls, + *, + n_parameters: int, + annotation_labels: list[str], + ) -> dict[str, object]: + """Return wrapper metadata for square matrix plots.""" + margins = cls._posterior_pair_layout_margin(annotation_labels) + plot_size = cls._square_matrix_target_plot_size_pixels(n_parameters) + aspect_width = round(plot_size + int(margins['l']) + int(margins['r'])) + aspect_height = round(plot_size + int(margins['t']) + int(margins['b'])) return { POSTERIOR_PAIR_FIXED_ASPECT_META_KEY: { - 'aspect_ratio': POSTERIOR_PAIR_FIXED_ASPECT_RATIO, + 'aspect_ratio': f'{aspect_width} / {aspect_height}', } } @@ -1722,7 +1805,10 @@ def _finalize_posterior_pairs_figure( *subplot_title_annotations, ], shapes=subplot_border_shapes, - meta=self._posterior_pair_layout_meta(), + meta=self._square_matrix_layout_meta( + n_parameters=context.n_parameters, + annotation_labels=context.annotation_labels, + ), legend={ 'bgcolor': 'rgba(0, 0, 0, 0)', 'xanchor': 'right', @@ -3702,7 +3788,7 @@ def _plot_correlation_heatmap( precision: int, ) -> None: """ - Render a Plotly correlation matrix with pair-plot styling. + Delegate correlation heatmap rendering to the backend. Parameters ---------- @@ -3731,9 +3817,8 @@ def _build_correlation_heatmap_plot( threshold: float | None, precision: int, ) -> object: - """Build a Plotly correlation matrix with pair-plot geometry.""" - make_subplots = __import__('plotly.subplots', fromlist=['make_subplots']).make_subplots - + """Build a compact pair-plot-style correlation heatmap.""" + go = __import__('plotly.graph_objects', fromlist=['Figure', 'Heatmap']) context = _CorrelationHeatmapContext( corr_df=corr_df, row_labels=self._posterior_pair_axis_title_labels(corr_df.index.tolist()), @@ -3741,27 +3826,40 @@ def _build_correlation_heatmap_plot( threshold=threshold, precision=precision, ) - subplot_title_annotations: list[dict[str, object]] = [] - subplot_border_shapes: list[dict[str, object]] = [] - fig = make_subplots( - rows=context.n_rows, - cols=context.n_cols, - shared_xaxes='columns', - shared_yaxes='rows', - horizontal_spacing=PAIR_PLOT_SUBPLOT_SPACING, - vertical_spacing=PAIR_PLOT_SUBPLOT_SPACING, + plot_extent = self._square_matrix_plot_extent(context.n_cols) + x_edges = self._correlation_heatmap_edges(context.n_cols) + y_edges = self._correlation_heatmap_edges(context.n_rows) + x_centers = self._correlation_heatmap_centers(context.n_cols) + y_centers = self._correlation_heatmap_centers(context.n_rows) + + heatmap = go.Heatmap( + z=self._correlation_heatmap_values(context.corr_df), + x=x_edges, + y=y_edges, + customdata=self._correlation_heatmap_customdata(context.corr_df), + zmin=-1.0, + zmax=1.0, + zmid=0.0, + colorscale=self._plot_correlation_colorscale(), + showscale=False, + hoverongaps=False, + hovertemplate=( + '%{customdata[0]}
' + '%{customdata[1]}
' + f'correlation: %{{z:.{context.precision}f}}' + ), ) - - for row_index in range(context.n_rows): - for col_index in range(context.n_cols): - self._populate_correlation_heatmap_panel( - fig=fig, - context=context, - row_index=row_index, - col_index=col_index, - subplot_title_annotations=subplot_title_annotations, - subplot_border_shapes=subplot_border_shapes, - ) + label_trace = PlotlyPlotter._get_correlation_label_trace( + context.corr_df, + x_centers=x_centers, + y_centers=y_centers, + threshold=context.threshold, + precision=context.precision, + ) + traces = [heatmap] + if label_trace is not None: + traces.append(label_trace) + fig = go.Figure(data=traces) fig.update_layout( autosize=True, @@ -3769,19 +3867,169 @@ def _build_correlation_heatmap_plot( *context.row_labels, *context.col_labels, ]), - annotations=[ - self._square_matrix_title_annotation( - title, - [*context.row_labels, *context.col_labels], - ), - *subplot_title_annotations, - ], - shapes=subplot_border_shapes, - meta=self._posterior_pair_layout_meta(), + annotations=self._correlation_heatmap_annotations( + title=title, + context=context, + plot_extent=plot_extent, + x_centers=x_centers, + y_centers=y_centers, + ), + shapes=self._correlation_heatmap_grid_shapes(context), + meta=self._square_matrix_layout_meta( + n_parameters=context.n_cols, + annotation_labels=[*context.row_labels, *context.col_labels], + ), showlegend=False, ) + fig.update_xaxes( + range=[0.0, plot_extent], + showline=False, + mirror=False, + zeroline=False, + showgrid=False, + ticks='', + ticklen=0, + tickwidth=0, + showticklabels=False, + title_text=None, + layer='above traces', + constrain='domain', + ) + fig.update_yaxes( + range=[plot_extent, 0.0], + showline=False, + mirror=False, + zeroline=False, + showgrid=False, + ticks='', + ticklen=0, + tickwidth=0, + showticklabels=False, + title_text=None, + layer='above traces', + constrain='domain', + scaleanchor='x', + scaleratio=1, + ) return fig + @classmethod + def _correlation_heatmap_edges(cls, n_parameters: int) -> np.ndarray: + """Return expanded heatmap edges with pair-plot-like gaps.""" + if n_parameters <= 0: + return np.asarray([0.0], dtype=float) + + gap_width = cls._square_matrix_gap_data_width(n_parameters) + if np.isclose(gap_width, 0.0): + return np.arange(n_parameters + 1, dtype=float) + + widths = [1.0 if index % 2 == 0 else gap_width for index in range(2 * n_parameters - 1)] + return np.concatenate(([0.0], np.cumsum(np.asarray(widths, dtype=float)))) + + @classmethod + def _correlation_heatmap_centers(cls, n_parameters: int) -> np.ndarray: + """Return visible-cell centers for a gapped heatmap.""" + gap_width = cls._square_matrix_gap_data_width(n_parameters) + return np.arange(n_parameters, dtype=float) * (1.0 + gap_width) + 0.5 + + @staticmethod + def _correlation_heatmap_values(corr_df: pd.DataFrame) -> np.ndarray: + """Return a gapped heatmap array for correlation cells.""" + n_rows, n_cols = corr_df.shape + expanded = np.full((2 * n_rows - 1, 2 * n_cols - 1), np.nan, dtype=float) + expanded[0::2, 0::2] = corr_df.to_numpy(dtype=float) + return expanded + + @staticmethod + def _correlation_heatmap_customdata( + corr_df: pd.DataFrame, + ) -> np.ndarray: + """Return hover labels for a correlation heatmap.""" + n_rows, n_cols = corr_df.shape + expanded = np.empty((2 * n_rows - 1, 2 * n_cols - 1, 2), dtype=object) + expanded[..., 0] = '' + expanded[..., 1] = '' + for row_index, row_label in enumerate(corr_df.index): + for col_index, col_label in enumerate(corr_df.columns): + expanded[2 * row_index, 2 * col_index, 0] = str(col_label) + expanded[2 * row_index, 2 * col_index, 1] = str(row_label) + return expanded + + def _correlation_heatmap_annotations( + self, + *, + title: str, + context: _CorrelationHeatmapContext, + plot_extent: float, + x_centers: np.ndarray, + y_centers: np.ndarray, + ) -> list[dict[str, object]]: + """Return pair-plot-like title and axis annotations.""" + annotations = [ + self._square_matrix_title_annotation( + title, + [*context.row_labels, *context.col_labels], + ) + ] + for row_index, row_label in enumerate(context.row_labels): + annotations.append({ + 'x': 0.0, + 'xref': 'paper', + 'xanchor': 'right', + 'xshift': -POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS, + 'y': 1.0 - (float(y_centers[row_index]) / plot_extent), + 'yref': 'paper', + 'yanchor': 'middle', + 'text': row_label, + 'align': 'center', + 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + 'textangle': -90, + 'showarrow': False, + }) + for col_index, col_label in enumerate(context.col_labels): + annotations.append({ + 'x': float(x_centers[col_index]) / plot_extent, + 'xref': 'paper', + 'xanchor': 'center', + 'y': 0.0, + 'yref': 'paper', + 'yanchor': 'top', + 'yshift': -POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS, + 'text': col_label, + 'align': 'center', + 'font': {'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + 'showarrow': False, + }) + return annotations + + def _correlation_heatmap_grid_shapes( + self, + context: _CorrelationHeatmapContext, + ) -> list[dict[str, object]]: + """Return per-cell borders for the visible lower triangle.""" + axis_frame_color = self._plot_axis_frame_color() + gap_width = self._square_matrix_gap_data_width(context.n_cols) + return [ + { + 'type': 'rect', + 'xref': 'x', + 'yref': 'y', + 'x0': float(col_index * (1.0 + gap_width)), + 'x1': float(col_index * (1.0 + gap_width) + 1.0), + 'y0': float(row_index * (1.0 + gap_width)), + 'y1': float(row_index * (1.0 + gap_width) + 1.0), + 'layer': 'above', + 'line': { + 'color': axis_frame_color, + 'width': POSTERIOR_PAIR_AXIS_LINE_WIDTH, + }, + 'fillcolor': 'rgba(0, 0, 0, 0)', + } + for row_index in range(context.n_rows) + for col_index in range(context.n_cols) + if col_index <= row_index + ] + def _populate_correlation_heatmap_panel( self, *, diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py index 6ee5e1f4..9ac35b57 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py @@ -308,9 +308,13 @@ def test_build_driver_stops_mapper_when_driver_clip_fails(): with ( patch.object(minimizer, '_build_mapper', return_value='mapper'), - patch('easydiffraction.analysis.minimizers.bumps_dream.FitProblem', return_value='problem'), + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.FitProblem', return_value='problem' + ), patch('easydiffraction.analysis.minimizers.bumps_dream.FitDriver') as mock_driver_cls, - patch('easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper') as stop_mapper, + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper' + ) as stop_mapper, ): mock_driver_cls.return_value.clip.side_effect = RuntimeError('clip failed') @@ -333,7 +337,9 @@ def test_execute_driver_stops_mapper_when_seed_is_invalid(): driver = SimpleNamespace(fit=MagicMock(), fitter=SimpleNamespace(state=None)) - with patch('easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper') as stop_mapper: + with patch( + 'easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper' + ) as stop_mapper: result = BumpsDreamMinimizer._execute_driver(driver=driver, random_seed=-1) assert isinstance(result.error, ValueError) diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 0b21b53d..889e805a 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -322,7 +322,18 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): assert figure.layout.autosize is True assert figure.layout.width is None assert figure.layout.height is None - assert figure.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] == '1 / 1' + assert ( + figure.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] + == plotter._square_matrix_layout_meta( + n_parameters=4, + annotation_labels=[ + 'length_a', + 'broad_gauss_u', + 'broad_gauss_v', + 'twotheta_offset', + ], + )['fixed_aspect_wrapper']['aspect_ratio'] + ) assert [annotation.text for annotation in figure.layout.annotations] == [ 'Posterior pair plot', 'length_a', @@ -608,7 +619,9 @@ def test_plot_posterior_predictive_summary_uses_consistent_labels_and_styles(mon captured: dict[str, object] = {} plotter = Plotter() - plotter._backend = SimpleNamespace(_show_figure=lambda figure: captured.setdefault('fig', figure)) + plotter._backend = SimpleNamespace( + _show_figure=lambda figure: captured.setdefault('fig', figure) + ) plotter._plot_posterior_predictive_summary( expt_name='hrpt', @@ -1561,25 +1574,26 @@ class Project: p.plot_param_correlations() fig = captured['fig'] + heatmap = fig.data[0] + text_trace = fig.data[1] + gap_width = Plotter._square_matrix_gap_data_width(2) assert len(fig.data) == 2 - assert fig.data[0].type == 'heatmap' - assert list(fig.data[0].x) == [0.0, 1.0] - assert list(fig.data[0].y) == [0.0, 1.0] - assert fig.data[0].xgap in (None, 0) - assert fig.data[0].ygap in (None, 0) - assert fig.data[0].showscale is False - assert ( - fig.data[0].hovertemplate - == 'phase.scale
phase.cell.length_c
correlation: %{z:.2f}' + assert heatmap.type == 'heatmap' + assert list(heatmap.x) == pytest.approx([0.0, 1.0, 1.0 + gap_width, 2.0 + gap_width]) + assert list(heatmap.y) == pytest.approx([0.0, 1.0, 1.0 + gap_width, 2.0 + gap_width]) + assert heatmap.showscale is False + assert heatmap.hovertemplate == ( + '%{customdata[0]}
%{customdata[1]}
correlation: %{z:.2f}' ) - assert pytest.approx(fig.data[0].z[0][0], rel=1e-9) == -0.5 - assert fig.data[1].type == 'scatter' - assert fig.data[1].mode == 'text' - assert list(fig.data[1].x) == [0.5] - assert list(fig.data[1].y) == [0.5] - assert list(fig.data[1].text) == ['-0.50'] - assert fig.data[1].textposition == 'middle center' - assert fig.data[1].hoverinfo == 'skip' + assert list(heatmap.customdata[2][0]) == ['phase.scale', 'phase.cell.length_c'] + assert pytest.approx(np.nanmin(np.asarray(heatmap.z, dtype=float)), rel=1e-9) == -0.5 + assert text_trace.type == 'scatter' + assert text_trace.mode == 'text' + assert list(text_trace.x) == [0.5] + assert list(text_trace.y) == pytest.approx([1.5 + gap_width]) + assert list(text_trace.text) == ['-0.50'] + assert text_trace.textposition == 'middle center' + assert text_trace.hoverinfo == 'skip' assert [annotation.text for annotation in fig.layout.annotations] == [ 'Refined parameter correlation matrix', 'phase.
scale', @@ -1597,24 +1611,30 @@ class Project: assert fig.layout.margin.b == ( POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + 2 * POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS ) - assert fig.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] == '1 / 1' - assert fig.layout.xaxis.domain[1] < fig.layout.xaxis2.domain[0] + assert ( + fig.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] + == Plotter._square_matrix_layout_meta( + n_parameters=2, + annotation_labels=[ + 'phase.
scale', + 'phase.
cell.
length_c', + 'phase.
scale', + 'phase.
cell.
length_c', + ], + )['fixed_aspect_wrapper']['aspect_ratio'] + ) assert fig.layout.xaxis.showline is False assert fig.layout.xaxis.mirror is False - assert fig.layout.xaxis.layer == 'above traces' - assert fig.layout.xaxis.showticklabels is False - assert fig.layout.xaxis.title.text is None assert fig.layout.yaxis.showline is False assert fig.layout.yaxis.mirror is False - assert fig.layout.yaxis.layer == 'above traces' + assert fig.layout.xaxis.showticklabels is False assert fig.layout.yaxis.showticklabels is False + assert fig.layout.xaxis.title.text is None assert fig.layout.yaxis.title.text is None assert fig.layout.paper_bgcolor is None assert fig.layout.plot_bgcolor is None assert len(fig.layout.shapes) == 3 assert all(shape.type == 'rect' for shape in fig.layout.shapes) - assert all(shape.xref == 'paper' for shape in fig.layout.shapes) - assert all(shape.yref == 'paper' for shape in fig.layout.shapes) def test_plot_param_correlations_plotly_labels_respect_threshold(monkeypatch): @@ -1673,11 +1693,111 @@ class Project: fig = captured['fig'] heatmap_traces = [trace for trace in fig.data if trace.type == 'heatmap'] text_traces = [trace for trace in fig.data if trace.type == 'scatter' and trace.mode == 'text'] - assert len(heatmap_traces) == 10 - assert [trace.text[0] for trace in text_traces] == ['-0.91', '0.83', '-0.89', '0.82'] + assert len(heatmap_traces) == 1 + assert len(text_traces) == 1 + assert list(text_traces[0].text) == ['-0.91', '0.83', '-0.89', '0.82'] + assert len(fig.layout.shapes) == 15 + + +def test_plot_param_correlations_limits_default_table_to_five_parameters(monkeypatch): + from easydiffraction.display.plotting import Plotter + from easydiffraction.display.tables import TableRenderer + + captured = {} + + class FakeTabler: + def render(self, df): + captured['df'] = df + + monkeypatch.setattr(TableRenderer, 'get', staticmethod(lambda: FakeTabler())) + + class Param: + def __init__(self, uid, unique_name): + self._minimizer_uid = uid + self.unique_name = unique_name + + class RawResult: + covar = None + var_names = ['p1', 'p2', 'p3', 'p4', 'p5', 'p6'] + + class ParamResult: + def __init__(self, correl): + self.correl = correl + + params = { + 'p1': ParamResult({'p2': 0.95}), + 'p2': ParamResult({'p1': 0.95, 'p3': 0.94}), + 'p3': ParamResult({'p2': 0.94, 'p4': 0.93}), + 'p4': ParamResult({'p3': 0.93, 'p5': 0.92}), + 'p5': ParamResult({'p4': 0.92, 'p6': 0.91}), + 'p6': ParamResult({'p5': 0.91}), + } + + class FitResults: + engine_result = RawResult() + parameters = [ + Param('p1', 'phase.scale'), + Param('p2', 'phase.cell.length_a'), + Param('p3', 'phase.background'), + Param('p4', 'phase.profile.u'), + Param('p5', 'phase.profile.v'), + Param('p6', 'phase.profile.w'), + ] + + class Analysis: + fit_results = FitResults() + + class Project: + analysis = Analysis() + + p = Plotter() + p.engine = 'asciichartpy' + p._set_project(Project()) + p.plot_param_correlations() + + df = captured['df'] + assert [column.strip() for column in df.columns.get_level_values(0)] == [ + 'parameter', + '1', + '2', + '3', + '4', + '5', + ] + assert list(df.index) == [0, 1, 2, 3, 4] + assert df.iloc[0, 0] == 'phase.scale' + assert df.iloc[0, 1] == '' + assert df.iloc[0, 2] == '' + assert df.iloc[0, 3] == '' + assert df.iloc[0, 4] == '' + assert df.iloc[0, 5] == '' + assert df.iloc[1, 0] == 'phase.cell.length_a' + assert _strip_markup(df.iloc[1, 1]).strip() == '0.95' + assert df.iloc[1, 2] == '' + assert df.iloc[1, 3] == '' + assert df.iloc[1, 4] == '' + assert df.iloc[1, 5] == '' + assert df.iloc[2, 0] == 'phase.background' + assert df.iloc[2, 1] == '' + assert _strip_markup(df.iloc[2, 2]).strip() == '0.94' + assert df.iloc[2, 3] == '' + assert df.iloc[2, 4] == '' + assert df.iloc[2, 5] == '' + assert df.iloc[3, 0] == 'phase.profile.u' + assert df.iloc[3, 1] == '' + assert df.iloc[3, 2] == '' + assert _strip_markup(df.iloc[3, 3]).strip() == '0.93' + assert df.iloc[3, 4] == '' + assert df.iloc[3, 5] == '' + assert df.iloc[4, 0] == 'phase.profile.v' + assert df.iloc[4, 1] == '' + assert df.iloc[4, 2] == '' + assert df.iloc[4, 3] == '' + assert _strip_markup(df.iloc[4, 4]).strip() == '0.92' + assert df.iloc[4, 5] == '' -def test_plot_param_correlations_shows_full_table_by_default(monkeypatch): +def test_plot_param_correlations_shows_full_table_when_threshold_is_zero(monkeypatch): from easydiffraction.display.plotting import Plotter from easydiffraction.display.tables import TableRenderer @@ -1725,7 +1845,7 @@ class Project: p = Plotter() p.engine = 'asciichartpy' p._set_project(Project()) - p.plot_param_correlations() + p.plot_param_correlations(threshold=0) df = captured['df'] assert [column.strip() for column in df.columns.get_level_values(0)] == [ From 39683b5001b6c7b2b224954640a885520946f705 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 23:05:32 +0200 Subject: [PATCH 083/106] Apply the latest templates --- .copier-answers.yml | 2 +- .github/workflows/coverage.yml | 2 - .github/workflows/issues-labels.yml | 149 +++------------------- .github/workflows/pr-labels.yml | 74 ++++------- .github/workflows/test.yml | 6 +- docs/docs/installation-and-setup/index.md | 13 +- docs/mkdocs.yml | 4 +- 7 files changed, 62 insertions(+), 188 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index a807c84d..b7376e06 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,6 +1,6 @@ # WARNING: Do not edit this file manually. # Any changes will be overwritten by Copier. -_commit: v0.11.1-12-gbb9bb30 +_commit: v0.11.2-5-gd120259 _src_path: gh:easyscience/templates app_docs_url: https://easyscience.github.io/diffraction-app app_doi: 10.5281/zenodo.18163581 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 95c190c6..d96e5b87 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -5,8 +5,6 @@ on: push: branches: - develop - # 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 diff --git a/.github/workflows/issues-labels.yml b/.github/workflows/issues-labels.yml index 56ab5b19..4fbf4fab 100644 --- a/.github/workflows/issues-labels.yml +++ b/.github/workflows/issues-labels.yml @@ -1,6 +1,5 @@ -# Verifies if the current issue has at least one real `[scope]` label and one -# real `[priority]` label. If either is missing, the workflow adds a reminder -# label with a warning emoji. +# Verifies if the current issue has at least one `[scope]` label and one +# `[priority]` label. If either is missing, the workflow adds a reminder label. name: Issue labels check @@ -20,130 +19,22 @@ jobs: cancel-in-progress: true steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Sync missing-label reminders - uses: ./.github/actions/github-script + - name: Ensure [scope] label + uses: Rindrics/expect-label-prefix@v1.2.1 with: - script: | - const fs = require('fs'); - - const issueNumber = context.issue.number; - const action = context.payload.action; - const changedLabel = context.payload.label?.name ?? null; - const labels = context.payload.issue.labels.map(({ name }) => name); - const requirements = [ - { - prefix: '[scope] ', - reminder: '[scope] ⚠️ label needed', - }, - { - prefix: '[priority] ', - reminder: '[priority] ⚠️ label needed', - }, - ]; - - const labelsToAdd = []; - const labelsToRemove = []; - const evaluations = []; - - console.log(`::group::Issue label check for #${issueNumber}`); - console.log(`Event action: ${action}`); - if (changedLabel) { - console.log(`Event label: ${changedLabel}`); - } - console.log( - `Current labels: ${labels.length > 0 ? labels.join(', ') : '(none)'}`, - ); - - for (const { prefix, reminder } of requirements) { - const matchingRealLabels = labels.filter( - (name) => name.startsWith(prefix) && name !== reminder, - ); - const hasRealLabel = matchingRealLabels.length > 0; - const hasReminderLabel = labels.includes(reminder); - - evaluations.push({ - prefix, - reminder, - matchingRealLabels, - hasReminderLabel, - }); - - if (hasRealLabel && hasReminderLabel) { - labelsToRemove.push(reminder); - } else if (!hasRealLabel && !hasReminderLabel) { - labelsToAdd.push(reminder); - } - } - - for (const evaluation of evaluations) { - if (evaluation.matchingRealLabels.length > 0) { - console.log( - `Found required ${evaluation.prefix}label(s): ${evaluation.matchingRealLabels.join(', ')}`, - ); - } else { - console.log(`Missing required ${evaluation.prefix}label.`); - } - - if (evaluation.hasReminderLabel) { - console.log(`Reminder label already present: ${evaluation.reminder}`); - } - } - - if (labelsToAdd.length > 0) { - console.log(`Adding reminder labels: ${labelsToAdd.join(', ')}`); - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - labels: labelsToAdd, - }); - } - - for (const name of labelsToRemove) { - console.log(`Removing reminder label: ${name}`); - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - name, - }); - } - - if (labelsToAdd.length === 0 && labelsToRemove.length === 0) { - console.log('No label changes required.'); - } - - console.log('::endgroup::'); - - if (process.env.GITHUB_STEP_SUMMARY) { - const summaryLines = [ - '### Issue Label Check', - `- Issue: #${issueNumber}`, - `- Event: ${action}`, - `- Trigger label: ${changedLabel ?? '(none)'}`, - `- Current labels: ${labels.length > 0 ? labels.join(', ') : '(none)'}`, - '', - '#### Requirement status', - ...evaluations.map((evaluation) => { - const status = - evaluation.matchingRealLabels.length > 0 - ? `found ${evaluation.matchingRealLabels.join(', ')}` - : 'missing'; - const reminder = evaluation.hasReminderLabel - ? `reminder present: ${evaluation.reminder}` - : `reminder absent: ${evaluation.reminder}`; - return `- ${evaluation.prefix}: ${status}; ${reminder}`; - }), - '', - `- Labels to add: ${labelsToAdd.length > 0 ? labelsToAdd.join(', ') : '(none)'}`, - `- Labels to remove: ${labelsToRemove.length > 0 ? labelsToRemove.join(', ') : '(none)'}`, - ]; - - fs.appendFileSync( - process.env.GITHUB_STEP_SUMMARY, - `${summaryLines.join('\n')}\n`, - ); - } + repository_full_name: ${{ github.repository }} + token: ${{ github.token }} + label_prefix: '[scope]' + label_separator: ' ' + add_label: 'true' + default_label: '[scope] ⚠️ label needed' + + - name: Ensure [priority] label + uses: Rindrics/expect-label-prefix@v1.2.1 + with: + repository_full_name: ${{ github.repository }} + token: ${{ github.token }} + label_prefix: '[priority]' + label_separator: ' ' + add_label: 'true' + default_label: '[priority] ⚠️ label needed' diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml index 25710633..fcb8a78c 100644 --- a/.github/workflows/pr-labels.yml +++ b/.github/workflows/pr-labels.yml @@ -1,17 +1,9 @@ # 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. -# The `concurrency` configuration below ensures that only the latest run -# for the same PR remains active, canceling any previous in-progress -# run. +# The label validation is delegated to `mheap/github-action-required-labels`, +# which checks the current PR labels via the GitHub API and can add or update a +# PR comment when the required label set is missing. name: PR labels check @@ -19,45 +11,35 @@ on: pull_request_target: types: [opened, labeled, unlabeled, synchronize] -concurrency: - group: pr-labels-${{ github.event.pull_request.number }} - cancel-in-progress: true - permissions: - pull-requests: read + issues: write + pull-requests: write jobs: check-labels: runs-on: ubuntu-latest steps: - - 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=( - "[bot] release" - "[scope] bug" - "[scope] documentation" - "[scope] enhancement" - "[scope] maintenance" - "[scope] significant" - ) - - found=false - for label in "${VALID_LABELS[@]}"; do - if echo "$PR_LABELS" | grep -Fxq "$label"; then - echo "βœ… Found valid label: $label" - found=true - break - fi - done - - if [ "$found" = false ]; then - echo "ERROR: PR must have at least one of the following labels:" - for label in "${VALID_LABELS[@]}"; do - echo " - $label" - done - exit 1 - fi + - name: Checkout repository + uses: actions/checkout@v6 + + - 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 }} + + - uses: mheap/github-action-required-labels@v5 + with: + token: ${{ steps.bot.outputs.token }} + add_comment: true + mode: minimum + count: 1 + labels: | + [bot] release + [scope] bug + [scope] documentation + [scope] enhancement + [scope] maintenance + [scope] significant diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d0298f95..86bfa606 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -248,10 +248,10 @@ jobs: exit 1 fi - whl_url="file://$(python -c 'import os,sys; print(os.path.abspath(sys.argv[1]))' "${whl_path[0]}")" + whl_abs_path="$(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 "Adding easydiffraction from: $whl_abs_path" + pixi add --pypi "easydiffraction[dev] @ ${whl_abs_path}" echo "Exiting pixi project directory" cd .. diff --git a/docs/docs/installation-and-setup/index.md b/docs/docs/installation-and-setup/index.md index 41036f1d..ee86679b 100644 --- a/docs/docs/installation-and-setup/index.md +++ b/docs/docs/installation-and-setup/index.md @@ -254,8 +254,8 @@ once using the command line, as shown below. ```txt pixi run easydiffraction download-all-tutorials ``` -- Start JupyterLab in the `tutorials/` directory to access the - notebooks: +- Start the JupyterLab server in the `tutorials/` directory to access + the notebooks: ```txt pixi run jupyter lab tutorials/ ``` @@ -278,13 +278,14 @@ once using the command line, as shown below. ```txt python -m easydiffraction download-all-tutorials ``` -- Launch the Jupyter Notebook server (opens browser automatically at - `http://localhost:8888/`): +- Start the Jupyter Notebook server in the `tutorials/` directory to + access the notebooks: ```txt jupyter notebook tutorials/ ``` -- Open one of the `*.ipynb` files and select the - `EasyDiffraction Python kernel` to get started. +- Your web browser should open automatically. Click on one of the + `*.ipynb` files and select the `EasyDiffraction Python kernel` to get + started. ### Run Tutorials via Google Colab diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 6ad6b770..42294197 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -148,8 +148,10 @@ plugins: python: paths: ['src'] # Change 'src' to your actual sources directory options: + annotations_path: source docstring_style: numpy - group_by_category: false + group_by_category: true + members_order: source heading_level: 1 show_root_heading: true show_root_full_path: false From 078842cc8df7909f5d39f0da3b5fef02fdd905f4 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 23:12:55 +0200 Subject: [PATCH 084/106] Bump setup-pixi to v0.9.5 --- .github/actions/setup-pixi/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-pixi/action.yml b/.github/actions/setup-pixi/action.yml index ec7d7ba7..dc3232c6 100644 --- a/.github/actions/setup-pixi/action.yml +++ b/.github/actions/setup-pixi/action.yml @@ -33,7 +33,7 @@ inputs: runs: using: 'composite' steps: - - uses: prefix-dev/setup-pixi@v0.9.4 + - uses: prefix-dev/setup-pixi@v0.9.5 with: environments: ${{ inputs.environments }} activate-environment: ${{ inputs.activate-environment }} From ab3843bfbd2d0f57bdd9c7c67baf902e48e4ff12 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 23:13:38 +0200 Subject: [PATCH 085/106] Bump dependencies --- pixi.lock | 1065 ++++++++++++++++++++++++++--------------------------- 1 file changed, 531 insertions(+), 534 deletions(-) diff --git a/pixi.lock b/pixi.lock index 3ac082e7..0d0a058d 100644 --- a/pixi.lock +++ b/pixi.lock @@ -76,32 +76,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-6_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_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-6_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.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.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda - - 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/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-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.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/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_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/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-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.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -161,7 +161,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -195,8 +195,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/b2/e6/65abe97bbd42eb6ef73d3a58566ce89b097ae049511b7d9708288714a798/crysfml-0.6.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -239,16 +239,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -267,7 +267,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -278,7 +278,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/15/88/3cdd54fa279341afa10acf8d2b503556b1375245dccc9315659f795dd2e9/pandas-3.0.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl @@ -291,7 +291,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -319,7 +319,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-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/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -334,7 +334,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -418,30 +418,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-6_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_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-6_hb0561ab_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_18.conda - - 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/libgcc-15.2.0-hcbb3090_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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.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/libopenblas-0.3.33-openmp_he657e61_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.4-hc7d1edf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -503,7 +503,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -537,8 +537,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d0/42/bf7fb4d923a15b99b678ecb3bdcc02d336ee34baa876c6f41c5c55038b9c/crysfml-0.6.1-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -580,16 +580,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -608,7 +608,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -619,7 +619,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/95/25/bdb9326c3b5455f8d4d3549fce7abcf967259de146fe2cf7a82368141948/pandas-3.0.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl @@ -632,7 +632,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -660,7 +660,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-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/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -675,7 +675,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -755,8 +755,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.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/libblas-3.11.0-7_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 @@ -769,11 +769,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h692994f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.4-h4fa8253_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.5-h4fa8253_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.1-hac47afa_12.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda @@ -781,7 +781,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2025.3.1-h57928b3_12.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda @@ -833,7 +833,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda @@ -871,8 +871,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d9/1a/8a81b3a66f36969c8456f8af3a12f7d601fdd9cfed2ad5b4e72a2fb7ea8d/crysfml-0.6.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -915,16 +915,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -943,7 +943,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -954,7 +954,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/60/aba6a38de456e7341285102bede27514795c1eaa353bc0e7638b6b785356/pandas-3.0.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl @@ -967,7 +967,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -995,7 +995,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-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/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -1010,7 +1010,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -1104,33 +1104,33 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-6_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_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-6_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.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.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda - - 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/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_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.32-pthreads_h94d23a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_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/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-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.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -1190,7 +1190,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -1224,8 +1224,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/06/fe/2a936f465588dc7ef28793c2917b60a1c0bd26b0b716f4e43b228763c74b/crysfml-0.6.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/69/ff/6699e7b71e60d3049eb2bdcbc95ee3f35707b2b0e48f32e9e63d3ce30c08/coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/97/37/ce5c3ef2595dac2be35039f7b91a0691ef643aa3d954815b3b51e026e0ab/crysfml-0.6.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -1268,16 +1268,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -1296,7 +1296,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -1307,7 +1307,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0a/0d/0e3ecece05b7a7e87ab9fb587855548da437a061326fff64a223b6dcb78a/numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c4/a8/3a61a721472959ab0ce865ef05d10b0d6bfe27ce8801c99f33d4fa996e65/pandas-3.0.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl @@ -1320,7 +1320,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -1348,7 +1348,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-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/1e/e7/cd78635d0ece7e4d3393f2c1d2ebabf6ff4bd615da142891b1d42ad58abf/scipp-26.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -1363,7 +1363,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -1447,29 +1447,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-6_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_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-6_hb0561ab_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_18.conda - - 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/libgcc-15.2.0-hcbb3090_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.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/libopenblas-0.3.33-openmp_he657e61_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.4-hc7d1edf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -1531,7 +1531,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -1565,8 +1565,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/36/28/46c4b0dfc8eb52c4fe8c902601b5e0acfc6b943f97cf8c53447ef9e1c66c/crysfml-0.6.1-cp312-cp312-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/34/23/35c7aea1274aef7525bdd2dc92f710bdde6d11652239d71d1ec450067939/coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/15/1d/9f9e30d76300b0150afaa8b37fab9a0194d44fd4f6b1e5038aca4a1440ed/crysfml-0.6.2-cp312-cp312-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -1608,16 +1608,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/18/4880dd762e40cd360c1bf06e890c5a97b997e91cb324602b1a19950ad5ce/matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -1636,7 +1636,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -1647,7 +1647,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/fd/e5ecca1e78c05106d98028114f5c00d3eddb41207686b2b7de3e477b0e22/numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/35/d0/4831af68ce30cc2d03c697bea8450e3225a835ef497d0d70f31b8cdde965/pandas-3.0.2-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl @@ -1660,7 +1660,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -1688,7 +1688,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-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/44/7b/537a61906eac58d94131273084d21d4eb219f5453f0ed30de3aca580a2b4/scipp-26.3.1-cp312-cp312-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -1703,7 +1703,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -1783,8 +1783,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.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/libblas-3.11.0-7_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 @@ -1796,11 +1796,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h692994f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.4-h4fa8253_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.5-h4fa8253_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.1-hac47afa_12.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py312he06e257_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda @@ -1808,7 +1808,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2025.3.1-h57928b3_12.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda @@ -1860,7 +1860,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda @@ -1898,8 +1898,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/2c/58/d025d34259682d555db962eab098f5add29187443c31081cbaf5c7ec4bea/crysfml-0.6.1-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/85/19/93853133df2cb371083285ef6a93982a0173e7a233b0f61373ba9fd30eb2/coverage-7.14.0-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/1a/c7/78200c18404ded028758b28b588aa1f4f3acd851271a74156a2a3db9eadf/crysfml-0.6.2-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -1942,16 +1942,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -1970,7 +1970,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -1981,7 +1981,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2d/5b/e1deebf88ff431b01b7406ca3583ab2bbb90972bbe1c568732e49c844f7e/numpy-2.4.4-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/8b/721a9cff6fa6a91b162eb51019c6243b82b3226c71bb6c8ef4a9bd65cbc6/pandas-3.0.2-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl @@ -1994,7 +1994,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -2022,7 +2022,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-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/1a/1f/86b4d15221096cb5500bcd73bf350745749e3ba056cdd7a7f75f126f154e/scipp-26.3.1-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -2037,7 +2037,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -2131,32 +2131,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-6_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_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-6_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.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.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda - - 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/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-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.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/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_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/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-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.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -2216,7 +2216,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -2250,8 +2250,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/b2/e6/65abe97bbd42eb6ef73d3a58566ce89b097ae049511b7d9708288714a798/crysfml-0.6.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -2294,16 +2294,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -2322,7 +2322,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -2333,7 +2333,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/15/88/3cdd54fa279341afa10acf8d2b503556b1375245dccc9315659f795dd2e9/pandas-3.0.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl @@ -2346,7 +2346,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -2374,7 +2374,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-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/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -2389,7 +2389,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -2473,30 +2473,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-6_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_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-6_hb0561ab_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_18.conda - - 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/libgcc-15.2.0-hcbb3090_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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.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/libopenblas-0.3.33-openmp_he657e61_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.4-hc7d1edf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -2558,7 +2558,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -2592,8 +2592,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d0/42/bf7fb4d923a15b99b678ecb3bdcc02d336ee34baa876c6f41c5c55038b9c/crysfml-0.6.1-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -2635,16 +2635,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -2663,7 +2663,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -2674,7 +2674,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/95/25/bdb9326c3b5455f8d4d3549fce7abcf967259de146fe2cf7a82368141948/pandas-3.0.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl @@ -2687,7 +2687,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -2715,7 +2715,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-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/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -2730,7 +2730,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -2810,8 +2810,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.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/libblas-3.11.0-7_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 @@ -2824,11 +2824,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h692994f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.4-h4fa8253_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.5-h4fa8253_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.1-hac47afa_12.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda @@ -2836,7 +2836,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2025.3.1-h57928b3_12.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda @@ -2888,7 +2888,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda @@ -2926,8 +2926,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d9/1a/8a81b3a66f36969c8456f8af3a12f7d601fdd9cfed2ad5b4e72a2fb7ea8d/crysfml-0.6.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -2970,16 +2970,16 @@ environments: - 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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl @@ -2998,7 +2998,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl @@ -3009,7 +3009,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/60/aba6a38de456e7341285102bede27514795c1eaa353bc0e7638b6b785356/pandas-3.0.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl @@ -3022,7 +3022,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl @@ -3050,7 +3050,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-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/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -3065,7 +3065,7 @@ environments: - 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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl @@ -3158,17 +3158,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_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/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-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/libsodium-1.0.21-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_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/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.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/markupsafe-3.0.3-py314h67df5f8_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -3227,7 +3227,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -3251,7 +3251,7 @@ environments: - 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/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/b2/e6/65abe97bbd42eb6ef73d3a58566ce89b097ae049511b7d9708288714a798/crysfml-0.6.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -3281,7 +3281,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl @@ -3289,13 +3289,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/15/88/3cdd54fa279341afa10acf8d2b503556b1375245dccc9315659f795dd2e9/pandas-3.0.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl @@ -3304,7 +3304,7 @@ environments: - 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/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz @@ -3317,7 +3317,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -3399,7 +3399,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda @@ -3409,7 +3409,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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/markupsafe-3.0.3-py314h6e9b3f0_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -3470,7 +3470,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda @@ -3494,7 +3494,7 @@ environments: - 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/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d0/42/bf7fb4d923a15b99b678ecb3bdcc02d336ee34baa876c6f41c5c55038b9c/crysfml-0.6.1-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -3523,7 +3523,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl @@ -3531,13 +3531,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/95/25/bdb9326c3b5455f8d4d3549fce7abcf967259de146fe2cf7a82368141948/pandas-3.0.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl @@ -3546,7 +3546,7 @@ environments: - 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/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz @@ -3559,7 +3559,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -3649,7 +3649,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_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/markupsafe-3.0.3-py314h2359020_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -3707,7 +3707,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda @@ -3735,7 +3735,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d9/1a/8a81b3a66f36969c8456f8af3a12f7d601fdd9cfed2ad5b4e72a2fb7ea8d/crysfml-0.6.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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 @@ -3765,7 +3765,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl @@ -3773,13 +3773,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/db/60/aba6a38de456e7341285102bede27514795c1eaa353bc0e7638b6b785356/pandas-3.0.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl @@ -3788,7 +3788,7 @@ environments: - 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/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz @@ -3801,7 +3801,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl @@ -4008,7 +4008,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/anyio?source=compressed-mapping + - pkg:pypi/anyio?source=hash-mapping size: 146764 timestamp: 1774359453364 - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda @@ -4360,7 +4360,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/babel?source=compressed-mapping + - pkg:pypi/babel?source=hash-mapping size: 7684321 timestamp: 1772555330347 - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.4.0-py312h90b7ffd_0.conda @@ -4374,7 +4374,7 @@ packages: - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - - pkg:pypi/backports-zstd?source=compressed-mapping + - pkg:pypi/backports-zstd?source=hash-mapping size: 238360 timestamp: 1777848717715 - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda @@ -4397,7 +4397,7 @@ packages: - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - - pkg:pypi/backports-zstd?source=compressed-mapping + - pkg:pypi/backports-zstd?source=hash-mapping size: 239305 timestamp: 1777848727027 - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.4.0-py312h06d0912_0.conda @@ -4412,7 +4412,7 @@ packages: - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - - pkg:pypi/backports-zstd?source=compressed-mapping + - pkg:pypi/backports-zstd?source=hash-mapping size: 237107 timestamp: 1777848740547 - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl @@ -4722,7 +4722,7 @@ packages: - python >=3.10 license: ISC purls: - - pkg:pypi/certifi?source=compressed-mapping + - pkg:pypi/certifi?source=hash-mapping size: 135656 timestamp: 1776866680878 - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda @@ -4864,7 +4864,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/charset-normalizer?source=compressed-mapping + - pkg:pypi/charset-normalizer?source=hash-mapping size: 58872 timestamp: 1775127203018 - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl @@ -5077,45 +5077,45 @@ packages: - 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/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/34/23/35c7aea1274aef7525bdd2dc92f710bdde6d11652239d71d1ec450067939/coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl name: coverage - version: 7.13.5 - sha256: 6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510 + version: 7.14.0 + sha256: 829994cfe1aeb773ca27bf246d4badc1e764893e3bfb98fff820fcecd1ca4662 requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/69/ff/6699e7b71e60d3049eb2bdcbc95ee3f35707b2b0e48f32e9e63d3ce30c08/coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl name: coverage - version: 7.13.5 - sha256: d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810 + version: 7.14.0 + sha256: ca3d9cf2c32b521bd9518385608787fa86f38daf993695307531822c3430ed67 requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/85/19/93853133df2cb371083285ef6a93982a0173e7a233b0f61373ba9fd30eb2/coverage-7.14.0-cp312-cp312-win_amd64.whl name: coverage - version: 7.13.5 - sha256: 03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5 + version: 7.14.0 + sha256: 70390b0da32cb90b501953716302906e8bcce087cb283e70d8c97729f22e92b2 requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl name: coverage - version: 7.13.5 - sha256: 2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633 + version: 7.14.0 + sha256: 5ebb8f4614a3787d567e610bbfdf96a4798dd69a1afb1bd8ad228d4111fe6ff3 requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl name: coverage - version: 7.13.5 - sha256: 0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422 + version: 7.14.0 + sha256: ba3b8390db29296dbbf49e91b6fe08f990743a90c8f447ba4c2ffc29670dfa63 requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl name: coverage - version: 7.13.5 - sha256: 9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e + version: 7.14.0 + sha256: 45e0f79d8351fa76e256716df91eab12890d32678b9590df7ae1042e4bd4cf5d requires_dist: - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' @@ -5141,45 +5141,45 @@ packages: purls: [] size: 49809 timestamp: 1775614256655 -- pypi: https://files.pythonhosted.org/packages/06/fe/2a936f465588dc7ef28793c2917b60a1c0bd26b0b716f4e43b228763c74b/crysfml-0.6.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl name: crysfml - version: 0.6.1 - sha256: aaa0c38132f99976fa95c7cb728ee98113137a0023819a60893461943dcefd93 + version: 0.6.2 + sha256: 4278178f2028360f489f2cdfda7f2f7f26e4f1674b50eb934f403bb443a8f00a requires_dist: - numpy requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/2c/58/d025d34259682d555db962eab098f5add29187443c31081cbaf5c7ec4bea/crysfml-0.6.1-cp312-cp312-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/15/1d/9f9e30d76300b0150afaa8b37fab9a0194d44fd4f6b1e5038aca4a1440ed/crysfml-0.6.2-cp312-cp312-macosx_14_0_arm64.whl name: crysfml - version: 0.6.1 - sha256: 13c51e0021b70dd939cb6d38ac4e82dc11e173e7e43125d1cd4c55050371cf2f + version: 0.6.2 + sha256: 75bba671d2237f6fbbb1284c473543eb143b5bd3ab69f40a2d2cf343dbe0977f requires_dist: - numpy requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/36/28/46c4b0dfc8eb52c4fe8c902601b5e0acfc6b943f97cf8c53447ef9e1c66c/crysfml-0.6.1-cp312-cp312-macosx_14_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/1a/c7/78200c18404ded028758b28b588aa1f4f3acd851271a74156a2a3db9eadf/crysfml-0.6.2-cp312-cp312-win_amd64.whl name: crysfml - version: 0.6.1 - sha256: 6321b1d45e29968976e2e504fba51cc9c01165a9911cde86a6b5b0473653f29a + version: 0.6.2 + sha256: cd2027d98252a138bd7260b57f77c8d3c69e0da95454a44a9b80551198e8a327 requires_dist: - numpy requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/b2/e6/65abe97bbd42eb6ef73d3a58566ce89b097ae049511b7d9708288714a798/crysfml-0.6.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl name: crysfml - version: 0.6.1 - sha256: 419f99e6fb4756185e00a2ca9f95377ae2ac1559fc0b965060bbec8a66a7eb4a + version: 0.6.2 + sha256: 2ca0cb14298c8db170d897e7744007a0e2f29762151ac458a0b38a1a1a9c2967 requires_dist: - numpy requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/d0/42/bf7fb4d923a15b99b678ecb3bdcc02d336ee34baa876c6f41c5c55038b9c/crysfml-0.6.1-cp314-cp314-macosx_14_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl name: crysfml - version: 0.6.1 - sha256: 341ca456a1b4ee5a607df283e6a630db7e25585b560c166edc4fc35dbb4c27e3 + version: 0.6.2 + sha256: 8274d3c1ac37444d779b7819e752cba03ba3029953fed61479e4537225b3ee99 requires_dist: - numpy requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/d9/1a/8a81b3a66f36969c8456f8af3a12f7d601fdd9cfed2ad5b4e72a2fb7ea8d/crysfml-0.6.1-cp314-cp314-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/97/37/ce5c3ef2595dac2be35039f7b91a0691ef643aa3d954815b3b51e026e0ab/crysfml-0.6.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl name: crysfml - version: 0.6.1 - sha256: b4aa83292665847f0d9aafa44b69c7abb779d0e1e13b5eb1ed516bc4c811ca6f + version: 0.6.2 + sha256: e18ff9ea04b0b823dbc1558afb974bd5b66f3ce13f9e18b25adedfcfde1a59a4 requires_dist: - numpy requires_python: '>=3.11,<3.15' @@ -5561,7 +5561,7 @@ packages: requires_python: '>=3.12' - pypi: ./ name: easydiffraction - version: 0.16.0+devdirty7 + version: 0.16.0+dev86 sha256: 0b4085f9386dbebf4b7c5a85d5f98b35d8cf1fc69f791bd0759d20995c534a33 requires_dist: - arviz @@ -6298,7 +6298,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/h11?source=compressed-mapping + - pkg:pypi/h11?source=hash-mapping size: 39069 timestamp: 1767729720872 - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda @@ -6449,7 +6449,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/idna?source=compressed-mapping + - pkg:pypi/idna?source=hash-mapping size: 59038 timestamp: 1776947141407 - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda @@ -6462,7 +6462,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/importlib-metadata?source=compressed-mapping + - pkg:pypi/importlib-metadata?source=hash-mapping size: 34387 timestamp: 1773931568510 - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl @@ -6616,7 +6616,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/ipython?source=compressed-mapping + - pkg:pypi/ipython?source=hash-mapping size: 651632 timestamp: 1777038396606 - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda @@ -6640,7 +6640,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/ipython?source=compressed-mapping + - pkg:pypi/ipython?source=hash-mapping size: 650593 timestamp: 1777038425499 - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda @@ -6704,7 +6704,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jinja2?source=compressed-mapping + - pkg:pypi/jinja2?source=hash-mapping size: 120685 timestamp: 1764517220861 - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl @@ -6724,7 +6724,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/json5?source=compressed-mapping + - pkg:pypi/json5?source=hash-mapping size: 34731 timestamp: 1774655440045 - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda @@ -6798,7 +6798,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyter-lsp?source=compressed-mapping + - pkg:pypi/jupyter-lsp?source=hash-mapping size: 61633 timestamp: 1775136333147 - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl @@ -6876,7 +6876,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyter-events?source=compressed-mapping + - pkg:pypi/jupyter-events?source=hash-mapping size: 24002 timestamp: 1776861872237 - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda @@ -6904,8 +6904,9 @@ packages: - websocket-client >=1.7 - python license: BSD-3-Clause + license_family: BSD purls: - - pkg:pypi/jupyter-server?source=compressed-mapping + - pkg:pypi/jupyter-server?source=hash-mapping size: 360522 timestamp: 1778060967727 - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda @@ -6943,7 +6944,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyterlab?source=compressed-mapping + - pkg:pypi/jupyterlab?source=hash-mapping size: 8861204 timestamp: 1777483115382 - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl @@ -6988,10 +6989,10 @@ packages: name: jupyterquiz version: 2.9.6.4 sha256: f8c4418f6c827454523fc882a30d744b585cb58ac1ae277769c3059d04fc272b -- pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl name: jupytext - version: 1.19.1 - sha256: d8975035155d034bdfde5c0c37891425314b7ea8d3a6c4b5d18c294348714cd9 + version: 1.19.2 + sha256: 8a31e896c7e9215841783aade24336e945543057e1c2d7f00b22f9e870348688 requires_dist: - markdown-it-py>=1.0 - mdit-py-plugins @@ -7215,58 +7216,55 @@ packages: purls: [] size: 1229639 timestamp: 1770863511331 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda - build_number: 6 - sha256: 7bfe936dbb5db04820cf300a9cc1f5ee8d5302fc896c2d66e30f1ee2f20fbfd6 - md5: 6d6d225559bfa6e2f3c90ee9c03d4e2e +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda + build_number: 7 + sha256: 081c850f99bc355821fac9c6e3727d40b3f8ce3beb50a5437cf03726b611ff39 + md5: 955b44e8b00b7f7ef4ce0130cef12394 depends: - - libopenblas >=0.3.32,<0.3.33.0a0 - - libopenblas >=0.3.32,<1.0a0 + - libopenblas >=0.3.33,<0.3.34.0a0 + - libopenblas >=0.3.33,<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 + - libcblas 3.11.0 7*_openblas + - blas 2.307 openblas + - liblapack 3.11.0 7*_openblas + - liblapacke 3.11.0 7*_openblas + - mkl <2027 license: BSD-3-Clause - license_family: BSD purls: [] - size: 18621 - timestamp: 1774503034895 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-6_h51639a9_openblas.conda - build_number: 6 - sha256: 979227fc03628925037ab2dfda008eb7b5592644d9c2c21dd285cefe8c42553d - md5: e551103471911260488a02155cef9c94 + size: 18716 + timestamp: 1778489854108 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_h51639a9_openblas.conda + build_number: 7 + sha256: 662935bfb93d2d097e26e273a3a2f504a9f833f64aa6f9e295b577655478c39b + md5: ab6670d099d19fe70cb9efb88a1b5f78 depends: - - libopenblas >=0.3.32,<0.3.33.0a0 - - libopenblas >=0.3.32,<1.0a0 + - libopenblas >=0.3.33,<0.3.34.0a0 + - libopenblas >=0.3.33,<1.0a0 constrains: - - liblapacke 3.11.0 6*_openblas - - liblapack 3.11.0 6*_openblas - - blas 2.306 openblas - - libcblas 3.11.0 6*_openblas - - mkl <2026 + - libcblas 3.11.0 7*_openblas + - blas 2.307 openblas + - mkl <2027 + - liblapack 3.11.0 7*_openblas + - liblapacke 3.11.0 7*_openblas license: BSD-3-Clause - license_family: BSD purls: [] - 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 + size: 18783 + timestamp: 1778489983152 +- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda + build_number: 7 + sha256: 9eec27eee4300284e62a61cb2298089c80d31f6f9e924eeabc06e9788a00cffe + md5: 269e54b44974ff48846b4c31d0397041 depends: - - mkl >=2025.3.1,<2026.0a0 + - mkl >=2026.0.0,<2027.0a0 constrains: - - blas 2.306 mkl - - liblapacke 3.11.0 6*_mkl - - liblapack 3.11.0 6*_mkl - - libcblas 3.11.0 6*_mkl + - blas 2.307 mkl + - libcblas 3.11.0 7*_mkl + - liblapacke 3.11.0 7*_mkl + - liblapack 3.11.0 7*_mkl license: BSD-3-Clause - license_family: BSD purls: [] - size: 68082 - timestamp: 1774503684284 + size: 68060 + timestamp: 1778490352569 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e md5: 72c8fd1af66bd67bf580645b426513ed @@ -7334,61 +7332,58 @@ packages: purls: [] size: 290754 timestamp: 1764018009077 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda - build_number: 6 - sha256: 57edafa7796f6fa3ebbd5367692dd4c7f552be42109c2dd1a7c89b55089bf374 - md5: 36ae340a916635b97ac8a0655ace2a35 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda + build_number: 7 + sha256: 956ae0bb1ec8b0c3663d75b151aceb0521b54e513bf97f621a035f9c87037970 + md5: 0675639dc24cb0032f199e7ff68e4633 depends: - - libblas 3.11.0 6_h4a7cf45_openblas + - libblas 3.11.0 7_h4a7cf45_openblas constrains: - - blas 2.306 openblas - - liblapack 3.11.0 6*_openblas - - liblapacke 3.11.0 6*_openblas + - liblapacke 3.11.0 7*_openblas + - blas 2.307 openblas + - liblapack 3.11.0 7*_openblas license: BSD-3-Clause - license_family: BSD purls: [] - size: 18622 - timestamp: 1774503050205 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-6_hb0561ab_openblas.conda - build_number: 6 - sha256: 2e6b3e9b1ab672133b70fc6730e42290e952793f132cb5e72eee22835463eba0 - md5: 805c6d31c5621fd75e53dfcf21fb243a + size: 18675 + timestamp: 1778489861559 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda + build_number: 7 + sha256: 3ac3d27022b3ca8b1980c087e0ede250434f6ed90a4fdc78a8a5ed382bc75505 + md5: 189b373453ec3904095dcb16f502bace depends: - - libblas 3.11.0 6_h51639a9_openblas + - libblas 3.11.0 7_h51639a9_openblas constrains: - - liblapacke 3.11.0 6*_openblas - - blas 2.306 openblas - - liblapack 3.11.0 6*_openblas + - blas 2.307 openblas + - liblapack 3.11.0 7*_openblas + - liblapacke 3.11.0 7*_openblas license: BSD-3-Clause - license_family: BSD purls: [] - 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 + size: 18810 + timestamp: 1778489991330 +- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda + build_number: 7 + sha256: 82da0f854831f783f9d3f1219c4255956e8167a474f3f526151128f02453871c + md5: 4700b7af6acefb26ff0127ba68230941 depends: - - libblas 3.11.0 6_hf2e6a31_mkl + - libblas 3.11.0 7_h8455456_mkl constrains: - - blas 2.306 mkl - - liblapacke 3.11.0 6*_mkl - - liblapack 3.11.0 6*_mkl + - blas 2.307 mkl + - liblapacke 3.11.0 7*_mkl + - liblapack 3.11.0 7*_mkl license: BSD-3-Clause - license_family: BSD purls: [] - size: 68221 - timestamp: 1774503722413 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda - sha256: 25a0d02148a39b665d9c2957676faf62a4d2a58494d53b201151199a197db4b0 - md5: 448a1af83a9205655ee1cf48d3875ca3 + size: 68594 + timestamp: 1778490364980 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda + sha256: dddd01bd6b338221342a89530a1caffe6051a70cc8f8b1d8bb591d5447a3c603 + md5: ff484b683fecf1e875dfc7aa01d19796 depends: - __osx >=11.0 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] - size: 569927 - timestamp: 1776816293111 + size: 569359 + timestamp: 1778191546305 - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 md5: c277e0a4d549b03ac1e9d6cbbe3d017b @@ -7504,70 +7499,70 @@ packages: purls: [] size: 45831 timestamp: 1769456418774 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda - sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 - md5: 0aa00f03f9e39fb9876085dee11a85d4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda + sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 + md5: 57736f29cc2b0ec0b6c2952d3f101b6a depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 constrains: - - libgcc-ng ==15.2.0=*_18 - - libgomp 15.2.0 he0feb66_18 + - libgcc-ng ==15.2.0=*_19 + - libgomp 15.2.0 he0feb66_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 1041788 - timestamp: 1771378212382 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_18.conda - sha256: 1d9c4f35586adb71bcd23e31b68b7f3e4c4ab89914c26bed5f2859290be5560e - md5: 92df6107310b1fff92c4cc84f0de247b + size: 1041084 + timestamp: 1778269013026 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda + sha256: 06644fa4d34d57c9e48f4d84b1256f9e5f654fdb37f43acc8a58a396952d42b7 + md5: 644058123986582db33aebd4ae2ca184 depends: - _openmp_mutex constrains: - - libgcc-ng ==15.2.0=*_18 - - libgomp 15.2.0 18 + - libgcc-ng ==15.2.0=*_19 + - libgomp 15.2.0 19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 401974 - timestamp: 1771378877463 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda - sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 - md5: d5e96b1ed75ca01906b3d2469b4ce493 + size: 404080 + timestamp: 1778273064154 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + sha256: 9dcf54adfaa5e861123c2da4f2f0451a685464ea7e5a41ad91cf67b31d658d98 + md5: 331ee9b72b9dff570d56b1302c5ab37d depends: - - libgcc 15.2.0 he0feb66_18 + - libgcc 15.2.0 he0feb66_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 27526 - timestamp: 1771378224552 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda - sha256: d2c9fad338fd85e4487424865da8e74006ab2e2475bd788f624d7a39b2a72aee - md5: 9063115da5bc35fdc3e1002e69b9ef6e + size: 27694 + timestamp: 1778269016987 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda + sha256: 561a42758ef25b9ce308c4e2cf56daee4f06138385a17e29a492cd928e00be6f + md5: 42bf7eca1a951735fa06c0e3c0d5c8e6 depends: - - libgfortran5 15.2.0 h68bc16d_18 + - libgfortran5 15.2.0 h68bc16d_19 constrains: - - libgfortran-ng ==15.2.0=*_18 + - libgfortran-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 27523 - timestamp: 1771378269450 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_18.conda - sha256: 63f89087c3f0c8621c5c89ecceec1e56e5e1c84f65fc9c5feca33a07c570a836 - md5: 26981599908ed2205366e8fc91b37fc6 + size: 27655 + timestamp: 1778269042954 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda + sha256: d4837b3b9b30af3132d260225e91ab9dde83be04c59513f500cc81050fb37486 + md5: 1ea03f87cdb1078fbc0e2b2deb63752c depends: - - libgfortran5 15.2.0 hdae7583_18 + - libgfortran5 15.2.0 hdae7583_19 constrains: - - libgfortran-ng ==15.2.0=*_18 + - libgfortran-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 138973 - timestamp: 1771379054939 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda - sha256: 539b57cf50ec85509a94ba9949b7e30717839e4d694bc94f30d41c9d34de2d12 - md5: 646855f357199a12f02a87382d429b75 + size: 139675 + timestamp: 1778273280875 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda + sha256: 057978bb69fea29ed715a9b98adf71015c31baecc4aeb2bfc20d4fd5d83579d4 + md5: 85072b0ad177c966294f129b7c04a2d5 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=15.2.0 @@ -7576,11 +7571,11 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 2482475 - timestamp: 1771378241063 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_18.conda - sha256: 91033978ba25e6a60fb86843cf7e1f7dc8ad513f9689f991c9ddabfaf0361e7e - md5: c4a6f7989cffb0544bfd9207b6789971 + size: 2483673 + timestamp: 1778269025089 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda + sha256: d0a68b7a121d115b80c169e24d1265dcc25a3fe58d107df1bbc430797e226d88 + md5: ba36d8c606a6a53fe0b8c12d47267b3d depends: - libgcc >=15.2.0 constrains: @@ -7588,18 +7583,18 @@ packages: license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 598634 - timestamp: 1771378886363 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda - sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 - md5: 239c5e9546c38a1e884d69effcf4c882 + size: 599691 + timestamp: 1778273075448 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b + md5: faac990cb7aedc7f3a2224f2c9b0c26c depends: - __glibc >=2.17,<3.0.a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 603262 - timestamp: 1771378117851 + size: 603817 + timestamp: 1778268942614 - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda sha256: 8cdf11333a81085468d9aa536ebb155abd74adc293576f6013fc0c85a7a90da3 md5: 3b576f6860f838f950c570f4433b086e @@ -7739,36 +7734,36 @@ packages: purls: [] size: 33731 timestamp: 1750274110928 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda - sha256: 6dc30b28f32737a1c52dada10c8f3a41bc9e021854215efca04a7f00487d09d9 - md5: 89d61bc91d3f39fda0ca10fcd3c68594 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda + sha256: 3d9aa85648e5e18a6d66db98b8c4317cc426721ad7a220aa86330d1ccedc8903 + md5: 2d3278b721e40468295ca755c3b84070 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libgfortran - libgfortran5 >=14.3.0 constrains: - - openblas >=0.3.32,<0.3.33.0a0 + - openblas >=0.3.33,<0.3.34.0a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 5928890 - timestamp: 1774471724897 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.32-openmp_he657e61_0.conda - sha256: 713e453bde3531c22a660577e59bf91ef578dcdfd5edb1253a399fa23514949a - md5: 3a1111a4b6626abebe8b978bb5a323bf + size: 5931919 + timestamp: 1776993658641 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + sha256: 9dd455b2d172aeedfa2058d324b5b5822b0bc1b7c1f32cd183d7078540d2f6eb + md5: 909e41855c29f0d52ae630198cd57135 depends: - __osx >=11.0 - libgfortran - libgfortran5 >=14.3.0 - llvm-openmp >=19.1.7 constrains: - - openblas >=0.3.32,<0.3.33.0a0 + - openblas >=0.3.33,<0.3.34.0a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 4308797 - timestamp: 1774472508546 + size: 4304965 + timestamp: 1776995497368 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda sha256: 64e5c80cbce4680a2d25179949739a6def695d72c40ca28f010711764e372d97 md5: 7af961ef4aa2c1136e11dd43ded245ab @@ -7831,19 +7826,19 @@ packages: purls: [] size: 1304178 timestamp: 1777986510497 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda - sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e - md5: 1b08cd684f34175e4514474793d44bcb +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc + md5: 5794b3bdc38177caf969dabd3af08549 depends: - __glibc >=2.17,<3.0.a0 - - libgcc 15.2.0 he0feb66_18 + - libgcc 15.2.0 he0feb66_19 constrains: - - libstdcxx-ng ==15.2.0=*_18 + - libstdcxx-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 5852330 - timestamp: 1771378262446 + size: 5852044 + timestamp: 1778269036376 - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 md5: 38ffe67b78c9d4de527be8315e5ada2c @@ -7971,34 +7966,32 @@ packages: purls: [] size: 58347 timestamp: 1774072851498 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.4-hc7d1edf_0.conda - sha256: a269273ccf48be6ac582bb958713ba8373262b9157a0fc76b7e5475e8a1d2a78 - md5: 46d04a647df7a4525e487d88068d19ef +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda + sha256: 2cd49562feda2bf324651050b2b035080fd635ed0f1c96c9ce7a59eff3cc0029 + md5: 8a4e2a54034b35bc6fa5bf9282913f45 depends: - __osx >=11.0 constrains: - - openmp 22.1.4|22.1.4.* + - openmp 22.1.5|22.1.5.* - intel-openmp <0.0a0 license: Apache-2.0 WITH LLVM-exception - license_family: APACHE purls: [] - size: 286406 - timestamp: 1776846235007 -- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.4-h4fa8253_0.conda - sha256: 7d827f8c125ac2fe3a9d5b47c1f95fc540bb8ef78685e4bcf941957257bb1eff - md5: 761757ab617e8bfef18cc422dd02bbad + size: 285806 + timestamp: 1778447786965 +- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.5-h4fa8253_1.conda + sha256: 7179e0266125c3333a097b399d0383734ee6c55fbadf332b447237a596e9698f + md5: bffe599d0eb2e78a32872712178e639c depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: + - openmp 22.1.5|22.1.5.* - intel-openmp <0.0a0 - - openmp 22.1.4|22.1.4.* license: Apache-2.0 WITH LLVM-exception - license_family: APACHE purls: [] - size: 347999 - timestamp: 1776846360348 + size: 347493 + timestamp: 1778448334890 - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl name: lmfit version: 1.3.4 @@ -8063,10 +8056,10 @@ packages: - mkdocs-section-index ; extra == 'docs' - mkdocs-literate-nav ; extra == 'docs' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/a8/88/802c82060c54bc7dde21eb0033e337838b8181a1323254aa9ec41cbfc3d1/markdown_it_py-4.1.0-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl name: markdown-it-py - version: 4.1.0 - sha256: d4939a62a2dd0cd9cb80a191a711ba1d39bac8ed5ef9e9966895b0171c01c46d + version: 4.2.0 + sha256: 9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a requires_dist: - mdurl~=0.1 - psutil ; extra == 'benchmarking' @@ -8158,7 +8151,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/markupsafe?source=compressed-mapping + - pkg:pypi/markupsafe?source=hash-mapping size: 27256 timestamp: 1772445397216 - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda @@ -8175,7 +8168,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/markupsafe?source=compressed-mapping + - pkg:pypi/markupsafe?source=hash-mapping size: 28510 timestamp: 1772445175216 - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda @@ -8309,22 +8302,22 @@ packages: - setuptools-scm>=7,<10 ; extra == 'dev' - setuptools>=64 ; extra == 'dev' requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - sha256: 9d690334de0cd1d22c51bc28420663f4277cfa60d34fa5cad1ce284a13f1d603 - md5: 00e120ce3e40bad7bfc78861ce3c4a25 +- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda + sha256: 35b43d7343f74452307fd018a1cca92b8f68961ff8e2ab6a81ce0a703c9a3764 + md5: 9acc1c385be401d533ff70ef5b50dae6 depends: - python >=3.10 - traitlets license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/matplotlib-inline?source=hash-mapping - size: 15175 - timestamp: 1761214578417 -- pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pkg:pypi/matplotlib-inline?source=compressed-mapping + size: 15725 + timestamp: 1778264403247 +- pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl name: mdit-py-plugins - version: 0.5.0 - sha256: 07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f + version: 0.6.0 + sha256: f7e7a25d8b616fee99cb1e330da73451d11a8061baf39bb9663ab9ce0e005b90 requires_dist: - markdown-it-py>=2.0.0,<5.0.0 - pre-commit ; extra == 'code-style' @@ -8334,6 +8327,7 @@ packages: - pytest ; extra == 'testing' - pytest-cov ; extra == 'testing' - pytest-regressions ; extra == 'testing' + - pytest-timeout ; extra == 'testing' requires_python: '>=3.10' - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl name: mdurl @@ -8374,8 +8368,9 @@ packages: - typing_extensions - python license: BSD-3-Clause + license_family: BSD purls: - - pkg:pypi/mistune?source=compressed-mapping + - pkg:pypi/mistune?source=hash-mapping size: 74567 timestamp: 1777824616382 - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl @@ -8514,21 +8509,21 @@ 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.1-hac47afa_12.conda - sha256: d7b8343e10053c8527e2e20fd96787d368c97129ffa799e863069a36bd299457 - md5: a3b1ee571898432da7e13ecb7bfd76ae +- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda + sha256: 76a43359adae10aef8de7ff8e4fab70647bda928146374298506afab2e4a7b4f + md5: 7741affec1b3d2275586397ed4c91639 depends: - llvm-openmp >=22.1.4 - - onemkl-license 2025.3.1 h57928b3_12 - - tbb >=2022.3.0 + - onemkl-license 2026.0.0 h57928b3_905 + - tbb >=2023.0.0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: LicenseRef-IntelSimplifiedSoftwareOct2022 license_family: Proprietary purls: [] - size: 100112670 - timestamp: 1776904283842 + size: 114620200 + timestamp: 1778111077072 - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl name: mpld3 version: 0.5.12 @@ -8716,10 +8711,10 @@ packages: requires_dist: - typing-extensions>=4.1.0 ; python_full_version < '3.11' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/d0/69/f24d3d1c38ad69e256138b4ec2452a8c7cf66be49dc214771ae99dd4f0a0/narwhals-2.20.0-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl name: narwhals - version: 2.20.0 - sha256: 16e750ea5507d4ba6e8d03455b5f93a535e0405976561baea235bca5dc9f475d + version: 2.21.0 + sha256: 1e6617d0fca68ae1fda29e5397c4eaacd3ffc9fffe6bcd6ded0c690475e853be requires_dist: - cudf-cu12>=24.10.0 ; extra == 'cudf' - dask[dataframe]>=2024.8 ; extra == 'dask' @@ -8750,7 +8745,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/nbclient?source=compressed-mapping + - pkg:pypi/nbclient?source=hash-mapping size: 28473 timestamp: 1766485646962 - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda @@ -8780,7 +8775,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/nbconvert?source=compressed-mapping + - pkg:pypi/nbconvert?source=hash-mapping size: 202229 timestamp: 1775615493260 - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda @@ -9066,14 +9061,14 @@ packages: version: 2.4.4 sha256: 715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2025.3.1-h57928b3_12.conda - sha256: 03eac4174077397a5bc480021e62412e73e80f34072d81053899f65dfe1045c7 - md5: 29ad104e60faa7ed1dc549ec029764bb +- conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda + sha256: 848a7215e1ce227139074461664d01c00e7e1e8a367ccbd6581c0860d6ec4a19 + md5: fea22e21062046ba44336de37f4b6372 license: LicenseRef-IntelSimplifiedSoftwareOct2022 license_family: Proprietary purls: [] - size: 40890 - timestamp: 1776904134221 + size: 41103 + timestamp: 1778110756075 - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb md5: da1b85b6a87e141f5140bb9924cecab0 @@ -9131,7 +9126,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/packaging?source=compressed-mapping + - pkg:pypi/packaging?source=hash-mapping size: 91574 timestamp: 1777103621679 - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl @@ -9142,10 +9137,10 @@ packages: - pytest ; extra == 'dev' - tox ; extra == 'dev' - black ; extra == 'lint' -- pypi: https://files.pythonhosted.org/packages/15/88/3cdd54fa279341afa10acf8d2b503556b1375245dccc9315659f795dd2e9/pandas-3.0.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl name: pandas - version: 3.0.2 - sha256: deeca1b5a931fdf0c2212c8a659ade6d3b1edc21f0914ce71ef24456ca7a6535 + version: 3.0.3 + sha256: 3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5 requires_dist: - numpy>=1.26.0 ; python_full_version < '3.14' - numpy>=2.3.3 ; python_full_version >= '3.14' @@ -9193,7 +9188,7 @@ packages: - pyqt5>=5.15.9 ; extra == 'clipboard' - qtpy>=2.4.2 ; extra == 'clipboard' - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2024.2 ; extra == 'timezone' + - pytz>=2020.1 ; extra == 'timezone' - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - beautifulsoup4>=4.12.3 ; extra == 'all' @@ -9219,7 +9214,7 @@ packages: - pytest>=8.3.4 ; extra == 'all' - pytest-xdist>=3.6.1 ; extra == 'all' - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2024.2 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' - pyxlsb>=1.0.10 ; extra == 'all' - qtpy>=2.4.2 ; extra == 'all' - scipy>=1.14.1 ; extra == 'all' @@ -9232,10 +9227,10 @@ packages: - xlsxwriter>=3.2.0 ; extra == 'all' - zstandard>=0.23.0 ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/35/d0/4831af68ce30cc2d03c697bea8450e3225a835ef497d0d70f31b8cdde965/pandas-3.0.2-cp312-cp312-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl name: pandas - version: 3.0.2 - sha256: 970762605cff1ca0d3f71ed4f3a769ea8f85fc8e6348f6e110b8fea7e6eb5a14 + version: 3.0.3 + sha256: 9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a requires_dist: - numpy>=1.26.0 ; python_full_version < '3.14' - numpy>=2.3.3 ; python_full_version >= '3.14' @@ -9283,7 +9278,7 @@ packages: - pyqt5>=5.15.9 ; extra == 'clipboard' - qtpy>=2.4.2 ; extra == 'clipboard' - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2024.2 ; extra == 'timezone' + - pytz>=2020.1 ; extra == 'timezone' - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - beautifulsoup4>=4.12.3 ; extra == 'all' @@ -9309,7 +9304,7 @@ packages: - pytest>=8.3.4 ; extra == 'all' - pytest-xdist>=3.6.1 ; extra == 'all' - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2024.2 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' - pyxlsb>=1.0.10 ; extra == 'all' - qtpy>=2.4.2 ; extra == 'all' - scipy>=1.14.1 ; extra == 'all' @@ -9322,10 +9317,10 @@ packages: - xlsxwriter>=3.2.0 ; extra == 'all' - zstandard>=0.23.0 ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/7b/8b/721a9cff6fa6a91b162eb51019c6243b82b3226c71bb6c8ef4a9bd65cbc6/pandas-3.0.2-cp312-cp312-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl name: pandas - version: 3.0.2 - sha256: a4785e1d6547d8427c5208b748ae2efb64659a21bd82bf440d4262d02bfa02a4 + version: 3.0.3 + sha256: 6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9 requires_dist: - numpy>=1.26.0 ; python_full_version < '3.14' - numpy>=2.3.3 ; python_full_version >= '3.14' @@ -9373,7 +9368,7 @@ packages: - pyqt5>=5.15.9 ; extra == 'clipboard' - qtpy>=2.4.2 ; extra == 'clipboard' - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2024.2 ; extra == 'timezone' + - pytz>=2020.1 ; extra == 'timezone' - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - beautifulsoup4>=4.12.3 ; extra == 'all' @@ -9399,7 +9394,7 @@ packages: - pytest>=8.3.4 ; extra == 'all' - pytest-xdist>=3.6.1 ; extra == 'all' - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2024.2 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' - pyxlsb>=1.0.10 ; extra == 'all' - qtpy>=2.4.2 ; extra == 'all' - scipy>=1.14.1 ; extra == 'all' @@ -9412,10 +9407,10 @@ packages: - xlsxwriter>=3.2.0 ; extra == 'all' - zstandard>=0.23.0 ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/95/25/bdb9326c3b5455f8d4d3549fce7abcf967259de146fe2cf7a82368141948/pandas-3.0.2-cp314-cp314-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl name: pandas - version: 3.0.2 - sha256: 0555c5882688a39317179ab4a0ed41d3ebc8812ab14c69364bbee8fb7a3f6288 + version: 3.0.3 + sha256: bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f requires_dist: - numpy>=1.26.0 ; python_full_version < '3.14' - numpy>=2.3.3 ; python_full_version >= '3.14' @@ -9463,7 +9458,7 @@ packages: - pyqt5>=5.15.9 ; extra == 'clipboard' - qtpy>=2.4.2 ; extra == 'clipboard' - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2024.2 ; extra == 'timezone' + - pytz>=2020.1 ; extra == 'timezone' - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - beautifulsoup4>=4.12.3 ; extra == 'all' @@ -9489,7 +9484,7 @@ packages: - pytest>=8.3.4 ; extra == 'all' - pytest-xdist>=3.6.1 ; extra == 'all' - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2024.2 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' - pyxlsb>=1.0.10 ; extra == 'all' - qtpy>=2.4.2 ; extra == 'all' - scipy>=1.14.1 ; extra == 'all' @@ -9502,10 +9497,10 @@ packages: - xlsxwriter>=3.2.0 ; extra == 'all' - zstandard>=0.23.0 ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/c4/a8/3a61a721472959ab0ce865ef05d10b0d6bfe27ce8801c99f33d4fa996e65/pandas-3.0.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl name: pandas - version: 3.0.2 - sha256: ef8b27695c3d3dc78403c9a7d5e59a62d5464a7e1123b4e0042763f7104dc74f + version: 3.0.3 + sha256: c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc requires_dist: - numpy>=1.26.0 ; python_full_version < '3.14' - numpy>=2.3.3 ; python_full_version >= '3.14' @@ -9553,7 +9548,7 @@ packages: - pyqt5>=5.15.9 ; extra == 'clipboard' - qtpy>=2.4.2 ; extra == 'clipboard' - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2024.2 ; extra == 'timezone' + - pytz>=2020.1 ; extra == 'timezone' - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - beautifulsoup4>=4.12.3 ; extra == 'all' @@ -9579,7 +9574,7 @@ packages: - pytest>=8.3.4 ; extra == 'all' - pytest-xdist>=3.6.1 ; extra == 'all' - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2024.2 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' - pyxlsb>=1.0.10 ; extra == 'all' - qtpy>=2.4.2 ; extra == 'all' - scipy>=1.14.1 ; extra == 'all' @@ -9592,10 +9587,10 @@ packages: - xlsxwriter>=3.2.0 ; extra == 'all' - zstandard>=0.23.0 ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/db/60/aba6a38de456e7341285102bede27514795c1eaa353bc0e7638b6b785356/pandas-3.0.2-cp314-cp314-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl name: pandas - version: 3.0.2 - sha256: b35d14bb5d8285d9494fe93815a9e9307c0876e10f1e8e89ac5b88f728ec8dcf + version: 3.0.3 + sha256: b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4 requires_dist: - numpy>=1.26.0 ; python_full_version < '3.14' - numpy>=2.3.3 ; python_full_version >= '3.14' @@ -9643,7 +9638,7 @@ packages: - pyqt5>=5.15.9 ; extra == 'clipboard' - qtpy>=2.4.2 ; extra == 'clipboard' - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2024.2 ; extra == 'timezone' + - pytz>=2020.1 ; extra == 'timezone' - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - beautifulsoup4>=4.12.3 ; extra == 'all' @@ -9669,7 +9664,7 @@ packages: - pytest>=8.3.4 ; extra == 'all' - pytest-xdist>=3.6.1 ; extra == 'all' - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2024.2 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' - pyxlsb>=1.0.10 ; extra == 'all' - qtpy>=2.4.2 ; extra == 'all' - scipy>=1.14.1 ; extra == 'all' @@ -9702,7 +9697,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/parso?source=compressed-mapping + - pkg:pypi/parso?source=hash-mapping size: 82472 timestamp: 1777722955579 - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl @@ -9960,7 +9955,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/platformdirs?source=compressed-mapping + - pkg:pypi/platformdirs?source=hash-mapping size: 25862 timestamp: 1775741140609 - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl @@ -10132,7 +10127,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/prometheus-client?source=compressed-mapping + - pkg:pypi/prometheus-client?source=hash-mapping size: 57113 timestamp: 1775771465170 - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda @@ -10149,36 +10144,36 @@ packages: - pkg:pypi/prompt-toolkit?source=hash-mapping size: 273927 timestamp: 1756321848365 -- pypi: https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl name: propcache - version: 0.4.1 - sha256: f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl + version: 0.5.2 + sha256: 6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl name: propcache - version: 0.4.1 - sha256: 5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + version: 0.5.2 + sha256: e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl name: propcache - version: 0.4.1 - sha256: 15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl + version: 0.5.2 + sha256: e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl name: propcache - version: 0.4.1 - sha256: cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + version: 0.5.2 + sha256: d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl name: propcache - version: 0.4.1 - sha256: 8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl + version: 0.5.2 + sha256: 81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl name: propcache - version: 0.4.1 - sha256: 9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded - requires_python: '>=3.9' + version: 0.5.2 + sha256: 97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539 + requires_python: '>=3.10' - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda sha256: d834fd656133c9e4eaf63ffe9a117c7d0917d86d89f7d64073f4e3a0020bd8a7 md5: dd94c506b119130aef5a9382aed648e7 @@ -10190,7 +10185,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/psutil?source=compressed-mapping + - pkg:pypi/psutil?source=hash-mapping size: 225545 timestamp: 1769678155334 - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda @@ -10426,7 +10421,7 @@ packages: license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/pygments?source=compressed-mapping + - pkg:pypi/pygments?source=hash-mapping size: 893031 timestamp: 1774796815820 - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl @@ -10829,7 +10824,7 @@ packages: license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/python-json-logger?source=compressed-mapping + - pkg:pypi/python-json-logger?source=hash-mapping size: 18969 timestamp: 1777318679482 - pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl @@ -10854,7 +10849,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/tzdata?source=compressed-mapping + - pkg:pypi/tzdata?source=hash-mapping size: 146639 timestamp: 1777068997932 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda @@ -11189,7 +11184,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/requests?source=compressed-mapping + - pkg:pypi/requests?source=hash-mapping size: 63728 timestamp: 1777030058920 - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda @@ -11532,10 +11527,10 @@ packages: - nodejs ; extra == 'all' - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/82/9b/cf7e6f157c53d2c8bc0165580350c53939aea3b2a8390ec8e07f0adb82de/scippneutron-26.4.1-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl name: scippneutron - version: 26.4.1 - sha256: 3b9865ebdb7923eb25739b7cda624555d45275341000f099c1dcf371b1dd7e35 + version: 26.5.0 + sha256: e9cfad09b974867c6dc2a175cd2e575e06eaa951b2409e9ef863db237853bf99 requires_dist: - python-dateutil>=2.8 - email-validator>=2 @@ -11545,10 +11540,10 @@ packages: - numpy>=1.20 - plopp>=26.4.1 - pydantic>=2 - - scipp>=24.7.0 + - scipp>=25.8.0 - scippnexus>=23.11.0 - scipy>=1.7.0 - - scipp[all]>=23.7.0 ; extra == 'all' + - scipp[all]>=25.8.0 ; extra == 'all' - pooch>=1.5 ; extra == 'all' - hypothesis>=6.100 ; extra == 'test' - ipympl>0.9.0 ; extra == 'test' @@ -12336,6 +12331,7 @@ packages: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 + license_family: APACHE purls: [] size: 156910 timestamp: 1777976465531 @@ -12463,7 +12459,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping + - pkg:pypi/tornado?source=hash-mapping size: 859665 timestamp: 1774358032165 - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda @@ -12491,7 +12487,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping + - pkg:pypi/tornado?source=hash-mapping size: 859155 timestamp: 1774358568476 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda @@ -12520,7 +12516,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping + - pkg:pypi/tornado?source=hash-mapping size: 859726 timestamp: 1774358173994 - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda @@ -12545,8 +12541,9 @@ packages: - python >=3.10 - python license: BSD-3-Clause + license_family: BSD purls: - - pkg:pypi/traitlets?source=compressed-mapping + - pkg:pypi/traitlets?source=hash-mapping size: 115165 timestamp: 1778074251714 - pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl @@ -12559,10 +12556,10 @@ packages: - pandas ; extra == 'test' - xarray ; extra == 'test' - pytest ; extra == 'test' -- pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl name: trove-classifiers - version: 2026.4.28.13 - sha256: 8f4b1eb4e16296b57d612965444f87a83861cc989a0451ac97fe4265ddef03b8 + version: 2026.5.7.17 + sha256: 5ec0800de5e2ddbd7c663cb4c0c15328f132dc168813897c18866c5c7b93db33 - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl name: typeguard version: 4.5.1 @@ -12664,9 +12661,9 @@ packages: - pkg:pypi/uri-template?source=hash-mapping size: 23990 timestamp: 1733323714454 -- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a - md5: 9272daa869e03efe68833e3dc7a02130 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 + md5: cbb88288f74dbe6ada1c6c7d0a97223e depends: - backports.zstd >=1.0.0 - brotli-python >=1.2.0 @@ -12677,8 +12674,8 @@ packages: license_family: MIT purls: - pkg:pypi/urllib3?source=hash-mapping - size: 103172 - timestamp: 1767817860341 + size: 103560 + timestamp: 1778188657149 - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl name: validate-pyproject version: '0.25' @@ -12805,7 +12802,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/wcwidth?source=compressed-mapping + - pkg:pypi/wcwidth?source=hash-mapping size: 82917 timestamp: 1777744489106 - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda @@ -13104,7 +13101,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/zipp?source=compressed-mapping + - pkg:pypi/zipp?source=hash-mapping size: 24461 timestamp: 1776131454755 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda From 45b2fc56a24b2dc4e5cfddd47852b6ebe5351f17 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 May 2026 23:14:57 +0200 Subject: [PATCH 086/106] Bump pixi.lock from v6 to v7 --- pixi.lock | 21812 ++++++++++++++++++++++++++-------------------------- 1 file changed, 10903 insertions(+), 10909 deletions(-) diff --git a/pixi.lock b/pixi.lock index 0d0a058d..73f8d611 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1,4 +1,8 @@ -version: 6 +version: 7 +platforms: +- name: linux-64 +- name: osx-arm64 +- name: win-64 environments: default: channels: @@ -6,15 +10,64 @@ environments: - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple - options: - pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_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.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_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-7_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-7_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.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.8.0-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-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.68.1-h877daf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-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.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_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.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda @@ -24,31 +77,24 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - - 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.4.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda @@ -71,47 +117,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-7_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-7_h0358290_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.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.8.0-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-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.68.1-h877daf1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-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.2-h25fd6f3_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -121,29 +134,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -152,9 +159,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -166,199 +171,194 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: . + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz + - 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/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-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/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-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/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - 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/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-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/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-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/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.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/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/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-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/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-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/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-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/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d8/8b/e2bbeb42068f0c48899e8eddd34902afc0f7429d4d2a152d2dc2670dc661/pythreejs-2.4.2-py3-none-any.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/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.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/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-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/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-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/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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-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/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda @@ -368,31 +368,24 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda - - 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.4.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda @@ -415,43 +408,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-7_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-7_hb0561ab_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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.68.1-h8f3e76b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -461,31 +425,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -494,9 +450,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -508,196 +462,243 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl - - 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/04/f1/58c14b37525dc075f3bdf149251f079723049a9f1c82eb48835a0e6b8db3/diffpy_pdffit2-1.6.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_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/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_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.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_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-7_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-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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.68.1-h8f3e76b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_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.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: . + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/f1/58c14b37525dc075f3bdf149251f079723049a9f1c82eb48835a0e6b8db3/diffpy_pdffit2-1.6.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/06/41/4e70dea1d0311016c0b0b1c53a24a266f9f8a34c6bc1af0f17cfca20aa1d/gemmi-0.7.5-cp314-cp314-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-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/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-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/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - 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/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.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/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-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/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-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/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.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/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-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/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.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/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.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/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda @@ -707,24 +708,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda - - 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.4.22-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda @@ -753,36 +749,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 - - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda - - 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.3-h692994f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.5-h4fa8253_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -791,317 +765,291 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_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/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda + - 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.3-h692994f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.5-h4fa8253_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.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/onemkl-license-2026.0.0-h57928b3_905.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: . + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-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/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-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/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-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/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.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/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-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/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-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/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.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/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-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/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-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/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/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-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/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-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/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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-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/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.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/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-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/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.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/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-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/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.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/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.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/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-win_amd64.whl py-312-env: channels: - url: https://conda.anaconda.org/nodefaults/ - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple - options: - pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.4.0-py312h90b7ffd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - 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.4.22-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py312h8285ef7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-7_h4a7cf45_openblas.conda @@ -1130,17 +1078,80 @@ environments: - 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.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_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.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py312h868fb18_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -1150,29 +1161,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py312h868fb18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -1181,9 +1186,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -1195,233 +1198,220 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: . + - pypi: https://files.pythonhosted.org/packages/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_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/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0a/0d/0e3ecece05b7a7e87ab9fb587855548da437a061326fff64a223b6dcb78a/numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/ff/6699e7b71e60d3049eb2bdcbc95ee3f35707b2b0e48f32e9e63d3ce30c08/coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/97/37/ce5c3ef2595dac2be35039f7b91a0691ef643aa3d954815b3b51e026e0ab/crysfml-0.6.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9b/8a/99c8b3c3888c5c474c08dbfd7c8899786de9604b727fcefb055b42c84bba/fonttools-4.62.1-cp312-cp312-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/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/e8/88/5a431cd1ea7587408a66947384b39beb2ab2bcc1c87b7c4082f05036719f/gemmi-0.7.5-cp312-cp312-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/2b/e0/2e13df68f367e2f9960616927d60857dd7e56aaadd59a47c644216b2f920/greenlet-3.5.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/e9/1a19e42cd43cc1365e127db6aae85e1c671da1d9a5d746f4d34a50edb577/h5py-3.16.0-cp312-cp312-manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/e7/cd78635d0ece7e4d3393f2c1d2ebabf6ff4bd615da142891b1d42ad58abf/scipp-26.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/e0/2e13df68f367e2f9960616927d60857dd7e56aaadd59a47c644216b2f920/greenlet-3.5.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/fa/65fcae2ed62f84ab72cf89536c7c3217a156e71a2c111b1305ab6f0690e2/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/75/98a7eb100dc5cfd20b019046452f08d5e67dfbacc71d8f28763d32426fd3/spglib-2.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_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/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz + - 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/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-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/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0a/0d/0e3ecece05b7a7e87ab9fb587855548da437a061326fff64a223b6dcb78a/numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-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/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.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/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/66/3e/868e5c3364b6cee19ff3e1a122194fa4ce51def02c61023970442162859e/yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/ff/6699e7b71e60d3049eb2bdcbc95ee3f35707b2b0e48f32e9e63d3ce30c08/coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-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/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ae/61/3c1ea8c10bf4f6bf83c33a7f5b4a3143f4cc1f979859dec5498b6cc31900/pycifrw-5.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-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/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-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/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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-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/1e/e7/cd78635d0ece7e4d3393f2c1d2ebabf6ff4bd615da142891b1d42ad58abf/scipp-26.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/33/75/98a7eb100dc5cfd20b019046452f08d5e67dfbacc71d8f28763d32426fd3/spglib-2.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/2c/fa/65fcae2ed62f84ab72cf89536c7c3217a156e71a2c111b1305ab6f0690e2/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/37/ce5c3ef2595dac2be35039f7b91a0691ef643aa3d954815b3b51e026e0ab/crysfml-0.6.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/8a/99c8b3c3888c5c474c08dbfd7c8899786de9604b727fcefb055b42c84bba/fonttools-4.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/e9/1a19e42cd43cc1365e127db6aae85e1c671da1d9a5d746f4d34a50edb577/h5py-3.16.0-cp312-cp312-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/61/3c1ea8c10bf4f6bf83c33a7f5b4a3143f4cc1f979859dec5498b6cc31900/pycifrw-5.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.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/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-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/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.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/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/66/3e/868e5c3364b6cee19ff3e1a122194fa4ce51def02c61023970442162859e/yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e8/88/5a431cd1ea7587408a66947384b39beb2ab2bcc1c87b7c4082f05036719f/gemmi-0.7.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.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/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py312h4409184_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.4.0-py312h87c4bb7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda - - 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.4.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py312h1b4d9a2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py312h6510ced_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda @@ -1444,42 +1434,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-7_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-7_hb0561ab_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.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.33-openmp_he657e61_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -1489,31 +1451,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py312h19bbe71_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py312h1de3e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py312h6ef9ec0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -1522,9 +1476,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -1536,223 +1488,264 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl - - 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/9c/2f/4c5af01fd1a7506a1d5375403d68925eac70289229492db5aa68b58103d8/chardet-7.4.3-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/34/23/35c7aea1274aef7525bdd2dc92f710bdde6d11652239d71d1ec450067939/coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/15/1d/9f9e30d76300b0150afaa8b37fab9a0194d44fd4f6b1e5038aca4a1440ed/crysfml-0.6.2-cp312-cp312-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/01/5c/87b5fefdd3c4b157c8a16833f2236723136806814584c4589610217252f0/diffpy_pdffit2-1.6.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/47/d4/dbacced3953544b9a93088cc10ef2b596d348c983d5c67a404fa41ec51ba/fonttools-4.62.1-cp312-cp312-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/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/b0/3e/a6497e1c2c9bc6ed2b79e0f2d31a4ce509fd2a9eed4e4f7ac63eda8113cb/gemmi-0.7.5-cp312-cp312-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py312h4409184_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.4.0-py312h87c4bb7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py312h1b4d9a2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py312h6510ced_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.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_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-7_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-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.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.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py312h2bbb03f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_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.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py312h19bbe71_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py312h1de3e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py312h6ef9ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: . + - pypi: https://files.pythonhosted.org/packages/01/5c/87b5fefdd3c4b157c8a16833f2236723136806814584c4589610217252f0/diffpy_pdffit2-1.6.0-cp312-cp312-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/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b0/42/c84efcc1d4caebafb1ecd8be4643f39c85c47a80fe254d92b8b43b1eadaf/h5py-3.16.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/18/4880dd762e40cd360c1bf06e890c5a97b997e91cb324602b1a19950ad5ce/matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/1d/9f9e30d76300b0150afaa8b37fab9a0194d44fd4f6b1e5038aca4a1440ed/crysfml-0.6.2-cp312-cp312-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/19/2a/725ecc166d53438bc88f76822ed4b1e3b10756e790bafd7b523fe97c322d/yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-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/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/a0/37fb236da6040e337381dd656cafb97d09eacb998c5db3057547f5ffddd9/pycifrw-5.0.1-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-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/23/35c7aea1274aef7525bdd2dc92f710bdde6d11652239d71d1ec450067939/coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9b/fd/e5ecca1e78c05106d98028114f5c00d3eddb41207686b2b7de3e477b0e22/numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-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/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/7b/537a61906eac58d94131273084d21d4eb219f5453f0ed30de3aca580a2b4/scipp-26.3.1-cp312-cp312-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/47/d4/dbacced3953544b9a93088cc10ef2b596d348c983d5c67a404fa41ec51ba/fonttools-4.62.1-cp312-cp312-macosx_10_13_universal2.whl + - pypi: https://files.pythonhosted.org/packages/49/b3/2de412451330756aaaa72d27131db6dde23995efe62c941184e15242a5fa/sqlalchemy-2.0.49-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-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/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-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/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.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/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-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/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/a0/37fb236da6040e337381dd656cafb97d09eacb998c5db3057547f5ffddd9/pycifrw-5.0.1-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/9b/fd/e5ecca1e78c05106d98028114f5c00d3eddb41207686b2b7de3e477b0e22/numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/9c/2f/4c5af01fd1a7506a1d5375403d68925eac70289229492db5aa68b58103d8/chardet-7.4.3-cp312-cp312-macosx_11_0_arm64.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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.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/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.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/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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/44/7b/537a61906eac58d94131273084d21d4eb219f5453f0ed30de3aca580a2b4/scipp-26.3.1-cp312-cp312-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/b0/3e/a6497e1c2c9bc6ed2b79e0f2d31a4ce509fd2a9eed4e4f7ac63eda8113cb/gemmi-0.7.5-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b0/42/c84efcc1d4caebafb1ecd8be4643f39c85c47a80fe254d92b8b43b1eadaf/h5py-3.16.0-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/18/4880dd762e40cd360c1bf06e890c5a97b997e91cb324602b1a19950ad5ce/matplotlib-3.10.9-cp312-cp312-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/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-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/bd/8c/d4907ad4f6bdc5bf79462d8767728713a7b316918a7444df372958a0e417/spglib-2.6.0-cp312-cp312-macosx_11_0_arm64.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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.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/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.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/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-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/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/bd/8c/d4907ad4f6bdc5bf79462d8767728713a7b316918a7444df372958a0e417/spglib-2.6.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/49/b3/2de412451330756aaaa72d27131db6dde23995efe62c941184e15242a5fa/sqlalchemy-2.0.49-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-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/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.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/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.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/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/2a/725ecc166d53438bc88f76822ed4b1e3b10756e790bafd7b523fe97c322d/yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.4.0-py312h06d0912_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda - - 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.4.22-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py312he06e257_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py312ha1a9051_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda @@ -1781,35 +1774,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 - - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda - - 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.3-h692994f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.5-h4fa8253_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py312he06e257_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -1818,317 +1790,290 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py312he5662c2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.13-h0159041_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py312h829343e_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py312h275cf98_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py312h05f76fc_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py312hdabe01f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py312he06e257_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.4.0-py312h06d0912_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py312he06e257_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py312ha1a9051_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/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda + - 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.3-h692994f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.5-h4fa8253_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py312he06e257_0.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/onemkl-license-2026.0.0-h57928b3_905.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py312he5662c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.13-h0159041_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py312h829343e_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py312h275cf98_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py312h05f76fc_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py312hdabe01f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py312he06e257_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl - - 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: . + - pypi: https://files.pythonhosted.org/packages/03/c1/0976b235cf29ead553e22f2fb6385a8252b533715e00d0ae52ed7b900582/h5py-3.16.0-cp312-cp312-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/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.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/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/19/93853133df2cb371083285ef6a93982a0173e7a233b0f61373ba9fd30eb2/coverage-7.14.0-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/1a/1f/86b4d15221096cb5500bcd73bf350745749e3ba056cdd7a7f75f126f154e/scipp-26.3.1-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/1a/c7/78200c18404ded028758b28b588aa1f4f3acd851271a74156a2a3db9eadf/crysfml-0.6.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/6f/0c/8297c8d978c919ad6318011631a6123082d5da940da5f8612e75a247d739/diffpy_pdffit2-1.6.0-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.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/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/55/5733807f4af131ea6194309ac0f43eb5b05463c676d036ef948f3143c1f2/pycifrw-5.0.1-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/b1/0c2ab56a16f409c6c8a68816e6af707827ad5d629634691ff60a52879792/fonttools-4.62.1-cp312-cp312-win_amd64.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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-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/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/5b/e1deebf88ff431b01b7406ca3583ab2bbb90972bbe1c568732e49c844f7e/numpy-2.4.4-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/eb/f2/53be7a4ba5816e13c39be0f728facac4bcb39cf4903ceeec54b006511c8f/gemmi-0.7.5-cp312-cp312-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/4c/fe/4fb3a0805bd5165da5ebf858da7cc01cce8061674106d2cf5bdab32cbfde/greenlet-3.5.0-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/03/c1/0976b235cf29ead553e22f2fb6385a8252b533715e00d0ae52ed7b900582/h5py-3.16.0-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-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/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-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/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/9e/fd90114059175cac64e4fafa9bf3ac20584384d66de40793ae2e2f26f3bb/sqlalchemy-2.0.49-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/fe/4fb3a0805bd5165da5ebf858da7cc01cce8061674106d2cf5bdab32cbfde/greenlet-3.5.0-cp312-cp312-win_amd64.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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-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/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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2d/5b/e1deebf88ff431b01b7406ca3583ab2bbb90972bbe1c568732e49c844f7e/numpy-2.4.4-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-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/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-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/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/55/5733807f4af131ea6194309ac0f43eb5b05463c676d036ef948f3143c1f2/pycifrw-5.0.1-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6f/0c/8297c8d978c919ad6318011631a6123082d5da940da5f8612e75a247d739/diffpy_pdffit2-1.6.0-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-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/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-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/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-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/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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-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/1a/1f/86b4d15221096cb5500bcd73bf350745749e3ba056cdd7a7f75f126f154e/scipp-26.3.1-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/8f/82/b54e646be7b938fcbdda10030c6533bd2bb1a59930a1381cc83d6050a49c/spglib-2.6.0-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/47/9e/fd90114059175cac64e4fafa9bf3ac20584384d66de40793ae2e2f26f3bb/sqlalchemy-2.0.49-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/19/93853133df2cb371083285ef6a93982a0173e7a233b0f61373ba9fd30eb2/coverage-7.14.0-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8f/82/b54e646be7b938fcbdda10030c6533bd2bb1a59930a1381cc83d6050a49c/spglib-2.6.0-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.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/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-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/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/f2/53be7a4ba5816e13c39be0f728facac4bcb39cf4903ceeec54b006511c8f/gemmi-0.7.5-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.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/f5/be/25216a49daeeb7af2bec0db22d5e7df08ed1d7c9f65d78b14f3b74fd72fc/yarl-1.23.0-cp312-cp312-win_amd64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.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/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl py-314-env: channels: - url: https://conda.anaconda.org/nodefaults/ - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple - options: - pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - 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.4.22-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-7_h4a7cf45_openblas.conda @@ -2156,17 +2101,81 @@ environments: - 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.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_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.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -2176,29 +2185,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -2207,9 +2210,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -2221,199 +2222,194 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: . + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz + - 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/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-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/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-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/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - 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/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-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/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-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/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.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/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/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-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/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-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/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-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/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d8/8b/e2bbeb42068f0c48899e8eddd34902afc0f7429d4d2a152d2dc2670dc661/pythreejs-2.4.2-py3-none-any.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/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.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/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-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/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-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/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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-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/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda @@ -2423,31 +2419,24 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda - - 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.4.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda @@ -2470,43 +2459,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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-7_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-7_hb0561ab_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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.68.1-h8f3e76b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -2516,31 +2476,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -2549,9 +2501,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -2563,196 +2513,243 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl - - 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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_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.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_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-7_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-7_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_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.8.0-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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.68.1-h8f3e76b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_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.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: . + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/04/f1/58c14b37525dc075f3bdf149251f079723049a9f1c82eb48835a0e6b8db3/diffpy_pdffit2-1.6.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_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/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/06/41/4e70dea1d0311016c0b0b1c53a24a266f9f8a34c6bc1af0f17cfca20aa1d/gemmi-0.7.5-cp314-cp314-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-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/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-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/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-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/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - 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/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.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/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-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/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-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/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.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/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-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/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.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/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.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/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda @@ -2762,24 +2759,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda - - 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.4.22-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda @@ -2808,36 +2800,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 - - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda - - 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.3-h692994f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.5-h4fa8253_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -2846,314 +2816,287 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_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/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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 + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda + - 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.3-h692994f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_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.5-h4fa8253_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.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/onemkl-license-2026.0.0-h57928b3_905.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: . + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-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/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.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/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-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/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/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.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/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-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/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.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/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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-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/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.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/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.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/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-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/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-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/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-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/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.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/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/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/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-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/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.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/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-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/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/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-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/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-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/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-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/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/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.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/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-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/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl - - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.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/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-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/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.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/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-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/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - 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/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.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/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.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/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.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/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl - - pypi: ./ + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-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/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.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/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.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/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.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/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.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/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-win_amd64.whl user: channels: - url: https://conda.anaconda.org/nodefaults/ - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple - options: - pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_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/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda @@ -3168,182 +3111,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.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/markupsafe-3.0.3-py314h67df5f8_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - 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/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-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/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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - 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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.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/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda @@ -3353,17 +3137,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda @@ -3377,7 +3157,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda @@ -3397,28 +3177,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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/libsodium-1.0.21-h1a92334_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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/markupsafe-3.0.3-py314h6e9b3f0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 @@ -3428,32 +3194,24 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda @@ -3461,9 +3219,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -3475,116 +3231,114 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-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/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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/04/f1/58c14b37525dc075f3bdf149251f079723049a9f1c82eb48835a0e6b8db3/diffpy_pdffit2-1.6.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/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/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-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/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl - - pypi: https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/06/41/4e70dea1d0311016c0b0b1c53a24a266f9f8a34c6bc1af0f17cfca20aa1d/gemmi-0.7.5-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-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/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-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/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-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/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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl - - 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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.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/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl - win-64: + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda @@ -3594,18 +3348,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda - - 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.4.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda @@ -3619,8 +3368,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda @@ -3632,3576 +3381,3225 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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/liblzma-5.8.3-hfd05255_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_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/markupsafe-3.0.3-py314h2359020_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-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/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_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/markupsafe-3.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/04/f1/58c14b37525dc075f3bdf149251f079723049a9f1c82eb48835a0e6b8db3/diffpy_pdffit2-1.6.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/06/41/4e70dea1d0311016c0b0b1c53a24a266f9f8a34c6bc1af0f17cfca20aa1d/gemmi-0.7.5-cp314-cp314-macosx_11_0_arm64.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/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-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/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-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/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-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/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.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/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-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/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/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/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.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/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-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/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-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/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-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/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-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/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-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/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.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/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-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/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/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.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/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl - - 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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - - pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.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/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.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/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-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/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-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/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl -packages: -- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - build_number: 20 - sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 - md5: a9f577daf3de00bca7c3c76c0ecbd1de - depends: - - __glibc >=2.17,<3.0.a0 - - libgomp >=7.5.0 - constrains: - - openmp_impl <0.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 28948 - timestamp: 1770939786096 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - build_number: 7 - sha256: 7acaa2e0782cad032bdaf756b536874346ac1375745fb250e9bdd6a48a7ab3cd - md5: a44032f282e7d2acdeb1c240308052dd - depends: - - llvm-openmp >=9.0.1 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 8325 - timestamp: 1764092507920 -- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 - md5: aaa2a381ccc56eac91d63b6c1240312f - depends: - - cpython - - python-gil - license: MIT - license_family: MIT - purls: [] - size: 8191 - timestamp: 1744137672556 -- pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - name: aiohappyeyeballs - version: 2.6.1 - sha256: f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl - name: aiohttp - version: 3.13.5 - sha256: f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 - requires_dist: - - aiohappyeyeballs>=2.5.0 - - aiosignal>=1.4.0 - - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' - - attrs>=17.3.0 - - frozenlist>=1.1.1 - - multidict>=4.5,<7.0 - - propcache>=0.2.0 - - yarl>=1.17.0,<2.0 - - aiodns>=3.3.0 ; extra == 'speedups' - - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' - - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' - - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl - name: aiohttp - version: 3.13.5 - sha256: ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 - requires_dist: - - aiohappyeyeballs>=2.5.0 - - aiosignal>=1.4.0 - - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' - - attrs>=17.3.0 - - frozenlist>=1.1.1 - - multidict>=4.5,<7.0 - - propcache>=0.2.0 - - yarl>=1.17.0,<2.0 - - aiodns>=3.3.0 ; extra == 'speedups' - - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' - - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' - - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: aiohttp - version: 3.13.5 - sha256: b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 - requires_dist: - - aiohappyeyeballs>=2.5.0 - - aiosignal>=1.4.0 - - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' - - attrs>=17.3.0 - - frozenlist>=1.1.1 - - multidict>=4.5,<7.0 - - propcache>=0.2.0 - - yarl>=1.17.0,<2.0 - - aiodns>=3.3.0 ; extra == 'speedups' - - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' - - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' - - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl - name: aiohttp - version: 3.13.5 - sha256: 756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 - requires_dist: - - aiohappyeyeballs>=2.5.0 - - aiosignal>=1.4.0 - - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' - - attrs>=17.3.0 - - frozenlist>=1.1.1 - - multidict>=4.5,<7.0 - - propcache>=0.2.0 - - yarl>=1.17.0,<2.0 - - aiodns>=3.3.0 ; extra == 'speedups' - - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' - - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' - - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl - name: aiohttp - version: 3.13.5 - sha256: 110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 - requires_dist: - - aiohappyeyeballs>=2.5.0 - - aiosignal>=1.4.0 - - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' - - attrs>=17.3.0 - - frozenlist>=1.1.1 - - multidict>=4.5,<7.0 - - propcache>=0.2.0 - - yarl>=1.17.0,<2.0 - - aiodns>=3.3.0 ; extra == 'speedups' - - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' - - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' - - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: aiohttp - version: 3.13.5 - sha256: 241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b - requires_dist: - - aiohappyeyeballs>=2.5.0 - - aiosignal>=1.4.0 - - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' - - attrs>=17.3.0 - - frozenlist>=1.1.1 - - multidict>=4.5,<7.0 - - propcache>=0.2.0 - - yarl>=1.17.0,<2.0 - - aiodns>=3.3.0 ; extra == 'speedups' - - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' - - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' - - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - name: aiosignal - version: 1.4.0 - sha256: 053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e - requires_dist: - - frozenlist>=1.1.0 - - typing-extensions>=4.2 ; python_full_version < '3.13' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl - name: annotated-doc - version: 0.0.4 - sha256: 571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320 - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl - name: annotated-types - version: 0.7.0 - sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 - requires_dist: - - typing-extensions>=4.0.0 ; python_full_version < '3.9' - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda - sha256: f09aed24661cd45ba54a43772504f05c0698248734f9ae8cd289d314ac89707e - md5: af2df4b9108808da3dc76710fe50eae2 - depends: - - exceptiongroup >=1.0.2 - - idna >=2.8 - - python >=3.10 - - typing_extensions >=4.5 - - python - constrains: - - trio >=0.32.0 - - uvloop >=0.22.1 - - winloop >=0.2.3 - license: MIT - license_family: MIT - purls: - - pkg:pypi/anyio?source=hash-mapping - size: 146764 - timestamp: 1774359453364 -- conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - sha256: 8f032b140ea4159806e4969a68b4a3c0a7cab1ad936eb958a2b5ffe5335e19bf - md5: 54898d0f524c9dee622d44bbb081a8ab - depends: - - python >=3.9 - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/appnope?source=hash-mapping - size: 10076 - timestamp: 1733332433806 -- conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - sha256: bea62005badcb98b1ae1796ec5d70ea0fc9539e7d59708ac4e7d41e2f4bb0bad - md5: 8ac12aff0860280ee0cff7fa2cf63f3b - depends: - - argon2-cffi-bindings - - python >=3.9 - - typing-extensions - constrains: - - argon2_cffi ==999 - license: MIT - license_family: MIT - purls: - - pkg:pypi/argon2-cffi?source=hash-mapping - size: 18715 - timestamp: 1749017288144 -- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda - sha256: 7988c207b2b766dad5ebabf25a92b8d75cb8faed92f256fd7a4e0875c9ec6d58 - md5: 1567f06d717246abab170736af8bad1b - depends: - - __glibc >=2.17,<3.0.a0 - - cffi >=1.0.1 - - libgcc >=14 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 35646 - timestamp: 1762509443854 -- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda - sha256: 39234a99df3d2e3065383808ed8bfda36760de5ef590c54c3692bb53571ef02b - md5: 3cca1b74b2752917b5b65b81f61f0553 - depends: - - __glibc >=2.17,<3.0.a0 - - cffi >=2.0.0b1 - - libgcc >=14 - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 35598 - timestamp: 1762509505285 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py312h4409184_2.conda - sha256: 24c475f6f7abf03ef3cc2ac572b7a6d713bede00ef984591be92cdc439b09fbc - md5: 0a2a07b42db3f92b8dccf0f60b5ebee8 - depends: - - __osx >=11.0 - - cffi >=1.0.1 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 34224 - timestamp: 1762509989973 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda - sha256: aab60bbaea5cc49dff37438d1ad469d64025cda2ce58103cf68da61701ed2075 - md5: a240a79a49a95b388ef81ccda27a5e51 - depends: - - __osx >=11.0 - - cffi >=2.0.0b1 - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 34218 - timestamp: 1762509977830 -- conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda - sha256: 38c5e43d991b0c43713fa2ceba3063afa4ccad2dd4c8eb720143de54d461a338 - md5: 5dc3781bbc4ddce0bf250a04c1a192c2 - depends: - - cffi >=1.0.1 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: MIT - license_family: MIT - purls: - - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 38535 - timestamp: 1762509763237 -- conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda - sha256: a742e7cd0d5534bfff3fd550a0c1e430411fad60a24f88930d261056ab08096f - md5: ffa247e46f47e157851dc547f4c513e4 - depends: - - cffi >=2.0.0b1 - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: MIT - license_family: MIT - purls: - - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 38653 - timestamp: 1762509771011 -- conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - sha256: 792da8131b1b53ff667bd6fc617ea9087b570305ccb9913deb36b8e12b3b5141 - md5: 85c4f19f377424eafc4ed7911b291642 - depends: - - python >=3.10 - - python-dateutil >=2.7.0 - - python-tzdata - - python - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/arrow?source=hash-mapping - size: 113854 - timestamp: 1760831179410 -- pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl - name: arviz - version: 1.1.0 - sha256: 87ebd21ce052f30d21f932b4166fc31b91c0bc7443f8da7fed3518b342267010 - requires_dist: - - arviz-base>=1.1.0,<1.2.0 - - arviz-stats[xarray]>=1.1.0,<1.2.0 - - arviz-plots>=1.1.0,<1.2.0 - - arviz-plots[bokeh] ; extra == 'bokeh' - - build ; extra == 'check' - - pre-commit ; extra == 'check' - - h5netcdf ; extra == 'doc' - - h5py ; extra == 'doc' - - jupyter-sphinx ; extra == 'doc' - - matplotlib ; extra == 'doc' - - myst-parser[linkify] ; extra == 'doc' - - myst-nb ; extra == 'doc' - - pydata-sphinx-theme>=0.13 ; extra == 'doc' - - sphinx>=5 ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - sphinx-design ; extra == 'doc' - - sphinx-notfound-page ; extra == 'doc' - - sphinxcontrib-youtube ; extra == 'doc' - - sphinx-togglebutton ; extra == 'doc' - - sphobjinv ; extra == 'doc' - - arviz-base[h5netcdf] ; extra == 'h5netcdf' - - arviz-plots[matplotlib] ; extra == 'matplotlib' - - arviz-base[netcdf4] ; extra == 'netcdf4' - - arviz-plots[plotly] ; extra == 'plotly' - - pytest ; extra == 'test' - - arviz-base[zarr] ; extra == 'zarr' - requires_python: '>=3.12' -- pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl - name: arviz-base - version: 1.1.0 - sha256: 4f97016f697751038f45d144331a1830c921f0ebc2739d5df343120fba453e83 - requires_dist: - - numpy>=2 - - xarray>=2024.11.0 - - typing-extensions>=3.10 - - lazy-loader>=0.4 - - build ; extra == 'check' - - pre-commit ; extra == 'check' - - docstub==0.4 ; extra == 'check' - - mypy ; extra == 'check' - - pre-commit ; extra == 'ci' - - cloudpickle ; extra == 'ci' - - sphinx-book-theme ; extra == 'doc' - - myst-parser[linkify] ; extra == 'doc' - - myst-nb ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - numpydoc ; extra == 'doc' - - sphinx>=5 ; extra == 'doc' - - sphinx-design ; extra == 'doc' - - jupyter-sphinx ; extra == 'doc' - - h5netcdf[h5py] ; extra == 'doc' - - h5netcdf[h5py] ; extra == 'h5netcdf' - - netcdf4 ; extra == 'netcdf4' - - xarray!=2025.8.0 ; extra == 'test' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - scipy ; extra == 'test' - - zarr ; extra == 'zarr' - requires_python: '>=3.12' -- pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - name: arviz-plots - version: 1.1.0 - sha256: 5c7ab5b0c7c29cda6ddb5e04c699c70285fe68a76d2b1b42302c69a85742adde - requires_dist: - - arviz-base>=1.1,<1.2 - - arviz-stats[xarray]>=1.1,<1.2 - - bokeh>=3.4 ; extra == 'bokeh' - - sphinx-book-theme ; extra == 'doc' - - myst-parser[linkify] ; extra == 'doc' - - myst-nb ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - numpydoc ; extra == 'doc' - - sphinx>=6 ; extra == 'doc' - - sphinx-design ; extra == 'doc' - - jupyter-sphinx ; extra == 'doc' - - h5netcdf[h5py] ; extra == 'doc' - - plotly<6 ; extra == 'doc' - - matplotlib>=3.9 ; extra == 'matplotlib' - - plotly>=5.19 ; extra == 'plotly' - - webcolors ; extra == 'plotly' - - hypothesis ; extra == 'test' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - h5netcdf[h5py] ; extra == 'test' - - kaleido ; extra == 'test' - requires_python: '>=3.12' -- pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl - name: arviz-stats - version: 1.1.0 - sha256: ed47334ccff8670a0b90a50e1a37e7257268084eb3436e6b7b15e623f1001947 - requires_dist: - - numpy>=2 - - scipy>=1.13 - - sphinx-book-theme ; extra == 'doc' - - myst-parser[linkify] ; extra == 'doc' - - myst-nb ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - numpydoc ; extra == 'doc' - - sphinx<9 ; extra == 'doc' - - sphinx-design ; extra == 'doc' - - jupyter-sphinx ; extra == 'doc' - - h5netcdf[h5py] ; extra == 'doc' - - sphinx-autosummary-accessors ; extra == 'doc' - - numba ; extra == 'numba' - - xarray-einstats[einops,numba] ; extra == 'numba' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest ; extra == 'test-xarray' - - pytest-cov ; extra == 'test-xarray' - - h5netcdf[h5py] ; extra == 'test-xarray' - - arviz-base>=1.1,<1.2 ; extra == 'xarray' - - xarray-einstats ; extra == 'xarray' - - xarray>=2024.11.0 ; extra == 'xarray' - requires_python: '>=3.12' -- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl - name: asciichartpy - version: 1.5.25 - sha256: 33c417a3c8ef7d0a11b98eb9ea6dd9b2c1b17559e539b207a17d26d4302d0258 - requires_dist: - - setuptools - - flake8 ; extra == 'qa' -- pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl - name: ase - 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' - - pytest-xdist>=3.2.0 ; extra == 'test' - - spglib>=1.9 ; extra == 'spglib' - - mypy ; extra == 'lint' - - ruff ; extra == 'lint' - - types-docutils ; extra == 'lint' - - types-pymysql ; extra == 'lint' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - name: asteval - version: 1.0.8 - sha256: 6c64385c6ff859a474953c124987c7ee8354d781c76509b2c598741c4d1d28e9 - requires_dist: - - build ; extra == 'dev' - - twine ; extra == 'dev' - - sphinx ; extra == 'doc' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - coverage ; extra == 'test' - - asteval[dev,doc,test] ; extra == 'all' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - sha256: ee4da0f3fe9d59439798ee399ef3e482791e48784873d546e706d0935f9ff010 - md5: 9673a61a297b00016442e022d689faa6 - depends: - - python >=3.10 - constrains: - - astroid >=2,<5 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/asttokens?source=hash-mapping - size: 28797 - timestamp: 1763410017955 -- conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - sha256: ea8486637cfb89dc26dc9559921640cd1d5fd37e5e02c33d85c94572139f2efe - md5: b85e84cb64c762569cc1a760c2327e0a - depends: - - python >=3.10 - - typing_extensions >=4.0.0 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/async-lru?source=hash-mapping - size: 22949 - timestamp: 1773926359134 -- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab - md5: c6b0543676ecb1fb2d7643941fe375f2 - depends: - - python >=3.10 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/attrs?source=hash-mapping - size: 64927 - timestamp: 1773935801332 -- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl - name: autopep8 - version: 2.3.2 - sha256: ce8ad498672c845a0c3de2629c15b635ec2b05ef8177a6e7c91c74f3e9b51128 - requires_dist: - - pycodestyle>=2.12.0 - - tomli ; python_full_version < '3.11' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - sha256: a14a9ad02101aab25570543a59c5193043b73dc311a25650134ed9e6cb691770 - md5: f1976ce927373500cc19d3c0b2c85177 - depends: - - python >=3.10 - - python - constrains: - - pytz >=2015.7 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/babel?source=hash-mapping - size: 7684321 - timestamp: 1772555330347 -- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.4.0-py312h90b7ffd_0.conda - sha256: e8c83696e6529ac1909a96690c58624bb376312fd0768409380cd9b05e248c9b - md5: 542da724e75cdeef19e29cca23935c25 - depends: - - python - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - - zstd >=1.5.7,<1.6.0a0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 238360 - timestamp: 1777848717715 -- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda - noarch: generic - sha256: de1755a35258eb1b59f2288559bbf0b76da60bd2fa6cd6f768ead442f85bd666 - md5: b712198b257f378e9bd8cde277218296 - depends: - - python >=3.14 - license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: [] - size: 7546 - timestamp: 1777848733980 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.4.0-py312h87c4bb7_0.conda - sha256: 7dbd64d3f06622ef8286be6dfceeb8e6008450fb4e6d9309fbb908b12f3937ff - md5: 95a833465ec45ac1e8f2ed1aaba8ec37 - depends: - - python - - __osx >=11.0 - - zstd >=1.5.7,<1.6.0a0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 239305 - timestamp: 1777848727027 -- conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.4.0-py312h06d0912_0.conda - sha256: 71caf40c0fdeb11fafaac639e6e6f9120112aa105a7a5e9dfb5b4b06db9ca97a - md5: 77d0a2bdd46dd8d502bb27eb80353fcd - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - zstd >=1.5.7,<1.6.0a0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 237107 - timestamp: 1777848740547 -- pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl - name: backrefs - version: '7.0' - sha256: ca42ce6a49ace3d75684dfa9937f3373902a63284ecb385ce36d15e5dcb41c12 - requires_dist: - - regex ; extra == 'extras' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl - name: backrefs - version: '7.0' - sha256: a6448b28180e3ca01134c9cf09dcebafad8531072e09903c5451748a05f24bc9 - requires_dist: - - regex ; extra == 'extras' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - sha256: bf1e71c3c0a5b024e44ff928225a0874fc3c3356ec1a0b6fe719108e6d1288f6 - md5: 5267bef8efea4127aacd1f4e1f149b6e - depends: - - python >=3.10 - - soupsieve >=1.2 - - typing-extensions - license: MIT - license_family: MIT - purls: - - pkg:pypi/beautifulsoup4?source=hash-mapping - size: 90399 - timestamp: 1764520638652 -- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl - name: bidict - version: 0.23.1 - sha256: 5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5 - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - sha256: f8ff1f98423674278964a46c93a1766f9e91960d44efd91c6c3ed56a33813f46 - md5: 7c5ebdc286220e8021bf55e6384acd67 - depends: - - python >=3.10 - - webencodings - - python - constrains: - - tinycss2 >=1.1.0,<1.5 - license: Apache-2.0 AND MIT - purls: - - pkg:pypi/bleach?source=hash-mapping - size: 142008 - timestamp: 1770719370680 -- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda - sha256: 7c07a865e5e4cca233cc4e0eb3f0f5ff6c90776461687b4fb0b1764133e1fd61 - md5: f11a319b9700b203aa14c295858782b6 - depends: - - bleach ==6.3.0 pyhcf101f3_1 - - tinycss2 - license: Apache-2.0 AND MIT - purls: [] - size: 4409 - timestamp: 1770719370682 -- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - name: blinker - version: 1.9.0 - sha256: ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda - sha256: 49df13a1bb5e388ca0e4e87022260f9501ed4192656d23dc9d9a1b4bf3787918 - md5: 64088dffd7413a2dd557ce837b4cbbdb - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libstdcxx >=14 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - constrains: - - libbrotlicommon 1.2.0 hb03c661_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli?source=hash-mapping - size: 368300 - timestamp: 1764017300621 -- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda - sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 - md5: 8910d2c46f7e7b519129f486e0fe927a - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libstdcxx >=14 - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - constrains: - - libbrotlicommon 1.2.0 hb03c661_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli?source=hash-mapping - size: 367376 - timestamp: 1764017265553 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda - sha256: 6178775a86579d5e8eec6a7ab316c24f1355f6c6ccbe84bb341f342f1eda2440 - md5: 311fcf3f6a8c4eb70f912798035edd35 - depends: - - __osx >=11.0 - - libcxx >=19 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - constrains: - - libbrotlicommon 1.2.0 hc919400_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli?source=hash-mapping - size: 359503 - timestamp: 1764018572368 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda - sha256: 5c2e471fd262fcc3c5a9d5ea4dae5917b885e0e9b02763dbd0f0d9635ed4cb99 - md5: f9501812fe7c66b6548c7fcaa1c1f252 - depends: - - __osx >=11.0 - - libcxx >=19 - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python_abi 3.14.* *_cp314 - constrains: - - libbrotlicommon 1.2.0 hc919400_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli?source=hash-mapping - size: 359854 - timestamp: 1764018178608 -- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda - sha256: 2bb6f384a51929ef2d5d6039fcf6c294874f20aaab2f63ca768cbe462ed4b379 - md5: e8e7a6346a9e50d19b4daf41f367366f - depends: - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - libbrotlicommon 1.2.0 hfd05255_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli?source=hash-mapping - size: 335482 - timestamp: 1764018063640 -- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda - sha256: 6854ee7675135c57c73a04849c29cbebc2fb6a3a3bfee1f308e64bf23074719b - md5: 1302b74b93c44791403cbeee6a0f62a3 - depends: - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - libbrotlicommon 1.2.0 hfd05255_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli?source=hash-mapping - size: 335782 - timestamp: 1764018443683 -- pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl - name: build - version: 1.5.0 - sha256: 13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f - requires_dist: - - packaging>=24.0 - - pyproject-hooks - - colorama ; os_name == 'nt' - - importlib-metadata>=4.6 ; python_full_version < '3.10.2' - - tomli>=1.1.0 ; python_full_version < '3.11' - - keyring ; extra == 'keyring' - - uv>=0.1.18 ; extra == 'uv' - - virtualenv>=20.17 ; python_full_version >= '3.10' and python_full_version < '3.14' and extra == 'virtualenv' - - virtualenv>=20.31 ; python_full_version >= '3.14' and extra == 'virtualenv' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl - name: bumps - version: 1.0.4 - sha256: 78b8cfaf9fbcbf2fd77f6d4a2f8c906b0e03a794804ba6caf64d56d6f6cce4d4 - requires_dist: - - numpy - - scipy - - h5py - - dill - - cloudpickle - - matplotlib - - blinker - - aiohttp - - python-socketio - - plotly - - mpld3 - - msgpack - - uncertainties - - build ; extra == 'dev' - - pre-commit ; extra == 'dev' - - pytest ; extra == 'dev' - - pytest-cov ; extra == 'dev' - - ruff ; extra == 'dev' - - wheel ; extra == 'dev' - - setuptools ; extra == 'dev' - - sphinx ; extra == 'dev' - - versioningit ; extra == 'dev' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 - md5: d2ffd7602c02f2b316fd921d39876885 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - license: bzip2-1.0.6 - license_family: BSD - purls: [] - size: 260182 - timestamp: 1771350215188 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda - sha256: 540fe54be35fac0c17feefbdc3e29725cce05d7367ffedfaaa1bdda234b019df - md5: 620b85a3f45526a8bc4d23fd78fc22f0 - depends: - - __osx >=11.0 - license: bzip2-1.0.6 - license_family: BSD - purls: [] - size: 124834 - timestamp: 1771350416561 -- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda - sha256: 76dfb71df5e8d1c4eded2dbb5ba15bb8fb2e2b0fe42d94145d5eed4c75c35902 - md5: 4cb8e6b48f67de0b018719cdf1136306 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: bzip2-1.0.6 - license_family: BSD - purls: [] - size: 56115 - timestamp: 1771350256444 -- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - sha256: cc9accf72fa028d31c2a038460787751127317dcfa991f8d1f1babf216bb454e - md5: 920bb03579f15389b9e512095ad995b7 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - license: MIT - license_family: MIT - purls: [] - size: 207882 - timestamp: 1765214722852 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - sha256: 2995f2aed4e53725e5efbc28199b46bf311c3cab2648fc4f10c2227d6d5fa196 - md5: bcb3cba70cf1eec964a03b4ba7775f01 - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: [] - size: 180327 - timestamp: 1765215064054 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-h4c7d964_0.conda - sha256: 6f4ff81534c19e76acf52fcabf4a258088a932b8f1ac56e9a59e98f6051f8e46 - md5: 56fb2c6c73efc627b40c77d14caecfba - depends: - - __win - license: ISC - purls: [] - size: 131388 - timestamp: 1776865633471 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda - sha256: c9dbcc8039a52023660d6d1bbf87594a93dd69c6ac5a2a44323af2c92976728d - md5: e18ad67cf881dcadee8b8d9e2f8e5f73 - depends: - - __unix - license: ISC - purls: [] - size: 131039 - timestamp: 1776865545798 -- conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - noarch: python - sha256: 561e6660f26c35d137ee150187d89767c988413c978e1b712d53f27ddf70ea17 - md5: 9b347a7ec10940d3f7941ff6c460b551 - depends: - - cached_property >=1.5.2,<1.5.3.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 4134 - timestamp: 1615209571450 -- conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - sha256: 6dbf7a5070cc43d90a1e4c2ec0c541c69d8e30a0e25f50ce9f6e4a432e42c5d7 - md5: 576d629e47797577ab0f1b351297ef4a - depends: - - python >=3.6 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/cached-property?source=hash-mapping - size: 11065 - timestamp: 1615209567874 -- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda - sha256: 989db6e5957c4b44fa600c68c681ec2f36a55e48f7c7f1c073d5e91caa8cd878 - md5: 929471569c93acefb30282a22060dcd5 - depends: - - python >=3.10 - license: ISC - purls: - - pkg:pypi/certifi?source=hash-mapping - size: 135656 - timestamp: 1776866680878 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda - sha256: 7dafe8173d5f94e46cf9cd597cc8ff476a8357fbbd4433a8b5697b2864845d9c - md5: 648ee28dcd4e07a1940a17da62eccd40 - depends: - - __glibc >=2.17,<3.0.a0 - - libffi >=3.5.2,<3.6.0a0 - - libgcc >=14 - - pycparser - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 295716 - timestamp: 1761202958833 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda - sha256: c6339858a0aaf5d939e00d345c98b99e4558f285942b27232ac098ad17ac7f8e - md5: cf45f4278afd6f4e6d03eda0f435d527 - depends: - - __glibc >=2.17,<3.0.a0 - - libffi >=3.5.2,<3.6.0a0 - - libgcc >=14 - - pycparser - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 300271 - timestamp: 1761203085220 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py312h1b4d9a2_1.conda - sha256: 597e986ac1a1bd1c9b29d6850e1cdea4a075ce8292af55568952ec670e7dd358 - md5: 503ac138ad3cfc09459738c0f5750705 - depends: - - __osx >=11.0 - - libffi >=3.5.2,<3.6.0a0 - - pycparser - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 288080 - timestamp: 1761203317419 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda - sha256: 5b5ee5de01eb4e4fd2576add5ec9edfc654fbaf9293e7b7ad2f893a67780aa98 - md5: 10dd19e4c797b8f8bdb1ec1fbb6821d7 - depends: - - __osx >=11.0 - - libffi >=3.5.2,<3.6.0a0 - - pycparser - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 292983 - timestamp: 1761203354051 -- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py312he06e257_1.conda - sha256: 3e3bdcb85a2e79fe47d9c8ce64903c76f663b39cb63b8e761f6f884e76127f82 - md5: 46f7dccfee37a52a97c0ed6f33fcf0a3 - depends: - - pycparser - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 291324 - timestamp: 1761203195397 -- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda - sha256: 924f2f01fa7a62401145ef35ab6fc95f323b7418b2644a87fea0ea68048880ed - md5: c360170be1c9183654a240aadbedad94 - depends: - - pycparser - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 294731 - timestamp: 1761203441365 -- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl - name: cfgv - version: 3.5.0 - sha256: a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl - name: chardet - version: 7.4.3 - sha256: 4b2799bd58e7245cfa8d4ab2e8ad1d76a5c3a5b1f32318eb6acca4c69a3e7101 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.whl - name: chardet - version: 7.4.3 - sha256: acc46d1b8b7d5783216afe15db56d1c179b9a40e5a1558bc13164c4fd20674c4 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/9c/2f/4c5af01fd1a7506a1d5375403d68925eac70289229492db5aa68b58103d8/chardet-7.4.3-cp312-cp312-macosx_11_0_arm64.whl - name: chardet - version: 7.4.3 - sha256: 29af5999f654e8729d251f1724a62b538b1262d9292cccaefddf8a02aae1ef6a - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl - name: chardet - version: 7.4.3 - sha256: b95c934b9ad59e2ba8abb9be49df70d3ad1b0d95d864b9fdb7588d4fa8bd921c - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: chardet - version: 7.4.3 - sha256: 6e3bd9f936e04bae89c254262af08d9e5b98f805175ba1e29d454e6cba3107b7 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: chardet - version: 7.4.3 - sha256: 9a4904dd5f071b7a7d7f50b4a67a86db3c902d243bf31708f1d5cde2f68239cb - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda - sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 - md5: a9167b9571f3baa9d448faa2139d1089 - depends: - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/charset-normalizer?source=hash-mapping - size: 58872 - timestamp: 1775127203018 -- pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - name: click - version: 8.3.3 - sha256: a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613 - requires_dist: - - colorama ; sys_platform == 'win32' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - name: cloudpickle - version: 3.1.2 - sha256: 9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - name: colorama - version: 0.4.6 - sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 - 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/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 - md5: 962b9857ee8e7018c22f2776ffa0b2d7 - depends: - - python >=3.9 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/colorama?source=hash-mapping - size: 27011 - timestamp: 1733218222191 -- conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - sha256: 576a44729314ad9e4e5ebe055fbf48beb8116b60e58f9070278985b2b634f212 - md5: 2da13f2b299d8e1995bafbbe9689a2f7 - depends: - - python >=3.9 - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/comm?source=hash-mapping - size: 14690 - timestamp: 1753453984907 -- pypi: https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: contourpy - version: 1.3.3 - sha256: f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3 - requires_dist: - - numpy>=1.25 - - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - bokeh ; extra == 'bokeh' - - selenium ; extra == 'bokeh' - - contourpy[bokeh,docs] ; extra == 'mypy' - - bokeh ; extra == 'mypy' - - docutils-stubs ; extra == 'mypy' - - mypy==1.17.0 ; extra == 'mypy' - - types-pillow ; extra == 'mypy' - - contourpy[test-no-images] ; extra == 'test' - - matplotlib ; extra == 'test' - - pillow ; extra == 'test' - - pytest ; extra == 'test-no-images' - - pytest-cov ; extra == 'test-no-images' - - pytest-rerunfailures ; extra == 'test-no-images' - - pytest-xdist ; extra == 'test-no-images' - - wurlitzer ; extra == 'test-no-images' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl - name: contourpy - version: 1.3.3 - sha256: 8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b - requires_dist: - - numpy>=1.25 - - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - bokeh ; extra == 'bokeh' - - selenium ; extra == 'bokeh' - - contourpy[bokeh,docs] ; extra == 'mypy' - - bokeh ; extra == 'mypy' - - docutils-stubs ; extra == 'mypy' - - mypy==1.17.0 ; extra == 'mypy' - - types-pillow ; extra == 'mypy' - - contourpy[test-no-images] ; extra == 'test' - - matplotlib ; extra == 'test' - - pillow ; extra == 'test' - - pytest ; extra == 'test-no-images' - - pytest-cov ; extra == 'test-no-images' - - pytest-rerunfailures ; extra == 'test-no-images' - - pytest-xdist ; extra == 'test-no-images' - - wurlitzer ; extra == 'test-no-images' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl - name: contourpy - version: 1.3.3 - sha256: 556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6 - requires_dist: - - numpy>=1.25 - - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - bokeh ; extra == 'bokeh' - - selenium ; extra == 'bokeh' - - contourpy[bokeh,docs] ; extra == 'mypy' - - bokeh ; extra == 'mypy' - - docutils-stubs ; extra == 'mypy' - - mypy==1.17.0 ; extra == 'mypy' - - types-pillow ; extra == 'mypy' - - contourpy[test-no-images] ; extra == 'test' - - matplotlib ; extra == 'test' - - pillow ; extra == 'test' - - pytest ; extra == 'test-no-images' - - pytest-cov ; extra == 'test-no-images' - - pytest-rerunfailures ; extra == 'test-no-images' - - pytest-xdist ; extra == 'test-no-images' - - wurlitzer ; extra == 'test-no-images' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl - name: contourpy - version: 1.3.3 - sha256: cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd - requires_dist: - - numpy>=1.25 - - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - bokeh ; extra == 'bokeh' - - selenium ; extra == 'bokeh' - - contourpy[bokeh,docs] ; extra == 'mypy' - - bokeh ; extra == 'mypy' - - docutils-stubs ; extra == 'mypy' - - mypy==1.17.0 ; extra == 'mypy' - - types-pillow ; extra == 'mypy' - - contourpy[test-no-images] ; extra == 'test' - - matplotlib ; extra == 'test' - - pillow ; extra == 'test' - - pytest ; extra == 'test-no-images' - - pytest-cov ; extra == 'test-no-images' - - pytest-rerunfailures ; extra == 'test-no-images' - - pytest-xdist ; extra == 'test-no-images' - - wurlitzer ; extra == 'test-no-images' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: contourpy - version: 1.3.3 - sha256: 4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1 - requires_dist: - - numpy>=1.25 - - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - bokeh ; extra == 'bokeh' - - selenium ; extra == 'bokeh' - - contourpy[bokeh,docs] ; extra == 'mypy' - - bokeh ; extra == 'mypy' - - docutils-stubs ; extra == 'mypy' - - mypy==1.17.0 ; extra == 'mypy' - - types-pillow ; extra == 'mypy' - - contourpy[test-no-images] ; extra == 'test' - - matplotlib ; extra == 'test' - - pillow ; extra == 'test' - - pytest ; extra == 'test-no-images' - - pytest-cov ; extra == 'test-no-images' - - pytest-rerunfailures ; extra == 'test-no-images' - - pytest-xdist ; extra == 'test-no-images' - - wurlitzer ; extra == 'test-no-images' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl - name: contourpy - version: 1.3.3 - sha256: cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77 - requires_dist: - - numpy>=1.25 - - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - bokeh ; extra == 'bokeh' - - selenium ; extra == 'bokeh' - - contourpy[bokeh,docs] ; extra == 'mypy' - - bokeh ; extra == 'mypy' - - docutils-stubs ; extra == 'mypy' - - mypy==1.17.0 ; extra == 'mypy' - - types-pillow ; extra == 'mypy' - - contourpy[test-no-images] ; extra == 'test' - - matplotlib ; extra == 'test' - - pillow ; extra == 'test' - - pytest ; extra == 'test-no-images' - - pytest-cov ; extra == 'test-no-images' - - pytest-rerunfailures ; extra == 'test-no-images' - - pytest-xdist ; extra == 'test-no-images' - - wurlitzer ; extra == 'test-no-images' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl - name: copier - version: 9.15.0 - sha256: 0f59c2ea36df42f3ded85c091c3f1e2c8d3814b537504f0abc8c2e508f7e013d - 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/34/23/35c7aea1274aef7525bdd2dc92f710bdde6d11652239d71d1ec450067939/coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl - name: coverage - version: 7.14.0 - sha256: 829994cfe1aeb773ca27bf246d4badc1e764893e3bfb98fff820fcecd1ca4662 - requires_dist: - - tomli ; python_full_version <= '3.11' and extra == 'toml' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/69/ff/6699e7b71e60d3049eb2bdcbc95ee3f35707b2b0e48f32e9e63d3ce30c08/coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - name: coverage - version: 7.14.0 - sha256: ca3d9cf2c32b521bd9518385608787fa86f38daf993695307531822c3430ed67 - requires_dist: - - tomli ; python_full_version <= '3.11' and extra == 'toml' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/85/19/93853133df2cb371083285ef6a93982a0173e7a233b0f61373ba9fd30eb2/coverage-7.14.0-cp312-cp312-win_amd64.whl - name: coverage - version: 7.14.0 - sha256: 70390b0da32cb90b501953716302906e8bcce087cb283e70d8c97729f22e92b2 - requires_dist: - - tomli ; python_full_version <= '3.11' and extra == 'toml' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - name: coverage - version: 7.14.0 - sha256: 5ebb8f4614a3787d567e610bbfdf96a4798dd69a1afb1bd8ad228d4111fe6ff3 - requires_dist: - - tomli ; python_full_version <= '3.11' and extra == 'toml' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl - name: coverage - version: 7.14.0 - sha256: ba3b8390db29296dbbf49e91b6fe08f990743a90c8f447ba4c2ffc29670dfa63 - requires_dist: - - tomli ; python_full_version <= '3.11' and extra == 'toml' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl - name: coverage - version: 7.14.0 - sha256: 45e0f79d8351fa76e256716df91eab12890d32678b9590df7ae1042e4bd4cf5d - requires_dist: - - tomli ; python_full_version <= '3.11' and extra == 'toml' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda - noarch: generic - sha256: d3e9bbd7340199527f28bbacf947702368f31de60c433a16446767d3c6aaf6fe - md5: f54c1ffb8ecedb85a8b7fcde3a187212 - depends: - - python >=3.12,<3.13.0a0 - - python_abi * *_cp312 - license: Python-2.0 - purls: [] - size: 46463 - timestamp: 1772728929620 -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda - noarch: generic - sha256: 40dc224f2b718e5f034efd2332bc315a719063235f63673468d26a24770094ee - md5: f111d4cfaf1fe9496f386bc98ae94452 - depends: - - python >=3.14,<3.15.0a0 - - python_abi * *_cp314 - license: Python-2.0 - purls: [] - size: 49809 - timestamp: 1775614256655 -- pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl - name: crysfml - version: 0.6.2 - sha256: 4278178f2028360f489f2cdfda7f2f7f26e4f1674b50eb934f403bb443a8f00a - requires_dist: - - numpy - requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/15/1d/9f9e30d76300b0150afaa8b37fab9a0194d44fd4f6b1e5038aca4a1440ed/crysfml-0.6.2-cp312-cp312-macosx_14_0_arm64.whl - name: crysfml - version: 0.6.2 - sha256: 75bba671d2237f6fbbb1284c473543eb143b5bd3ab69f40a2d2cf343dbe0977f - requires_dist: - - numpy - requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/1a/c7/78200c18404ded028758b28b588aa1f4f3acd851271a74156a2a3db9eadf/crysfml-0.6.2-cp312-cp312-win_amd64.whl - name: crysfml - version: 0.6.2 - sha256: cd2027d98252a138bd7260b57f77c8d3c69e0da95454a44a9b80551198e8a327 - requires_dist: - - numpy - requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - name: crysfml - version: 0.6.2 - sha256: 2ca0cb14298c8db170d897e7744007a0e2f29762151ac458a0b38a1a1a9c2967 - requires_dist: - - numpy - requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: crysfml - version: 0.6.2 - sha256: 8274d3c1ac37444d779b7819e752cba03ba3029953fed61479e4537225b3ee99 - requires_dist: - - numpy - requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/97/37/ce5c3ef2595dac2be35039f7b91a0691ef643aa3d954815b3b51e026e0ab/crysfml-0.6.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: crysfml - version: 0.6.2 - sha256: e18ff9ea04b0b823dbc1558afb974bd5b66f3ce13f9e18b25adedfcfde1a59a4 - requires_dist: - - numpy - requires_python: '>=3.11,<3.15' -- pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl - name: cryspy - version: 0.11.0 - sha256: 0b650655a0fbdc3cfcb28826c2ab9fbc5f491e32e1ea9a47d9b75976cd43f26f - requires_dist: - - numpy - - scipy - - pycifstar - - matplotlib -- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl - name: cyclebane - version: 24.10.0 - sha256: 902dd318667e4a222afc270cc5bc72c67d5d6047d2e0e1c36018885fb80f5e5d - requires_dist: - - networkx - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - name: cycler - version: 0.12.1 - sha256: 85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 - requires_dist: - - ipython ; extra == 'docs' - - matplotlib ; extra == 'docs' - - numpydoc ; extra == 'docs' - - sphinx ; extra == 'docs' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-xdist ; extra == 'tests' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl - name: darkdetect - version: 0.8.0 - sha256: a7509ccf517eaad92b31c214f593dbcf138ea8a43b2935406bbd565e15527a85 - requires_dist: - - pyobjc-framework-cocoa ; sys_platform == 'darwin' and extra == 'macos-listener' - requires_python: '>=3.6' -- pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl - name: dask - version: 2026.3.0 - sha256: be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d - requires_dist: - - click>=8.1 - - cloudpickle>=3.0.0 - - fsspec>=2021.9.0 - - packaging>=20.0 - - partd>=1.4.0 - - pyyaml>=5.3.1 - - toolz>=0.12.0 - - importlib-metadata>=4.13.0 ; python_full_version < '3.12' - - numpy>=1.24 ; extra == 'array' - - dask[array] ; extra == 'dataframe' - - pandas>=2.0 ; extra == 'dataframe' - - pyarrow>=16.0 ; extra == 'dataframe' - - 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' - - pyarrow>=16.0 ; extra == 'complete' - - lz4>=4.3.2 ; extra == 'complete' - - pandas[test] ; extra == 'test' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-mock ; extra == 'test' - - pytest-rerunfailures ; extra == 'test' - - pytest-timeout ; extra == 'test' - - pytest-xdist ; extra == 'test' - - pre-commit ; extra == 'test' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py312h8285ef7_0.conda - sha256: f20121b67149ff80bf951ccae7442756586d8789204cd08ade59397b22bfd098 - md5: ee1b48795ceb07311dd3e665dd4f5f33 - depends: - - python - - libgcc >=14 - - libstdcxx >=14 - - __glibc >=2.17,<3.0.a0 - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/debugpy?source=hash-mapping - size: 2858582 - timestamp: 1769744978783 -- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda - sha256: d9e89e351d7189c41615cfceca76b3bcacaa9c81d9945ac1caa6fb9e5184f610 - md5: 57e6fad901c05754d5256fe3ab9f277b - depends: - - python - - libgcc >=14 - - libstdcxx >=14 - - __glibc >=2.17,<3.0.a0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/debugpy?source=hash-mapping - size: 2886804 - timestamp: 1769744977998 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py312h6510ced_0.conda - sha256: f0ca130b5ffd6949673d3c61d7b8562ab76ad8debafb83f8b3443d30c172f5eb - md5: da3b5efcb0caabcede61a6ce4e0a7669 - depends: - - python - - __osx >=11.0 - - python 3.12.* *_cpython - - libcxx >=19 - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/debugpy?source=hash-mapping - size: 2752978 - timestamp: 1769744996462 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda - sha256: 7736a82ebe75c0f3ea6991298363d1f2edb34291f8616c1d3719862881c3a167 - md5: 407c74dc27356ba6bf3a0191070e3ac0 - depends: - - python - - python 3.14.* *_cp314 - - __osx >=11.0 - - libcxx >=19 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/debugpy?source=hash-mapping - size: 2778080 - timestamp: 1769745040206 -- conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py312ha1a9051_0.conda - sha256: 5a886b1af3c66bf58213c7f3d802ea60fe8218313d9072bc1c9e8f7840548ba0 - md5: 032746a0b0663920f0afb18cec61062b - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/debugpy?source=hash-mapping - size: 3996113 - timestamp: 1769745013982 -- conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda - sha256: ece1d8299ad081edaf1e5279f2a900bdedddb2c795ac029a06401543cd7610ad - md5: 48ae8370a4562f7049d587d017792a3a - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/debugpy?source=hash-mapping - size: 4026404 - timestamp: 1769745008861 -- conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - sha256: c17c6b9937c08ad63cb20a26f403a3234088e57d4455600974a0ce865cb14017 - md5: 9ce473d1d1be1cc3810856a48b3fab32 - depends: - - python >=3.9 - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/decorator?source=hash-mapping - size: 14129 - timestamp: 1740385067843 -- conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - sha256: 9717a059677553562a8f38ff07f3b9f61727bd614f505658b0a5ecbcf8df89be - md5: 961b3a227b437d82ad7054484cfa71b2 - depends: - - python >=3.6 - license: PSF-2.0 - license_family: PSF - purls: - - pkg:pypi/defusedxml?source=hash-mapping - size: 24062 - timestamp: 1615232388757 -- pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl - name: dfo-ls - version: 1.6.5 - sha256: d147d42e471e240f9abf8bc38351a88f555ea6a8fcfd83119bbbf93c36f75ab2 - requires_dist: - - setuptools - - numpy - - scipy>=1.11 - - pandas - - pytest ; extra == 'dev' - - sphinx ; extra == 'dev' - - sphinx-rtd-theme ; extra == 'dev' - - trustregion>=1.1 ; extra == 'trustregion' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/01/5c/87b5fefdd3c4b157c8a16833f2236723136806814584c4589610217252f0/diffpy_pdffit2-1.6.0-cp312-cp312-macosx_11_0_arm64.whl - name: diffpy-pdffit2 - version: 1.6.0 - sha256: 4c4418388b9ab4eaeb485a9950a455b3713d21319a98d61e9f69ca5b9a6b45e3 - requires_dist: - - diffpy-structure - requires_python: '>=3.12,<3.15' -- pypi: https://files.pythonhosted.org/packages/04/f1/58c14b37525dc075f3bdf149251f079723049a9f1c82eb48835a0e6b8db3/diffpy_pdffit2-1.6.0-cp314-cp314-macosx_11_0_arm64.whl - name: diffpy-pdffit2 - version: 1.6.0 - sha256: 0e178ff1d40e6b652dedb96b744a2eb04320f58b21012304b29d52167b62afa5 - requires_dist: - - diffpy-structure - requires_python: '>=3.12,<3.15' -- pypi: https://files.pythonhosted.org/packages/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz - name: diffpy-pdffit2 - version: 1.6.0 - sha256: 11a65466f8790f5ac7ae45f2f3fc0d5d116d156d274bcfc079df653123d080e2 - requires_dist: - - diffpy-structure - requires_python: '>=3.12,<3.15' -- pypi: https://files.pythonhosted.org/packages/6f/0c/8297c8d978c919ad6318011631a6123082d5da940da5f8612e75a247d739/diffpy_pdffit2-1.6.0-cp312-cp312-win_amd64.whl - name: diffpy-pdffit2 - version: 1.6.0 - sha256: 6c7865218f78effeeb8374fb62a5aef2b084264da96e77c03160aa411d33c2a0 - requires_dist: - - diffpy-structure - requires_python: '>=3.12,<3.15' -- pypi: https://files.pythonhosted.org/packages/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl - name: diffpy-pdffit2 - version: 1.6.0 - sha256: dc4b5c57c5bcdac4983ff3ec33a960b0f45b3d8d0e20f44347f533861b890c2a - requires_dist: - - diffpy-structure - requires_python: '>=3.12,<3.15' -- pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl - name: diffpy-structure - version: 3.4.0 - sha256: bd0f06a96635d80316f51ebc0a08003bdeb2cb48c9bb18cbed1455ac60645e48 - requires_dist: - - numpy - - pycifrw - - diffpy-utils - requires_python: '>=3.12,<3.15' -- pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl - name: diffpy-utils - version: 3.7.2 - sha256: 6100600736791a8e4638e3dd476704f4dabe3cab75bcb5c60c83c16a2032519a - requires_dist: - - numpy - - xraydb - - scipy - 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 - sha256: 1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d - requires_dist: - - objgraph>=1.7.2 ; extra == 'graph' - - gprof2dot>=2022.7.29 ; extra == 'profile' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl - name: distlib - version: 0.4.0 - sha256: 9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16 -- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl - name: dnspython - version: 2.8.0 - sha256: 01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af - requires_dist: - - black>=25.1.0 ; extra == 'dev' - - coverage>=7.0 ; extra == 'dev' - - flake8>=7 ; extra == 'dev' - - hypercorn>=0.17.0 ; extra == 'dev' - - mypy>=1.17 ; extra == 'dev' - - pylint>=3 ; extra == 'dev' - - pytest-cov>=6.2.0 ; extra == 'dev' - - pytest>=8.4 ; extra == 'dev' - - quart-trio>=0.12.0 ; extra == 'dev' - - sphinx-rtd-theme>=3.0.0 ; extra == 'dev' - - sphinx>=8.2.0 ; extra == 'dev' - - twine>=6.1.0 ; extra == 'dev' - - wheel>=0.45.0 ; extra == 'dev' - - cryptography>=45 ; extra == 'dnssec' - - h2>=4.2.0 ; extra == 'doh' - - httpcore>=1.0.0 ; extra == 'doh' - - httpx>=0.28.0 ; extra == 'doh' - - aioquic>=1.2.0 ; extra == 'doq' - - idna>=3.10 ; extra == 'idna' - - 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/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/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl - name: docstripy - version: 0.7.2 - sha256: c4ba35de6c1b1c51f7afad4a46d8953aad55dce1a490d198f7e98c8c63efefda - requires_dist: - - nbformat - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl - name: dunamai - version: 1.26.1 - sha256: 2727d939c5b4257cb01ea404372803b477f5176e5a347c43beaf89cd5072e853 - requires_dist: - - importlib-metadata>=1.6.0 ; python_full_version < '3.8' - - packaging>=20.9 - requires_python: '>=3.5' -- pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.0-py3-none-any.whl - name: easydiffraction - version: 0.16.0 - sha256: 2691a1e175974ca79e0ec3c219d92b77f277c38fb3b0b8d25f6f7e99696bf70f - requires_dist: - - asciichartpy - - asteval - - bumps - - colorama - - crysfml - - cryspy - - darkdetect - - dfo-ls - - diffpy-pdffit2 - - diffpy-utils - - essdiffraction - - gemmi - - lmfit - - numpy - - pandas - - plotly - - pooch - - py3dmol - - rich - - scipy - - sympy - - tabulate - - typeguard - - typer - - uncertainties - - varname - - build ; extra == 'dev' - - copier ; extra == 'dev' - - docstripy ; 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-benchmark ; 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' - requires_python: '>=3.12' -- pypi: ./ - name: easydiffraction - version: 0.16.0+dev86 - sha256: 0b4085f9386dbebf4b7c5a85d5f98b35d8cf1fc69f791bd0759d20995c534a33 - requires_dist: - - arviz - - asciichartpy - - asteval - - bumps - - colorama - - crysfml - - cryspy - - darkdetect - - dfo-ls - - diffpy-pdffit2 - - diffpy-utils - - gemmi - - lmfit - - numpy - - pandas - - plotly - - pooch - - py3dmol - - rich - - scipy - - sympy - - tabulate - - typeguard - - typer - - uncertainties - - varname - - build ; extra == 'dev' - - copier ; extra == 'dev' - - docstripy ; extra == 'dev' - - essdiffraction ; 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-benchmark ; 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' - requires_python: '>=3.12' -- 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 - sha256: 80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4 - requires_dist: - - dnspython>=2.0.0 - - idna>=2.0.0 - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl - name: essdiffraction - version: 26.5.1 - sha256: 8a6c779078c71be250714619214069221ab7968a69580d4e4d3f4b3e9a1a53ad - requires_dist: - - dask>=2022.1.0 - - essreduce>=26.4.0 - - graphviz - - numpy>=2 - - plopp>=26.2.0 - - pythreejs>=2.4.1 - - sciline>=25.4.1 - - scipp>=25.11.0 - - scippneutron>=26.3.0 - - scippnexus>=23.12.0 - - tof>=25.12.0 - - ncrystal[cif]>=4.1.0 - - spglib!=2.7 - - pandas>=2.1.2 ; extra == 'test' - - pooch>=1.5 ; extra == 'test' - - pytest>=7.0 ; extra == 'test' - - ipywidgets>=8.1.7 ; extra == 'test' - - autodoc-pydantic ; extra == 'docs' - - ipykernel ; extra == 'docs' - - ipympl ; extra == 'docs' - - ipython!=8.7.0 ; extra == 'docs' - - myst-parser ; extra == 'docs' - - nbsphinx ; extra == 'docs' - - pandas ; extra == 'docs' - - pooch ; extra == 'docs' - - pydata-sphinx-theme>=0.14 ; extra == 'docs' - - sphinx ; extra == 'docs' - - sphinx-autodoc-typehints ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-design ; extra == 'docs' - - sphinxcontrib-bibtex ; extra == 'docs' - - pyarrow ; extra == 'docs' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl - name: essreduce - version: 26.4.1 - sha256: 1758a18fffca9c7c2a6fa9547cf87bf45f9d52fc3ccbdffcf7524f71bc060424 - requires_dist: - - sciline>=25.11.0 - - scipp>=26.3.1 - - scippneutron>=25.11.1 - - scippnexus>=25.6.0 - - graphviz>=0.20 ; extra == 'test' - - ipywidgets>=8.1 ; extra == 'test' - - matplotlib>=3.10.7 ; extra == 'test' - - numba>=0.63 ; extra == 'test' - - pooch>=1.9.0 ; extra == 'test' - - pytest>=7.0 ; extra == 'test' - - scipy>=1.14 ; extra == 'test' - - tof>=25.12.0 ; extra == 'test' - - autodoc-pydantic ; extra == 'docs' - - graphviz>=0.20 ; extra == 'docs' - - ipykernel ; extra == 'docs' - - ipython!=8.7.0 ; extra == 'docs' - - ipywidgets>=8.1 ; extra == 'docs' - - myst-parser ; extra == 'docs' - - nbsphinx ; extra == 'docs' - - numba>=0.63 ; extra == 'docs' - - plopp ; extra == 'docs' - - pydata-sphinx-theme>=0.14 ; extra == 'docs' - - sphinx>=7 ; extra == 'docs' - - sphinx-autodoc-typehints ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-design ; extra == 'docs' - - tof>=25.12.0 ; extra == 'docs' - requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 - md5: 8e662bd460bda79b1ea39194e3c4c9ab - depends: - - python >=3.10 - - typing_extensions >=4.6.0 - license: MIT and PSF-2.0 - purls: - - pkg:pypi/exceptiongroup?source=hash-mapping - size: 21333 - timestamp: 1763918099466 -- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl - name: execnet - version: 2.1.2 - sha256: 67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec - requires_dist: - - hatch ; extra == 'testing' - - pre-commit ; extra == 'testing' - - pytest ; extra == 'testing' - - tox ; extra == 'testing' - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - sha256: 210c8165a58fdbf16e626aac93cc4c14dbd551a01d1516be5ecad795d2422cad - md5: ff9efb7f7469aed3c4a8106ffa29593c - depends: - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/executing?source=hash-mapping - size: 30753 - timestamp: 1756729456476 -- pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl - name: filelock - version: 3.29.0 - sha256: 96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: fonttools - version: 4.62.1 - sha256: 8d337fdd49a79b0d51c4da87bc38169d21c3abbf0c1aa9367eff5c6656fb6dae - requires_dist: - - lxml>=4.0 ; extra == 'lxml' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - zopfli>=0.1.4 ; extra == 'woff' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' - - lz4>=1.7.4.2 ; extra == 'graphite' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - pycairo ; extra == 'interpolatable' - - matplotlib ; extra == 'plot' - - sympy ; extra == 'symfont' - - xattr ; sys_platform == 'darwin' and extra == 'type1' - - skia-pathops>=0.5.0 ; extra == 'pathops' - - uharfbuzz>=0.45.0 ; extra == 'repacker' - - lxml>=4.0 ; extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - pycairo ; extra == 'all' - - matplotlib ; extra == 'all' - - sympy ; extra == 'all' - - xattr ; sys_platform == 'darwin' and extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.45.0 ; extra == 'all' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/28/b1/0c2ab56a16f409c6c8a68816e6af707827ad5d629634691ff60a52879792/fonttools-4.62.1-cp312-cp312-win_amd64.whl - name: fonttools - version: 4.62.1 - sha256: 9e7863e10b3de72376280b515d35b14f5eeed639d1aa7824f4cf06779ec65e42 - requires_dist: - - lxml>=4.0 ; extra == 'lxml' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - zopfli>=0.1.4 ; extra == 'woff' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' - - lz4>=1.7.4.2 ; extra == 'graphite' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - pycairo ; extra == 'interpolatable' - - matplotlib ; extra == 'plot' - - sympy ; extra == 'symfont' - - xattr ; sys_platform == 'darwin' and extra == 'type1' - - skia-pathops>=0.5.0 ; extra == 'pathops' - - uharfbuzz>=0.45.0 ; extra == 'repacker' - - lxml>=4.0 ; extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - pycairo ; extra == 'all' - - matplotlib ; extra == 'all' - - sympy ; extra == 'all' - - xattr ; sys_platform == 'darwin' and extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.45.0 ; extra == 'all' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl - name: fonttools - version: 4.62.1 - sha256: fa1d16210b6b10a826d71bed68dd9ec24a9e218d5a5e2797f37c573e7ec215ca - requires_dist: - - lxml>=4.0 ; extra == 'lxml' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - zopfli>=0.1.4 ; extra == 'woff' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' - - lz4>=1.7.4.2 ; extra == 'graphite' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - pycairo ; extra == 'interpolatable' - - matplotlib ; extra == 'plot' - - sympy ; extra == 'symfont' - - xattr ; sys_platform == 'darwin' and extra == 'type1' - - skia-pathops>=0.5.0 ; extra == 'pathops' - - uharfbuzz>=0.45.0 ; extra == 'repacker' - - lxml>=4.0 ; extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - pycairo ; extra == 'all' - - matplotlib ; extra == 'all' - - sympy ; extra == 'all' - - xattr ; sys_platform == 'darwin' and extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.45.0 ; extra == 'all' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/47/d4/dbacced3953544b9a93088cc10ef2b596d348c983d5c67a404fa41ec51ba/fonttools-4.62.1-cp312-cp312-macosx_10_13_universal2.whl - name: fonttools - version: 4.62.1 - sha256: 90365821debbd7db678809c7491ca4acd1e0779b9624cdc6ddaf1f31992bf974 - requires_dist: - - lxml>=4.0 ; extra == 'lxml' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - zopfli>=0.1.4 ; extra == 'woff' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' - - lz4>=1.7.4.2 ; extra == 'graphite' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - pycairo ; extra == 'interpolatable' - - matplotlib ; extra == 'plot' - - sympy ; extra == 'symfont' - - xattr ; sys_platform == 'darwin' and extra == 'type1' - - skia-pathops>=0.5.0 ; extra == 'pathops' - - uharfbuzz>=0.45.0 ; extra == 'repacker' - - lxml>=4.0 ; extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - pycairo ; extra == 'all' - - matplotlib ; extra == 'all' - - sympy ; extra == 'all' - - xattr ; sys_platform == 'darwin' and extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.45.0 ; extra == 'all' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-win_amd64.whl - name: fonttools - version: 4.62.1 - sha256: 1eecc128c86c552fb963fe846ca4e011b1be053728f798185a1687502f6d398e - requires_dist: - - lxml>=4.0 ; extra == 'lxml' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - zopfli>=0.1.4 ; extra == 'woff' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' - - lz4>=1.7.4.2 ; extra == 'graphite' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - pycairo ; extra == 'interpolatable' - - matplotlib ; extra == 'plot' - - sympy ; extra == 'symfont' - - xattr ; sys_platform == 'darwin' and extra == 'type1' - - skia-pathops>=0.5.0 ; extra == 'pathops' - - uharfbuzz>=0.45.0 ; extra == 'repacker' - - lxml>=4.0 ; extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - pycairo ; extra == 'all' - - matplotlib ; extra == 'all' - - sympy ; extra == 'all' - - xattr ; sys_platform == 'darwin' and extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.45.0 ; extra == 'all' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/9b/8a/99c8b3c3888c5c474c08dbfd7c8899786de9604b727fcefb055b42c84bba/fonttools-4.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: fonttools - version: 4.62.1 - sha256: 149f7d84afca659d1a97e39a4778794a2f83bf344c5ee5134e09995086cc2392 - requires_dist: - - lxml>=4.0 ; extra == 'lxml' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - zopfli>=0.1.4 ; extra == 'woff' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' - - lz4>=1.7.4.2 ; extra == 'graphite' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - pycairo ; extra == 'interpolatable' - - matplotlib ; extra == 'plot' - - sympy ; extra == 'symfont' - - xattr ; sys_platform == 'darwin' and extra == 'type1' - - skia-pathops>=0.5.0 ; extra == 'pathops' - - uharfbuzz>=0.45.0 ; extra == 'repacker' - - lxml>=4.0 ; extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' - - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - pycairo ; extra == 'all' - - matplotlib ; extra == 'all' - - sympy ; extra == 'all' - - xattr ; sys_platform == 'darwin' and extra == 'all' - - 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' -- conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - sha256: 2509992ec2fd38ab27c7cdb42cf6cadc566a1cc0d1021a2673475d9fa87c6276 - md5: d3549fd50d450b6d9e7dddff25dd2110 - depends: - - cached-property >=1.3.0 - - python >=3.9,<4 - license: MPL-2.0 - license_family: MOZILLA - purls: - - pkg:pypi/fqdn?source=hash-mapping - size: 16705 - timestamp: 1733327494780 -- pypi: https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl - name: frozenlist - version: 1.8.0 - sha256: f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl - name: frozenlist - version: 1.8.0 - sha256: 3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - name: frozenlist - version: 1.8.0 - sha256: 494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl - name: frozenlist - version: 1.8.0 - sha256: 4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - name: frozenlist - version: 1.8.0 - sha256: cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl - name: frozenlist - version: 1.8.0 - sha256: 34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl - name: fsspec - version: 2026.4.0 - sha256: 11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2 - requires_dist: - - adlfs ; extra == 'abfs' - - adlfs ; extra == 'adl' - - pyarrow>=1 ; extra == 'arrow' - - dask ; extra == 'dask' - - distributed ; extra == 'dask' - - pre-commit ; extra == 'dev' - - ruff>=0.5 ; extra == 'dev' - - numpydoc ; extra == 'doc' - - sphinx ; extra == 'doc' - - sphinx-design ; extra == 'doc' - - sphinx-rtd-theme ; extra == 'doc' - - yarl ; extra == 'doc' - - dropbox ; extra == 'dropbox' - - dropboxdrivefs ; extra == 'dropbox' - - requests ; extra == 'dropbox' - - adlfs ; extra == 'full' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' - - dask ; extra == 'full' - - distributed ; extra == 'full' - - dropbox ; extra == 'full' - - dropboxdrivefs ; extra == 'full' - - fusepy ; extra == 'full' - - gcsfs>2024.2.0 ; extra == 'full' - - libarchive-c ; extra == 'full' - - ocifs ; extra == 'full' - - panel ; extra == 'full' - - paramiko ; extra == 'full' - - pyarrow>=1 ; extra == 'full' - - pygit2 ; extra == 'full' - - requests ; extra == 'full' - - s3fs>2024.2.0 ; extra == 'full' - - smbprotocol ; extra == 'full' - - tqdm ; extra == 'full' - - fusepy ; extra == 'fuse' - - gcsfs>2024.2.0 ; extra == 'gcs' - - pygit2 ; extra == 'git' - - requests ; extra == 'github' - - gcsfs ; extra == 'gs' - - panel ; extra == 'gui' - - pyarrow>=1 ; extra == 'hdfs' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' - - libarchive-c ; extra == 'libarchive' - - ocifs ; extra == 'oci' - - s3fs>2024.2.0 ; extra == 's3' - - paramiko ; extra == 'sftp' - - smbprotocol ; extra == 'smb' - - paramiko ; extra == 'ssh' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test' - - numpy ; extra == 'test' - - pytest ; extra == 'test' - - pytest-asyncio!=0.22.0 ; extra == 'test' - - pytest-benchmark ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-mock ; extra == 'test' - - pytest-recording ; extra == 'test' - - pytest-rerunfailures ; extra == 'test' - - requests ; extra == 'test' - - aiobotocore>=2.5.4,<3.0.0 ; extra == 'test-downstream' - - dask[dataframe,test] ; extra == 'test-downstream' - - moto[server]>4,<5 ; extra == 'test-downstream' - - pytest-timeout ; extra == 'test-downstream' - - xarray ; extra == 'test-downstream' - - adlfs ; extra == 'test-full' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test-full' - - backports-zstd ; python_full_version < '3.14' and extra == 'test-full' - - cloudpickle ; extra == 'test-full' - - dask ; extra == 'test-full' - - distributed ; extra == 'test-full' - - dropbox ; extra == 'test-full' - - dropboxdrivefs ; extra == 'test-full' - - fastparquet ; extra == 'test-full' - - fusepy ; extra == 'test-full' - - gcsfs ; extra == 'test-full' - - jinja2 ; extra == 'test-full' - - kerchunk ; extra == 'test-full' - - libarchive-c ; extra == 'test-full' - - lz4 ; extra == 'test-full' - - notebook ; extra == 'test-full' - - numpy ; extra == 'test-full' - - ocifs ; extra == 'test-full' - - pandas<3.0.0 ; extra == 'test-full' - - panel ; extra == 'test-full' - - paramiko ; extra == 'test-full' - - pyarrow ; extra == 'test-full' - - pyarrow>=1 ; extra == 'test-full' - - pyftpdlib ; extra == 'test-full' - - pygit2 ; extra == 'test-full' - - pytest ; extra == 'test-full' - - pytest-asyncio!=0.22.0 ; extra == 'test-full' - - pytest-benchmark ; extra == 'test-full' - - pytest-cov ; extra == 'test-full' - - pytest-mock ; extra == 'test-full' - - pytest-recording ; extra == 'test-full' - - pytest-rerunfailures ; extra == 'test-full' - - python-snappy ; extra == 'test-full' - - requests ; extra == 'test-full' - - smbprotocol ; extra == 'test-full' - - tqdm ; extra == 'test-full' - - urllib3 ; extra == 'test-full' - - zarr ; extra == 'test-full' - - 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/06/41/4e70dea1d0311016c0b0b1c53a24a266f9f8a34c6bc1af0f17cfca20aa1d/gemmi-0.7.5-cp314-cp314-macosx_11_0_arm64.whl - name: gemmi - version: 0.7.5 - sha256: 5144f107f2bca479d1b8266a79649bd631ee92c5b1319b27b0279157331ebc89 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/b0/3e/a6497e1c2c9bc6ed2b79e0f2d31a4ce509fd2a9eed4e4f7ac63eda8113cb/gemmi-0.7.5-cp312-cp312-macosx_11_0_arm64.whl - name: gemmi - version: 0.7.5 - sha256: 5682920985109c6a08616ae9aae080f8b46a9714534dc864b535e3e6d203d5b8 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: gemmi - version: 0.7.5 - sha256: bdc67ad4a7fc420974ab3102f7f6ad1517fa0c3d9f2f7561e42e5f7017635242 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/e8/88/5a431cd1ea7587408a66947384b39beb2ab2bcc1c87b7c4082f05036719f/gemmi-0.7.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: gemmi - version: 0.7.5 - sha256: 217bb9ac9da7c90704026dacfc0a0652a38f4df1e318225d8f35c75f1f8c7ebf - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/eb/f2/53be7a4ba5816e13c39be0f728facac4bcb39cf4903ceeec54b006511c8f/gemmi-0.7.5-cp312-cp312-win_amd64.whl - name: gemmi - version: 0.7.5 - sha256: a1fdb6f72006495b5119e3a8bb5c3185efa708b785bd4a5ce4397ef7abb3fec7 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-win_amd64.whl - name: gemmi - version: 0.7.5 - sha256: 419c36d9ea0f28dda0ff0d6db17035170d0888ca78aff82a0f9f604613aec58f - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl - name: ghp-import - version: 2.1.0 - sha256: 8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 - requires_dist: - - python-dateutil>=2.8.1 - - twine ; extra == 'dev' - - 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/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl - name: gitpython - version: 3.1.50 - sha256: d352abe2908d07355014abdd21ddf798c2a961469239afec4962e9da884858f9 - 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.4.7,<8 ; 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' - sha256: 54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42 - requires_dist: - - build ; extra == 'dev' - - wheel ; extra == 'dev' - - twine ; extra == 'dev' - - flake8 ; extra == 'dev' - - flake8-pyproject ; extra == 'dev' - - pep8-naming ; extra == 'dev' - - tox>=3 ; extra == 'dev' - - pytest>=7,<8.1 ; extra == 'test' - - pytest-mock>=3 ; extra == 'test' - - pytest-cov ; extra == 'test' - - coverage ; extra == 'test' - - sphinx>=5,<7 ; extra == 'docs' - - sphinx-autodoc-typehints ; extra == 'docs' - - sphinx-rtd-theme>=0.2.5 ; extra == 'docs' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/2b/e0/2e13df68f367e2f9960616927d60857dd7e56aaadd59a47c644216b2f920/greenlet-3.5.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - name: greenlet - version: 3.5.0 - sha256: 9d280a7f5c331622c69f97eb167f33577ff2d1df282c41cd15907fc0a3ca198c - requires_dist: - - sphinx ; extra == 'docs' - - furo ; extra == 'docs' - - objgraph ; extra == 'test' - - psutil ; extra == 'test' - - setuptools ; extra == 'test' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/4c/fe/4fb3a0805bd5165da5ebf858da7cc01cce8061674106d2cf5bdab32cbfde/greenlet-3.5.0-cp312-cp312-win_amd64.whl - name: greenlet - version: 3.5.0 - sha256: d4d9f0624c775f2dfc56ba54d515a8c771044346852a918b405914f6b19d7fd8 - requires_dist: - - sphinx ; extra == 'docs' - - furo ; extra == 'docs' - - objgraph ; extra == 'test' - - psutil ; extra == 'test' - - setuptools ; extra == 'test' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/91/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl - name: greenlet - version: 3.5.0 - sha256: 3bc59be3945ae9750b9e7d45067d01ae3fe90ea5f9ade99239dabdd6e28a5033 - requires_dist: - - sphinx ; extra == 'docs' - - furo ; extra == 'docs' - - objgraph ; extra == 'test' - - psutil ; extra == 'test' - - setuptools ; extra == 'test' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - name: greenlet - version: 3.5.0 - sha256: 8f52a464e4ed91780bdfbbdd2b97197f3accaa629b98c200f4dffada759f3ae7 - requires_dist: - - sphinx ; extra == 'docs' - - furo ; extra == 'docs' - - objgraph ; extra == 'test' - - psutil ; extra == 'test' - - setuptools ; extra == 'test' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl - name: griffelib - version: 2.0.2 - sha256: 925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1 - requires_dist: - - pip>=24.0 ; extra == 'pypi' - - platformdirs>=4.2 ; extra == 'pypi' - - wheel>=0.42 ; extra == 'pypi' - requires_python: '>=3.10' + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-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/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_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/markupsafe-3.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-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/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-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/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-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/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-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/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-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/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-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/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.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/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-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/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-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/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.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/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.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/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-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/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.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/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-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/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-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/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.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/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.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/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-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/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-win_amd64.whl +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28948 + timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda + sha256: 7988c207b2b766dad5ebabf25a92b8d75cb8faed92f256fd7a4e0875c9ec6d58 + md5: 1567f06d717246abab170736af8bad1b + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.0.1 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 35646 + timestamp: 1762509443854 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda + sha256: 39234a99df3d2e3065383808ed8bfda36760de5ef590c54c3692bb53571ef02b + md5: 3cca1b74b2752917b5b65b81f61f0553 + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=2.0.0b1 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 35598 + timestamp: 1762509505285 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.4.0-py312h90b7ffd_0.conda + sha256: e8c83696e6529ac1909a96690c58624bb376312fd0768409380cd9b05e248c9b + md5: 542da724e75cdeef19e29cca23935c25 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 238360 + timestamp: 1777848717715 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda + sha256: 49df13a1bb5e388ca0e4e87022260f9501ed4192656d23dc9d9a1b4bf3787918 + md5: 64088dffd7413a2dd557ce837b4cbbdb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 368300 + timestamp: 1764017300621 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda + sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 + md5: 8910d2c46f7e7b519129f486e0fe927a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 367376 + timestamp: 1764017265553 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 + md5: d2ffd7602c02f2b316fd921d39876885 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 260182 + timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + sha256: cc9accf72fa028d31c2a038460787751127317dcfa991f8d1f1babf216bb454e + md5: 920bb03579f15389b9e512095ad995b7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 207882 + timestamp: 1765214722852 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda + sha256: 7dafe8173d5f94e46cf9cd597cc8ff476a8357fbbd4433a8b5697b2864845d9c + md5: 648ee28dcd4e07a1940a17da62eccd40 + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 295716 + timestamp: 1761202958833 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + sha256: c6339858a0aaf5d939e00d345c98b99e4558f285942b27232ac098ad17ac7f8e + md5: cf45f4278afd6f4e6d03eda0f435d527 + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 300271 + timestamp: 1761203085220 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py312h8285ef7_0.conda + sha256: f20121b67149ff80bf951ccae7442756586d8789204cd08ade59397b22bfd098 + md5: ee1b48795ceb07311dd3e665dd4f5f33 + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2858582 + timestamp: 1769744978783 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda + sha256: d9e89e351d7189c41615cfceca76b3bcacaa9c81d9945ac1caa6fb9e5184f610 + md5: 57e6fad901c05754d5256fe3ab9f277b + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2886804 + timestamp: 1769744977998 - conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda sha256: f923af07c3a3db746d3be8efebdaa9c819a6007ee3cc12445cee059641611e05 md5: 04e128d2adafe3c844cde58f103c481b depends: - - __glibc >=2.17,<3.0.a0 - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libgcc >=13 - license: GPL-3.0-or-later - license_family: GPL - purls: [] - size: 2486744 - timestamp: 1737621160295 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda - sha256: f11d8f2007f6591022afa958d8fe15afbe4211198d1603c0eb886bc21a9eb19e - md5: cc261442bead590d89ca9f96884a344f + - __glibc >=2.17,<3.0.a0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc >=13 + license: GPL-3.0-or-later + license_family: GPL + purls: [] + size: 2486744 + timestamp: 1737621160295 +- 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 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12723451 + timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 + md5: b38117a3c920364aff79f870c984b4a3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-or-later + purls: [] + size: 134088 + timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 + md5: fb53fb07ce46a575c5d004bbc96032c2 + depends: + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1386730 + timestamp: 1769769569681 +- 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 + constrains: + - binutils_impl_linux-64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 728002 + timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + sha256: a7a4481a4d217a3eadea0ec489826a69070fcc3153f00443aa491ed21527d239 + md5: 6f7b4302263347698fd24565fbf11310 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + constrains: + - libabseil-static =20260107.1=cxx17* + - abseil-cpp =20260107.1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 1384817 + timestamp: 1770863194876 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda + build_number: 7 + sha256: 081c850f99bc355821fac9c6e3727d40b3f8ce3beb50a5437cf03726b611ff39 + md5: 955b44e8b00b7f7ef4ce0130cef12394 + depends: + - libopenblas >=0.3.33,<0.3.34.0a0 + - libopenblas >=0.3.33,<1.0a0 + constrains: + - libcblas 3.11.0 7*_openblas + - blas 2.307 openblas + - liblapack 3.11.0 7*_openblas + - liblapacke 3.11.0 7*_openblas + - mkl <2027 + license: BSD-3-Clause + purls: [] + size: 18716 + timestamp: 1778489854108 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda + sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e + md5: 72c8fd1af66bd67bf580645b426513ed + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 79965 + timestamp: 1764017188531 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda + sha256: 12fff21d38f98bc446d82baa890e01fd82e3b750378fedc720ff93522ffb752b + md5: 366b40a69f0ad6072561c1d09301c886 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 hb03c661_1 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 34632 + timestamp: 1764017199083 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda + sha256: a0c15c79997820bbd3fbc8ecf146f4fe0eca36cc60b62b63ac6cf78857f1dd0d + md5: 4ffbb341c8b616aa2494b6afb26a0c5f + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 hb03c661_1 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 298378 + timestamp: 1764017210931 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda + build_number: 7 + sha256: 956ae0bb1ec8b0c3663d75b151aceb0521b54e513bf97f621a035f9c87037970 + md5: 0675639dc24cb0032f199e7ff68e4633 + depends: + - libblas 3.11.0 7_h4a7cf45_openblas + constrains: + - liblapacke 3.11.0 7*_openblas + - blas 2.307 openblas + - liblapack 3.11.0 7*_openblas + license: BSD-3-Clause + purls: [] + size: 18675 + timestamp: 1778489861559 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 + md5: c277e0a4d549b03ac1e9d6cbbe3d017b + depends: + - ncurses + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 134676 + timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 + md5: 172bf1cd1ff8629f2b1179945ed45055 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 112766 + timestamp: 1702146165126 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda + sha256: ea33c40977ea7a2c3658c522230058395bc2ee0d89d99f0711390b6a1ee80d12 + md5: a3b390520c563d78cc58974de95a03e5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.8.0.* + license: MIT + license_family: MIT + purls: [] + size: 77241 + timestamp: 1777846112704 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda + sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 + md5: 57736f29cc2b0ec0b6c2952d3f101b6a + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.2.0=*_19 + - libgomp 15.2.0 he0feb66_19 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1041084 + timestamp: 1778269013026 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda + sha256: 9dcf54adfaa5e861123c2da4f2f0451a685464ea7e5a41ad91cf67b31d658d98 + md5: 331ee9b72b9dff570d56b1302c5ab37d + depends: + - libgcc 15.2.0 he0feb66_19 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27694 + timestamp: 1778269016987 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda + sha256: 561a42758ef25b9ce308c4e2cf56daee4f06138385a17e29a492cd928e00be6f + md5: 42bf7eca1a951735fa06c0e3c0d5c8e6 + depends: + - libgfortran5 15.2.0 h68bc16d_19 + constrains: + - libgfortran-ng ==15.2.0=*_19 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27655 + timestamp: 1778269042954 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda + sha256: 057978bb69fea29ed715a9b98adf71015c31baecc4aeb2bfc20d4fd5d83579d4 + md5: 85072b0ad177c966294f129b7c04a2d5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15.2.0 + constrains: + - libgfortran 15.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 2483673 + timestamp: 1778269025089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b + md5: faac990cb7aedc7f3a2224f2c9b0c26c + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 603817 + timestamp: 1778268942614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d + md5: b88d90cad08e6bc8ad540cb310a761fb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + size: 113478 + timestamp: 1775825492909 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 + md5: 2c21e66f50753a083cbe6b80f38268fa + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 92400 + timestamp: 1769482286018 +- 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.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.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 663344 + timestamp: 1773854035739 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 33731 + timestamp: 1750274110928 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda + sha256: 3d9aa85648e5e18a6d66db98b8c4317cc426721ad7a220aa86330d1ccedc8903 + md5: 2d3278b721e40468295ca755c3b84070 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + constrains: + - openblas >=0.3.33,<0.3.34.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 5931919 + timestamp: 1776993658641 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + sha256: 64e5c80cbce4680a2d25179949739a6def695d72c40ca28f010711764e372d97 + md5: 7af961ef4aa2c1136e11dd43ded245ab + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: ISC + purls: [] + size: 277661 + timestamp: 1772479381288 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda + sha256: 54cdcd3214313b62c2a8ee277e6f42150d9b748264c1b70d958bf735e420ef8d + md5: 7dc38adcbf71e6b38748e919e16e0dce + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + size: 954962 + timestamp: 1777986471789 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc + md5: 5794b3bdc38177caf969dabd3af08549 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 he0feb66_19 + constrains: + - libstdcxx-ng ==15.2.0=*_19 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 5852044 + timestamp: 1778269036376 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 + md5: 38ffe67b78c9d4de527be8315e5ada2c + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 40297 + timestamp: 1775052476770 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + sha256: c180f4124a889ac343fc59d15558e93667d894a966ec6fdb61da1604481be26b + md5: 0f03292cc56bf91a077a134ea8747118 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 895108 + timestamp: 1753948278280 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 100393 + timestamp: 1702724383534 +- 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 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 63629 + timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda + sha256: 5f3aad1f3a685ed0b591faad335957dbdb1b73abfd6fc731a0d42718e0653b33 + md5: 93a4752d42b12943a355b682ee43285b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 26057 + timestamp: 1772445297924 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf + md5: 9a17c4307d23318476d7fbf0fedc0cde + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 27424 + timestamp: 1772445227915 +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py312h4c3975b_0.conda + sha256: 25eb262c378a922eeed85c941ab7de2687ea842daed80521b861b7472b5a7f9a + md5: 5e07dc45b4458c19fdc085bd6c1aa51f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 218330 + timestamp: 1776337395109 +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda + sha256: 52565ceea81e801c59dcaeaf5a9c77fba2fade445e67e0864fda50d4b944e15b + md5: 4a8ea416a56e58f012e445f7af2bbcc8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 220990 + timestamp: 1776337508167 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 + md5: fc21868a1a5aacc937e7a18747acb8a5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: X11 AND BSD-3-Clause + purls: [] + size: 918956 + timestamp: 1777422145199 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda + sha256: d1a673d1418d9e956b6e4e46c23e72a511c5c1d45dc5519c947457427036d5e2 + md5: baffb1570b3918c784d4490babc52fbf + depends: + - libgcc >=14 + - 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 + license: MIT + license_family: MIT + purls: [] + size: 18829340 + timestamp: 1774514313036 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb + md5: da1b85b6a87e141f5140bb9924cecab0 + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3167099 + timestamp: 1775587756857 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda + sha256: d834fd656133c9e4eaf63ffe9a117c7d0917d86d89f7d64073f4e3a0020bd8a7 + md5: dd94c506b119130aef5a9382aed648e7 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 225545 + timestamp: 1769678155334 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda + sha256: f15574ed6c8c8ed8c15a0c5a00102b1efe8b867c0bd286b498cd98d95bd69ae5 + md5: 4f225a966cfee267a79c5cb6382bd121 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 231303 + timestamp: 1769678156552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + sha256: a44655c1c3e1d43ed8704890a91e12afd68130414ea2c0872e154e5633a13d7e + md5: 7eccb41177e15cc672e1babe9056018e + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 31608571 + timestamp: 1772730708989 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda + build_number: 100 + sha256: dec247c5badc811baa34d6085df9d0465535883cf745e22e8d79092ad54a3a7b + md5: a443f87920815d41bfe611296e507995 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.5,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.52.0,<4.0a0 + - libuuid >=2.42,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.6,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + size: 36705460 + timestamp: 1775614357822 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda + sha256: cb142bfd92f6e55749365ddc244294fa7b64db6d08c45b018ff1c658907bfcbf + md5: 15878599a87992e44c059731771591cb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 198293 + timestamp: 1770223620706 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d + md5: 2035f68f96be30dc60a5dfd7452c7941 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 202391 + timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + noarch: python + sha256: be66c1f85c3b48137200d62c12d918f4f8ad329423daef04fed292818efd3c28 + md5: 082985717303dab433c976986c674b35 + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - zeromq >=4.3.5,<4.4.0a0 + - _python_abi3_support 1.* + - cpython >=3.12 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 211567 + timestamp: 1771716961404 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py312h868fb18_0.conda + sha256: 62f46e85caaba30b459da7dfcf3e5488ca24fd11675c33ce4367163ab191a42c + md5: 3ffc5a3572db8751c2f15bacf6a0e937 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.12.* *_cp312 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 383750 + timestamp: 1764543174231 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda + sha256: e53b0cbf3b324eaa03ca1fe1a688fdf4ab42cea9c25270b0a7307d8aaaa4f446 + md5: c1c368b5437b0d1a68f372ccf01cb133 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 376121 + timestamp: 1764543122774 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3301196 + timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda + sha256: 4629b1c9139858fb08bb357df917ffc12e4d284c57ff389806bb3ae476ef4e0a + md5: 2b37798adbc54fd9e591d24679d2133a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 859665 + timestamp: 1774358032165 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda + sha256: ed8d06093ff530a2dae9ed1e51eb6f908fbfd171e8b62f4eae782d67b420be5a + md5: dc1ff1e915ab35a06b6fa61efae73ab5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 912476 + timestamp: 1774358032579 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad + md5: a77f85f77be52ff59391544bfe73390a + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + purls: [] + size: 85189 + timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + sha256: 325d370b28e2b9cc1f765c5b4cdb394c91a5d958fbd15da1a14607a28fee09f6 + md5: 755b096086851e1193f3b10347415d7c + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 311150 + timestamp: 1772476812121 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 601375 + timestamp: 1764777111296 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 + md5: aaa2a381ccc56eac91d63b6c1240312f + depends: + - cpython + - python-gil + license: MIT + license_family: MIT + purls: [] + size: 8191 + timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + sha256: f09aed24661cd45ba54a43772504f05c0698248734f9ae8cd289d314ac89707e + md5: af2df4b9108808da3dc76710fe50eae2 + depends: + - exceptiongroup >=1.0.2 + - idna >=2.8 + - python >=3.10 + - typing_extensions >=4.5 + - python + constrains: + - trio >=0.32.0 + - uvloop >=0.22.1 + - winloop >=0.2.3 + license: MIT + license_family: MIT + purls: + - pkg:pypi/anyio?source=hash-mapping + size: 146764 + timestamp: 1774359453364 +- conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda + sha256: 8f032b140ea4159806e4969a68b4a3c0a7cab1ad936eb958a2b5ffe5335e19bf + md5: 54898d0f524c9dee622d44bbb081a8ab + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/appnope?source=hash-mapping + size: 10076 + timestamp: 1733332433806 +- conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + sha256: bea62005badcb98b1ae1796ec5d70ea0fc9539e7d59708ac4e7d41e2f4bb0bad + md5: 8ac12aff0860280ee0cff7fa2cf63f3b + depends: + - argon2-cffi-bindings + - python >=3.9 + - typing-extensions + constrains: + - argon2_cffi ==999 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi?source=hash-mapping + size: 18715 + timestamp: 1749017288144 +- conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + sha256: 792da8131b1b53ff667bd6fc617ea9087b570305ccb9913deb36b8e12b3b5141 + md5: 85c4f19f377424eafc4ed7911b291642 + depends: + - python >=3.10 + - python-dateutil >=2.7.0 + - python-tzdata + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/arrow?source=hash-mapping + size: 113854 + timestamp: 1760831179410 +- conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + sha256: ee4da0f3fe9d59439798ee399ef3e482791e48784873d546e706d0935f9ff010 + md5: 9673a61a297b00016442e022d689faa6 + depends: + - python >=3.10 + constrains: + - astroid >=2,<5 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/asttokens?source=hash-mapping + size: 28797 + timestamp: 1763410017955 +- conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + sha256: ea8486637cfb89dc26dc9559921640cd1d5fd37e5e02c33d85c94572139f2efe + md5: b85e84cb64c762569cc1a760c2327e0a + depends: + - python >=3.10 + - typing_extensions >=4.0.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/async-lru?source=hash-mapping + size: 22949 + timestamp: 1773926359134 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab + md5: c6b0543676ecb1fb2d7643941fe375f2 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/attrs?source=hash-mapping + size: 64927 + timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + sha256: a14a9ad02101aab25570543a59c5193043b73dc311a25650134ed9e6cb691770 + md5: f1976ce927373500cc19d3c0b2c85177 + depends: + - python >=3.10 + - python + constrains: + - pytz >=2015.7 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/babel?source=hash-mapping + size: 7684321 + timestamp: 1772555330347 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + noarch: generic + sha256: de1755a35258eb1b59f2288559bbf0b76da60bd2fa6cd6f768ead442f85bd666 + md5: b712198b257f378e9bd8cde277218296 + depends: + - python >=3.14 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: [] + size: 7546 + timestamp: 1777848733980 +- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + sha256: bf1e71c3c0a5b024e44ff928225a0874fc3c3356ec1a0b6fe719108e6d1288f6 + md5: 5267bef8efea4127aacd1f4e1f149b6e + depends: + - python >=3.10 + - soupsieve >=1.2 + - typing-extensions + license: MIT + license_family: MIT + purls: + - pkg:pypi/beautifulsoup4?source=hash-mapping + size: 90399 + timestamp: 1764520638652 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + sha256: f8ff1f98423674278964a46c93a1766f9e91960d44efd91c6c3ed56a33813f46 + md5: 7c5ebdc286220e8021bf55e6384acd67 + depends: + - python >=3.10 + - webencodings + - python + constrains: + - tinycss2 >=1.1.0,<1.5 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/bleach?source=hash-mapping + size: 142008 + timestamp: 1770719370680 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + sha256: 7c07a865e5e4cca233cc4e0eb3f0f5ff6c90776461687b4fb0b1764133e1fd61 + md5: f11a319b9700b203aa14c295858782b6 + depends: + - bleach ==6.3.0 pyhcf101f3_1 + - tinycss2 + license: Apache-2.0 AND MIT + purls: [] + size: 4409 + timestamp: 1770719370682 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-h4c7d964_0.conda + sha256: 6f4ff81534c19e76acf52fcabf4a258088a932b8f1ac56e9a59e98f6051f8e46 + md5: 56fb2c6c73efc627b40c77d14caecfba + depends: + - __win + license: ISC + purls: [] + size: 131388 + timestamp: 1776865633471 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + sha256: c9dbcc8039a52023660d6d1bbf87594a93dd69c6ac5a2a44323af2c92976728d + md5: e18ad67cf881dcadee8b8d9e2f8e5f73 + depends: + - __unix + license: ISC + purls: [] + size: 131039 + timestamp: 1776865545798 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + noarch: python + sha256: 561e6660f26c35d137ee150187d89767c988413c978e1b712d53f27ddf70ea17 + md5: 9b347a7ec10940d3f7941ff6c460b551 + depends: + - cached_property >=1.5.2,<1.5.3.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 4134 + timestamp: 1615209571450 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + sha256: 6dbf7a5070cc43d90a1e4c2ec0c541c69d8e30a0e25f50ce9f6e4a432e42c5d7 + md5: 576d629e47797577ab0f1b351297ef4a + depends: + - python >=3.6 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/cached-property?source=hash-mapping + size: 11065 + timestamp: 1615209567874 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + sha256: 989db6e5957c4b44fa600c68c681ec2f36a55e48f7c7f1c073d5e91caa8cd878 + md5: 929471569c93acefb30282a22060dcd5 + depends: + - python >=3.10 + license: ISC + purls: + - pkg:pypi/certifi?source=hash-mapping + size: 135656 + timestamp: 1776866680878 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 + md5: a9167b9571f3baa9d448faa2139d1089 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/charset-normalizer?source=hash-mapping + size: 58872 + timestamp: 1775127203018 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama?source=hash-mapping + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + sha256: 576a44729314ad9e4e5ebe055fbf48beb8116b60e58f9070278985b2b634f212 + md5: 2da13f2b299d8e1995bafbbe9689a2f7 + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/comm?source=hash-mapping + size: 14690 + timestamp: 1753453984907 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + noarch: generic + sha256: d3e9bbd7340199527f28bbacf947702368f31de60c433a16446767d3c6aaf6fe + md5: f54c1ffb8ecedb85a8b7fcde3a187212 + depends: + - python >=3.12,<3.13.0a0 + - python_abi * *_cp312 + license: Python-2.0 + purls: [] + size: 46463 + timestamp: 1772728929620 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + noarch: generic + sha256: 40dc224f2b718e5f034efd2332bc315a719063235f63673468d26a24770094ee + md5: f111d4cfaf1fe9496f386bc98ae94452 + depends: + - python >=3.14,<3.15.0a0 + - python_abi * *_cp314 + license: Python-2.0 + purls: [] + size: 49809 + timestamp: 1775614256655 +- conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + sha256: c17c6b9937c08ad63cb20a26f403a3234088e57d4455600974a0ce865cb14017 + md5: 9ce473d1d1be1cc3810856a48b3fab32 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/decorator?source=hash-mapping + size: 14129 + timestamp: 1740385067843 +- conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + sha256: 9717a059677553562a8f38ff07f3b9f61727bd614f505658b0a5ecbcf8df89be + md5: 961b3a227b437d82ad7054484cfa71b2 + depends: + - python >=3.6 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/defusedxml?source=hash-mapping + size: 24062 + timestamp: 1615232388757 +- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 + md5: 8e662bd460bda79b1ea39194e3c4c9ab + depends: + - python >=3.10 + - typing_extensions >=4.6.0 + license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup?source=hash-mapping + size: 21333 + timestamp: 1763918099466 +- conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + sha256: 210c8165a58fdbf16e626aac93cc4c14dbd551a01d1516be5ecad795d2422cad + md5: ff9efb7f7469aed3c4a8106ffa29593c + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/executing?source=hash-mapping + size: 30753 + timestamp: 1756729456476 +- conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + sha256: 2509992ec2fd38ab27c7cdb42cf6cadc566a1cc0d1021a2673475d9fa87c6276 + md5: d3549fd50d450b6d9e7dddff25dd2110 + depends: + - cached-property >=1.3.0 + - python >=3.9,<4 + license: MPL-2.0 + license_family: MOZILLA + purls: + - pkg:pypi/fqdn?source=hash-mapping + size: 16705 + timestamp: 1733327494780 +- conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + sha256: 96cac6573fd35ae151f4d6979bab6fbc90cb6b1fb99054ba19eb075da9822fcb + md5: b8993c19b0c32a2f7b66cbb58ca27069 + depends: + - python >=3.10 + - typing_extensions + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h11?source=hash-mapping + size: 39069 + timestamp: 1767729720872 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 + md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 + depends: + - python >=3.10 + - hyperframe >=6.1,<7 + - hpack >=4.1,<5 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h2?source=hash-mapping + size: 95967 + timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba + md5: 0a802cb9888dd14eeefc611f05c40b6e + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hpack?source=hash-mapping + size: 30731 + timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + sha256: 04d49cb3c42714ce533a8553986e1642d0549a05dc5cc48e0d43ff5be6679a5b + md5: 4f14640d58e2cc0aa0819d9d8ba125bb + depends: + - python >=3.9 + - h11 >=0.16 + - h2 >=3,<5 + - sniffio 1.* + - anyio >=4.0,<5.0 + - certifi + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/httpcore?source=hash-mapping + size: 49483 + timestamp: 1745602916758 +- conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + sha256: cd0f1de3697b252df95f98383e9edb1d00386bfdd03fdf607fa42fe5fcb09950 + md5: d6989ead454181f4f9bc987d3dc4e285 + depends: + - anyio + - certifi + - httpcore 1.* + - idna + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/httpx?source=hash-mapping + size: 63082 + timestamp: 1733663449209 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hyperframe?source=hash-mapping + size: 17397 + timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + sha256: 9ab620e6f64bb67737bd7bc1ad6f480770124e304c6710617aba7fe60b089f48 + md5: fb7130c190f9b4ec91219840a05ba3ac + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/idna?source=hash-mapping + size: 59038 + timestamp: 1776947141407 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 + md5: 080594bf4493e6bae2607e65390c520a + depends: + - python >=3.10 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/importlib-metadata?source=hash-mapping + size: 34387 + timestamp: 1773931568510 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda + sha256: 5c1f3e874adaf603449f2b135d48f168c5d510088c78c229bda0431268b43b27 + md5: 4b53d436f3fbc02ce3eeaf8ae9bebe01 + depends: + - appnope + - __osx + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.8.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio >=1.4 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + size: 132260 + timestamp: 1770566135697 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda + sha256: 9cdadaeef5abadca4113f92f5589db19f8b7df5e1b81cb0225f7024a3aedefa3 + md5: b3a7d5842f857414d9ae831a799444dd + depends: + - __win + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.8.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio >=1.4 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + size: 132382 + timestamp: 1770566174387 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda + sha256: b77ed58eb235e5ad80e742b03caeed4bbc2a2ef064cb9a2deee3b75dfae91b2a + md5: 8b267f517b81c13594ed68d646fd5dcb + depends: + - __linux + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.8.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio >=1.4 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + size: 133644 + timestamp: 1770566133040 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + sha256: a0af49948a1842dfd15a0b0b2fd56c94ddbd07e07a6c8b4bc70d43015eafaff0 + md5: 73e9657cd19605740d21efb14d8d0cb9 + depends: + - __unix + - decorator >=5.1.0 + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.2 + - matplotlib-inline >=0.1.6 + - prompt-toolkit >=3.0.41,<3.1.0 + - psutil >=7 + - pygments >=2.14.0 + - python >=3.11 + - stack_data >=0.6.0 + - traitlets >=5.13.0 + - typing_extensions >=4.6 + - pexpect >4.6 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython?source=hash-mapping + size: 651632 + timestamp: 1777038396606 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda + sha256: f252ec33597115ff21cbb31051f6f9be34ca36cbbbf3d266b597660d8d8edde9 + md5: 5631ab99e902463d9dd4221e5b4eab6d + depends: + - __win + - decorator >=5.1.0 + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.2 + - matplotlib-inline >=0.1.6 + - prompt-toolkit >=3.0.41,<3.1.0 + - psutil >=7 + - pygments >=2.14.0 + - python >=3.11 + - stack_data >=0.6.0 + - traitlets >=5.13.0 + - typing_extensions >=4.6 + - colorama >=0.4.4 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython?source=hash-mapping + size: 650593 + timestamp: 1777038425499 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + sha256: 894682a42a7d659ae12878dbcb274516a7031bbea9104e92f8e88c1f2765a104 + md5: bd80ba060603cc228d9d81c257093119 + depends: + - pygments + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython-pygments-lexers?source=hash-mapping + size: 13993 + timestamp: 1737123723464 +- conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + sha256: 08e838d29c134a7684bca0468401d26840f41c92267c4126d7b43a6b533b0aed + md5: 0b0154421989637d424ccf0f104be51a + depends: + - arrow >=0.15.0 + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/isoduration?source=hash-mapping + size: 19832 + timestamp: 1733493720346 +- conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + sha256: 92c4d217e2dc68983f724aa983cca5464dcb929c566627b26a2511159667dba8 + md5: a4f4c5dc9b80bc50e0d3dc4e6e8f1bd9 + depends: + - parso >=0.8.3,<0.9.0 + - python >=3.9 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/jedi?source=hash-mapping + size: 843646 + timestamp: 1733300981994 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b + md5: 04558c96691bed63104678757beb4f8d + depends: + - markupsafe >=2.0 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jinja2?source=hash-mapping + size: 120685 + timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + sha256: 9daa95bd164c8fa23b3ab196e906ef806141d749eddce2a08baa064f722d25fa + md5: 1269891272187518a0a75c286f7d0bbf + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/json5?source=hash-mapping + size: 34731 + timestamp: 1774655440045 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + sha256: a3d10301b6ff399ba1f3d39e443664804a3d28315a4fb81e745b6817845f70ae + md5: 89bf346df77603055d3c8fe5811691e6 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jsonpointer?source=hash-mapping + size: 14190 + timestamp: 1774311356147 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 + md5: ada41c863af263cc4c5fcbaff7c3e4dc + depends: + - attrs >=22.2.0 + - jsonschema-specifications >=2023.3.6 + - python >=3.10 + - referencing >=0.28.4 + - rpds-py >=0.25.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/jsonschema?source=hash-mapping + size: 82356 + timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 + md5: 439cd0f567d697b20a8f45cb70a1005a + depends: + - python >=3.10 + - referencing >=0.31.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/jsonschema-specifications?source=hash-mapping + size: 19236 + timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + sha256: 6886fc61e4e4edd38fd38729976b134e8bd2143f7fce56cc80d7ac7bac99bce1 + md5: 8368d58342d0825f0843dc6acdd0c483 + depends: + - jsonschema >=4.26.0,<4.26.1.0a0 + - fqdn + - idna + - isoduration + - jsonpointer >1.13 + - rfc3339-validator + - rfc3986-validator >0.1.0 + - rfc3987-syntax >=1.1.0 + - uri-template + - webcolors >=24.6.0 + license: MIT + license_family: MIT + purls: [] + size: 4740 + timestamp: 1767839954258 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + sha256: 3766e2ae59641c172cec8a821528bfa6bf9543ffaaeb8b358bfd5259dcf18e4e + md5: 0c3b465ceee138b9c39279cc02e5c4a0 + depends: + - importlib-metadata >=4.8.3 + - jupyter_server >=1.1.2 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-lsp?source=hash-mapping + size: 61633 + timestamp: 1775136333147 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + sha256: e402bd119720862a33229624ec23645916a7d47f30e1711a4af9e005162b84f3 + md5: 8a3d6d0523f66cf004e563a50d9392b3 + depends: + - jupyter_core >=5.1 + - python >=3.10 + - python-dateutil >=2.8.2 + - pyzmq >=25.0 + - tornado >=6.4.1 + - traitlets >=5.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-client?source=hash-mapping + size: 112785 + timestamp: 1767954655912 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + sha256: ed709a6c25b731e01563521ef338b93986cd14b5bc17f35e9382000864872ccc + md5: a8db462b01221e9f5135be466faeb3e0 + depends: + - __win + - pywin32 + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-core?source=hash-mapping + size: 64679 + timestamp: 1760643889625 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a + md5: b38fe4e78ee75def7e599843ef4c1ab0 + depends: + - __unix + - python + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-core?source=hash-mapping + size: 65503 + timestamp: 1760643864586 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + sha256: c7edb5682c6316a95ad781dccb1b6589cd2ec0bf94f23c21152974eb0363b5d7 + md5: bf42ee94c750c0b2e7e998b79ac299ea + depends: + - jsonschema-with-format-nongpl >=4.18.0 + - packaging + - python >=3.10 + - python-json-logger >=2.0.4 + - pyyaml >=5.3 + - referencing + - rfc3339-validator + - rfc3986-validator >=0.1.1 + - traitlets >=5.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-events?source=hash-mapping + size: 24002 + timestamp: 1776861872237 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda + sha256: 04fb8ea7749f67abaf76df6257bf86688e1389ceed55eb4fb0176fd2e882dbd6 + md5: 5ee7945accf0f215ddd6055d25d7cd83 + depends: + - anyio >=3.1.0 + - argon2-cffi >=21.1 + - jinja2 >=3.0.3 + - jupyter_client >=7.4.4 + - jupyter_core >=4.12,!=5.0.* + - jupyter_events >=0.11.0 + - jupyter_server_terminals >=0.4.4 + - nbconvert-core >=6.4.4 + - nbformat >=5.3.0 + - overrides >=5.0 + - packaging >=22.0 + - prometheus_client >=0.9 + - python >=3.10 + - pyzmq >=24 + - send2trash >=1.8.2 + - terminado >=0.8.3 + - tornado >=6.2.0 + - traitlets >=5.6.0 + - websocket-client >=1.7 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-server?source=hash-mapping + size: 360522 + timestamp: 1778060967727 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + sha256: 5eda79ed9f53f590031d29346abd183051263227dd9ee667b5ca1133ce297654 + md5: 7b8bace4943e0dc345fc45938826f2b8 + depends: + - python >=3.10 + - terminado >=0.8.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-server-terminals?source=hash-mapping + size: 22052 + timestamp: 1768574057200 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda + sha256: b85befad5ba1f50c0cc042a2ffb26441d13ffc2f18572dc20d3541476da0c7b9 + md5: 2ffe77234070324e763a6eddabb5f467 + depends: + - async-lru >=1.0.0 + - httpx >=0.25.0,<1 + - ipykernel >=6.5.0,!=6.30.0 + - jinja2 >=3.0.3 + - jupyter-lsp >=2.0.0 + - jupyter_core + - jupyter_server >=2.4.0,<3 + - jupyterlab_server >=2.28.0,<3 + - notebook-shim >=0.2 + - packaging + - python >=3.10 + - setuptools >=41.1.0 + - tomli >=1.2.2 + - tornado >=6.2.0 + - traitlets + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab?source=hash-mapping + size: 8861204 + timestamp: 1777483115382 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + sha256: dc24b900742fdaf1e077d9a3458fd865711de80bca95fe3c6d46610c532c6ef0 + md5: fd312693df06da3578383232528c468d + depends: + - pygments >=2.4.1,<3 + - python >=3.9 + constrains: + - jupyterlab >=4.0.8,<5.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-pygments?source=hash-mapping + size: 18711 + timestamp: 1733328194037 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + sha256: 381d2d6a259a3be5f38a69463e0f6c5dcf1844ae113058007b51c3bef13a7cee + md5: a63877cb23de826b1620d3adfccc4014 + depends: + - babel >=2.10 + - jinja2 >=3.0.3 + - json5 >=0.9.0 + - jsonschema >=4.18 + - jupyter_server >=1.21,<3 + - packaging >=21.3 + - python >=3.10 + - requests >=2.31 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-server?source=hash-mapping + size: 51621 + timestamp: 1761145478692 +- conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + sha256: 49570840fb15f5df5d4b4464db8ee43a6d643031a2bc70ef52120a52e3809699 + md5: 9b965c999135d43a3d0f7bd7d024e26a + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/lark?source=hash-mapping + size: 94312 + timestamp: 1761596921009 +- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda + sha256: 35b43d7343f74452307fd018a1cca92b8f68961ff8e2ab6a81ce0a703c9a3764 + md5: 9acc1c385be401d533ff70ef5b50dae6 + depends: + - python >=3.10 + - traitlets + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/matplotlib-inline?source=compressed-mapping + size: 15725 + timestamp: 1778264403247 +- conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda + sha256: b52dc6c78fbbe7a3008535cb8bfd87d70d8053e9250bbe16e387470a9df07070 + md5: b97e84d1553b4a1c765b87fff83453ad + depends: + - python >=3.10 + - typing_extensions + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/mistune?source=hash-mapping + size: 74567 + timestamp: 1777824616382 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + sha256: 1b66960ee06874ddceeebe375d5f17fb5f393d025a09e15b830ad0c4fffb585b + md5: 00f5b8dafa842e0c27c1cd7296aa4875 depends: - - __osx >=11.0 - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - license: GPL-3.0-or-later - license_family: GPL - purls: [] - size: 1862134 - timestamp: 1737621413640 -- conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda - sha256: 87a3468e09cc1ee0268e8639debad6a5b440090ef8cb1d2ee5eed66c86085528 - md5: a47cf810b7c03955139a150b228b93ca + - jupyter_client >=6.1.12 + - jupyter_core >=4.12,!=5.0.* + - nbformat >=5.1 + - python >=3.8 + - traitlets >=5.4 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbclient?source=hash-mapping + size: 28473 + timestamp: 1766485646962 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + sha256: ab2ac79c5892c5434d50b3542d96645bdaa06d025b6e03734be29200de248ac2 + md5: 2bce0d047658a91b99441390b9b27045 depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: GPL-3.0-or-later - license_family: GPL - purls: [] - size: 1528970 - timestamp: 1737622367981 -- conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - sha256: 96cac6573fd35ae151f4d6979bab6fbc90cb6b1fb99054ba19eb075da9822fcb - md5: b8993c19b0c32a2f7b66cbb58ca27069 + - beautifulsoup4 + - bleach-with-css !=5.0.0 + - defusedxml + - importlib-metadata >=3.6 + - jinja2 >=3.0 + - jupyter_core >=4.7 + - jupyterlab_pygments + - markupsafe >=2.0 + - mistune >=2.0.3,<4 + - nbclient >=0.5.0 + - nbformat >=5.7 + - packaging + - pandocfilters >=1.4.1 + - pygments >=2.4.1 + - python >=3.10 + - traitlets >=5.1 + - python + constrains: + - pandoc >=2.9.2,<4.0.0 + - nbconvert ==7.17.1 *_0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbconvert?source=hash-mapping + size: 202229 + timestamp: 1775615493260 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + sha256: 7a5bd30a2e7ddd7b85031a5e2e14f290898098dc85bea5b3a5bf147c25122838 + md5: bbe1963f1e47f594070ffe87cdf612ea + depends: + - jsonschema >=2.6 + - jupyter_core >=4.12,!=5.0.* + - python >=3.9 + - python-fastjsonschema >=2.15 + - traitlets >=5.1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbformat?source=hash-mapping + size: 100945 + timestamp: 1733402844974 +- conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + sha256: bb7b21d7fd0445ddc0631f64e66d91a179de4ba920b8381f29b9d006a42788c0 + md5: 598fd7d4d0de2455fb74f56063969a97 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/nest-asyncio?source=hash-mapping + size: 11543 + timestamp: 1733325673691 +- conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + sha256: 7b920e46b9f7a2d2aa6434222e5c8d739021dbc5cc75f32d124a8191d86f9056 + md5: e7f89ea5f7ea9401642758ff50a2d9c1 + depends: + - jupyter_server >=1.8,<3 + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/notebook-shim?source=hash-mapping + size: 16817 + timestamp: 1733408419340 +- conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c + md5: e51f1e4089cad105b6cac64bd8166587 + depends: + - python >=3.9 + - typing_utils + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/overrides?source=hash-mapping + size: 30139 + timestamp: 1734587755455 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 + md5: 4c06a92e74452cfa53623a81592e8934 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=hash-mapping + size: 91574 + timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + sha256: 2bb9ba9857f4774b85900c2562f7e711d08dd48e2add9bee4e1612fbee27e16f + md5: 457c2c8c08e54905d6954e79cb5b5db9 + depends: + - python !=3.0,!=3.1,!=3.2,!=3.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pandocfilters?source=hash-mapping + size: 11627 + timestamp: 1631603397334 +- conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda + sha256: 611882f7944b467281c46644ffde6c5145d1a7730388bcde26e7e86819b0998e + md5: 39894c952938276405a1bd30e4ce2caf depends: - python >=3.10 - - typing_extensions - python license: MIT license_family: MIT purls: - - pkg:pypi/h11?source=hash-mapping - size: 39069 - timestamp: 1767729720872 -- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 - md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 + - pkg:pypi/parso?source=hash-mapping + size: 82472 + timestamp: 1777722955579 +- conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + sha256: 202af1de83b585d36445dc1fda94266697341994d1a3328fabde4989e1b3d07a + md5: d0d408b1f18883a944376da5cf8101ea + depends: + - ptyprocess >=0.5 + - python >=3.9 + license: ISC + purls: + - pkg:pypi/pexpect?source=hash-mapping + size: 53561 + timestamp: 1733302019362 +- conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + sha256: 506c9330b8dc5ae98f4c32629fa59fa40e6bdd42a681c48d2f9554693dd01156 + md5: d57ef7cb7ad6b5d62cef8b9bdf1d400b depends: + - ipykernel >=6 + - jupyter_client >=7 + - jupyter_server >=2.4 + - msgspec >=0.18 - python >=3.10 - - hyperframe >=6.1,<7 - - hpack >=4.1,<5 - - python + - returns >=0.23 + - tomli >=2 license: MIT license_family: MIT purls: - - pkg:pypi/h2?source=hash-mapping - size: 95967 - timestamp: 1756364871835 -- pypi: https://files.pythonhosted.org/packages/03/c1/0976b235cf29ead553e22f2fb6385a8252b533715e00d0ae52ed7b900582/h5py-3.16.0-cp312-cp312-win_amd64.whl - name: h5py - version: 3.16.0 - sha256: 96b422019a1c8975c2d5dadcf61d4ba6f01c31f92bbde6e4649607885fe502d6 - requires_dist: - - numpy>=1.21.2 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.whl - name: h5py - version: 3.16.0 - sha256: fa48993a0b799737ba7fd21e2350fa0a60701e58180fae9f2de834bc39a147ab - requires_dist: - - numpy>=1.21.2 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl - name: h5py - version: 3.16.0 - sha256: 8c1eff849cdd53cbc73c214c30ebdb6f1bb8b64790b4b4fc36acdb5e43570210 - requires_dist: - - numpy>=1.21.2 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/9e/e9/1a19e42cd43cc1365e127db6aae85e1c671da1d9a5d746f4d34a50edb577/h5py-3.16.0-cp312-cp312-manylinux_2_28_x86_64.whl - name: h5py - version: 3.16.0 - sha256: dfc21898ff025f1e8e67e194965a95a8d4754f452f83454538f98f8a3fcb207e - requires_dist: - - numpy>=1.21.2 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/b0/42/c84efcc1d4caebafb1ecd8be4643f39c85c47a80fe254d92b8b43b1eadaf/h5py-3.16.0-cp312-cp312-macosx_11_0_arm64.whl - name: h5py - version: 3.16.0 - sha256: 42b012933a83e1a558c673176676a10ce2fd3759976a0fedee1e672d1e04fc9d - requires_dist: - - numpy>=1.21.2 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl - name: h5py - version: 3.16.0 - sha256: e4360f15875a532bc7b98196c7592ed4fc92672a57c0a621355961cafb17a6dd - requires_dist: - - numpy>=1.21.2 - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba - md5: 0a802cb9888dd14eeefc611f05c40b6e + - pkg:pypi/pixi-kernel?source=hash-mapping + size: 39509 + timestamp: 1764156429044 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + sha256: 8f29915c172f1f7f4f7c9391cd5dac3ebf5d13745c8b7c8006032615246345a5 + md5: 89c0b6d1793601a2a3a3f7d2d3d8b937 depends: - - python >=3.9 + - python >=3.10 + - python license: MIT license_family: MIT purls: - - pkg:pypi/hpack?source=hash-mapping - size: 30731 - timestamp: 1737618390337 -- conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - sha256: 04d49cb3c42714ce533a8553986e1642d0549a05dc5cc48e0d43ff5be6679a5b - md5: 4f14640d58e2cc0aa0819d9d8ba125bb + - pkg:pypi/platformdirs?source=hash-mapping + size: 25862 + timestamp: 1775741140609 +- conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + sha256: 4d7ec90d4f9c1f3b4a50623fefe4ebba69f651b102b373f7c0e9dbbfa43d495c + md5: a11ab1f31af799dd93c3a39881528884 depends: - - python >=3.9 - - h11 >=0.16 - - h2 >=3,<5 - - sniffio 1.* - - anyio >=4.0,<5.0 - - certifi - - python - license: BSD-3-Clause - license_family: BSD + - python >=3.10 + license: Apache-2.0 + license_family: Apache purls: - - pkg:pypi/httpcore?source=hash-mapping - size: 49483 - timestamp: 1745602916758 -- conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - sha256: cd0f1de3697b252df95f98383e9edb1d00386bfdd03fdf607fa42fe5fcb09950 - md5: d6989ead454181f4f9bc987d3dc4e285 + - pkg:pypi/prometheus-client?source=hash-mapping + size: 57113 + timestamp: 1775771465170 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + sha256: 4817651a276016f3838957bfdf963386438c70761e9faec7749d411635979bae + md5: edb16f14d920fb3faf17f5ce582942d6 depends: - - anyio - - certifi - - httpcore 1.* - - idna - - python >=3.9 + - python >=3.10 + - wcwidth + constrains: + - prompt_toolkit 3.0.52 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/httpx?source=hash-mapping - size: 63082 - timestamp: 1733663449209 -- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 - md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + - pkg:pypi/prompt-toolkit?source=hash-mapping + size: 273927 + timestamp: 1756321848365 +- conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + sha256: a7713dfe30faf17508ec359e0bc7e0983f5d94682492469bd462cdaae9c64d83 + md5: 7d9daffbb8d8e0af0f769dbbcd173a54 depends: - python >=3.9 - license: MIT - license_family: MIT + license: ISC purls: - - pkg:pypi/hyperframe?source=hash-mapping - size: 17397 - timestamp: 1737618427549 -- 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 - - libstdcxx >=14 - license: MIT - license_family: MIT - purls: [] - size: 12723451 - timestamp: 1773822285671 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda - sha256: 3a7907a17e9937d3a46dfd41cffaf815abad59a569440d1e25177c15fd0684e5 - md5: f1182c91c0de31a7abd40cedf6a5ebef + - pkg:pypi/ptyprocess?source=hash-mapping + size: 19457 + timestamp: 1733302371990 +- conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + sha256: 71bd24600d14bb171a6321d523486f6a06f855e75e547fa0cb2a0953b02047f0 + md5: 3bfdfb8dbcdc4af1ae3f9a8eb3948f04 depends: - - __osx >=11.0 + - python >=3.9 license: MIT license_family: MIT - purls: [] - size: 12361647 - timestamp: 1773822915649 -- pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl - name: identify - version: 2.6.19 - sha256: 20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a - requires_dist: - - ukkonen ; extra == 'license' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda - sha256: 9ab620e6f64bb67737bd7bc1ad6f480770124e304c6710617aba7fe60b089f48 - md5: fb7130c190f9b4ec91219840a05ba3ac + purls: + - pkg:pypi/pure-eval?source=hash-mapping + size: 16668 + timestamp: 1733569518868 +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 + md5: 12c566707c80111f9799308d9e265aef depends: - - python >=3.10 + - python >=3.9 - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/idna?source=hash-mapping - size: 59038 - timestamp: 1776947141407 -- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 - md5: 080594bf4493e6bae2607e65390c520a + - pkg:pypi/pycparser?source=hash-mapping + size: 110100 + timestamp: 1733195786147 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 + md5: 16c18772b340887160c79a6acc022db0 depends: - python >=3.10 - - zipp >=3.20 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/pygments?source=hash-mapping + size: 893031 + timestamp: 1774796815820 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + sha256: d016e04b0e12063fbee4a2d5fbb9b39a8d191b5a0042f0b8459188aedeabb0ca + md5: e2fd202833c4a981ce8a65974fe4abd1 + depends: + - __win + - python >=3.9 + - win_inet_pton + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + size: 21784 + timestamp: 1733217448189 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 + md5: 461219d1a5bd61342293efa2c0c90eac + depends: + - __unix + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + size: 21085 + timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 + md5: 5b8d21249ff20967101ffa321cab24e8 + depends: + - python >=3.9 + - six >=1.5 - python license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/importlib-metadata?source=hash-mapping - size: 34387 - timestamp: 1773931568510 -- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl - name: iniconfig - version: 2.3.0 - sha256: f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl - name: interrogate - version: 1.7.0 - sha256: b13ff4dd8403369670e2efe684066de9fcb868ad9d7f2b4095d8112142dc9d12 - requires_dist: - - attrs - - click>=7.1 - - colorama - - py - - tabulate - - tomli ; python_full_version < '3.11' - - cairosvg ; extra == 'dev' - - sphinx ; extra == 'dev' - - sphinx-autobuild ; extra == 'dev' - - pytest ; extra == 'dev' - - pytest-cov ; extra == 'dev' - - pytest-mock ; extra == 'dev' - - coverage[toml] ; extra == 'dev' - - wheel ; extra == 'dev' - - pre-commit ; extra == 'dev' - - sphinx ; extra == 'docs' - - sphinx-autobuild ; extra == 'docs' - - cairosvg ; extra == 'png' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-mock ; extra == 'tests' - - coverage[toml] ; extra == 'tests' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl - name: ipydatawidgets - version: 4.3.5 - sha256: d590cdb7c364f2f6ab346f20b9d2dd661d27a834ef7845bc9d7113118f05ec87 - requires_dist: - - ipywidgets>=7.0.0 - - numpy - - traittypes>=0.2.0 - - sphinx ; extra == 'docs' - - recommonmark ; extra == 'docs' - - sphinx-rtd-theme ; extra == 'docs' - - pytest>=4 ; extra == 'test' - - pytest-cov ; extra == 'test' - - nbval>=0.9.2 ; extra == 'test' - requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda - sha256: 5c1f3e874adaf603449f2b135d48f168c5d510088c78c229bda0431268b43b27 - md5: 4b53d436f3fbc02ce3eeaf8ae9bebe01 + - pkg:pypi/python-dateutil?source=hash-mapping + size: 233310 + timestamp: 1751104122689 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + sha256: df9aa74e9e28e8d1309274648aac08ec447a92512c33f61a8de0afa9ce32ebe8 + md5: 23029aae904a2ba587daba708208012f + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/fastjsonschema?source=hash-mapping + size: 244628 + timestamp: 1755304154927 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + sha256: 97327b9509ae3aae28d27217a5d7bd31aff0ab61a02041e9c6f98c11d8a53b29 + md5: 32780d6794b8056b78602103a04e90ef + depends: + - cpython 3.12.13.* + - python_abi * *_cp312 + license: Python-2.0 + purls: [] + size: 46449 + timestamp: 1772728979370 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + sha256: 36ff7984e4565c85149e64f8206303d412a0652e55cf806dcb856903fa056314 + md5: e4e60721757979d01d3964122f674959 + depends: + - cpython 3.14.4.* + - python_abi * *_cp314 + license: Python-2.0 + purls: [] + size: 49806 + timestamp: 1775614307464 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + sha256: 1c55116c22512cef7b01d55ae49697707f2c1fd829407183c19817e2d300fd8d + md5: 1cd2f3e885162ee1366312bd1b1677fd depends: - - appnope - - __osx - - comm >=0.1.1 - - debugpy >=1.6.5 - - ipython >=7.23.1 - - jupyter_client >=8.8.0 - - jupyter_core >=5.1,!=6.0.* - - matplotlib-inline >=0.1 - - nest-asyncio >=1.4 - - packaging >=22 - - psutil >=5.7 - python >=3.10 - - pyzmq >=25 - - tornado >=6.4.1 - - traitlets >=5.4.0 - - python - constrains: - - appnope >=0.1.2 - license: BSD-3-Clause + - typing_extensions + license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/ipykernel?source=hash-mapping - size: 132260 - timestamp: 1770566135697 -- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda - sha256: 9cdadaeef5abadca4113f92f5589db19f8b7df5e1b81cb0225f7024a3aedefa3 - md5: b3a7d5842f857414d9ae831a799444dd + - pkg:pypi/python-json-logger?source=hash-mapping + size: 18969 + timestamp: 1777318679482 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + sha256: e943f9c15a6bdba2e1b9f423ab913b3f6b02197b0ef9f8e6b7464d78b59965b9 + md5: f6ad7450fc21e00ecc23812baed6d2e4 depends: - - __win - - comm >=0.1.1 - - debugpy >=1.6.5 - - ipython >=7.23.1 - - jupyter_client >=8.8.0 - - jupyter_core >=5.1,!=6.0.* - - matplotlib-inline >=0.1 - - nest-asyncio >=1.4 - - packaging >=22 - - psutil >=5.7 - python >=3.10 - - pyzmq >=25 - - tornado >=6.4.1 - - traitlets >=5.4.0 - - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/tzdata?source=hash-mapping + size: 146639 + timestamp: 1777068997932 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + build_number: 8 + sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 + md5: c3efd25ac4d74b1584d2f7a57195ddf1 constrains: - - appnope >=0.1.2 + - python 3.12.* *_cpython license: BSD-3-Clause license_family: BSD - purls: - - pkg:pypi/ipykernel?source=hash-mapping - size: 132382 - timestamp: 1770566174387 -- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - sha256: b77ed58eb235e5ad80e742b03caeed4bbc2a2ef064cb9a2deee3b75dfae91b2a - md5: 8b267f517b81c13594ed68d646fd5dcb - depends: - - __linux - - comm >=0.1.1 - - debugpy >=1.6.5 - - ipython >=7.23.1 - - jupyter_client >=8.8.0 - - jupyter_core >=5.1,!=6.0.* - - matplotlib-inline >=0.1 - - nest-asyncio >=1.4 - - packaging >=22 - - psutil >=5.7 - - python >=3.10 - - pyzmq >=25 - - tornado >=6.4.1 - - traitlets >=5.4.0 - - python + purls: [] + size: 6958 + timestamp: 1752805918820 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + build_number: 8 + sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 + md5: 0539938c55b6b1a59b560e843ad864a4 constrains: - - appnope >=0.1.2 + - python 3.14.* *_cp314 license: BSD-3-Clause license_family: BSD + purls: [] + size: 6989 + timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 + md5: 870293df500ca7e18bedefa5838a22ab + depends: + - attrs >=22.2.0 + - python >=3.10 + - rpds-py >=0.7.0 + - typing_extensions >=4.4.0 + - python + license: MIT + license_family: MIT purls: - - pkg:pypi/ipykernel?source=hash-mapping - size: 133644 - timestamp: 1770566133040 -- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda - sha256: a0af49948a1842dfd15a0b0b2fd56c94ddbd07e07a6c8b4bc70d43015eafaff0 - md5: 73e9657cd19605740d21efb14d8d0cb9 + - pkg:pypi/referencing?source=hash-mapping + size: 51788 + timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + sha256: 7f2c24dd3bd3c104a1d2c9a10ead5ed6758b0976b74f972cfe9c19884ccc4241 + md5: 9659f587a8ceacc21864260acd02fc67 depends: - - __unix - - decorator >=5.1.0 - - ipython_pygments_lexers >=1.0.0 - - jedi >=0.18.2 - - matplotlib-inline >=0.1.6 - - prompt-toolkit >=3.0.41,<3.1.0 - - psutil >=7 - - pygments >=2.14.0 - - python >=3.11 - - stack_data >=0.6.0 - - traitlets >=5.13.0 - - typing_extensions >=4.6 - - pexpect >4.6 + - python >=3.10 + - certifi >=2023.5.7 + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - urllib3 >=1.26,<3 - python - license: BSD-3-Clause - license_family: BSD + constrains: + - chardet >=3.0.2,<8 + license: Apache-2.0 + license_family: APACHE purls: - - pkg:pypi/ipython?source=hash-mapping - size: 651632 - timestamp: 1777038396606 -- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda - sha256: f252ec33597115ff21cbb31051f6f9be34ca36cbbbf3d266b597660d8d8edde9 - md5: 5631ab99e902463d9dd4221e5b4eab6d + - pkg:pypi/requests?source=hash-mapping + size: 63728 + timestamp: 1777030058920 +- conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + sha256: 3b45efeae771f1a20307b36ecdb3a8911a89c05382836b50c62b0a99d8d3dfd8 + md5: da94ff04d97ec5efc42cbe5da3c43a84 depends: - - __win - - decorator >=5.1.0 - - ipython_pygments_lexers >=1.0.0 - - jedi >=0.18.2 - - matplotlib-inline >=0.1.6 - - prompt-toolkit >=3.0.41,<3.1.0 - - psutil >=7 - - pygments >=2.14.0 - python >=3.11 - - stack_data >=0.6.0 - - traitlets >=5.13.0 - - typing_extensions >=4.6 - - colorama >=0.4.4 + - typing_extensions >=4.0,<5.0 - python - license: BSD-3-Clause + license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/ipython?source=hash-mapping - size: 650593 - timestamp: 1777038425499 -- conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - sha256: 894682a42a7d659ae12878dbcb274516a7031bbea9104e92f8e88c1f2765a104 - md5: bd80ba060603cc228d9d81c257093119 + - pkg:pypi/returns?source=hash-mapping + size: 100559 + timestamp: 1776176903101 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + sha256: 2e4372f600490a6e0b3bac60717278448e323cab1c0fecd5f43f7c56535a99c5 + md5: 36de09a8d3e5d5e6f4ee63af49e59706 depends: - - pygments - python >=3.9 - license: BSD-3-Clause - license_family: BSD + - six + license: MIT + license_family: MIT purls: - - pkg:pypi/ipython-pygments-lexers?source=hash-mapping - size: 13993 - timestamp: 1737123723464 -- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl - name: ipywidgets - version: 8.1.8 - sha256: ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e - requires_dist: - - comm>=0.1.3 - - ipython>=6.1.0 - - traitlets>=4.3.1 - - widgetsnbextension~=4.0.14 - - jupyterlab-widgets~=3.0.15 - - jsonschema ; extra == 'test' - - ipykernel ; extra == 'test' - - pytest>=3.6.0 ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytz ; extra == 'test' - requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - sha256: 08e838d29c134a7684bca0468401d26840f41c92267c4126d7b43a6b533b0aed - md5: 0b0154421989637d424ccf0f104be51a + - pkg:pypi/rfc3339-validator?source=hash-mapping + size: 10209 + timestamp: 1733600040800 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + sha256: 2a5b495a1de0f60f24d8a74578ebc23b24aa53279b1ad583755f223097c41c37 + md5: 912a71cc01012ee38e6b90ddd561e36f depends: - - arrow >=0.15.0 - - python >=3.9 + - python license: MIT license_family: MIT purls: - - pkg:pypi/isoduration?source=hash-mapping - size: 19832 - timestamp: 1733493720346 -- conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - sha256: 92c4d217e2dc68983f724aa983cca5464dcb929c566627b26a2511159667dba8 - md5: a4f4c5dc9b80bc50e0d3dc4e6e8f1bd9 + - pkg:pypi/rfc3986-validator?source=hash-mapping + size: 7818 + timestamp: 1598024297745 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + sha256: 70001ac24ee62058557783d9c5a7bbcfd97bd4911ef5440e3f7a576f9e43bc92 + md5: 7234f99325263a5af6d4cd195035e8f2 depends: - - parso >=0.8.3,<0.9.0 - python >=3.9 - license: Apache-2.0 AND MIT + - lark >=1.2.2 + - python + license: MIT + license_family: MIT purls: - - pkg:pypi/jedi?source=hash-mapping - size: 843646 - timestamp: 1733300981994 -- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b - md5: 04558c96691bed63104678757beb4f8d + - pkg:pypi/rfc3987-syntax?source=hash-mapping + size: 22913 + timestamp: 1752876729969 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + sha256: 8fc024bf1a7b99fc833b131ceef4bef8c235ad61ecb95a71a6108be2ccda63e8 + md5: b70e2d44e6aa2beb69ba64206a16e4c6 + depends: + - __osx + - pyobjc-framework-cocoa + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/send2trash?source=hash-mapping + size: 22519 + timestamp: 1770937603551 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + sha256: 305446a0b018f285351300463653d3d3457687270e20eda37417b12ee386ef76 + md5: 6ac53f3fff2c416d63511843a04646fa depends: - - markupsafe >=2.0 + - __win + - pywin32 - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jinja2?source=hash-mapping - size: 120685 - timestamp: 1764517220861 -- 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' -- conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda - sha256: 9daa95bd164c8fa23b3ab196e906ef806141d749eddce2a08baa064f722d25fa - md5: 1269891272187518a0a75c286f7d0bbf - depends: - - python >=3.10 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/json5?source=hash-mapping - size: 34731 - timestamp: 1774655440045 -- conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda - sha256: a3d10301b6ff399ba1f3d39e443664804a3d28315a4fb81e745b6817845f70ae - md5: 89bf346df77603055d3c8fe5811691e6 + - pkg:pypi/send2trash?source=hash-mapping + size: 22864 + timestamp: 1770937641143 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda + sha256: 59656f6b2db07229351dfb3a859c35e57cc8e8bcbc86d4e501bff881a6f771f1 + md5: 28eb91468df04f655a57bcfbb35fc5c5 depends: + - __linux - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jsonpointer?source=hash-mapping - size: 14190 - timestamp: 1774311356147 -- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 - md5: ada41c863af263cc4c5fcbaff7c3e4dc + - pkg:pypi/send2trash?source=hash-mapping + size: 24108 + timestamp: 1770937597662 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + sha256: 82088a6e4daa33329a30bc26dc19a98c7c1d3f05c0f73ce9845d4eab4924e9e1 + md5: 8e194e7b992f99a5015edbd4ebd38efd depends: - - attrs >=22.2.0 - - jsonschema-specifications >=2023.3.6 - python >=3.10 - - referencing >=0.28.4 - - rpds-py >=0.25.0 - - python license: MIT license_family: MIT purls: - - pkg:pypi/jsonschema?source=hash-mapping - size: 82356 - timestamp: 1767839954256 -- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 - md5: 439cd0f567d697b20a8f45cb70a1005a + - pkg:pypi/setuptools?source=hash-mapping + size: 639697 + timestamp: 1773074868565 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 depends: - - python >=3.10 - - referencing >=0.31.0 + - python >=3.9 - python license: MIT license_family: MIT purls: - - pkg:pypi/jsonschema-specifications?source=hash-mapping - size: 19236 - timestamp: 1757335715225 -- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - sha256: 6886fc61e4e4edd38fd38729976b134e8bd2143f7fce56cc80d7ac7bac99bce1 - md5: 8368d58342d0825f0843dc6acdd0c483 - depends: - - jsonschema >=4.26.0,<4.26.1.0a0 - - fqdn - - idna - - isoduration - - jsonpointer >1.13 - - rfc3339-validator - - rfc3986-validator >0.1.0 - - rfc3987-syntax >=1.1.0 - - uri-template - - webcolors >=24.6.0 - license: MIT - license_family: MIT - purls: [] - size: 4740 - timestamp: 1767839954258 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda - sha256: 3766e2ae59641c172cec8a821528bfa6bf9543ffaaeb8b358bfd5259dcf18e4e - md5: 0c3b465ceee138b9c39279cc02e5c4a0 + - pkg:pypi/six?source=hash-mapping + size: 18455 + timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad + md5: 03fe290994c5e4ec17293cfb6bdce520 depends: - - importlib-metadata >=4.8.3 - - jupyter_server >=1.1.2 - python >=3.10 - - python - license: BSD-3-Clause - license_family: BSD + license: Apache-2.0 + license_family: Apache purls: - - pkg:pypi/jupyter-lsp?source=hash-mapping - size: 61633 - timestamp: 1775136333147 -- 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' -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - sha256: e402bd119720862a33229624ec23645916a7d47f30e1711a4af9e005162b84f3 - md5: 8a3d6d0523f66cf004e563a50d9392b3 + - pkg:pypi/sniffio?source=hash-mapping + size: 15698 + timestamp: 1762941572482 +- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + sha256: 23b71ecf089967d2900126920e7f9ff18cdcef82dbff3e2f54ffa360243a17ac + md5: 18de09b20462742fe093ba39185d9bac depends: - - jupyter_core >=5.1 - python >=3.10 - - python-dateutil >=2.8.2 - - pyzmq >=25.0 - - tornado >=6.4.1 - - traitlets >=5.3 - - python - license: BSD-3-Clause - license_family: BSD + license: MIT + license_family: MIT purls: - - pkg:pypi/jupyter-client?source=hash-mapping - size: 112785 - timestamp: 1767954655912 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda - sha256: ed709a6c25b731e01563521ef338b93986cd14b5bc17f35e9382000864872ccc - md5: a8db462b01221e9f5135be466faeb3e0 + - pkg:pypi/soupsieve?source=hash-mapping + size: 38187 + timestamp: 1769034509657 +- conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + sha256: 570da295d421661af487f1595045760526964f41471021056e993e73089e9c41 + md5: b1b505328da7a6b246787df4b5a49fbc + depends: + - asttokens + - executing + - pure_eval + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/stack-data?source=hash-mapping + size: 26988 + timestamp: 1733569565672 +- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + sha256: b375e8df0d5710717c31e7c8e93c025c37fa3504aea325c7a55509f64e5d4340 + md5: e43ca10d61e55d0a8ec5d8c62474ec9e depends: - __win - - pywin32 - - platformdirs >=2.5 + - pywinpty >=1.1.0 - python >=3.10 - - traitlets >=5.3 + - tornado >=6.1.0 - python - constrains: - - pywin32 >=300 - license: BSD-3-Clause + license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/jupyter-core?source=hash-mapping - size: 64679 - timestamp: 1760643889625 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a - md5: b38fe4e78ee75def7e599843ef4c1ab0 + - pkg:pypi/terminado?source=hash-mapping + size: 23665 + timestamp: 1766513806974 +- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + sha256: 6b6727a13d1ca6a23de5e6686500d0669081a117736a87c8abf444d60c1e40eb + md5: 17b43cee5cc84969529d5d0b0309b2cb depends: - __unix - - python - - platformdirs >=2.5 + - ptyprocess - python >=3.10 - - traitlets >=5.3 + - tornado >=6.1.0 - python - constrains: - - pywin32 >=300 - license: BSD-3-Clause + license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/jupyter-core?source=hash-mapping - size: 65503 - timestamp: 1760643864586 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda - sha256: c7edb5682c6316a95ad781dccb1b6589cd2ec0bf94f23c21152974eb0363b5d7 - md5: bf42ee94c750c0b2e7e998b79ac299ea + - pkg:pypi/terminado?source=hash-mapping + size: 24749 + timestamp: 1766513766867 +- conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + sha256: cad582d6f978276522f84bd209a5ddac824742fe2d452af6acf900f8650a73a2 + md5: f1acf5fdefa8300de697982bcb1761c9 depends: - - jsonschema-with-format-nongpl >=4.18.0 - - packaging - - python >=3.10 - - python-json-logger >=2.0.4 - - pyyaml >=5.3 - - referencing - - rfc3339-validator - - rfc3986-validator >=0.1.1 - - traitlets >=5.3 - - python + - python >=3.5 + - webencodings >=0.4 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyter-events?source=hash-mapping - size: 24002 - timestamp: 1776861872237 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.18.2-pyhcf101f3_0.conda - sha256: 04fb8ea7749f67abaf76df6257bf86688e1389ceed55eb4fb0176fd2e882dbd6 - md5: 5ee7945accf0f215ddd6055d25d7cd83 + - pkg:pypi/tinycss2?source=hash-mapping + size: 28285 + timestamp: 1729802975370 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd + md5: b5325cf06a000c5b14970462ff5e4d58 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=hash-mapping + size: 21561 + timestamp: 1774492402955 +- conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda + sha256: dfb681579be59c2e790c95f7f49b7529a9b0511d6385ad276e3c8988cbd54d2c + md5: 4bada6a6d908a27262af8ebddf4f7492 depends: - - anyio >=3.1.0 - - argon2-cffi >=21.1 - - jinja2 >=3.0.3 - - jupyter_client >=7.4.4 - - jupyter_core >=4.12,!=5.0.* - - jupyter_events >=0.11.0 - - jupyter_server_terminals >=0.4.4 - - nbconvert-core >=6.4.4 - - nbformat >=5.3.0 - - overrides >=5.0 - - packaging >=22.0 - - prometheus_client >=0.9 - python >=3.10 - - pyzmq >=24 - - send2trash >=1.8.2 - - terminado >=0.8.3 - - tornado >=6.2.0 - - traitlets >=5.6.0 - - websocket-client >=1.7 - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyter-server?source=hash-mapping - size: 360522 - timestamp: 1778060967727 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - sha256: 5eda79ed9f53f590031d29346abd183051263227dd9ee667b5ca1133ce297654 - md5: 7b8bace4943e0dc345fc45938826f2b8 + - pkg:pypi/traitlets?source=hash-mapping + size: 115165 + timestamp: 1778074251714 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c + md5: edd329d7d3a4ab45dcf905899a7a6115 + depends: + - typing_extensions ==4.15.0 pyhcf101f3_0 + license: PSF-2.0 + license_family: PSF + purls: [] + size: 91383 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 + md5: 0caa1af407ecff61170c9437a808404d depends: - python >=3.10 - - terminado >=0.8.3 - python - license: BSD-3-Clause - license_family: BSD + license: PSF-2.0 + license_family: PSF purls: - - pkg:pypi/jupyter-server-terminals?source=hash-mapping - size: 22052 - timestamp: 1768574057200 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.7-pyhd8ed1ab_0.conda - sha256: b85befad5ba1f50c0cc042a2ffb26441d13ffc2f18572dc20d3541476da0c7b9 - md5: 2ffe77234070324e763a6eddabb5f467 + - pkg:pypi/typing-extensions?source=hash-mapping + size: 51692 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + sha256: 3088d5d873411a56bf988eee774559335749aed6f6c28e07bf933256afb9eb6c + md5: f6d7aa696c67756a650e91e15e88223c + depends: + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/typing-utils?source=hash-mapping + size: 15183 + timestamp: 1733331395943 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + purls: [] + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + sha256: e0eb6c8daf892b3056f08416a96d68b0a358b7c46b99c8a50481b22631a4dfc0 + md5: e7cb0f5745e4c5035a460248334af7eb + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/uri-template?source=hash-mapping + size: 23990 + timestamp: 1733323714454 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 + md5: cbb88288f74dbe6ada1c6c7d0a97223e + depends: + - backports.zstd >=1.0.0 + - brotli-python >=1.2.0 + - h2 >=4,<5 + - pysocks >=1.5.6,<2.0,!=1.5.7 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/urllib3?source=hash-mapping + size: 103560 + timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda + sha256: 1ee2d8384972ecbf8630ce8a3ea9d16858358ad3e8566675295e66996d5352da + md5: eb9538b8e55069434a18547f43b96059 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/wcwidth?source=hash-mapping + size: 82917 + timestamp: 1777744489106 +- conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + sha256: 21f6c8a20fe050d09bfda3fb0a9c3493936ce7d6e1b3b5f8b01319ee46d6c6f6 + md5: 6639b6b0d8b5a284f027a2003669aa65 depends: - - async-lru >=1.0.0 - - httpx >=0.25.0,<1 - - ipykernel >=6.5.0,!=6.30.0 - - jinja2 >=3.0.3 - - jupyter-lsp >=2.0.0 - - jupyter_core - - jupyter_server >=2.4.0,<3 - - jupyterlab_server >=2.28.0,<3 - - notebook-shim >=0.2 - - packaging - python >=3.10 - - setuptools >=41.1.0 - - tomli >=1.2.2 - - tornado >=6.2.0 - - traitlets license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyterlab?source=hash-mapping - size: 8861204 - timestamp: 1777483115382 -- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - name: jupyterlab-widgets - version: 3.0.16 - sha256: 45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8 - requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - sha256: dc24b900742fdaf1e077d9a3458fd865711de80bca95fe3c6d46610c532c6ef0 - md5: fd312693df06da3578383232528c468d + - pkg:pypi/webcolors?source=hash-mapping + size: 18987 + timestamp: 1761899393153 +- conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + sha256: 19ff205e138bb056a46f9e3839935a2e60bd1cf01c8241a5e172a422fed4f9c6 + md5: 2841eb5bfc75ce15e9a0054b98dcd64d depends: - - pygments >=2.4.1,<3 - python >=3.9 - constrains: - - jupyterlab >=4.0.8,<5.0.0 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyterlab-pygments?source=hash-mapping - size: 18711 - timestamp: 1733328194037 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - sha256: 381d2d6a259a3be5f38a69463e0f6c5dcf1844ae113058007b51c3bef13a7cee - md5: a63877cb23de826b1620d3adfccc4014 + - pkg:pypi/webencodings?source=hash-mapping + size: 15496 + timestamp: 1733236131358 +- conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + sha256: 42a2b61e393e61cdf75ced1f5f324a64af25f347d16c60b14117393a98656397 + md5: 2f1ed718fcd829c184a6d4f0f2e07409 depends: - - babel >=2.10 - - jinja2 >=3.0.3 - - json5 >=0.9.0 - - jsonschema >=4.18 - - jupyter_server >=1.21,<3 - - packaging >=21.3 - python >=3.10 - - requests >=2.31 - - python - license: BSD-3-Clause - license_family: BSD + license: Apache-2.0 + license_family: APACHE purls: - - pkg:pypi/jupyterlab-server?source=hash-mapping - size: 51621 - timestamp: 1761145478692 -- pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - name: jupyterquiz - version: 2.9.6.4 - sha256: f8c4418f6c827454523fc882a30d744b585cb58ac1ae277769c3059d04fc272b -- pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl - name: jupytext - version: 1.19.2 - sha256: 8a31e896c7e9215841783aade24336e945543057e1c2d7f00b22f9e870348688 - requires_dist: - - markdown-it-py>=1.0 - - mdit-py-plugins - - nbformat - - packaging - - pyyaml - - tomli ; python_full_version < '3.11' - - autopep8 ; extra == 'dev' - - black ; extra == 'dev' - - flake8 ; extra == 'dev' - - gitpython ; extra == 'dev' - - ipykernel ; extra == 'dev' - - isort ; extra == 'dev' - - jupyter-fs[fs]>=1.0 ; extra == 'dev' - - jupyter-server!=2.11 ; extra == 'dev' - - marimo>=0.17.6,<=0.19.4 ; extra == 'dev' - - nbconvert ; extra == 'dev' - - pre-commit ; extra == 'dev' - - pytest ; extra == 'dev' - - pytest-asyncio ; extra == 'dev' - - pytest-cov>=2.6.1 ; extra == 'dev' - - pytest-randomly ; extra == 'dev' - - pytest-xdist ; extra == 'dev' - - sphinx ; extra == 'dev' - - sphinx-gallery>=0.8 ; extra == 'dev' - - myst-parser ; extra == 'docs' - - sphinx ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-rtd-theme ; extra == 'docs' - - pytest ; extra == 'test' - - pytest-asyncio ; extra == 'test' - - pytest-randomly ; extra == 'test' - - pytest-xdist ; extra == 'test' - - black ; extra == 'test-cov' - - ipykernel ; extra == 'test-cov' - - jupyter-server!=2.11 ; extra == 'test-cov' - - nbconvert ; extra == 'test-cov' - - pytest ; extra == 'test-cov' - - pytest-asyncio ; extra == 'test-cov' - - pytest-cov>=2.6.1 ; extra == 'test-cov' - - pytest-randomly ; extra == 'test-cov' - - pytest-xdist ; extra == 'test-cov' - - autopep8 ; extra == 'test-external' - - black ; extra == 'test-external' - - flake8 ; extra == 'test-external' - - gitpython ; extra == 'test-external' - - ipykernel ; extra == 'test-external' - - isort ; extra == 'test-external' - - jupyter-fs[fs]>=1.0 ; extra == 'test-external' - - jupyter-server!=2.11 ; extra == 'test-external' - - marimo>=0.17.6,<=0.19.4 ; extra == 'test-external' - - nbconvert ; extra == 'test-external' - - pre-commit ; extra == 'test-external' - - pytest ; extra == 'test-external' - - pytest-asyncio ; extra == 'test-external' - - pytest-randomly ; extra == 'test-external' - - pytest-xdist ; extra == 'test-external' - - sphinx ; extra == 'test-external' - - sphinx-gallery>=0.8 ; extra == 'test-external' - - black ; extra == 'test-functional' - - pytest ; extra == 'test-functional' - - pytest-asyncio ; extra == 'test-functional' - - pytest-randomly ; extra == 'test-functional' - - pytest-xdist ; extra == 'test-functional' - - black ; extra == 'test-integration' - - ipykernel ; extra == 'test-integration' - - jupyter-server!=2.11 ; extra == 'test-integration' - - nbconvert ; extra == 'test-integration' - - pytest ; extra == 'test-integration' - - pytest-asyncio ; extra == 'test-integration' - - pytest-randomly ; extra == 'test-integration' - - pytest-xdist ; extra == 'test-integration' - - bash-kernel ; extra == 'test-ui' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 - md5: b38117a3c920364aff79f870c984b4a3 + - pkg:pypi/websocket-client?source=hash-mapping + size: 61391 + timestamp: 1759928175142 +- conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + sha256: 93807369ab91f230cf9e6e2a237eaa812492fe00face5b38068735858fba954f + md5: 46e441ba871f524e2b067929da3051c2 + depends: + - __win + - python >=3.9 + license: LicenseRef-Public-Domain + purls: + - pkg:pypi/win-inet-pton?source=hash-mapping + size: 9555 + timestamp: 1733130678956 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + sha256: 523616c0530d305d2216c2b4a8dfd3872628b60083255b89c5e0d8c42e738cca + md5: e1c36c6121a7c9c76f2f148f1e83b983 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - license: LGPL-2.1-or-later + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/zipp?source=hash-mapping + size: 24461 + timestamp: 1776131454755 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + build_number: 7 + sha256: 7acaa2e0782cad032bdaf756b536874346ac1375745fb250e9bdd6a48a7ab3cd + md5: a44032f282e7d2acdeb1c240308052dd + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD purls: [] - size: 134088 - timestamp: 1754905959823 -- pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl - name: kiwisolver - version: 1.5.0 - sha256: 0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl - name: kiwisolver - version: 1.5.0 - sha256: ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl - name: kiwisolver - version: 1.5.0 - sha256: d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl - name: kiwisolver - version: 1.5.0 - sha256: f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: kiwisolver - version: 1.5.0 - sha256: bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: kiwisolver - version: 1.5.0 - sha256: 80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda - sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 - md5: fb53fb07ce46a575c5d004bbc96032c2 + size: 8325 + timestamp: 1764092507920 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py312h4409184_2.conda + sha256: 24c475f6f7abf03ef3cc2ac572b7a6d713bede00ef984591be92cdc439b09fbc + md5: 0a2a07b42db3f92b8dccf0f60b5ebee8 depends: - - __glibc >=2.17,<3.0.a0 - - keyutils >=1.6.3,<2.0a0 - - libedit >=3.1.20250104,<3.2.0a0 - - libedit >=3.1.20250104,<4.0a0 - - libgcc >=14 - - libstdcxx >=14 - - openssl >=3.5.5,<4.0a0 + - __osx >=11.0 + - cffi >=1.0.1 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 license: MIT license_family: MIT - purls: [] - size: 1386730 - timestamp: 1769769569681 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda - sha256: c0a0bf028fe7f3defcdcaa464e536cf1b202d07451e18ad83fdd169d15bef6ed - md5: e446e1822f4da8e5080a9de93474184d + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 34224 + timestamp: 1762509989973 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + sha256: aab60bbaea5cc49dff37438d1ad469d64025cda2ce58103cf68da61701ed2075 + md5: a240a79a49a95b388ef81ccda27a5e51 + depends: + - __osx >=11.0 + - cffi >=2.0.0b1 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 34218 + timestamp: 1762509977830 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.4.0-py312h87c4bb7_0.conda + sha256: 7dbd64d3f06622ef8286be6dfceeb8e6008450fb4e6d9309fbb908b12f3937ff + md5: 95a833465ec45ac1e8f2ed1aaba8ec37 + depends: + - python + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 239305 + timestamp: 1777848727027 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda + sha256: 6178775a86579d5e8eec6a7ab316c24f1355f6c6ccbe84bb341f342f1eda2440 + md5: 311fcf3f6a8c4eb70f912798035edd35 depends: - __osx >=11.0 - libcxx >=19 - - libedit >=3.1.20250104,<3.2.0a0 - - libedit >=3.1.20250104,<4.0a0 - - openssl >=3.5.5,<4.0a0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 359503 + timestamp: 1764018572368 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + sha256: 5c2e471fd262fcc3c5a9d5ea4dae5917b885e0e9b02763dbd0f0d9635ed4cb99 + md5: f9501812fe7c66b6548c7fcaa1c1f252 + depends: + - __osx >=11.0 + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 hc919400_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 359854 + timestamp: 1764018178608 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + sha256: 540fe54be35fac0c17feefbdc3e29725cce05d7367ffedfaaa1bdda234b019df + md5: 620b85a3f45526a8bc4d23fd78fc22f0 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD purls: [] - size: 1160828 - timestamp: 1769770119811 -- conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda - sha256: eb60f1ad8b597bcf95dee11bc11fe71a8325bc1204cf51d2bb1f2120ffd77761 - md5: 4432f52dc0c8eb6a7a6abc00a037d93c + size: 124834 + timestamp: 1771350416561 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + sha256: 2995f2aed4e53725e5efbc28199b46bf311c3cab2648fc4f10c2227d6d5fa196 + md5: bcb3cba70cf1eec964a03b4ba7775f01 depends: - - openssl >=3.5.5,<4.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 + - __osx >=11.0 license: MIT license_family: MIT purls: [] - size: 751055 - timestamp: 1769769688841 -- conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - sha256: 49570840fb15f5df5d4b4464db8ee43a6d643031a2bc70ef52120a52e3809699 - md5: 9b965c999135d43a3d0f7bd7d024e26a + size: 180327 + timestamp: 1765215064054 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py312h1b4d9a2_1.conda + sha256: 597e986ac1a1bd1c9b29d6850e1cdea4a075ce8292af55568952ec670e7dd358 + md5: 503ac138ad3cfc09459738c0f5750705 depends: - - python >=3.10 + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pycparser + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 license: MIT license_family: MIT purls: - - pkg:pypi/lark?source=hash-mapping - size: 94312 - timestamp: 1761596921009 -- pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl - name: lazy-loader - version: '0.5' - sha256: ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005 - requires_dist: - - packaging - - pytest>=8.0 ; extra == 'test' - - pytest-cov>=5.0 ; extra == 'test' - - coverage[toml]>=7.2 ; extra == 'test' - - pre-commit==4.3.0 ; extra == 'lint' - - 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_102.conda - sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c - md5: 18335a698559cdbcd86150a48bf54ba6 + - pkg:pypi/cffi?source=hash-mapping + size: 288080 + timestamp: 1761203317419 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + sha256: 5b5ee5de01eb4e4fd2576add5ec9edfc654fbaf9293e7b7ad2f893a67780aa98 + md5: 10dd19e4c797b8f8bdb1ec1fbb6821d7 depends: - - __glibc >=2.17,<3.0.a0 - - zstd >=1.5.7,<1.6.0a0 - constrains: - - binutils_impl_linux-64 2.45.1 - license: GPL-3.0-only + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 292983 + timestamp: 1761203354051 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py312h6510ced_0.conda + sha256: f0ca130b5ffd6949673d3c61d7b8562ab76ad8debafb83f8b3443d30c172f5eb + md5: da3b5efcb0caabcede61a6ce4e0a7669 + depends: + - python + - __osx >=11.0 + - python 3.12.* *_cpython + - libcxx >=19 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2752978 + timestamp: 1769744996462 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda + sha256: 7736a82ebe75c0f3ea6991298363d1f2edb34291f8616c1d3719862881c3a167 + md5: 407c74dc27356ba6bf3a0191070e3ac0 + depends: + - python + - python 3.14.* *_cp314 + - __osx >=11.0 + - libcxx >=19 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2778080 + timestamp: 1769745040206 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gsl-2.8-h8d0574d_1.conda + sha256: f11d8f2007f6591022afa958d8fe15afbe4211198d1603c0eb886bc21a9eb19e + md5: cc261442bead590d89ca9f96884a344f + depends: + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + license: GPL-3.0-or-later license_family: GPL purls: [] - size: 728002 - timestamp: 1774197446916 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda - sha256: a7a4481a4d217a3eadea0ec489826a69070fcc3153f00443aa491ed21527d239 - md5: 6f7b4302263347698fd24565fbf11310 + size: 1862134 + timestamp: 1737621413640 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + sha256: 3a7907a17e9937d3a46dfd41cffaf815abad59a569440d1e25177c15fd0684e5 + md5: f1182c91c0de31a7abd40cedf6a5ebef depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libstdcxx >=14 - constrains: - - libabseil-static =20260107.1=cxx17* - - abseil-cpp =20260107.1 - license: Apache-2.0 - license_family: Apache + - __osx >=11.0 + license: MIT + license_family: MIT purls: [] - size: 1384817 - timestamp: 1770863194876 + size: 12361647 + timestamp: 1773822915649 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + sha256: c0a0bf028fe7f3defcdcaa464e536cf1b202d07451e18ad83fdd169d15bef6ed + md5: e446e1822f4da8e5080a9de93474184d + depends: + - __osx >=11.0 + - libcxx >=19 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1160828 + timestamp: 1769770119811 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda sha256: 756611fbb8d2957a5b4635d9772bd8432cb6ddac05580a6284cca6fdc9b07fca md5: bb65152e0d7c7178c0f1ee25692c9fd1 @@ -7216,23 +6614,6 @@ packages: purls: [] size: 1229639 timestamp: 1770863511331 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda - build_number: 7 - sha256: 081c850f99bc355821fac9c6e3727d40b3f8ce3beb50a5437cf03726b611ff39 - md5: 955b44e8b00b7f7ef4ce0130cef12394 - depends: - - libopenblas >=0.3.33,<0.3.34.0a0 - - libopenblas >=0.3.33,<1.0a0 - constrains: - - libcblas 3.11.0 7*_openblas - - blas 2.307 openblas - - liblapack 3.11.0 7*_openblas - - liblapacke 3.11.0 7*_openblas - - mkl <2027 - license: BSD-3-Clause - purls: [] - size: 18716 - timestamp: 1778489854108 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-7_h51639a9_openblas.conda build_number: 7 sha256: 662935bfb93d2d097e26e273a3a2f504a9f833f64aa6f9e295b577655478c39b @@ -7250,32 +6631,6 @@ packages: purls: [] size: 18783 timestamp: 1778489983152 -- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda - build_number: 7 - sha256: 9eec27eee4300284e62a61cb2298089c80d31f6f9e924eeabc06e9788a00cffe - md5: 269e54b44974ff48846b4c31d0397041 - depends: - - mkl >=2026.0.0,<2027.0a0 - constrains: - - blas 2.307 mkl - - libcblas 3.11.0 7*_mkl - - liblapacke 3.11.0 7*_mkl - - liblapack 3.11.0 7*_mkl - license: BSD-3-Clause - purls: [] - size: 68060 - timestamp: 1778490352569 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e - md5: 72c8fd1af66bd67bf580645b426513ed - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - license: MIT - license_family: MIT - purls: [] - size: 79965 - timestamp: 1764017188531 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda sha256: a7cb9e660531cf6fbd4148cff608c85738d0b76f0975c5fc3e7d5e92840b7229 md5: 006e7ddd8a110771134fcc4e1e3a6ffa @@ -7286,18 +6641,6 @@ packages: purls: [] size: 79443 timestamp: 1764017945924 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - sha256: 12fff21d38f98bc446d82baa890e01fd82e3b750378fedc720ff93522ffb752b - md5: 366b40a69f0ad6072561c1d09301c886 - depends: - - __glibc >=2.17,<3.0.a0 - - libbrotlicommon 1.2.0 hb03c661_1 - - libgcc >=14 - license: MIT - license_family: MIT - purls: [] - size: 34632 - timestamp: 1764017199083 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda sha256: 2eae444039826db0454b19b52a3390f63bfe24f6b3e63089778dd5a5bf48b6bf md5: 079e88933963f3f149054eec2c487bc2 @@ -7309,18 +6652,6 @@ packages: purls: [] size: 29452 timestamp: 1764017979099 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - sha256: a0c15c79997820bbd3fbc8ecf146f4fe0eca36cc60b62b63ac6cf78857f1dd0d - md5: 4ffbb341c8b616aa2494b6afb26a0c5f - depends: - - __glibc >=2.17,<3.0.a0 - - libbrotlicommon 1.2.0 hb03c661_1 - - libgcc >=14 - license: MIT - license_family: MIT - purls: [] - size: 298378 - timestamp: 1764017210931 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda sha256: 01436c32bb41f9cb4bcf07dda647ce4e5deb8307abfc3abdc8da5317db8189d1 md5: b2b7c8288ca1a2d71ff97a8e6a1e8883 @@ -7332,20 +6663,6 @@ packages: purls: [] size: 290754 timestamp: 1764018009077 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - build_number: 7 - sha256: 956ae0bb1ec8b0c3663d75b151aceb0521b54e513bf97f621a035f9c87037970 - md5: 0675639dc24cb0032f199e7ff68e4633 - depends: - - libblas 3.11.0 7_h4a7cf45_openblas - constrains: - - liblapacke 3.11.0 7*_openblas - - blas 2.307 openblas - - liblapack 3.11.0 7*_openblas - license: BSD-3-Clause - purls: [] - size: 18675 - timestamp: 1778489861559 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-7_hb0561ab_openblas.conda build_number: 7 sha256: 3ac3d27022b3ca8b1980c087e0ede250434f6ed90a4fdc78a8a5ed382bc75505 @@ -7360,20 +6677,6 @@ packages: purls: [] size: 18810 timestamp: 1778489991330 -- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda - build_number: 7 - sha256: 82da0f854831f783f9d3f1219c4255956e8167a474f3f526151128f02453871c - md5: 4700b7af6acefb26ff0127ba68230941 - depends: - - libblas 3.11.0 7_h8455456_mkl - constrains: - - blas 2.307 mkl - - liblapacke 3.11.0 7*_mkl - - liblapack 3.11.0 7*_mkl - license: BSD-3-Clause - purls: [] - size: 68594 - timestamp: 1778490364980 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.5-h55c6f16_1.conda sha256: dddd01bd6b338221342a89530a1caffe6051a70cc8f8b1d8bb591d5447a3c603 md5: ff484b683fecf1e875dfc7aa01d19796 @@ -7384,19 +6687,6 @@ packages: purls: [] size: 569359 timestamp: 1778191546305 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 - md5: c277e0a4d549b03ac1e9d6cbbe3d017b - depends: - - ncurses - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - - ncurses >=6.5,<7.0a0 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 134676 - timestamp: 1738479519902 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 md5: 44083d2d2c2025afca315c7a172eab2b @@ -7409,16 +6699,6 @@ packages: purls: [] size: 107691 timestamp: 1738479560845 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda - sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 - md5: 172bf1cd1ff8629f2b1179945ed45055 - depends: - - libgcc-ng >=12 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 112766 - timestamp: 1702146165126 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f md5: 36d33e440c31857372a72137f78bacf5 @@ -7427,19 +6707,6 @@ packages: purls: [] size: 107458 timestamp: 1702146414478 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.0-hecca717_0.conda - sha256: ea33c40977ea7a2c3658c522230058395bc2ee0d89d99f0711390b6a1ee80d12 - md5: a3b390520c563d78cc58974de95a03e5 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - constrains: - - expat 2.8.0.* - license: MIT - license_family: MIT - purls: [] - size: 77241 - timestamp: 1777846112704 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.0-hf6b4638_0.conda sha256: f4b1cafc59afaede8fa0a2d9cf376840f1c553001acd72f6ead18bbc8ac8c49c md5: 65466e82c09e888ca7560c11a97d5450 @@ -7452,31 +6719,6 @@ packages: purls: [] size: 68789 timestamp: 1777846180142 -- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-hac47afa_0.conda - sha256: 2d81d647c1f01108803457cac999b947456f44dd0a3c2325395677feacaeca67 - md5: 264e350e035092b5135a2147c238aec4 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - expat 2.8.0.* - license: MIT - license_family: MIT - purls: [] - size: 71094 - timestamp: 1777846223617 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 - md5: a360c33a5abe61c07959e449fa1453eb - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - license: MIT - license_family: MIT - purls: [] - size: 58592 - timestamp: 1769456073053 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda sha256: 6686a26466a527585e6a75cc2a242bf4a3d97d6d6c86424a441677917f28bec7 md5: 43c04d9cb46ef176bb2a4c77e324d599 @@ -7484,70 +6726,22 @@ packages: - __osx >=11.0 license: MIT license_family: MIT - purls: [] - size: 40979 - timestamp: 1769456747661 -- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - sha256: 59d01f2dfa8b77491b5888a5ab88ff4e1574c9359f7e229da254cdfe27ddc190 - md5: 720b39f5ec0610457b725eb3f396219a - depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: MIT - license_family: MIT - purls: [] - size: 45831 - timestamp: 1769456418774 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 - md5: 57736f29cc2b0ec0b6c2952d3f101b6a - depends: - - __glibc >=2.17,<3.0.a0 - - _openmp_mutex >=4.5 - constrains: - - libgcc-ng ==15.2.0=*_19 - - libgomp 15.2.0 he0feb66_19 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 1041084 - timestamp: 1778269013026 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda - sha256: 06644fa4d34d57c9e48f4d84b1256f9e5f654fdb37f43acc8a58a396952d42b7 - md5: 644058123986582db33aebd4ae2ca184 - depends: - - _openmp_mutex - constrains: - - libgcc-ng ==15.2.0=*_19 - - libgomp 15.2.0 19 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 404080 - timestamp: 1778273064154 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda - sha256: 9dcf54adfaa5e861123c2da4f2f0451a685464ea7e5a41ad91cf67b31d658d98 - md5: 331ee9b72b9dff570d56b1302c5ab37d - depends: - - libgcc 15.2.0 he0feb66_19 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 27694 - timestamp: 1778269016987 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda - sha256: 561a42758ef25b9ce308c4e2cf56daee4f06138385a17e29a492cd928e00be6f - md5: 42bf7eca1a951735fa06c0e3c0d5c8e6 + purls: [] + size: 40979 + timestamp: 1769456747661 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_19.conda + sha256: 06644fa4d34d57c9e48f4d84b1256f9e5f654fdb37f43acc8a58a396952d42b7 + md5: 644058123986582db33aebd4ae2ca184 depends: - - libgfortran5 15.2.0 h68bc16d_19 + - _openmp_mutex constrains: - - libgfortran-ng ==15.2.0=*_19 + - libgcc-ng ==15.2.0=*_19 + - libgomp 15.2.0 19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 27655 - timestamp: 1778269042954 + size: 404080 + timestamp: 1778273064154 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_19.conda sha256: d4837b3b9b30af3132d260225e91ab9dde83be04c59513f500cc81050fb37486 md5: 1ea03f87cdb1078fbc0e2b2deb63752c @@ -7560,19 +6754,6 @@ packages: purls: [] size: 139675 timestamp: 1778273280875 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda - sha256: 057978bb69fea29ed715a9b98adf71015c31baecc4aeb2bfc20d4fd5d83579d4 - md5: 85072b0ad177c966294f129b7c04a2d5 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=15.2.0 - constrains: - - libgfortran 15.2.0 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 2483673 - timestamp: 1778269025089 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_19.conda sha256: d0a68b7a121d115b80c169e24d1265dcc25a3fe58d107df1bbc430797e226d88 md5: ba36d8c606a6a53fe0b8c12d47267b3d @@ -7585,54 +6766,6 @@ packages: purls: [] size: 599691 timestamp: 1778273075448 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b - md5: faac990cb7aedc7f3a2224f2c9b0c26c - depends: - - __glibc >=2.17,<3.0.a0 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 603817 - timestamp: 1778268942614 -- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - sha256: 8cdf11333a81085468d9aa536ebb155abd74adc293576f6013fc0c85a7a90da3 - md5: 3b576f6860f838f950c570f4433b086e - depends: - - libwinpthread >=12.0.0.r4.gg4f2fc60ca - - libxml2 - - libxml2-16 >=2.14.6 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 2411241 - timestamp: 1765104337762 -- conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - sha256: 0dcdb1a5f01863ac4e8ba006a8b0dc1a02d2221ec3319b5915a1863254d7efa7 - md5: 64571d1dd6cdcfa25d0664a5950fdaa2 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: LGPL-2.1-only - purls: [] - size: 696926 - timestamp: 1754909290005 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d - md5: b88d90cad08e6bc8ad540cb310a761fb - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - constrains: - - xz 5.8.3.* - license: 0BSD - purls: [] - size: 113478 - timestamp: 1775825492909 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda sha256: 34878d87275c298f1a732c6806349125cebbf340d24c6c23727268184bba051e md5: b1fd823b5ae54fbec272cea0811bd8a9 @@ -7644,30 +6777,6 @@ packages: purls: [] size: 92472 timestamp: 1775825802659 -- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda - sha256: d636d1a25234063642f9c531a7bb58d84c1c496411280a36ea000bd122f078f1 - md5: 8f83619ab1588b98dd99c90b0bfc5c6d - depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - xz 5.8.3.* - license: 0BSD - purls: [] - size: 106486 - timestamp: 1775825663227 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 - md5: 2c21e66f50753a083cbe6b80f38268fa - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 92400 - timestamp: 1769482286018 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda sha256: 1089c7f15d5b62c622625ec6700732ece83be8b705da8c6607f4dabb0c4bd6d2 md5: 57c4be259f5e0b99a5983799a228ae55 @@ -7678,35 +6787,6 @@ packages: purls: [] size: 73690 timestamp: 1769482560514 -- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - sha256: 40dcd0b9522a6e0af72a9db0ced619176e7cfdb114855c7a64f278e73f8a7514 - md5: e4a9fc2bba3b022dad998c78856afe47 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 89411 - timestamp: 1769482314283 -- 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.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.5,<4.0a0 - license: MIT - license_family: MIT - purls: [] - size: 663344 - timestamp: 1773854035739 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda sha256: 2bc7bc3978066f2c274ebcbf711850cc9ab92e023e433b9631958a098d11e10a md5: 6ea18834adbc3b33df9bd9fb45eaf95b @@ -7723,792 +6803,900 @@ packages: purls: [] size: 576526 timestamp: 1773854624224 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 - md5: d864d34357c3b65a4b731f78c0801dc4 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - license: LGPL-2.1-only - license_family: GPL - purls: [] - size: 33731 - timestamp: 1750274110928 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda - sha256: 3d9aa85648e5e18a6d66db98b8c4317cc426721ad7a220aa86330d1ccedc8903 - md5: 2d3278b721e40468295ca755c3b84070 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda + sha256: 9dd455b2d172aeedfa2058d324b5b5822b0bc1b7c1f32cd183d7078540d2f6eb + md5: 909e41855c29f0d52ae630198cd57135 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 + - __osx >=11.0 - libgfortran - libgfortran5 >=14.3.0 + - llvm-openmp >=19.1.7 constrains: - openblas >=0.3.33,<0.3.34.0a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 5931919 - timestamp: 1776993658641 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.33-openmp_he657e61_0.conda - sha256: 9dd455b2d172aeedfa2058d324b5b5822b0bc1b7c1f32cd183d7078540d2f6eb - md5: 909e41855c29f0d52ae630198cd57135 + size: 4304965 + timestamp: 1776995497368 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + sha256: df603472ea1ebd8e7d4fb71e4360fe48d10b11c240df51c129de1da2ff9e8227 + md5: 7cc5247987e6d115134ebab15186bc13 + depends: + - __osx >=11.0 + license: ISC + purls: [] + size: 248039 + timestamp: 1772479570912 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_0.conda + sha256: 49daec7c83e70d4efc17b813547824bc2bcf2f7256d84061d24fbfe537da9f74 + md5: 6681822ea9d362953206352371b6a904 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + size: 920047 + timestamp: 1777987051643 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda + sha256: 042c7488ad97a5629ec0a991a8b2a3345599401ecc75ad6a5af73b60e6db9689 + md5: c0d87c3c8e075daf1daf6c31b53e8083 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 421195 + timestamp: 1753948426421 +- 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.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 47759 + timestamp: 1774072956767 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda + sha256: 2cd49562feda2bf324651050b2b035080fd635ed0f1c96c9ce7a59eff3cc0029 + md5: 8a4e2a54034b35bc6fa5bf9282913f45 + depends: + - __osx >=11.0 + constrains: + - openmp 22.1.5|22.1.5.* + - intel-openmp <0.0a0 + license: Apache-2.0 WITH LLVM-exception + purls: [] + size: 285806 + timestamp: 1778447786965 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda + sha256: 330394fb9140995b29ae215a19fad46fcc6691bdd1b7654513d55a19aaa091c1 + md5: 11d95ab83ef0a82cc2de12c1e0b47fe4 + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 25564 + timestamp: 1772445846939 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + sha256: 411153d14ee0d98be6e3751cf5cc0502db17bce2deebebb8779e33d29d0e525f + md5: d33c0a15882b70255abdd54711b06a45 + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 27256 + timestamp: 1772445397216 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py312h2bbb03f_0.conda + sha256: 50e284832520f08ef1e37e0ca20459f5df2c048f59dfba1f2e3ee0ccfe7be317 + md5: ae340bdc5bdf5abd3183c5962517cbde + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 212357 + timestamp: 1776338798628 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda + sha256: 24a9105921e94fa526ffde1e956fa550c48ddb9ce4b0cf19ae22e79ed267261e + md5: 26fce586b13842a0f9f9a3aabae3e943 depends: - __osx >=11.0 - - libgfortran - - libgfortran5 >=14.3.0 - - llvm-openmp >=19.1.7 - constrains: - - openblas >=0.3.33,<0.3.34.0a0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 license: BSD-3-Clause license_family: BSD - purls: [] - size: 4304965 - timestamp: 1776995497368 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda - sha256: 64e5c80cbce4680a2d25179949739a6def695d72c40ca28f010711764e372d97 - md5: 7af961ef4aa2c1136e11dd43ded245ab - depends: - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - license: ISC - purls: [] - size: 277661 - timestamp: 1772479381288 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda - sha256: df603472ea1ebd8e7d4fb71e4360fe48d10b11c240df51c129de1da2ff9e8227 - md5: 7cc5247987e6d115134ebab15186bc13 + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 216965 + timestamp: 1776338889692 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda + sha256: 4ea6c620b87bd1d42bb2ccc2c87cd2483fa2d7f9e905b14c223f11ff3f4c455d + md5: 343d10ed5b44030a2f67193905aea159 depends: - __osx >=11.0 - license: ISC - purls: [] - size: 248039 - timestamp: 1772479570912 -- conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda - sha256: d915f4fa8ebbf237c7a6e511ed458f2cfdc7c76843a924740318a15d0dd33d6d - md5: da2aa614d16a795b3007b6f4a1318a81 - depends: - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - license: ISC - purls: [] - size: 276860 - timestamp: 1772479407566 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda - sha256: 54cdcd3214313b62c2a8ee277e6f42150d9b748264c1b70d958bf735e420ef8d - md5: 7dc38adcbf71e6b38748e919e16e0dce - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libzlib >=1.3.2,<2.0a0 - license: blessing + license: X11 AND BSD-3-Clause purls: [] - size: 954962 - timestamp: 1777986471789 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.1-h1b79a29_0.conda - sha256: 49daec7c83e70d4efc17b813547824bc2bcf2f7256d84061d24fbfe537da9f74 - md5: 6681822ea9d362953206352371b6a904 + size: 805509 + timestamp: 1777423252320 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda + sha256: 4782b172b3b8a557b60bf5f591821cf100e2092ba7a5494ce047dfa41626de26 + md5: ca8277c52fdface8bb8ebff7cd9a6f56 depends: + - libcxx >=19 - __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 - license: blessing + - 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* + license: MIT + license_family: MIT purls: [] - size: 920047 - timestamp: 1777987051643 -- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda - sha256: e70562450332ca8954bc16f3455468cca5ef3695c7d7187ecc87f8fc3c70e9eb - md5: 7fea434a17c323256acc510a041b80d7 + size: 17101803 + timestamp: 1774517834028 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + sha256: c91bf510c130a1ea1b6ff023e28bac0ccaef869446acd805e2016f69ebdc49ea + md5: 25dcccd4f80f1638428613e0d7c9b4e1 depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: blessing + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache purls: [] - size: 1304178 - timestamp: 1777986510497 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc - md5: 5794b3bdc38177caf969dabd3af08549 + size: 3106008 + timestamp: 1775587972483 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda + sha256: 6d0e21c76436374635c074208cfeee62a94d3c37d0527ad67fd8a7615e546a05 + md5: fd856899666759403b3c16dcba2f56ff depends: - - __glibc >=2.17,<3.0.a0 - - libgcc 15.2.0 he0feb66_19 - constrains: - - libstdcxx-ng ==15.2.0=*_19 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 5852044 - timestamp: 1778269036376 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda - sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 - md5: 38ffe67b78c9d4de527be8315e5ada2c + - python + - __osx >=11.0 + - python 3.12.* *_cpython + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 239031 + timestamp: 1769678393511 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda + sha256: e0f31c053eb11803d63860c213b2b1b57db36734f5f84a3833606f7c91fedff9 + md5: fc4c7ab223873eee32080d51600ce7e7 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 + - python + - __osx >=11.0 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 license: BSD-3-Clause license_family: BSD - purls: [] - size: 40297 - timestamp: 1775052476770 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda - sha256: c180f4124a889ac343fc59d15558e93667d894a966ec6fdb61da1604481be26b - md5: 0f03292cc56bf91a077a134ea8747118 + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 245502 + timestamp: 1769678303655 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py312h19bbe71_0.conda + sha256: b015f430fe9ea2c53e14be13639f1b781f68deaa5ae74cd8c1d07720890cd02a + md5: c65d7abdc9e60fd3af0ed852591adf1b depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + - setuptools license: MIT license_family: MIT - purls: [] - size: 895108 - timestamp: 1753948278280 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda - sha256: 042c7488ad97a5629ec0a991a8b2a3345599401ecc75ad6a5af73b60e6db9689 - md5: c0d87c3c8e075daf1daf6c31b53e8083 + purls: + - pkg:pypi/pyobjc-core?source=hash-mapping + size: 476750 + timestamp: 1763151865523 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda + sha256: df5af268c5a74b7160d772c263ece6f43257faff571783443e34b5f1d5a61cf2 + md5: 75a84fc8337557347252cc4fd3ba2a93 depends: - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - setuptools license: MIT license_family: MIT - purls: [] - size: 421195 - timestamp: 1753948426421 -- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - sha256: 0fccf2d17026255b6e10ace1f191d0a2a18f2d65088fd02430be17c701f8ffe0 - md5: 8a86073cf3b343b87d03f41790d8b4e5 - depends: - - ucrt - constrains: - - pthreads-win32 <0.0a0 - - msys2-conda-epoch <0.0a0 - license: MIT AND BSD-3-Clause-Clear - purls: [] - size: 36621 - timestamp: 1759768399557 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c - md5: 5aa797f8787fe7a17d1b0821485b5adc - depends: - - libgcc-ng >=12 - license: LGPL-2.1-or-later - purls: [] - size: 100393 - timestamp: 1702724383534 -- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_0.conda - sha256: da68af9d9d28d65a6916db1bef68f8a25c64c4fdcf759f32a2d2f2f143220adf - md5: e3b5acbb857a12f5d59e8d174bc536c0 + purls: + - pkg:pypi/pyobjc-core?source=hash-mapping + size: 483374 + timestamp: 1763151489724 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py312h1de3e18_0.conda + sha256: 3710f5ae09c2ea77ba4d82cc51e876d9fc009b878b197a40d3c6347c09ae7d7c + md5: f0bae1b67ece138378923e340b940051 depends: - - libiconv >=1.18,<2.0a0 - - liblzma >=5.8.3,<6.0a0 - - libxml2-16 2.15.3 h692994f_0 - - libzlib >=1.3.2,<2.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - icu <0.0a0 + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pyobjc-core 12.1.* + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 license: MIT license_family: MIT - purls: [] - size: 43916 - timestamp: 1776376994334 -- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h692994f_0.conda - sha256: 8038084c60eda2006d0122d05e3364fe8db0a18935ca6ed0168b5ba5aa33f904 - md5: f7d6fcda29570e20851b78d92ea2154e + purls: + - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping + size: 377723 + timestamp: 1763160705325 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda + sha256: aa76ee4328d0514d7c1c455dcd2d3b547db1c59797e54ce0a3f27de5b970e508 + md5: 4219bb3408016e22316cf8b443b5ef93 depends: - - libiconv >=1.18,<2.0a0 - - liblzma >=5.8.3,<6.0a0 - - libzlib >=1.3.2,<2.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - libxml2 2.15.3 - - icu <0.0a0 + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pyobjc-core 12.1.* + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 license: MIT license_family: MIT - purls: [] - size: 518869 - timestamp: 1776376971242 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 - md5: d87ff7921124eccd67248aa483c23fec + purls: + - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping + size: 374792 + timestamp: 1763160601898 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda + sha256: e658e647a4a15981573d6018928dec2c448b10c77c557c29872043ff23c0eb6a + md5: 8e7608172fa4d1b90de9a745c2fd2b81 depends: - - __glibc >=2.17,<3.0.a0 + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata constrains: - - zlib 1.3.2 *_2 - license: Zlib - license_family: Other + - python_abi 3.12.* *_cp312 + license: Python-2.0 purls: [] - size: 63629 - timestamp: 1774072609062 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda - sha256: 361415a698514b19a852f5d1123c5da746d4642139904156ddfca7c922d23a05 - md5: bc5a5721b6439f2f62a84f2548136082 + size: 12127424 + timestamp: 1772730755512 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda + build_number: 100 + sha256: 27e7d6cbe021f37244b643f06a98e46767255f7c2907108dd3736f042757ddad + md5: e1bc5a3015a4bbeb304706dba5a32b7f depends: - __osx >=11.0 - constrains: - - zlib 1.3.2 *_2 - license: Zlib - license_family: Other + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.5,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.52.0,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.6,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 purls: [] - size: 47759 - timestamp: 1774072956767 -- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda - sha256: 88609816e0cc7452bac637aaf65783e5edf4fee8a9f8e22bdc3a75882c536061 - md5: dbabbd6234dea34040e631f87676292f + size: 13533346 + timestamp: 1775616188373 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda + sha256: 737959262d03c9c305618f2d48c7f1691fb996f14ae420bfd05932635c99f873 + md5: 95a5f0831b5e0b1075bbd80fcffc52ac depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - zlib 1.3.2 *_2 - license: Zlib - license_family: Other - purls: [] - size: 58347 - timestamp: 1774072851498 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.5-hc7d1edf_1.conda - sha256: 2cd49562feda2bf324651050b2b035080fd635ed0f1c96c9ce7a59eff3cc0029 - md5: 8a4e2a54034b35bc6fa5bf9282913f45 + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 187278 + timestamp: 1770223990452 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + sha256: 95f385f9606e30137cf0b5295f63855fd22223a4cf024d306cf9098ea1c4a252 + md5: dcf51e564317816cb8d546891019b3ab depends: - __osx >=11.0 - constrains: - - openmp 22.1.5|22.1.5.* - - intel-openmp <0.0a0 - license: Apache-2.0 WITH LLVM-exception - purls: [] - size: 285806 - timestamp: 1778447786965 -- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.5-h4fa8253_1.conda - sha256: 7179e0266125c3333a097b399d0383734ee6c55fbadf332b447237a596e9698f - md5: bffe599d0eb2e78a32872712178e639c + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 189475 + timestamp: 1770223788648 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + noarch: python + sha256: 2f31f799a46ed75518fae0be75ecc8a1b84360dbfd55096bc2fe8bd9c797e772 + md5: 2f6b79700452ef1e91f45a99ab8ffe5a depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - openmp 22.1.5|22.1.5.* - - intel-openmp <0.0a0 - license: Apache-2.0 WITH LLVM-exception + - python + - libcxx >=19 + - __osx >=11.0 + - _python_abi3_support 1.* + - cpython >=3.12 + - zeromq >=4.3.5,<4.4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 191641 + timestamp: 1771717073430 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 + md5: f8381319127120ce51e081dce4865cf4 + depends: + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL purls: [] - size: 347493 - timestamp: 1778448334890 -- pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - name: lmfit - version: 1.3.4 - sha256: afce1593b42324d37ae2908249b0c55445e2f4c1a0474ff706a8e2f7b5d949fa - requires_dist: - - asteval>=1.0 - - numpy>=1.24 - - scipy>=1.10.0 - - uncertainties>=3.2.2 - - dill>=0.3.4 - - build ; extra == 'dev' - - check-wheel-contents ; extra == 'dev' - - flake8-pyproject ; extra == 'dev' - - pre-commit ; extra == 'dev' - - twine ; extra == 'dev' - - cairosvg ; extra == 'doc' - - corner ; extra == 'doc' - - emcee>=3.0.0 ; extra == 'doc' - - ipykernel ; extra == 'doc' - - jupyter-sphinx>=0.2.4 ; extra == 'doc' - - matplotlib ; extra == 'doc' - - numdifftools ; extra == 'doc' - - pandas ; extra == 'doc' - - pillow ; extra == 'doc' - - pycairo ; sys_platform == 'win32' and extra == 'doc' - - sphinx ; extra == 'doc' - - sphinx-gallery>=0.10 ; extra == 'doc' - - sphinxcontrib-svg2pdfconverter ; extra == 'doc' - - sympy ; extra == 'doc' - - coverage ; extra == 'test' - - flaky ; extra == 'test' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - lmfit[dev,doc,test] ; extra == 'all' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - name: locket - version: 1.0.0 - sha256: b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3 - requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' -- pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl - name: mando - version: 0.7.1 - sha256: 26ef1d70928b6057ee3ca12583d73c63e05c49de8972d620c278a7b206581a8a - requires_dist: - - six - - argparse ; python_full_version < '2.7' - - funcsigs ; python_full_version < '3.3' - - rst2ansi ; extra == 'restructuredtext' -- pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - name: markdown - version: 3.10.2 - sha256: e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36 - requires_dist: - - coverage ; extra == 'testing' - - pyyaml ; extra == 'testing' - - mkdocs>=1.6 ; extra == 'docs' - - mkdocs-nature>=0.6 ; extra == 'docs' - - mdx-gh-links>=0.2 ; extra == 'docs' - - mkdocstrings[python]>=0.28.3 ; extra == 'docs' - - mkdocs-gen-files ; extra == 'docs' - - mkdocs-section-index ; extra == 'docs' - - mkdocs-literate-nav ; extra == 'docs' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl - name: markdown-it-py - version: 4.2.0 - sha256: 9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a - requires_dist: - - mdurl~=0.1 - - psutil ; extra == 'benchmarking' - - pytest ; extra == 'benchmarking' - - pytest-benchmark ; extra == 'benchmarking' - - commonmark~=0.9 ; extra == 'compare' - - markdown~=3.4 ; extra == 'compare' - - mistletoe~=1.0 ; extra == 'compare' - - mistune~=3.0 ; extra == 'compare' - - panflute~=2.3 ; extra == 'compare' - - markdown-it-pyrs ; extra == 'compare' - - linkify-it-py>=1,<3 ; extra == 'linkify' - - mdit-py-plugins>=0.5.0 ; extra == 'plugins' - - gprof2dot ; extra == 'profiling' - - mdit-py-plugins>=0.5.0 ; extra == 'rtd' - - myst-parser ; extra == 'rtd' - - pyyaml ; extra == 'rtd' - - sphinx ; extra == 'rtd' - - sphinx-copybutton ; extra == 'rtd' - - sphinx-design ; extra == 'rtd' - - sphinx-book-theme~=1.0 ; extra == 'rtd' - - jupyter-sphinx ; extra == 'rtd' - - ipykernel ; extra == 'rtd' - - coverage ; extra == 'testing' - - pytest ; extra == 'testing' - - pytest-cov ; extra == 'testing' - - pytest-regressions ; extra == 'testing' - - pytest-timeout ; extra == 'testing' - - requests ; extra == 'testing' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda - sha256: 5f3aad1f3a685ed0b591faad335957dbdb1b73abfd6fc731a0d42718e0653b33 - md5: 93a4752d42b12943a355b682ee43285b + size: 313930 + timestamp: 1765813902568 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py312h6ef9ec0_0.conda + sha256: ea06f6f66b1bea97244c36fd2788ccd92fd1fb06eae98e469dd95ee80831b057 + md5: a7cfbbdeb93bb9a3f249bc4c3569cd4c depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.12,<3.13.0a0 + - python + - __osx >=11.0 + - python 3.12.* *_cpython - python_abi 3.12.* *_cp312 constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD + - __osx >=11.0 + license: MIT + license_family: MIT purls: - - pkg:pypi/markupsafe?source=hash-mapping - size: 26057 - timestamp: 1772445297924 -- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda - sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf - md5: 9a17c4307d23318476d7fbf0fedc0cde + - pkg:pypi/rpds-py?source=hash-mapping + size: 358853 + timestamp: 1764543161524 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda + sha256: e161dd97403b8b8a083d047369a5cf854557dba1204d29e2f0250f5ac4403925 + md5: 76a4f88d1b7748c477abf3c341edc64c depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.14,<3.15.0a0 + - python + - __osx >=11.0 + - python 3.14.* *_cp314 - python_abi 3.14.* *_cp314 constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD + - __osx >=11.0 + license: MIT + license_family: MIT purls: - - pkg:pypi/markupsafe?source=hash-mapping - size: 27424 - timestamp: 1772445227915 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda - sha256: 330394fb9140995b29ae215a19fad46fcc6691bdd1b7654513d55a19aaa091c1 - md5: 11d95ab83ef0a82cc2de12c1e0b47fe4 + - pkg:pypi/rpds-py?source=hash-mapping + size: 350976 + timestamp: 1764543169524 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 + md5: a9d86bc62f39b94c4661716624eb21b0 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3127137 + timestamp: 1769460817696 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda + sha256: 29edd36311b4a810a9e6208437bdbedb28c9ac15221caf812cb5c5cf48375dca + md5: 02cce5319b0f1317d9642dcb2e475379 depends: - __osx >=11.0 - python >=3.12,<3.13.0a0 - python >=3.12,<3.13.0a0 *_cpython - python_abi 3.12.* *_cp312 - constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD + license: Apache-2.0 + license_family: Apache purls: - - pkg:pypi/markupsafe?source=hash-mapping - size: 25564 - timestamp: 1772445846939 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda - sha256: 411153d14ee0d98be6e3751cf5cc0502db17bce2deebebb8779e33d29d0e525f - md5: d33c0a15882b70255abdd54711b06a45 + - pkg:pypi/tornado?source=hash-mapping + size: 859155 + timestamp: 1774358568476 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda + sha256: 4ccc4a20d676c0ba85adee9c99015bec7f5b685df0cf8006e34573f1d6c2ce75 + md5: 3f81f8b2fe2c26a82c0abf57ab2b9610 depends: - __osx >=11.0 - python >=3.14,<3.15.0a0 - python >=3.14,<3.15.0a0 *_cp314 - python_abi 3.14.* *_cp314 - constrains: - - jinja2 >=3.0.0 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 910845 + timestamp: 1774358965067 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + sha256: b03433b13d89f5567e828ea9f1a7d5c5d697bf374c28a4168d71e9464f5dafac + md5: 78a0fe9e9c50d2c381e8ee47e3ea437d + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 83386 + timestamp: 1753484079473 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + sha256: 2705360c72d4db8de34291493379ffd13b09fd594d0af20c9eefa8a3f060d868 + md5: e85dcd3bde2b10081cdcaeae15797506 + depends: + - __osx >=11.0 + - libcxx >=19 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 245246 + timestamp: 1772476886668 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 + md5: ab136e4c34e97f34fb621d2592a393d8 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD + purls: [] + size: 433413 + timestamp: 1764777166076 +- conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda + sha256: 38c5e43d991b0c43713fa2ceba3063afa4ccad2dd4c8eb720143de54d461a338 + md5: 5dc3781bbc4ddce0bf250a04c1a192c2 + depends: + - cffi >=1.0.1 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT purls: - - pkg:pypi/markupsafe?source=hash-mapping - size: 27256 - timestamp: 1772445397216 -- conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda - sha256: b744287a780211ac4595126ef96a44309c791f155d4724021ef99092bae4aace - md5: a73298d225c7852f97403ca105d10a13 + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 38535 + timestamp: 1762509763237 +- conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda + sha256: a742e7cd0d5534bfff3fd550a0c1e430411fad60a24f88930d261056ab08096f + md5: ffa247e46f47e157851dc547f4c513e4 + depends: + - cffi >=2.0.0b1 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 38653 + timestamp: 1762509771011 +- conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.4.0-py312h06d0912_0.conda + sha256: 71caf40c0fdeb11fafaac639e6e6f9120112aa105a7a5e9dfb5b4b06db9ca97a + md5: 77d0a2bdd46dd8d502bb27eb80353fcd + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 237107 + timestamp: 1777848740547 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda + sha256: 2bb6f384a51929ef2d5d6039fcf6c294874f20aaab2f63ca768cbe462ed4b379 + md5: e8e7a6346a9e50d19b4daf41f367366f + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hfd05255_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 335482 + timestamp: 1764018063640 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + sha256: 6854ee7675135c57c73a04849c29cbebc2fb6a3a3bfee1f308e64bf23074719b + md5: 1302b74b93c44791403cbeee6a0f62a3 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hfd05255_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 335782 + timestamp: 1764018443683 +- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + sha256: 76dfb71df5e8d1c4eded2dbb5ba15bb8fb2e2b0fe42d94145d5eed4c75c35902 + md5: 4cb8e6b48f67de0b018719cdf1136306 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 56115 + timestamp: 1771350256444 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py312he06e257_1.conda + sha256: 3e3bdcb85a2e79fe47d9c8ce64903c76f663b39cb63b8e761f6f884e76127f82 + md5: 46f7dccfee37a52a97c0ed6f33fcf0a3 depends: + - pycparser - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 291324 + timestamp: 1761203195397 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + sha256: 924f2f01fa7a62401145ef35ab6fc95f323b7418b2644a87fea0ea68048880ed + md5: c360170be1c9183654a240aadbedad94 + depends: + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 294731 + timestamp: 1761203441365 +- conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py312ha1a9051_0.conda + sha256: 5a886b1af3c66bf58213c7f3d802ea60fe8218313d9072bc1c9e8f7840548ba0 + md5: 032746a0b0663920f0afb18cec61062b + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 3996113 + timestamp: 1769745013982 +- conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda + sha256: ece1d8299ad081edaf1e5279f2a900bdedddb2c795ac029a06401543cd7610ad + md5: 48ae8370a4562f7049d587d017792a3a + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT purls: - - pkg:pypi/markupsafe?source=hash-mapping - size: 28510 - timestamp: 1772445175216 -- conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda - sha256: 02805a0f3cd168dbf13afc5e4aed75cc00fe538ce143527a6471485b36f5887c - md5: 8de7b40f8b30a8fcaa423c2537fe4199 + - pkg:pypi/debugpy?source=hash-mapping + size: 4026404 + timestamp: 1769745008861 +- conda: https://conda.anaconda.org/conda-forge/win-64/gsl-2.8-h5b8d9c4_1.conda + sha256: 87a3468e09cc1ee0268e8639debad6a5b440090ef8cb1d2ee5eed66c86085528 + md5: a47cf810b7c03955139a150b228b93ca depends: - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: GPL-3.0-or-later + license_family: GPL + purls: [] + size: 1528970 + timestamp: 1737622367981 +- conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + sha256: eb60f1ad8b597bcf95dee11bc11fe71a8325bc1204cf51d2bb1f2120ffd77761 + md5: 4432f52dc0c8eb6a7a6abc00a037d93c + depends: + - openssl >=3.5.5,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 751055 + timestamp: 1769769688841 +- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-7_h8455456_mkl.conda + build_number: 7 + sha256: 9eec27eee4300284e62a61cb2298089c80d31f6f9e924eeabc06e9788a00cffe + md5: 269e54b44974ff48846b4c31d0397041 + depends: + - mkl >=2026.0.0,<2027.0a0 constrains: - - jinja2 >=3.0.0 + - blas 2.307 mkl + - libcblas 3.11.0 7*_mkl + - liblapacke 3.11.0 7*_mkl + - liblapack 3.11.0 7*_mkl license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/markupsafe?source=hash-mapping - size: 30022 - timestamp: 1772445159549 -- pypi: https://files.pythonhosted.org/packages/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.whl - name: matplotlib - version: 3.10.9 - sha256: d091f9d758b34aaaaa6331d13574bf01891d903b3dec59bfff458ef7551de5d6 - requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.23 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=3 - - python-dateutil>=2.7 - - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' - - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' - - setuptools-scm>=7,<10 ; extra == 'dev' - - setuptools>=64 ; extra == 'dev' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: matplotlib - version: 3.10.9 - sha256: 34cf8167e023ad956c15f36302911d5406bd99a9862c1a8499ea6f7c0e015dc2 - requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.23 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=3 - - python-dateutil>=2.7 - - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' - - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' - - setuptools-scm>=7,<10 ; extra == 'dev' - - setuptools>=64 ; extra == 'dev' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - name: matplotlib - version: 3.10.9 - sha256: ae20801130378b82d647ff5047c07316295b68dc054ca6b3c13519d0ea624285 - requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.23 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=3 - - python-dateutil>=2.7 - - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' - - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' - - setuptools-scm>=7,<10 ; extra == 'dev' - - setuptools>=64 ; extra == 'dev' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl - name: matplotlib - version: 3.10.9 - sha256: 97e35e8d39ccc85859095e01a53847432ba9a53ddf7986f7a54a11b73d0e143f - requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.23 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=3 - - python-dateutil>=2.7 - - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' - - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' - - setuptools-scm>=7,<10 ; extra == 'dev' - - setuptools>=64 ; extra == 'dev' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl - name: matplotlib - version: 3.10.9 - sha256: 336b9acc64d309063126edcdaca00db9373af3c476bb94388fe9c5a53ad13e6f - requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.23 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=3 - - python-dateutil>=2.7 - - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' - - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' - - setuptools-scm>=7,<10 ; extra == 'dev' - - setuptools>=64 ; extra == 'dev' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/b7/18/4880dd762e40cd360c1bf06e890c5a97b997e91cb324602b1a19950ad5ce/matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl - name: matplotlib - version: 3.10.9 - sha256: 41cb28c2bd769aa3e98322c6ab09854cbcc52ab69d2759d681bba3e327b2b320 - requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.23 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=3 - - python-dateutil>=2.7 - - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' - - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' - - setuptools-scm>=7,<10 ; extra == 'dev' - - setuptools>=64 ; extra == 'dev' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda - sha256: 35b43d7343f74452307fd018a1cca92b8f68961ff8e2ab6a81ce0a703c9a3764 - md5: 9acc1c385be401d533ff70ef5b50dae6 + purls: [] + size: 68060 + timestamp: 1778490352569 +- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-7_h2a3cdd5_mkl.conda + build_number: 7 + sha256: 82da0f854831f783f9d3f1219c4255956e8167a474f3f526151128f02453871c + md5: 4700b7af6acefb26ff0127ba68230941 depends: - - python >=3.10 - - traitlets - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/matplotlib-inline?source=compressed-mapping - size: 15725 - timestamp: 1778264403247 -- pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl - name: mdit-py-plugins - version: 0.6.0 - sha256: f7e7a25d8b616fee99cb1e330da73451d11a8061baf39bb9663ab9ce0e005b90 - requires_dist: - - markdown-it-py>=2.0.0,<5.0.0 - - pre-commit ; extra == 'code-style' - - myst-parser ; extra == 'rtd' - - sphinx-book-theme ; extra == 'rtd' - - coverage ; extra == 'testing' - - pytest ; extra == 'testing' - - pytest-cov ; extra == 'testing' - - pytest-regressions ; extra == 'testing' - - pytest-timeout ; extra == 'testing' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - name: mdurl - version: 0.1.2 - sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - name: mergedeep - version: 1.3.4 - sha256: 70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 - requires_python: '>=3.6' -- pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl - name: mike - version: 2.2.0 - sha256: e1f4981c1152eec7c2490a3401142292cc47d686194188416db2648fdfe1d040 - requires_dist: - - jinja2>=2.7 - - mkdocs~=1.0 - - pyparsing>=3.0 - - pyyaml>=5.1 - - pyyaml-env-tag - - verspec - - importlib-metadata ; python_full_version < '3.10' - - importlib-resources ; python_full_version < '3.10' - - coverage ; extra == 'dev' - - flake8-quotes ; extra == 'dev' - - flake8>=3.0 ; extra == 'dev' - - shtab ; extra == 'dev' - - coverage ; extra == 'test' - - flake8-quotes ; extra == 'test' - - flake8>=3.0 ; extra == 'test' - - shtab ; extra == 'test' -- conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.1-pyhcf101f3_0.conda - sha256: b52dc6c78fbbe7a3008535cb8bfd87d70d8053e9250bbe16e387470a9df07070 - md5: b97e84d1553b4a1c765b87fff83453ad + - libblas 3.11.0 7_h8455456_mkl + constrains: + - blas 2.307 mkl + - liblapacke 3.11.0 7*_mkl + - liblapack 3.11.0 7*_mkl + license: BSD-3-Clause + purls: [] + size: 68594 + timestamp: 1778490364980 +- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.0-hac47afa_0.conda + sha256: 2d81d647c1f01108803457cac999b947456f44dd0a3c2325395677feacaeca67 + md5: 264e350e035092b5135a2147c238aec4 depends: - - python >=3.10 - - typing_extensions - - python + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - expat 2.8.0.* + license: MIT + license_family: MIT + purls: [] + size: 71094 + timestamp: 1777846223617 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + sha256: 59d01f2dfa8b77491b5888a5ab88ff4e1574c9359f7e229da254cdfe27ddc190 + md5: 720b39f5ec0610457b725eb3f396219a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 45831 + timestamp: 1769456418774 +- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda + sha256: 8cdf11333a81085468d9aa536ebb155abd74adc293576f6013fc0c85a7a90da3 + md5: 3b576f6860f838f950c570f4433b086e + depends: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - libxml2 + - libxml2-16 >=2.14.6 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD - purls: - - pkg:pypi/mistune?source=hash-mapping - size: 74567 - timestamp: 1777824616382 -- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl - name: mkdocs - version: 1.6.1 - sha256: db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e - requires_dist: - - click>=7.0 - - colorama>=0.4 ; sys_platform == 'win32' - - ghp-import>=1.0 - - importlib-metadata>=4.4 ; python_full_version < '3.10' - - jinja2>=2.11.1 - - markdown>=3.3.6 - - markupsafe>=2.0.1 - - mergedeep>=1.3.4 - - mkdocs-get-deps>=0.2.0 - - packaging>=20.5 - - pathspec>=0.11.1 - - pyyaml-env-tag>=0.1 - - pyyaml>=5.1 - - watchdog>=2.0 - - babel>=2.9.0 ; extra == 'i18n' - - babel==2.9.0 ; extra == 'min-versions' - - click==7.0 ; extra == 'min-versions' - - colorama==0.4 ; sys_platform == 'win32' and extra == 'min-versions' - - ghp-import==1.0 ; extra == 'min-versions' - - importlib-metadata==4.4 ; python_full_version < '3.10' and extra == 'min-versions' - - jinja2==2.11.1 ; extra == 'min-versions' - - markdown==3.3.6 ; extra == 'min-versions' - - markupsafe==2.0.1 ; extra == 'min-versions' - - mergedeep==1.3.4 ; extra == 'min-versions' - - mkdocs-get-deps==0.2.0 ; extra == 'min-versions' - - packaging==20.5 ; extra == 'min-versions' - - pathspec==0.11.1 ; extra == 'min-versions' - - pyyaml-env-tag==0.1 ; extra == 'min-versions' - - pyyaml==5.1 ; extra == 'min-versions' - - watchdog==2.0 ; extra == 'min-versions' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl - name: mkdocs-autorefs - version: 1.4.4 - sha256: 834ef5408d827071ad1bc69e0f39704fa34c7fc05bc8e1c72b227dfdc5c76089 - requires_dist: - - markdown>=3.3 - - markupsafe>=2.0.1 - - mkdocs>=1.1 - requires_python: '>=3.9' -- 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.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/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl - name: mkdocs-jupyter - version: 0.26.3 - sha256: cd6644fb578131157194d750fd4d10fc2fd8f1e84e00036ee62df3b5b4b84c82 - requires_dist: - - ipykernel>6.0.0,<8 - - jupytext>1.13.8,<2 - - mkdocs-material>9.0.0 - - mkdocs>=1.4.0,<2 - - nbconvert>=7.2.9,<8 - - pygments>2.12.0 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl - name: mkdocs-markdownextradata-plugin - version: 0.2.6 - sha256: 34dd40870781784c75809596b2d8d879da783815b075336d541de1f150c94242 - requires_dist: - - mkdocs - - pyyaml - requires_python: '>=3.6' -- pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl - name: mkdocs-material - version: 9.7.6 - sha256: 71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba - requires_dist: - - babel>=2.10 - - backrefs>=5.7.post1 - - colorama>=0.4 - - jinja2>=3.1 - - markdown>=3.2 - - mkdocs-material-extensions>=1.3 - - mkdocs>=1.6,<2 - - paginate>=0.5 - - pygments>=2.16 - - pymdown-extensions>=10.2 - - requests>=2.30 - - mkdocs-git-committers-plugin-2>=1.1 ; extra == 'git' - - mkdocs-git-revision-date-localized-plugin>=1.2.4 ; extra == 'git' - - cairosvg>=2.6 ; extra == 'imaging' - - pillow>=10.2 ; extra == 'imaging' - - mkdocs-minify-plugin>=0.7 ; extra == 'recommended' - - mkdocs-redirects>=1.2 ; extra == 'recommended' - - mkdocs-rss-plugin>=1.6 ; extra == 'recommended' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl - name: mkdocs-material-extensions - version: 1.3.1 - sha256: adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl - name: mkdocs-plugin-inline-svg - version: 0.1.0 - sha256: a5aab2d98a19b24019f8e650f54fc647c2f31e7d0e36fc5cf2d2161acc0ea49a - requires_dist: - - mkdocs - requires_python: '>=3.5' -- pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl - name: mkdocstrings - version: 1.0.4 - sha256: 63464b4b29053514f32a1dbbf604e52876d5e638111b0c295ab7ed3cac73ca9b - requires_dist: - - jinja2>=3.1 - - markdown>=3.6 - - markupsafe>=1.1 - - mkdocs>=1.6 - - mkdocs-autorefs>=1.4 - - pymdown-extensions>=6.3 - - mkdocstrings-crystal>=0.3.4 ; extra == 'crystal' - - mkdocstrings-python-legacy>=0.2.1 ; extra == 'python-legacy' - - mkdocstrings-python>=1.16.2 ; extra == 'python' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - name: mkdocstrings-python - version: 2.0.3 - sha256: 0b83513478bdfd803ff05aa43e9b1fca9dd22bcd9471f09ca6257f009bc5ee12 - requires_dist: - - mkdocstrings>=0.30 - - mkdocs-autorefs>=1.4 - - griffelib>=2.0 - - typing-extensions>=4.0 ; python_full_version < '3.11' - requires_python: '>=3.10' + purls: [] + size: 2411241 + timestamp: 1765104337762 +- conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + sha256: 0dcdb1a5f01863ac4e8ba006a8b0dc1a02d2221ec3319b5915a1863254d7efa7 + md5: 64571d1dd6cdcfa25d0664a5950fdaa2 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-only + purls: [] + size: 696926 + timestamp: 1754909290005 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + sha256: d636d1a25234063642f9c531a7bb58d84c1c496411280a36ea000bd122f078f1 + md5: 8f83619ab1588b98dd99c90b0bfc5c6d + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + size: 106486 + timestamp: 1775825663227 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + sha256: 40dcd0b9522a6e0af72a9db0ced619176e7cfdb114855c7a64f278e73f8a7514 + md5: e4a9fc2bba3b022dad998c78856afe47 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 89411 + timestamp: 1769482314283 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + sha256: d915f4fa8ebbf237c7a6e511ed458f2cfdc7c76843a924740318a15d0dd33d6d + md5: da2aa614d16a795b3007b6f4a1318a81 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: ISC + purls: [] + size: 276860 + timestamp: 1772479407566 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.1-hf5d6505_0.conda + sha256: e70562450332ca8954bc16f3455468cca5ef3695c7d7187ecc87f8fc3c70e9eb + md5: 7fea434a17c323256acc510a041b80d7 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: blessing + purls: [] + size: 1304178 + timestamp: 1777986510497 +- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + sha256: 0fccf2d17026255b6e10ace1f191d0a2a18f2d65088fd02430be17c701f8ffe0 + md5: 8a86073cf3b343b87d03f41790d8b4e5 + depends: + - ucrt + constrains: + - pthreads-win32 <0.0a0 + - msys2-conda-epoch <0.0a0 + license: MIT AND BSD-3-Clause-Clear + purls: [] + size: 36621 + timestamp: 1759768399557 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h692994f_0.conda + sha256: 8038084c60eda2006d0122d05e3364fe8db0a18935ca6ed0168b5ba5aa33f904 + md5: f7d6fcda29570e20851b78d92ea2154e + depends: + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libxml2 2.15.3 + - icu <0.0a0 + license: MIT + license_family: MIT + purls: [] + size: 518869 + timestamp: 1776376971242 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_0.conda + sha256: da68af9d9d28d65a6916db1bef68f8a25c64c4fdcf759f32a2d2f2f143220adf + md5: e3b5acbb857a12f5d59e8d174bc536c0 + depends: + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.3 h692994f_0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - icu <0.0a0 + license: MIT + license_family: MIT + purls: [] + size: 43916 + timestamp: 1776376994334 +- 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.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 58347 + timestamp: 1774072851498 +- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.5-h4fa8253_1.conda + sha256: 7179e0266125c3333a097b399d0383734ee6c55fbadf332b447237a596e9698f + md5: bffe599d0eb2e78a32872712178e639c + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - openmp 22.1.5|22.1.5.* + - intel-openmp <0.0a0 + license: Apache-2.0 WITH LLVM-exception + purls: [] + size: 347493 + timestamp: 1778448334890 +- conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda + sha256: b744287a780211ac4595126ef96a44309c791f155d4724021ef99092bae4aace + md5: a73298d225c7852f97403ca105d10a13 + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 28510 + timestamp: 1772445175216 +- conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + sha256: 02805a0f3cd168dbf13afc5e4aed75cc00fe538ce143527a6471485b36f5887c + md5: 8de7b40f8b30a8fcaa423c2537fe4199 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 30022 + timestamp: 1772445159549 - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.0.0-hac47afa_905.conda sha256: 76a43359adae10aef8de7ff8e4fab70647bda928146374298506afab2e4a7b4f md5: 7741affec1b3d2275586397ed4c91639 @@ -8524,1850 +7712,1886 @@ packages: purls: [] size: 114620200 timestamp: 1778111077072 -- pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl - name: mpld3 - version: 0.5.12 - sha256: bea31799a4041029a906f53f2662bbf1c49903e0c0bc712b412354158ec7cf54 - requires_dist: - - jinja2 - - matplotlib -- pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl - name: mpltoolbox - version: 26.2.0 - sha256: cd2668db4216fc4d7c2ba37974961aa61445f1517527b645b6082930e35ba7f0 - requires_dist: - - matplotlib - - ipympl ; extra == 'test' - - pytest>=8.0 ; extra == 'test' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - name: mpmath - version: 1.3.0 - sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c - requires_dist: - - pytest>=4.6 ; extra == 'develop' - - pycodestyle ; extra == 'develop' - - pytest-cov ; extra == 'develop' - - codecov ; extra == 'develop' - - wheel ; extra == 'develop' - - sphinx ; extra == 'docs' - - gmpy2>=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' - - pytest>=4.6 ; extra == 'tests' -- pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl - name: msgpack - version: 1.1.2 - sha256: 6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: msgpack - version: 1.1.2 - sha256: 180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl - name: msgpack - version: 1.1.2 - sha256: 446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: msgpack - version: 1.1.2 - sha256: 372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl - name: msgpack - version: 1.1.2 - sha256: 9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl - name: msgpack - version: 1.1.2 - sha256: 1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py312h4c3975b_0.conda - sha256: 25eb262c378a922eeed85c941ab7de2687ea842daed80521b861b7472b5a7f9a - md5: 5e07dc45b4458c19fdc085bd6c1aa51f +- conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py312he06e257_0.conda + sha256: 003de3343b481937b5eb500ecdbfc882e87cea608be3741dc1fb13d22f8ed95e + md5: 1f32f4f6aa595377a7e651e67ba53d30 + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 199413 + timestamp: 1776337631789 +- conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda + sha256: 6a076225fa315d29c5d556e3912a6319aea60b4f458c23f23f5ce66495cb9414 + md5: a4b20f401c93cf8651093fcc8380e3c9 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 201836 + timestamp: 1776337750218 +- 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: 31271315 + timestamp: 1774517904472 +- conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda + sha256: 848a7215e1ce227139074461664d01c00e7e1e8a367ccbd6581c0860d6ec4a19 + md5: fea22e21062046ba44336de37f4b6372 + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + size: 41103 + timestamp: 1778110756075 +- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + sha256: feb5815125c60f2be4a411e532db1ed1cd2d7261a6a43c54cb6ae90724e2e154 + md5: 05c7d624cff49dbd8db1ad5ba537a8a3 + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 9410183 + timestamp: 1775589779763 +- conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py312he5662c2_0.conda + sha256: edffc84c001a05b996b5f8607c8164432754e86ec9224e831cd00ebabdec04e7 + md5: a2724c93b745fc7861948eb8b9f6679a + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 242769 + timestamp: 1769678170631 +- conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + sha256: 17c8274ce5a32c9793f73a5a0094bd6188f3a13026a93147655143d4df034214 + md5: fd539ac231820f64066839251aa9fa48 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 249950 + timestamp: 1769678167309 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.13-h0159041_0_cpython.conda + sha256: a02b446d8b7b167b61733a3de3be5de1342250403e72a63b18dac89e99e6180e + md5: 2956dff38eb9f8332ad4caeba941cfe7 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 15840187 + timestamp: 1772728877265 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + build_number: 100 + sha256: e258d626b0ba778abb319f128de4c1211306fe86fe0803166817b1ce2514c920 + md5: 40b6a8f438afb5e7b314cc5c4a43cd84 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.12,<3.13.0a0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.5,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.52.0,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + - python_abi 3.14.* *_cp314 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + size: 18055445 + timestamp: 1775615317758 + python_site_packages_path: Lib/site-packages +- conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py312h829343e_1.conda + sha256: a7505522048dad63940d06623f07eb357b9b65510a8d23ff32b99add05aac3a1 + md5: 64cbe4ecbebe185a2261d3f298a60cde + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 - python_abi 3.12.* *_cp312 - license: BSD-3-Clause - license_family: BSD + license: PSF-2.0 + license_family: PSF purls: - - pkg:pypi/msgspec?source=hash-mapping - size: 218330 - timestamp: 1776337395109 -- conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda - sha256: 52565ceea81e801c59dcaeaf5a9c77fba2fade445e67e0864fda50d4b944e15b - md5: 4a8ea416a56e58f012e445f7af2bbcc8 + - pkg:pypi/pywin32?source=hash-mapping + size: 6684490 + timestamp: 1756487136116 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda + sha256: 6918a8067f296f3c65d43e84558170c9e6c3f4dd735cfe041af41a7fdba7b171 + md5: 2d7b7ba21e8a8ced0eca553d4d53f773 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.14,<3.15.0a0 + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 - python_abi 3.14.* *_cp314 - license: BSD-3-Clause - license_family: BSD + license: PSF-2.0 + license_family: PSF purls: - - pkg:pypi/msgspec?source=hash-mapping - size: 220990 - timestamp: 1776337508167 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py312h2bbb03f_0.conda - sha256: 50e284832520f08ef1e37e0ca20459f5df2c048f59dfba1f2e3ee0ccfe7be317 - md5: ae340bdc5bdf5abd3183c5962517cbde + - pkg:pypi/pywin32?source=hash-mapping + size: 6713155 + timestamp: 1756487145487 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py312h275cf98_1.conda + sha256: 61cc6c2c712ab4d2b8e7a73d884ef8d3262cb80cc93a4aa074e8b08aa7ddd648 + md5: 66255d136bd0daa41713a334db41d9f0 depends: - - __osx >=11.0 - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - python_abi 3.12.* *_cp312 - license: BSD-3-Clause - license_family: BSD + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - winpty + license: MIT + license_family: MIT purls: - - pkg:pypi/msgspec?source=hash-mapping - size: 212357 - timestamp: 1776338798628 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda - sha256: 24a9105921e94fa526ffde1e956fa550c48ddb9ce4b0cf19ae22e79ed267261e - md5: 26fce586b13842a0f9f9a3aabae3e943 + - pkg:pypi/pywinpty?source=hash-mapping + size: 215371 + timestamp: 1759557609855 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda + sha256: 048e20641da680aedaab285640a2aca56b7b5baf7a18f8f164f2796e13628c1f + md5: dd84e8748bd3c85a5c751b0576488080 depends: - - __osx >=11.0 - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 + - python >=3.14.0rc3,<3.15.0a0 - python_abi 3.14.* *_cp314 - license: BSD-3-Clause - license_family: BSD + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - winpty + license: MIT + license_family: MIT purls: - - pkg:pypi/msgspec?source=hash-mapping - size: 216965 - timestamp: 1776338889692 -- conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py312he06e257_0.conda - sha256: 003de3343b481937b5eb500ecdbfc882e87cea608be3741dc1fb13d22f8ed95e - md5: 1f32f4f6aa595377a7e651e67ba53d30 + - pkg:pypi/pywinpty?source=hash-mapping + size: 216325 + timestamp: 1759557436167 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py312h05f76fc_1.conda + sha256: 1cab6cbd6042b2a1d8ee4d6b4ec7f36637a41f57d2f5c5cf0c12b7c4ce6a62f6 + md5: 9f6ebef672522cb9d9a6257215ca5743 depends: - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - license: BSD-3-Clause - license_family: BSD + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT purls: - - pkg:pypi/msgspec?source=hash-mapping - size: 199413 - timestamp: 1776337631789 -- conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda - sha256: 6a076225fa315d29c5d556e3912a6319aea60b4f458c23f23f5ce66495cb9414 - md5: a4b20f401c93cf8651093fcc8380e3c9 + - pkg:pypi/pyyaml?source=hash-mapping + size: 179738 + timestamp: 1770223468771 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + sha256: a2aff34027aa810ff36a190b75002d2ff6f9fbef71ec66e567616ac3a679d997 + md5: 0cd9b88826d0f8db142071eb830bce56 depends: - python >=3.14,<3.15.0a0 - python_abi 3.14.* *_cp314 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - license: BSD-3-Clause - license_family: BSD + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT purls: - - pkg:pypi/msgspec?source=hash-mapping - size: 201836 - timestamp: 1776337750218 -- pypi: https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl - name: multidict - version: 6.7.1 - sha256: fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19 - requires_dist: - - typing-extensions>=4.1.0 ; python_full_version < '3.11' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl - name: multidict - version: 6.7.1 - sha256: b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7 - requires_dist: - - typing-extensions>=4.1.0 ; python_full_version < '3.11' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - name: multidict - version: 6.7.1 - sha256: 5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f - requires_dist: - - typing-extensions>=4.1.0 ; python_full_version < '3.11' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl - name: multidict - version: 6.7.1 - sha256: 0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1 - requires_dist: - - typing-extensions>=4.1.0 ; python_full_version < '3.11' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: multidict - version: 6.7.1 - sha256: bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961 - requires_dist: - - typing-extensions>=4.1.0 ; python_full_version < '3.11' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: multidict - version: 6.7.1 - sha256: 7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709 - requires_dist: - - typing-extensions>=4.1.0 ; python_full_version < '3.11' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl - name: narwhals - version: 2.21.0 - sha256: 1e6617d0fca68ae1fda29e5397c4eaacd3ffc9fffe6bcd6ded0c690475e853be - requires_dist: - - cudf-cu12>=24.10.0 ; extra == 'cudf' - - dask[dataframe]>=2024.8 ; extra == 'dask' - - duckdb>=1.1 ; extra == 'duckdb' - - ibis-framework>=6.0.0 ; extra == 'ibis' - - packaging ; extra == 'ibis' - - pyarrow-hotfix ; extra == 'ibis' - - rich ; extra == 'ibis' - - modin ; extra == 'modin' - - pandas>=1.1.3 ; extra == 'pandas' - - polars>=0.20.4 ; extra == 'polars' - - pyarrow>=13.0.0 ; extra == 'pyarrow' - - pyspark>=3.5.0 ; extra == 'pyspark' - - pyspark[connect]>=3.5.0 ; extra == 'pyspark-connect' - - duckdb>=1.1 ; extra == 'sql' - - sqlparse ; extra == 'sql' - - sqlframe>=3.22.0,!=3.39.3 ; extra == 'sqlframe' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - sha256: 1b66960ee06874ddceeebe375d5f17fb5f393d025a09e15b830ad0c4fffb585b - md5: 00f5b8dafa842e0c27c1cd7296aa4875 + - pkg:pypi/pyyaml?source=hash-mapping + size: 181257 + timestamp: 1770223460931 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + noarch: python + sha256: d84bcc19a945ca03d1fd794be3e9896ab6afc9f691d58d9c2da514abe584d4df + md5: eb1ec67a70b4d479f7dd76e6c8fe7575 depends: - - jupyter_client >=6.1.12 - - jupyter_core >=4.12,!=5.0.* - - nbformat >=5.1 - - python >=3.8 - - traitlets >=5.4 + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - zeromq >=4.3.5,<4.3.6.0a0 + - _python_abi3_support 1.* + - cpython >=3.12 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/nbclient?source=hash-mapping - size: 28473 - timestamp: 1766485646962 -- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda - sha256: ab2ac79c5892c5434d50b3542d96645bdaa06d025b6e03734be29200de248ac2 - md5: 2bce0d047658a91b99441390b9b27045 + - pkg:pypi/pyzmq?source=hash-mapping + size: 183235 + timestamp: 1771716967192 +- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py312hdabe01f_0.conda + sha256: faad05e6df2fc15e3ae06fdd71a36e17ff25364777aa4c40f2ec588740d64091 + md5: 2c51baeda0a355b0a5e7b6acb28cf02d + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 243577 + timestamp: 1764543069837 +- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda + sha256: e4435368c5c25076dc0f5918ba531c5a92caee8e0e2f9912ef6810049cf00db2 + md5: e86531e278ad304438e530953cd55d14 depends: - - beautifulsoup4 - - bleach-with-css !=5.0.0 - - defusedxml - - importlib-metadata >=3.6 - - jinja2 >=3.0 - - jupyter_core >=4.7 - - jupyterlab_pygments - - markupsafe >=2.0 - - mistune >=2.0.3,<4 - - nbclient >=0.5.0 - - nbformat >=5.7 - - packaging - - pandocfilters >=1.4.1 - - pygments >=2.4.1 - - python >=3.10 - - traitlets >=5.1 - python - constrains: - - pandoc >=2.9.2,<4.0.0 - - nbconvert ==7.17.1 *_0 - license: BSD-3-Clause + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 235780 + timestamp: 1764543046065 +- conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda + sha256: 5ff149ba6832bf4ded4b43bf0a41cde7be814802a95070553176c087f65b2a01 + md5: 34aa94d586fe95fa121966c0d4e73cf4 + depends: + - libhwloc >=2.12.2,<2.12.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 156910 + timestamp: 1777976465531 +- conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + sha256: 0e79810fae28f3b69fe7391b0d43f5474d6bd91d451d5f2bde02f55ae481d5e3 + md5: 0481bfd9814bf525bd4b3ee4b51494c4 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: TCL license_family: BSD + purls: [] + size: 3526350 + timestamp: 1769460339384 +- conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py312he06e257_0.conda + sha256: 1220c986664e9e8662e660dc64dd97ed823926b1ba05175771408cf1d6a46dd2 + md5: c6c66a64da3d2953c83ed2789a7f4bdb + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache purls: - - pkg:pypi/nbconvert?source=hash-mapping - size: 202229 - timestamp: 1775615493260 -- conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - sha256: 7a5bd30a2e7ddd7b85031a5e2e14f290898098dc85bea5b3a5bf147c25122838 - md5: bbe1963f1e47f594070ffe87cdf612ea + - pkg:pypi/tornado?source=hash-mapping + size: 859726 + timestamp: 1774358173994 +- conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda + sha256: 49d64837dd02475903479ca47b82669bd6c9f7e6afde61860c6f3f2bd57d8a03 + md5: 87b1215adf7f0ba1fb9250af9fc668e1 depends: - - jsonschema >=2.6 - - jupyter_core >=4.12,!=5.0.* - - python >=3.9 - - python-fastjsonschema >=2.15 - - traitlets >=5.1 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 914835 + timestamp: 1774358183098 +- conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 + md5: 71b24316859acd00bdb8b38f5e2ce328 + constrains: + - vc14_runtime >=14.29.30037 + - vs2015_runtime >=14.29.30037 + license: LicenseRef-MicrosoftWindowsSDK10 + purls: [] + size: 694692 + timestamp: 1756385147981 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + sha256: 9dc40c2610a6e6727d635c62cced5ef30b7b30123f5ef67d6139e23d21744b3a + md5: 1e610f2416b6acdd231c5f573d754a0f + depends: + - vc14_runtime >=14.44.35208 + track_features: + - vc14 license: BSD-3-Clause license_family: BSD - purls: - - pkg:pypi/nbformat?source=hash-mapping - size: 100945 - timestamp: 1733402844974 -- pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl - name: nbmake - version: 1.5.5 - sha256: c6fbe6e48b60cacac14af40b38bf338a3b88f47f085c54ac5b8639ff0babaf4b - requires_dist: - - ipykernel>=5.4.0 - - nbclient>=0.6.6 - - nbformat>=5.0.4 - - pygments>=2.7.3 - - pytest>=6.1.0 - requires_python: '>=3.8.0' -- pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl - name: nbqa - version: 1.9.1 - sha256: 95552d2f6c2c038136252a805aa78d85018aef922586270c3a074332737282e5 - requires_dist: - - autopep8>=1.5 - - ipython>=7.8.0 - - tokenize-rt>=3.2.0 - - tomli - - black ; extra == 'toolchain' - - blacken-docs ; extra == 'toolchain' - - flake8 ; extra == 'toolchain' - - isort ; extra == 'toolchain' - - jupytext ; extra == 'toolchain' - - mypy ; extra == 'toolchain' - - pylint ; extra == 'toolchain' - - pyupgrade ; extra == 'toolchain' - - ruff ; extra == 'toolchain' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl - name: nbstripout - version: 0.9.1 - sha256: ca027ee45742ee77e4f8e9080254f9a707f1161ba11367b82fdf4a29892c759e - requires_dist: - - nbformat - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl - name: ncrystal - version: 4.4.2 - sha256: e02fa7d743addc3fbea23287737a88b8d01192450fdca51554d3f9032fe4617c - requires_dist: - - ncrystal-core==4.4.2 - - ncrystal-python==4.4.2 - - spglib>=2.1.0 ; extra == 'composer' - - ase>=3.23.0 ; extra == 'cif' - - gemmi>=0.6.1 ; extra == 'cif' - - spglib>=2.1.0 ; extra == 'cif' - - endf-parserpy>=0.14.3 ; extra == 'endf' - - matplotlib>=3.6.0 ; extra == 'plot' - - ase>=3.23.0 ; extra == 'all' - - endf-parserpy>=0.14.3 ; extra == 'all' - - gemmi>=0.6.1 ; extra == 'all' - - matplotlib>=3.6.0 ; extra == 'all' - - spglib>=2.1.0 ; extra == 'all' - - pyyaml>=6.0.0 ; extra == 'devel' - - ase>=3.23.0 ; extra == 'devel' - - cppcheck ; extra == 'devel' - - endf-parserpy>=0.14.3 ; extra == 'devel' - - gemmi>=0.6.1 ; extra == 'devel' - - matplotlib>=3.6.0 ; extra == 'devel' - - mpmath>=1.3.0 ; extra == 'devel' - - numpy>=1.22 ; extra == 'devel' - - pybind11>=2.11.0 ; extra == 'devel' - - ruff>=0.8.1 ; extra == 'devel' - - simple-build-system>=1.6.0 ; extra == 'devel' - - spglib>=2.1.0 ; extra == 'devel' - - tomli>=2.0.0 ; python_full_version < '3.11' and extra == 'devel' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.whl - name: ncrystal-core - version: 4.4.2 - sha256: 9b28a90b63849e6a3a807a0a59f7c2ee57e4c64f5643b2dcb6a798ac8ccf666a - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.whl - name: ncrystal-core - version: 4.4.2 - sha256: b7e6101a6850aa18cf441825214381614db444ffcba648de8266fe1c4d1024ce - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: ncrystal-core - version: 4.4.2 - sha256: d0d9c47cd017b7cefc52dde50546d7c151bfdd75d345e42e2b3e74ab5fe83c62 - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl - name: ncrystal-python - version: 4.4.2 - sha256: f419318d088fade6bcff1e39e15baf6fe69fcf5306dd681fca1106d1f63a89ce - requires_dist: - - numpy>=1.22 - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 - md5: fc21868a1a5aacc937e7a18747acb8a5 + purls: [] + size: 19356 + timestamp: 1767320221521 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + sha256: 02732f953292cce179de9b633e74928037fa3741eb5ef91c3f8bae4f761d32a5 + md5: 37eb311485d2d8b2c419449582046a42 + depends: + - ucrt >=10.0.20348.0 + - vcomp14 14.44.35208 h818238b_34 + constrains: + - vs2015_runtime 14.44.35208.* *_34 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + size: 683233 + timestamp: 1767320219644 +- conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + sha256: 878d5d10318b119bd98ed3ed874bd467acbe21996e1d81597a1dbf8030ea0ce6 + md5: 242d9f25d2ae60c76b38a5e42858e51d + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.44.35208.* *_34 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + size: 115235 + timestamp: 1767320173250 +- conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + sha256: 9df10c5b607dd30e05ba08cbd940009305c75db242476f4e845ea06008b0a283 + md5: 1cee351bf20b830d991dbe0bc8cd7dfe + license: MIT + license_family: MIT + purls: [] + size: 1176306 +- conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + sha256: 80ee68c1e7683a35295232ea79bcc87279d31ffeda04a1665efdb43cbd50a309 + md5: 433699cba6602098ae8957a323da2664 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - license: X11 AND BSD-3-Clause + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT purls: [] - size: 918956 - timestamp: 1777422145199 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - sha256: 4ea6c620b87bd1d42bb2ccc2c87cd2483fa2d7f9e905b14c223f11ff3f4c455d - md5: 343d10ed5b44030a2f67193905aea159 + size: 63944 + timestamp: 1753484092156 +- conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda + sha256: b8568dfde46edf3455458912ea6ffb760e4456db8230a0cf34ecbc557d3c275f + md5: 1ab0237036bfb14e923d6107473b0021 depends: - - __osx >=11.0 - license: X11 AND BSD-3-Clause + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libsodium >=1.0.21,<1.0.22.0a0 + - krb5 >=1.22.2,<1.23.0a0 + license: MPL-2.0 + license_family: MOZILLA purls: [] - size: 805509 - timestamp: 1777423252320 -- conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - sha256: bb7b21d7fd0445ddc0631f64e66d91a179de4ba920b8381f29b9d006a42788c0 - md5: 598fd7d4d0de2455fb74f56063969a97 + size: 265665 + timestamp: 1772476832995 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + sha256: 368d8628424966fd8f9c8018326a9c779e06913dd39e646cf331226acc90e5b2 + md5: 053b84beec00b71ea8ff7a4f84b55207 depends: - - python >=3.9 - license: BSD-2-Clause + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause license_family: BSD - purls: - - pkg:pypi/nest-asyncio?source=hash-mapping - size: 11543 - timestamp: 1733325673691 -- pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl - name: networkx - version: 3.6.1 - sha256: d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762 + purls: [] + size: 388453 + timestamp: 1764777142545 +- pypi: . + name: easydiffraction + requires_dist: + - arviz + - asciichartpy + - asteval + - bumps + - colorama + - crysfml + - cryspy + - darkdetect + - dfo-ls + - diffpy-pdffit2 + - diffpy-utils + - gemmi + - lmfit + - numpy + - pandas + - plotly + - pooch + - py3dmol + - rich + - scipy + - sympy + - tabulate + - typeguard + - typer + - uncertainties + - varname + - build ; extra == 'dev' + - copier ; extra == 'dev' + - docstripy ; extra == 'dev' + - essdiffraction ; 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-benchmark ; 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' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/01/5c/87b5fefdd3c4b157c8a16833f2236723136806814584c4589610217252f0/diffpy_pdffit2-1.6.0-cp312-cp312-macosx_11_0_arm64.whl + name: diffpy-pdffit2 + version: 1.6.0 + sha256: 4c4418388b9ab4eaeb485a9950a455b3713d21319a98d61e9f69ca5b9a6b45e3 + requires_dist: + - diffpy-structure + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: scipy + version: 1.17.1 + sha256: 02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458 + requires_dist: + - numpy>=1.26.4,<2.7 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.10.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/03/c1/0976b235cf29ead553e22f2fb6385a8252b533715e00d0ae52ed7b900582/h5py-3.16.0-cp312-cp312-win_amd64.whl + name: h5py + version: 3.16.0 + sha256: 96b422019a1c8975c2d5dadcf61d4ba6f01c31f92bbde6e4649607885fe502d6 + requires_dist: + - numpy>=1.21.2 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + name: pyyaml-env-tag + version: '1.1' + sha256: 17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 + requires_dist: + - pyyaml + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: contourpy + version: 1.3.3 + sha256: f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3 + requires_dist: + - numpy>=1.25 + - furo ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - bokeh ; extra == 'bokeh' + - selenium ; extra == 'bokeh' + - contourpy[bokeh,docs] ; extra == 'mypy' + - bokeh ; extra == 'mypy' + - docutils-stubs ; extra == 'mypy' + - mypy==1.17.0 ; extra == 'mypy' + - types-pillow ; extra == 'mypy' + - contourpy[test-no-images] ; extra == 'test' + - matplotlib ; extra == 'test' + - pillow ; extra == 'test' + - pytest ; extra == 'test-no-images' + - pytest-cov ; extra == 'test-no-images' + - pytest-rerunfailures ; extra == 'test-no-images' + - pytest-xdist ; extra == 'test-no-images' + - wurlitzer ; extra == 'test-no-images' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.whl + name: matplotlib + version: 3.10.9 + sha256: d091f9d758b34aaaaa6331d13574bf01891d903b3dec59bfff458ef7551de5d6 + requires_dist: + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.23 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=3 + - python-dateutil>=2.7 + - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' + - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' + - setuptools-scm>=7,<10 ; extra == 'dev' + - setuptools>=64 ; extra == 'dev' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/04/f1/58c14b37525dc075f3bdf149251f079723049a9f1c82eb48835a0e6b8db3/diffpy_pdffit2-1.6.0-cp314-cp314-macosx_11_0_arm64.whl + name: diffpy-pdffit2 + version: 1.6.0 + sha256: 0e178ff1d40e6b652dedb96b744a2eb04320f58b21012304b29d52167b62afa5 + requires_dist: + - diffpy-structure + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/06/41/4e70dea1d0311016c0b0b1c53a24a266f9f8a34c6bc1af0f17cfca20aa1d/gemmi-0.7.5-cp314-cp314-macosx_11_0_arm64.whl + name: gemmi + version: 0.7.5 + sha256: 5144f107f2bca479d1b8266a79649bd631ee92c5b1319b27b0279157331ebc89 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl + name: python-socketio + version: 5.16.1 + sha256: a3eb1702e92aa2f2b5d3ba00261b61f062cce51f1cfb6900bf3ab4d1934d2d35 requires_dist: - - asv ; extra == 'benchmarking' - - virtualenv ; extra == 'benchmarking' - - numpy>=1.25 ; extra == 'default' - - scipy>=1.11.2 ; extra == 'default' - - matplotlib>=3.8 ; extra == 'default' - - pandas>=2.0 ; extra == 'default' - - pre-commit>=4.1 ; extra == 'developer' - - mypy>=1.15 ; extra == 'developer' - - sphinx>=8.0 ; extra == 'doc' - - pydata-sphinx-theme>=0.16 ; extra == 'doc' - - sphinx-gallery>=0.18 ; extra == 'doc' - - numpydoc>=1.8.0 ; extra == 'doc' - - pillow>=10 ; extra == 'doc' - - texext>=0.6.7 ; extra == 'doc' - - myst-nb>=1.1 ; extra == 'doc' - - intersphinx-registry ; extra == 'doc' - - osmnx>=2.0.0 ; extra == 'example' - - momepy>=0.7.2 ; extra == 'example' - - contextily>=1.6 ; extra == 'example' - - seaborn>=0.13 ; extra == 'example' - - cairocffi>=1.7 ; extra == 'example' - - igraph>=0.11 ; extra == 'example' - - scikit-learn>=1.5 ; extra == 'example' - - iplotx>=0.9.0 ; extra == 'example' - - lxml>=4.6 ; extra == 'extra' - - pygraphviz>=1.14 ; extra == 'extra' - - pydot>=3.0.1 ; extra == 'extra' - - sympy>=1.10 ; extra == 'extra' - - build>=0.10 ; extra == 'release' - - twine>=4.0 ; extra == 'release' - - wheel>=0.40 ; extra == 'release' - - changelist==0.5 ; extra == 'release' - - pytest>=7.2 ; extra == 'test' - - pytest-cov>=4.0 ; extra == 'test' - - pytest-xdist>=3.0 ; extra == 'test' - - pytest-mpl ; extra == 'test-extras' - - pytest-randomly ; extra == 'test-extras' - requires_python: '>=3.11,!=3.14.1' -- pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl - name: nodeenv - 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.8.2-he4ff34a_0.conda - sha256: d1a673d1418d9e956b6e4e46c23e72a511c5c1d45dc5519c947457427036d5e2 - md5: baffb1570b3918c784d4490babc52fbf - depends: - - libgcc >=14 - - 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 - license: MIT - license_family: MIT - purls: [] - size: 18829340 - timestamp: 1774514313036 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda - sha256: 4782b172b3b8a557b60bf5f591821cf100e2092ba7a5494ce047dfa41626de26 - md5: ca8277c52fdface8bb8ebff7cd9a6f56 - depends: - - libcxx >=19 - - __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* - license: MIT - license_family: MIT - purls: [] - 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: 31271315 - timestamp: 1774517904472 -- conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - sha256: 7b920e46b9f7a2d2aa6434222e5c8d739021dbc5cc75f32d124a8191d86f9056 - md5: e7f89ea5f7ea9401642758ff50a2d9c1 - depends: - - jupyter_server >=1.8,<3 - - python >=3.9 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/notebook-shim?source=hash-mapping - size: 16817 - timestamp: 1733408419340 + - bidict>=0.21.0 + - python-engineio>=4.11.0 + - requests>=2.21.0 ; extra == 'client' + - websocket-client>=0.54.0 ; extra == 'client' + - aiohttp>=3.4 ; extra == 'asyncio-client' + - tox ; extra == 'dev' + - sphinx ; extra == 'docs' + - furo ; extra == 'docs' + requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/0a/0d/0e3ecece05b7a7e87ab9fb587855548da437a061326fff64a223b6dcb78a/numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl name: numpy version: 2.4.4 sha256: 81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/2d/5b/e1deebf88ff431b01b7406ca3583ab2bbb90972bbe1c568732e49c844f7e/numpy-2.4.4-cp312-cp312-win_amd64.whl - name: numpy - version: 2.4.4 - sha256: b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl - name: numpy - version: 2.4.4 - sha256: 2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: numpy - version: 2.4.4 - sha256: 27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/9b/fd/e5ecca1e78c05106d98028114f5c00d3eddb41207686b2b7de3e477b0e22/numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl - name: numpy - version: 2.4.4 - sha256: 8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl - name: numpy - version: 2.4.4 - sha256: 715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 - requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/win-64/onemkl-license-2026.0.0-h57928b3_905.conda - sha256: 848a7215e1ce227139074461664d01c00e7e1e8a367ccbd6581c0860d6ec4a19 - md5: fea22e21062046ba44336de37f4b6372 - license: LicenseRef-IntelSimplifiedSoftwareOct2022 - license_family: Proprietary - purls: [] - size: 41103 - timestamp: 1778110756075 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda - sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb - md5: da1b85b6a87e141f5140bb9924cecab0 - depends: - - __glibc >=2.17,<3.0.a0 - - ca-certificates - - libgcc >=14 - license: Apache-2.0 - license_family: Apache - purls: [] - size: 3167099 - timestamp: 1775587756857 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda - sha256: c91bf510c130a1ea1b6ff023e28bac0ccaef869446acd805e2016f69ebdc49ea - md5: 25dcccd4f80f1638428613e0d7c9b4e1 - depends: - - __osx >=11.0 - - ca-certificates - license: Apache-2.0 - license_family: Apache - purls: [] - size: 3106008 - timestamp: 1775587972483 -- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda - sha256: feb5815125c60f2be4a411e532db1ed1cd2d7261a6a43c54cb6ae90724e2e154 - md5: 05c7d624cff49dbd8db1ad5ba537a8a3 - depends: - - ca-certificates - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: Apache-2.0 - license_family: Apache - purls: [] - size: 9410183 - timestamp: 1775589779763 -- conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c - md5: e51f1e4089cad105b6cac64bd8166587 - depends: - - python >=3.9 - - typing_utils - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/overrides?source=hash-mapping - size: 30139 - timestamp: 1734587755455 -- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 - md5: 4c06a92e74452cfa53623a81592e8934 - depends: - - python >=3.8 - - python - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/packaging?source=hash-mapping - size: 91574 - timestamp: 1777103621679 -- pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl - name: paginate - version: 0.5.7 - sha256: b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591 +- pypi: https://files.pythonhosted.org/packages/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: scipy + version: 1.17.1 + sha256: eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118 + requires_dist: + - numpy>=1.26.4,<2.7 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.10.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/0c/53/b50773ecf1d1e4a5858ee13011e30317ba02639ae4a1411a34967951fc9b/crysfml-0.6.2-cp314-cp314-win_amd64.whl + name: crysfml + version: 0.6.2 + sha256: 4278178f2028360f489f2cdfda7f2f7f26e4f1674b50eb934f403bb443a8f00a requires_dist: - - pytest ; extra == 'dev' - - tox ; extra == 'dev' - - black ; extra == 'lint' -- pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl - name: pandas - version: 3.0.3 - sha256: 3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5 + - numpy + requires_python: '>=3.11,<3.15' +- pypi: https://files.pythonhosted.org/packages/0d/1f/d398de1612f7a611e22d743280339c9af4903675635e41be3370091c704b/arviz_stats-1.1.0-py3-none-any.whl + name: arviz-stats + version: 1.1.0 + sha256: ed47334ccff8670a0b90a50e1a37e7257268084eb3436e6b7b15e623f1001947 requires_dist: - - numpy>=1.26.0 ; python_full_version < '3.14' - - numpy>=2.3.3 ; python_full_version >= '3.14' - - python-dateutil>=2.8.2 - - tzdata ; sys_platform == 'win32' - - tzdata ; sys_platform == 'emscripten' - - hypothesis>=6.116.0 ; extra == 'test' - - pytest>=8.3.4 ; extra == 'test' - - pytest-xdist>=3.6.1 ; extra == 'test' - - pyarrow>=13.0.0 ; extra == 'pyarrow' - - bottleneck>=1.4.2 ; extra == 'performance' - - numba>=0.60.0 ; extra == 'performance' - - numexpr>=2.10.2 ; extra == 'performance' - - scipy>=1.14.1 ; extra == 'computation' - - xarray>=2024.10.0 ; extra == 'computation' - - fsspec>=2024.10.0 ; extra == 'fss' - - s3fs>=2024.10.0 ; extra == 'aws' - - gcsfs>=2024.10.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.5 ; extra == 'excel' - - python-calamine>=0.3.0 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.2.0 ; extra == 'excel' - - pyarrow>=13.0.0 ; extra == 'parquet' - - pyarrow>=13.0.0 ; extra == 'feather' - - pyiceberg>=0.8.1 ; extra == 'iceberg' - - tables>=3.10.1 ; extra == 'hdf5' - - pyreadstat>=1.2.8 ; extra == 'spss' - - sqlalchemy>=2.0.36 ; extra == 'postgresql' - - psycopg2>=2.9.10 ; extra == 'postgresql' - - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.36 ; extra == 'mysql' - - pymysql>=1.1.1 ; extra == 'mysql' - - sqlalchemy>=2.0.36 ; extra == 'sql-other' - - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' - - beautifulsoup4>=4.12.3 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'xml' - - matplotlib>=3.9.3 ; extra == 'plot' - - jinja2>=3.1.5 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.4.2 ; extra == 'clipboard' - - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2020.1 ; extra == 'timezone' - - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - - beautifulsoup4>=4.12.3 ; extra == 'all' - - bottleneck>=1.4.2 ; extra == 'all' - - fastparquet>=2024.11.0 ; extra == 'all' - - fsspec>=2024.10.0 ; extra == 'all' - - gcsfs>=2024.10.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.116.0 ; extra == 'all' - - jinja2>=3.1.5 ; extra == 'all' - - lxml>=5.3.0 ; extra == 'all' - - matplotlib>=3.9.3 ; extra == 'all' - - numba>=0.60.0 ; extra == 'all' - - numexpr>=2.10.2 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.5 ; extra == 'all' - - psycopg2>=2.9.10 ; extra == 'all' - - pyarrow>=13.0.0 ; extra == 'all' - - pyiceberg>=0.8.1 ; extra == 'all' - - pymysql>=1.1.1 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.8 ; extra == 'all' - - pytest>=8.3.4 ; extra == 'all' - - pytest-xdist>=3.6.1 ; extra == 'all' - - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2020.1 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.4.2 ; extra == 'all' - - scipy>=1.14.1 ; extra == 'all' - - s3fs>=2024.10.0 ; extra == 'all' - - sqlalchemy>=2.0.36 ; extra == 'all' - - tables>=3.10.1 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2024.10.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.2.0 ; extra == 'all' - - zstandard>=0.23.0 ; extra == 'all' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - name: pandas - version: 3.0.3 - sha256: 9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a + - numpy>=2 + - scipy>=1.13 + - sphinx-book-theme ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx<9 ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'doc' + - sphinx-autosummary-accessors ; extra == 'doc' + - numba ; extra == 'numba' + - xarray-einstats[einops,numba] ; extra == 'numba' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest ; extra == 'test-xarray' + - pytest-cov ; extra == 'test-xarray' + - h5netcdf[h5py] ; extra == 'test-xarray' + - arviz-base>=1.1,<1.2 ; extra == 'xarray' + - xarray-einstats ; extra == 'xarray' + - xarray>=2024.11.0 ; extra == 'xarray' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl + name: build + version: 1.5.0 + sha256: 13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f requires_dist: - - numpy>=1.26.0 ; python_full_version < '3.14' - - numpy>=2.3.3 ; python_full_version >= '3.14' - - python-dateutil>=2.8.2 - - tzdata ; sys_platform == 'win32' - - tzdata ; sys_platform == 'emscripten' - - hypothesis>=6.116.0 ; extra == 'test' - - pytest>=8.3.4 ; extra == 'test' - - pytest-xdist>=3.6.1 ; extra == 'test' - - pyarrow>=13.0.0 ; extra == 'pyarrow' - - bottleneck>=1.4.2 ; extra == 'performance' - - numba>=0.60.0 ; extra == 'performance' - - numexpr>=2.10.2 ; extra == 'performance' - - scipy>=1.14.1 ; extra == 'computation' - - xarray>=2024.10.0 ; extra == 'computation' - - fsspec>=2024.10.0 ; extra == 'fss' - - s3fs>=2024.10.0 ; extra == 'aws' - - gcsfs>=2024.10.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.5 ; extra == 'excel' - - python-calamine>=0.3.0 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.2.0 ; extra == 'excel' - - pyarrow>=13.0.0 ; extra == 'parquet' - - pyarrow>=13.0.0 ; extra == 'feather' - - pyiceberg>=0.8.1 ; extra == 'iceberg' - - tables>=3.10.1 ; extra == 'hdf5' - - pyreadstat>=1.2.8 ; extra == 'spss' - - sqlalchemy>=2.0.36 ; extra == 'postgresql' - - psycopg2>=2.9.10 ; extra == 'postgresql' - - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.36 ; extra == 'mysql' - - pymysql>=1.1.1 ; extra == 'mysql' - - sqlalchemy>=2.0.36 ; extra == 'sql-other' - - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' - - beautifulsoup4>=4.12.3 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'xml' - - matplotlib>=3.9.3 ; extra == 'plot' - - jinja2>=3.1.5 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.4.2 ; extra == 'clipboard' - - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2020.1 ; extra == 'timezone' - - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - - beautifulsoup4>=4.12.3 ; extra == 'all' - - bottleneck>=1.4.2 ; extra == 'all' - - fastparquet>=2024.11.0 ; extra == 'all' - - fsspec>=2024.10.0 ; extra == 'all' - - gcsfs>=2024.10.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.116.0 ; extra == 'all' - - jinja2>=3.1.5 ; extra == 'all' - - lxml>=5.3.0 ; extra == 'all' - - matplotlib>=3.9.3 ; extra == 'all' - - numba>=0.60.0 ; extra == 'all' - - numexpr>=2.10.2 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.5 ; extra == 'all' - - psycopg2>=2.9.10 ; extra == 'all' - - pyarrow>=13.0.0 ; extra == 'all' - - pyiceberg>=0.8.1 ; extra == 'all' - - pymysql>=1.1.1 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.8 ; extra == 'all' - - pytest>=8.3.4 ; extra == 'all' - - pytest-xdist>=3.6.1 ; extra == 'all' - - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2020.1 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.4.2 ; extra == 'all' - - scipy>=1.14.1 ; extra == 'all' - - s3fs>=2024.10.0 ; extra == 'all' - - sqlalchemy>=2.0.36 ; extra == 'all' - - tables>=3.10.1 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2024.10.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.2.0 ; extra == 'all' - - zstandard>=0.23.0 ; extra == 'all' + - packaging>=24.0 + - pyproject-hooks + - colorama ; os_name == 'nt' + - importlib-metadata>=4.6 ; python_full_version < '3.10.2' + - tomli>=1.1.0 ; python_full_version < '3.11' + - keyring ; extra == 'keyring' + - uv>=0.1.18 ; extra == 'uv' + - virtualenv>=20.17 ; python_full_version >= '3.10' and python_full_version < '3.14' and extra == 'virtualenv' + - virtualenv>=20.31 ; python_full_version >= '3.14' and extra == 'virtualenv' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl + name: scipp + version: 26.3.1 + sha256: 1f103f6c5a33b08773206c613fe2dd9c02585f5c4e44b77311c54b7828a758ed + requires_dist: + - numpy>=2 + - pytest ; extra == 'test' + - matplotlib ; extra == 'test' + - beautifulsoup4 ; extra == 'test' + - ipython ; extra == 'test' + - h5py ; extra == 'extra' + - scipy>=1.7.0 ; extra == 'extra' + - graphviz ; extra == 'extra' + - pooch ; extra == 'extra' + - plopp ; extra == 'extra' + - matplotlib ; extra == 'extra' + - scipp[extra] ; extra == 'all' + - ipympl ; extra == 'all' + - ipython ; extra == 'all' + - ipywidgets ; extra == 'all' + - jupyterlab ; extra == 'all' + - jupyterlab-widgets ; extra == 'all' + - jupyter-nbextensions-configurator ; extra == 'all' + - nodejs ; extra == 'all' + - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - name: pandas - version: 3.0.3 - sha256: 6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9 +- pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + name: aiohappyeyeballs + version: 2.6.1 + sha256: f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + name: pyparsing + version: 3.3.2 + sha256: 850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d requires_dist: - - numpy>=1.26.0 ; python_full_version < '3.14' - - numpy>=2.3.3 ; python_full_version >= '3.14' - - python-dateutil>=2.8.2 - - tzdata ; sys_platform == 'win32' - - tzdata ; sys_platform == 'emscripten' - - hypothesis>=6.116.0 ; extra == 'test' - - pytest>=8.3.4 ; extra == 'test' - - pytest-xdist>=3.6.1 ; extra == 'test' - - pyarrow>=13.0.0 ; extra == 'pyarrow' - - bottleneck>=1.4.2 ; extra == 'performance' - - numba>=0.60.0 ; extra == 'performance' - - numexpr>=2.10.2 ; extra == 'performance' - - scipy>=1.14.1 ; extra == 'computation' - - xarray>=2024.10.0 ; extra == 'computation' - - fsspec>=2024.10.0 ; extra == 'fss' - - s3fs>=2024.10.0 ; extra == 'aws' - - gcsfs>=2024.10.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.5 ; extra == 'excel' - - python-calamine>=0.3.0 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.2.0 ; extra == 'excel' - - pyarrow>=13.0.0 ; extra == 'parquet' - - pyarrow>=13.0.0 ; extra == 'feather' - - pyiceberg>=0.8.1 ; extra == 'iceberg' - - tables>=3.10.1 ; extra == 'hdf5' - - pyreadstat>=1.2.8 ; extra == 'spss' - - sqlalchemy>=2.0.36 ; extra == 'postgresql' - - psycopg2>=2.9.10 ; extra == 'postgresql' - - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.36 ; extra == 'mysql' - - pymysql>=1.1.1 ; extra == 'mysql' - - sqlalchemy>=2.0.36 ; extra == 'sql-other' - - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' - - beautifulsoup4>=4.12.3 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'xml' - - matplotlib>=3.9.3 ; extra == 'plot' - - jinja2>=3.1.5 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.4.2 ; extra == 'clipboard' - - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2020.1 ; extra == 'timezone' - - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - - beautifulsoup4>=4.12.3 ; extra == 'all' - - bottleneck>=1.4.2 ; extra == 'all' - - fastparquet>=2024.11.0 ; extra == 'all' - - fsspec>=2024.10.0 ; extra == 'all' - - gcsfs>=2024.10.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.116.0 ; extra == 'all' - - jinja2>=3.1.5 ; extra == 'all' - - lxml>=5.3.0 ; extra == 'all' - - matplotlib>=3.9.3 ; extra == 'all' - - numba>=0.60.0 ; extra == 'all' - - numexpr>=2.10.2 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.5 ; extra == 'all' - - psycopg2>=2.9.10 ; extra == 'all' - - pyarrow>=13.0.0 ; extra == 'all' - - pyiceberg>=0.8.1 ; extra == 'all' - - pymysql>=1.1.1 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.8 ; extra == 'all' - - pytest>=8.3.4 ; extra == 'all' - - pytest-xdist>=3.6.1 ; extra == 'all' - - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2020.1 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.4.2 ; extra == 'all' - - scipy>=1.14.1 ; extra == 'all' - - s3fs>=2024.10.0 ; extra == 'all' - - sqlalchemy>=2.0.36 ; extra == 'all' - - tables>=3.10.1 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2024.10.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.2.0 ; extra == 'all' - - zstandard>=0.23.0 ; extra == 'all' + - railroad-diagrams ; extra == 'diagrams' + - jinja2 ; extra == 'diagrams' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl + name: blinker + version: 1.9.0 + sha256: ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + name: griffelib + version: 2.0.2 + sha256: 925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1 + requires_dist: + - pip>=24.0 ; extra == 'pypi' + - platformdirs>=4.2 ; extra == 'pypi' + - wheel>=0.42 ; extra == 'pypi' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: pillow + version: 12.2.0 + sha256: 4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286 + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - arro3-compute ; extra == 'test-arrow' + - arro3-core ; extra == 'test-arrow' + - nanoarrow ; extra == 'test-arrow' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma>=5 ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/12/aa/fb2a0649fdeef5ab7072d221e8f4df164098792c813af6c87e2581cfa860/mpltoolbox-26.2.0-py3-none-any.whl + name: mpltoolbox + version: 26.2.0 + sha256: cd2668db4216fc4d7c2ba37974961aa61445f1517527b645b6082930e35ba7f0 + requires_dist: + - matplotlib + - ipympl ; extra == 'test' + - pytest>=8.0 ; extra == 'test' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + name: interrogate + version: 1.7.0 + sha256: b13ff4dd8403369670e2efe684066de9fcb868ad9d7f2b4095d8112142dc9d12 + requires_dist: + - attrs + - click>=7.1 + - colorama + - py + - tabulate + - tomli ; python_full_version < '3.11' + - cairosvg ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-autobuild ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest-mock ; extra == 'dev' + - coverage[toml] ; extra == 'dev' + - wheel ; extra == 'dev' + - pre-commit ; extra == 'dev' + - sphinx ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - cairosvg ; extra == 'png' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-mock ; extra == 'tests' + - coverage[toml] ; extra == 'tests' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + name: mkdocs-jupyter + version: 0.26.3 + sha256: cd6644fb578131157194d750fd4d10fc2fd8f1e84e00036ee62df3b5b4b84c82 + requires_dist: + - ipykernel>6.0.0,<8 + - jupytext>1.13.8,<2 + - mkdocs-material>9.0.0 + - mkdocs>=1.4.0,<2 + - nbconvert>=7.2.9,<8 + - pygments>2.12.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: propcache + version: 0.5.2 + sha256: 6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/15/1d/9f9e30d76300b0150afaa8b37fab9a0194d44fd4f6b1e5038aca4a1440ed/crysfml-0.6.2-cp312-cp312-macosx_14_0_arm64.whl + name: crysfml + version: 0.6.2 + sha256: 75bba671d2237f6fbbb1284c473543eb143b5bd3ab69f40a2d2cf343dbe0977f + requires_dist: + - numpy + requires_python: '>=3.11,<3.15' +- pypi: https://files.pythonhosted.org/packages/19/2a/725ecc166d53438bc88f76822ed4b1e3b10756e790bafd7b523fe97c322d/yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl + name: yarl + version: 1.23.0 + sha256: 13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 + requires_dist: + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl + name: pydantic-core + version: 2.46.4 + sha256: 962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl + name: xarray-einstats + version: 0.10.0 + sha256: fa3169b46cee29092db820d8bbc203148bada4fc970ee75e62cbf3dd7c5a8945 + requires_dist: + - numpy>=2.0 + - scipy>=1.13 + - xarray>=2024.2.0 + - furo ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx>=5 ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - watermark ; extra == 'doc' + - matplotlib ; extra == 'doc' + - sphinx-togglebutton ; extra == 'doc' + - einops ; extra == 'einops' + - numba>=0.55 ; extra == 'numba' + - hypothesis ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - packaging ; extra == 'test' + - scipy>=1.15 ; extra == 'test' + - preliz>=0.19 ; extra == 'test' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl + name: contourpy + version: 1.3.3 + sha256: 8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b + requires_dist: + - numpy>=1.25 + - furo ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - bokeh ; extra == 'bokeh' + - selenium ; extra == 'bokeh' + - contourpy[bokeh,docs] ; extra == 'mypy' + - bokeh ; extra == 'mypy' + - docutils-stubs ; extra == 'mypy' + - mypy==1.17.0 ; extra == 'mypy' + - types-pillow ; extra == 'mypy' + - contourpy[test-no-images] ; extra == 'test' + - matplotlib ; extra == 'test' + - pillow ; extra == 'test' + - pytest ; extra == 'test-no-images' + - pytest-cov ; extra == 'test-no-images' + - pytest-rerunfailures ; extra == 'test-no-images' + - pytest-xdist ; extra == 'test-no-images' + - wurlitzer ; extra == 'test-no-images' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl - name: pandas - version: 3.0.3 - sha256: bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f +- pypi: https://files.pythonhosted.org/packages/1a/1f/86b4d15221096cb5500bcd73bf350745749e3ba056cdd7a7f75f126f154e/scipp-26.3.1-cp312-cp312-win_amd64.whl + name: scipp + version: 26.3.1 + sha256: 8b036876edf7895d17644f59711037d2d7d9ad048b1a503200646d8229fb1ad7 requires_dist: - - numpy>=1.26.0 ; python_full_version < '3.14' - - numpy>=2.3.3 ; python_full_version >= '3.14' - - python-dateutil>=2.8.2 - - tzdata ; sys_platform == 'win32' - - tzdata ; sys_platform == 'emscripten' - - hypothesis>=6.116.0 ; extra == 'test' - - pytest>=8.3.4 ; extra == 'test' - - pytest-xdist>=3.6.1 ; extra == 'test' - - pyarrow>=13.0.0 ; extra == 'pyarrow' - - bottleneck>=1.4.2 ; extra == 'performance' - - numba>=0.60.0 ; extra == 'performance' - - numexpr>=2.10.2 ; extra == 'performance' - - scipy>=1.14.1 ; extra == 'computation' - - xarray>=2024.10.0 ; extra == 'computation' - - fsspec>=2024.10.0 ; extra == 'fss' - - s3fs>=2024.10.0 ; extra == 'aws' - - gcsfs>=2024.10.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.5 ; extra == 'excel' - - python-calamine>=0.3.0 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.2.0 ; extra == 'excel' - - pyarrow>=13.0.0 ; extra == 'parquet' - - pyarrow>=13.0.0 ; extra == 'feather' - - pyiceberg>=0.8.1 ; extra == 'iceberg' - - tables>=3.10.1 ; extra == 'hdf5' - - pyreadstat>=1.2.8 ; extra == 'spss' - - sqlalchemy>=2.0.36 ; extra == 'postgresql' - - psycopg2>=2.9.10 ; extra == 'postgresql' - - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.36 ; extra == 'mysql' - - pymysql>=1.1.1 ; extra == 'mysql' - - sqlalchemy>=2.0.36 ; extra == 'sql-other' - - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' - - beautifulsoup4>=4.12.3 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'xml' - - matplotlib>=3.9.3 ; extra == 'plot' - - jinja2>=3.1.5 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.4.2 ; extra == 'clipboard' - - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2020.1 ; extra == 'timezone' - - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - - beautifulsoup4>=4.12.3 ; extra == 'all' - - bottleneck>=1.4.2 ; extra == 'all' - - fastparquet>=2024.11.0 ; extra == 'all' - - fsspec>=2024.10.0 ; extra == 'all' - - gcsfs>=2024.10.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.116.0 ; extra == 'all' - - jinja2>=3.1.5 ; extra == 'all' - - lxml>=5.3.0 ; extra == 'all' - - matplotlib>=3.9.3 ; extra == 'all' - - numba>=0.60.0 ; extra == 'all' - - numexpr>=2.10.2 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.5 ; extra == 'all' - - psycopg2>=2.9.10 ; extra == 'all' - - pyarrow>=13.0.0 ; extra == 'all' - - pyiceberg>=0.8.1 ; extra == 'all' - - pymysql>=1.1.1 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.8 ; extra == 'all' - - pytest>=8.3.4 ; extra == 'all' - - pytest-xdist>=3.6.1 ; extra == 'all' - - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2020.1 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.4.2 ; extra == 'all' - - scipy>=1.14.1 ; extra == 'all' - - s3fs>=2024.10.0 ; extra == 'all' - - sqlalchemy>=2.0.36 ; extra == 'all' - - tables>=3.10.1 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2024.10.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.2.0 ; extra == 'all' - - zstandard>=0.23.0 ; extra == 'all' + - numpy>=2 + - pytest ; extra == 'test' + - matplotlib ; extra == 'test' + - beautifulsoup4 ; extra == 'test' + - ipython ; extra == 'test' + - h5py ; extra == 'extra' + - scipy>=1.7.0 ; extra == 'extra' + - graphviz ; extra == 'extra' + - pooch ; extra == 'extra' + - plopp ; extra == 'extra' + - matplotlib ; extra == 'extra' + - scipp[extra] ; extra == 'all' + - ipympl ; extra == 'all' + - ipython ; extra == 'all' + - ipywidgets ; extra == 'all' + - jupyterlab ; extra == 'all' + - jupyterlab-widgets ; extra == 'all' + - jupyter-nbextensions-configurator ; extra == 'all' + - nodejs ; extra == 'all' + - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl - name: pandas - version: 3.0.3 - sha256: c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc +- pypi: https://files.pythonhosted.org/packages/1a/c7/78200c18404ded028758b28b588aa1f4f3acd851271a74156a2a3db9eadf/crysfml-0.6.2-cp312-cp312-win_amd64.whl + name: crysfml + version: 0.6.2 + sha256: cd2027d98252a138bd7260b57f77c8d3c69e0da95454a44a9b80551198e8a327 requires_dist: - - numpy>=1.26.0 ; python_full_version < '3.14' - - numpy>=2.3.3 ; python_full_version >= '3.14' - - python-dateutil>=2.8.2 - - tzdata ; sys_platform == 'win32' - - tzdata ; sys_platform == 'emscripten' - - hypothesis>=6.116.0 ; extra == 'test' - - pytest>=8.3.4 ; extra == 'test' - - pytest-xdist>=3.6.1 ; extra == 'test' - - pyarrow>=13.0.0 ; extra == 'pyarrow' - - bottleneck>=1.4.2 ; extra == 'performance' - - numba>=0.60.0 ; extra == 'performance' - - numexpr>=2.10.2 ; extra == 'performance' - - scipy>=1.14.1 ; extra == 'computation' - - xarray>=2024.10.0 ; extra == 'computation' - - fsspec>=2024.10.0 ; extra == 'fss' - - s3fs>=2024.10.0 ; extra == 'aws' - - gcsfs>=2024.10.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.5 ; extra == 'excel' - - python-calamine>=0.3.0 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.2.0 ; extra == 'excel' - - pyarrow>=13.0.0 ; extra == 'parquet' - - pyarrow>=13.0.0 ; extra == 'feather' - - pyiceberg>=0.8.1 ; extra == 'iceberg' - - tables>=3.10.1 ; extra == 'hdf5' - - pyreadstat>=1.2.8 ; extra == 'spss' - - sqlalchemy>=2.0.36 ; extra == 'postgresql' - - psycopg2>=2.9.10 ; extra == 'postgresql' - - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.36 ; extra == 'mysql' - - pymysql>=1.1.1 ; extra == 'mysql' - - sqlalchemy>=2.0.36 ; extra == 'sql-other' - - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' - - beautifulsoup4>=4.12.3 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'xml' - - matplotlib>=3.9.3 ; extra == 'plot' - - jinja2>=3.1.5 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.4.2 ; extra == 'clipboard' - - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2020.1 ; extra == 'timezone' - - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - - beautifulsoup4>=4.12.3 ; extra == 'all' - - bottleneck>=1.4.2 ; extra == 'all' - - fastparquet>=2024.11.0 ; extra == 'all' - - fsspec>=2024.10.0 ; extra == 'all' - - gcsfs>=2024.10.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.116.0 ; extra == 'all' - - jinja2>=3.1.5 ; extra == 'all' - - lxml>=5.3.0 ; extra == 'all' - - matplotlib>=3.9.3 ; extra == 'all' - - numba>=0.60.0 ; extra == 'all' - - numexpr>=2.10.2 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.5 ; extra == 'all' - - psycopg2>=2.9.10 ; extra == 'all' - - pyarrow>=13.0.0 ; extra == 'all' - - pyiceberg>=0.8.1 ; extra == 'all' - - pymysql>=1.1.1 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.8 ; extra == 'all' - - pytest>=8.3.4 ; extra == 'all' - - pytest-xdist>=3.6.1 ; extra == 'all' - - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2020.1 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.4.2 ; extra == 'all' - - scipy>=1.14.1 ; extra == 'all' - - s3fs>=2024.10.0 ; extra == 'all' - - sqlalchemy>=2.0.36 ; extra == 'all' - - tables>=3.10.1 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2024.10.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.2.0 ; extra == 'all' - - zstandard>=0.23.0 ; extra == 'all' + - numpy + requires_python: '>=3.11,<3.15' +- pypi: https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl + name: msgpack + version: 1.1.2 + sha256: 6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + name: versioningit + version: 3.3.0 + sha256: 23b1db3c4756cded9bd6b0ddec6643c261e3d0c471707da3e0b230b81ce53e4b + requires_dist: + - importlib-metadata>=3.6 ; python_full_version < '3.10' + - packaging>=17.1 + - tomli>=1.2,<3.0 ; python_full_version < '3.11' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl + name: dill + version: 0.4.1 + sha256: 1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d + requires_dist: + - objgraph>=1.7.2 ; extra == 'graph' + - gprof2dot>=2022.7.29 ; extra == 'profile' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + name: annotated-doc + version: 0.0.4 + sha256: 571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/1e/e7/cd78635d0ece7e4d3393f2c1d2ebabf6ff4bd615da142891b1d42ad58abf/scipp-26.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: scipp + version: 26.3.1 + sha256: 7525c843f673ef5461d229095054a701aeb3233db29af137fdf4bbf0884ad9d4 + requires_dist: + - numpy>=2 + - pytest ; extra == 'test' + - matplotlib ; extra == 'test' + - beautifulsoup4 ; extra == 'test' + - ipython ; extra == 'test' + - h5py ; extra == 'extra' + - scipy>=1.7.0 ; extra == 'extra' + - graphviz ; extra == 'extra' + - pooch ; extra == 'extra' + - plopp ; extra == 'extra' + - matplotlib ; extra == 'extra' + - scipp[extra] ; extra == 'all' + - ipympl ; extra == 'all' + - ipython ; extra == 'all' + - ipywidgets ; extra == 'all' + - jupyterlab ; extra == 'all' + - jupyterlab-widgets ; extra == 'all' + - jupyter-nbextensions-configurator ; extra == 'all' + - nodejs ; extra == 'all' + - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl - name: pandas - version: 3.0.3 - sha256: b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4 +- pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl + name: scipp + version: 26.3.1 + sha256: 26291c0a882b9d5aac868c6d6f2508b79baa821ed30060a22c50620dbcce9e75 requires_dist: - - numpy>=1.26.0 ; python_full_version < '3.14' - - numpy>=2.3.3 ; python_full_version >= '3.14' - - python-dateutil>=2.8.2 - - tzdata ; sys_platform == 'win32' - - tzdata ; sys_platform == 'emscripten' - - hypothesis>=6.116.0 ; extra == 'test' - - pytest>=8.3.4 ; extra == 'test' - - pytest-xdist>=3.6.1 ; extra == 'test' - - pyarrow>=13.0.0 ; extra == 'pyarrow' - - bottleneck>=1.4.2 ; extra == 'performance' - - numba>=0.60.0 ; extra == 'performance' - - numexpr>=2.10.2 ; extra == 'performance' - - scipy>=1.14.1 ; extra == 'computation' - - xarray>=2024.10.0 ; extra == 'computation' - - fsspec>=2024.10.0 ; extra == 'fss' - - s3fs>=2024.10.0 ; extra == 'aws' - - gcsfs>=2024.10.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.5 ; extra == 'excel' - - python-calamine>=0.3.0 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.2.0 ; extra == 'excel' - - pyarrow>=13.0.0 ; extra == 'parquet' - - pyarrow>=13.0.0 ; extra == 'feather' - - pyiceberg>=0.8.1 ; extra == 'iceberg' - - tables>=3.10.1 ; extra == 'hdf5' - - pyreadstat>=1.2.8 ; extra == 'spss' - - sqlalchemy>=2.0.36 ; extra == 'postgresql' - - psycopg2>=2.9.10 ; extra == 'postgresql' - - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.36 ; extra == 'mysql' - - pymysql>=1.1.1 ; extra == 'mysql' - - sqlalchemy>=2.0.36 ; extra == 'sql-other' - - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' - - beautifulsoup4>=4.12.3 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'html' - - lxml>=5.3.0 ; extra == 'xml' - - matplotlib>=3.9.3 ; extra == 'plot' - - jinja2>=3.1.5 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.4.2 ; extra == 'clipboard' - - zstandard>=0.23.0 ; extra == 'compression' - - pytz>=2020.1 ; extra == 'timezone' - - adbc-driver-postgresql>=1.2.0 ; extra == 'all' - - adbc-driver-sqlite>=1.2.0 ; extra == 'all' - - beautifulsoup4>=4.12.3 ; extra == 'all' - - bottleneck>=1.4.2 ; extra == 'all' - - fastparquet>=2024.11.0 ; extra == 'all' - - fsspec>=2024.10.0 ; extra == 'all' - - gcsfs>=2024.10.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.116.0 ; extra == 'all' - - jinja2>=3.1.5 ; extra == 'all' - - lxml>=5.3.0 ; extra == 'all' - - matplotlib>=3.9.3 ; extra == 'all' - - numba>=0.60.0 ; extra == 'all' - - numexpr>=2.10.2 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.5 ; extra == 'all' - - psycopg2>=2.9.10 ; extra == 'all' - - pyarrow>=13.0.0 ; extra == 'all' - - pyiceberg>=0.8.1 ; extra == 'all' - - pymysql>=1.1.1 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.8 ; extra == 'all' - - pytest>=8.3.4 ; extra == 'all' - - pytest-xdist>=3.6.1 ; extra == 'all' - - python-calamine>=0.3.0 ; extra == 'all' - - pytz>=2020.1 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.4.2 ; extra == 'all' - - scipy>=1.14.1 ; extra == 'all' - - s3fs>=2024.10.0 ; extra == 'all' - - sqlalchemy>=2.0.36 ; extra == 'all' - - tables>=3.10.1 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2024.10.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.2.0 ; extra == 'all' - - zstandard>=0.23.0 ; extra == 'all' + - numpy>=2 + - pytest ; extra == 'test' + - matplotlib ; extra == 'test' + - beautifulsoup4 ; extra == 'test' + - ipython ; extra == 'test' + - h5py ; extra == 'extra' + - scipy>=1.7.0 ; extra == 'extra' + - graphviz ; extra == 'extra' + - pooch ; extra == 'extra' + - plopp ; extra == 'extra' + - matplotlib ; extra == 'extra' + - scipp[extra] ; extra == 'all' + - ipympl ; extra == 'all' + - ipython ; extra == 'all' + - ipywidgets ; extra == 'all' + - jupyterlab ; extra == 'all' + - jupyterlab-widgets ; extra == 'all' + - jupyter-nbextensions-configurator ; extra == 'all' + - nodejs ; extra == 'all' + - pythreejs ; extra == 'all' requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - sha256: 2bb9ba9857f4774b85900c2562f7e711d08dd48e2add9bee4e1612fbee27e16f - md5: 457c2c8c08e54905d6954e79cb5b5db9 - depends: - - python !=3.0,!=3.1,!=3.2,!=3.3 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pandocfilters?source=hash-mapping - size: 11627 - timestamp: 1631603397334 -- conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda - sha256: 611882f7944b467281c46644ffde6c5145d1a7730388bcde26e7e86819b0998e - md5: 39894c952938276405a1bd30e4ce2caf - depends: - - python >=3.10 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/parso?source=hash-mapping - size: 82472 - timestamp: 1777722955579 -- pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - name: partd - version: 1.4.2 - sha256: 978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f +- pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl + name: crysfml + version: 0.6.2 + sha256: 2ca0cb14298c8db170d897e7744007a0e2f29762151ac458a0b38a1a1a9c2967 + requires_dist: + - numpy + requires_python: '>=3.11,<3.15' +- pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + name: nbstripout + version: 0.9.1 + sha256: ca027ee45742ee77e4f8e9080254f9a707f1161ba11367b82fdf4a29892c759e + requires_dist: + - nbformat + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl + name: gitpython + version: 3.1.50 + sha256: d352abe2908d07355014abdd21ddf798c2a961469239afec4962e9da884858f9 + 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.4.7,<8 ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - sphinx-autodoc-typehints ; extra == 'doc' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl + name: aiohttp + version: 3.13.5 + sha256: f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + name: mkdocs + version: 1.6.1 + sha256: db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e + requires_dist: + - click>=7.0 + - colorama>=0.4 ; sys_platform == 'win32' + - ghp-import>=1.0 + - importlib-metadata>=4.4 ; python_full_version < '3.10' + - jinja2>=2.11.1 + - markdown>=3.3.6 + - markupsafe>=2.0.1 + - mergedeep>=1.3.4 + - mkdocs-get-deps>=0.2.0 + - packaging>=20.5 + - pathspec>=0.11.1 + - pyyaml-env-tag>=0.1 + - pyyaml>=5.1 + - watchdog>=2.0 + - babel>=2.9.0 ; extra == 'i18n' + - babel==2.9.0 ; extra == 'min-versions' + - click==7.0 ; extra == 'min-versions' + - colorama==0.4 ; sys_platform == 'win32' and extra == 'min-versions' + - ghp-import==1.0 ; extra == 'min-versions' + - importlib-metadata==4.4 ; python_full_version < '3.10' and extra == 'min-versions' + - jinja2==2.11.1 ; extra == 'min-versions' + - markdown==3.3.6 ; extra == 'min-versions' + - markupsafe==2.0.1 ; extra == 'min-versions' + - mergedeep==1.3.4 ; extra == 'min-versions' + - mkdocs-get-deps==0.2.0 ; extra == 'min-versions' + - packaging==20.5 ; extra == 'min-versions' + - pathspec==0.11.1 ; extra == 'min-versions' + - pyyaml-env-tag==0.1 ; extra == 'min-versions' + - pyyaml==5.1 ; extra == 'min-versions' + - watchdog==2.0 ; extra == 'min-versions' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl + name: yarl + version: 1.23.0 + sha256: 23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 requires_dist: - - locket - - toolz - - numpy>=1.20.0 ; extra == 'complete' - - pandas>=1.3 ; extra == 'complete' - - pyzmq ; extra == 'complete' - - blosc ; extra == 'complete' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl - name: pathspec - version: 1.1.1 - sha256: a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl + name: py3dmol + version: 2.5.4 + sha256: 32806726b5310524a2b5bfee320737f7feef635cafc945c991062806daa9e43a requires_dist: - - hyperscan>=0.7 ; extra == 'hyperscan' - - typing-extensions>=4 ; extra == 'optional' - - google-re2>=1.1 ; extra == 're2' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - sha256: 202af1de83b585d36445dc1fda94266697341994d1a3328fabde4989e1b3d07a - md5: d0d408b1f18883a944376da5cf8101ea - depends: - - ptyprocess >=0.5 - - python >=3.9 - license: ISC - purls: - - pkg:pypi/pexpect?source=hash-mapping - size: 53561 - timestamp: 1733302019362 -- pypi: https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: pillow - version: 12.2.0 - sha256: 4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286 + - ipython ; extra == 'ipython' +- pypi: https://files.pythonhosted.org/packages/28/55/5733807f4af131ea6194309ac0f43eb5b05463c676d036ef948f3143c1f2/pycifrw-5.0.1-cp312-cp312-win_amd64.whl + name: pycifrw + version: 5.0.1 + sha256: 9d2939cce3bded805f02beda5a6aea62eb95951d59a1b99d73aa3463052fe4fe requires_dist: - - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx>=8.2 ; extra == 'docs' - - sphinx-autobuild ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - arro3-compute ; extra == 'test-arrow' - - arro3-core ; extra == 'test-arrow' - - nanoarrow ; extra == 'test-arrow' - - pyarrow ; extra == 'test-arrow' - - check-manifest ; extra == 'tests' - - coverage>=7.4.2 ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma>=5 ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - pytest-xdist ; extra == 'tests' - - trove-classifiers>=2024.10.12 ; extra == 'tests' - - defusedxml ; extra == 'xmp' + - prettytable + - ply + - numpy +- pypi: https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: fonttools + version: 4.62.1 + sha256: 8d337fdd49a79b0d51c4da87bc38169d21c3abbf0c1aa9367eff5c6656fb6dae + requires_dist: + - lxml>=4.0 ; extra == 'lxml' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - zopfli>=0.1.4 ; extra == 'woff' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' + - lz4>=1.7.4.2 ; extra == 'graphite' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' + - pycairo ; extra == 'interpolatable' + - matplotlib ; extra == 'plot' + - sympy ; extra == 'symfont' + - xattr ; sys_platform == 'darwin' and extra == 'type1' + - skia-pathops>=0.5.0 ; extra == 'pathops' + - uharfbuzz>=0.45.0 ; extra == 'repacker' + - lxml>=4.0 ; extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' + - pycairo ; extra == 'all' + - matplotlib ; extra == 'all' + - sympy ; extra == 'all' + - xattr ; sys_platform == 'darwin' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.45.0 ; extra == 'all' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: pillow - version: 12.2.0 - sha256: 62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780 +- pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + name: nbqa + version: 1.9.1 + sha256: 95552d2f6c2c038136252a805aa78d85018aef922586270c3a074332737282e5 requires_dist: - - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx>=8.2 ; extra == 'docs' - - sphinx-autobuild ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - arro3-compute ; extra == 'test-arrow' - - arro3-core ; extra == 'test-arrow' - - nanoarrow ; extra == 'test-arrow' - - pyarrow ; extra == 'test-arrow' - - check-manifest ; extra == 'tests' - - coverage>=7.4.2 ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma>=5 ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - pytest-xdist ; extra == 'tests' - - trove-classifiers>=2024.10.12 ; extra == 'tests' - - defusedxml ; extra == 'xmp' + - autopep8>=1.5 + - ipython>=7.8.0 + - tokenize-rt>=3.2.0 + - tomli + - black ; extra == 'toolchain' + - blacken-docs ; extra == 'toolchain' + - flake8 ; extra == 'toolchain' + - isort ; extra == 'toolchain' + - jupytext ; extra == 'toolchain' + - mypy ; extra == 'toolchain' + - pylint ; extra == 'toolchain' + - pyupgrade ; extra == 'toolchain' + - ruff ; extra == 'toolchain' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/28/b1/0c2ab56a16f409c6c8a68816e6af707827ad5d629634691ff60a52879792/fonttools-4.62.1-cp312-cp312-win_amd64.whl + name: fonttools + version: 4.62.1 + sha256: 9e7863e10b3de72376280b515d35b14f5eeed639d1aa7824f4cf06779ec65e42 + requires_dist: + - lxml>=4.0 ; extra == 'lxml' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - zopfli>=0.1.4 ; extra == 'woff' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' + - lz4>=1.7.4.2 ; extra == 'graphite' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' + - pycairo ; extra == 'interpolatable' + - matplotlib ; extra == 'plot' + - sympy ; extra == 'symfont' + - xattr ; sys_platform == 'darwin' and extra == 'type1' + - skia-pathops>=0.5.0 ; extra == 'pathops' + - uharfbuzz>=0.45.0 ; extra == 'repacker' + - lxml>=4.0 ; extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' + - pycairo ; extra == 'all' + - matplotlib ; extra == 'all' + - sympy ; extra == 'all' + - xattr ; sys_platform == 'darwin' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.45.0 ; extra == 'all' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl - name: pillow - version: 12.2.0 - sha256: 7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5 +- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + name: mkdocs-autorefs + version: 1.4.4 + sha256: 834ef5408d827071ad1bc69e0f39704fa34c7fc05bc8e1c72b227dfdc5c76089 requires_dist: - - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx>=8.2 ; extra == 'docs' - - sphinx-autobuild ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - arro3-compute ; extra == 'test-arrow' - - arro3-core ; extra == 'test-arrow' - - nanoarrow ; extra == 'test-arrow' - - pyarrow ; extra == 'test-arrow' - - check-manifest ; extra == 'tests' - - coverage>=7.4.2 ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma>=5 ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - pytest-xdist ; extra == 'tests' - - trove-classifiers>=2024.10.12 ; extra == 'tests' - - defusedxml ; extra == 'xmp' + - markdown>=3.3 + - markupsafe>=2.0.1 + - mkdocs>=1.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl + name: aiohttp + version: 3.13.5 + sha256: ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + name: pooch + version: 1.9.0 + sha256: f265597baa9f760d25ceb29d0beb8186c243d6607b0f60b83ecf14078dbc703b + requires_dist: + - platformdirs>=2.5.0 + - packaging>=20.0 + - requests>=2.19.0 + - tqdm>=4.41.0,<5.0.0 ; extra == 'progress' + - paramiko>=2.7.0 ; extra == 'sftp' + - xxhash>=1.4.3 ; extra == 'xxhash' + - pytest-httpserver ; extra == 'test' + - pytest-localftpserver ; extra == 'test' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: propcache + version: 0.5.2 + sha256: e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825 requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl - name: pillow - version: 12.2.0 - sha256: 80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae +- pypi: https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl + name: frozenlist + version: 1.8.0 + sha256: f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2b/e0/2e13df68f367e2f9960616927d60857dd7e56aaadd59a47c644216b2f920/greenlet-3.5.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: greenlet + version: 3.5.0 + sha256: 9d280a7f5c331622c69f97eb167f33577ff2d1df282c41cd15907fc0a3ca198c requires_dist: + - sphinx ; extra == 'docs' - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx>=8.2 ; extra == 'docs' - - sphinx-autobuild ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - arro3-compute ; extra == 'test-arrow' - - arro3-core ; extra == 'test-arrow' - - nanoarrow ; extra == 'test-arrow' - - pyarrow ; extra == 'test-arrow' - - check-manifest ; extra == 'tests' - - coverage>=7.4.2 ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma>=5 ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - pytest-xdist ; extra == 'tests' - - trove-classifiers>=2024.10.12 ; extra == 'tests' - - defusedxml ; extra == 'xmp' + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl - name: pillow - version: 12.2.0 - sha256: 4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150 +- pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + name: mkdocs-material + version: 9.7.6 + sha256: 71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba requires_dist: - - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx>=8.2 ; extra == 'docs' - - sphinx-autobuild ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - arro3-compute ; extra == 'test-arrow' - - arro3-core ; extra == 'test-arrow' - - nanoarrow ; extra == 'test-arrow' - - pyarrow ; extra == 'test-arrow' - - check-manifest ; extra == 'tests' - - coverage>=7.4.2 ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma>=5 ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - pytest-xdist ; extra == 'tests' - - trove-classifiers>=2024.10.12 ; extra == 'tests' - - defusedxml ; extra == 'xmp' + - babel>=2.10 + - backrefs>=5.7.post1 + - colorama>=0.4 + - jinja2>=3.1 + - markdown>=3.2 + - mkdocs-material-extensions>=1.3 + - mkdocs>=1.6,<2 + - paginate>=0.5 + - pygments>=2.16 + - pymdown-extensions>=10.2 + - requests>=2.30 + - mkdocs-git-committers-plugin-2>=1.1 ; extra == 'git' + - mkdocs-git-revision-date-localized-plugin>=1.2.4 ; extra == 'git' + - cairosvg>=2.6 ; extra == 'imaging' + - pillow>=10.2 ; extra == 'imaging' + - mkdocs-minify-plugin>=0.7 ; extra == 'recommended' + - mkdocs-redirects>=1.2 ; extra == 'recommended' + - mkdocs-rss-plugin>=1.6 ; extra == 'recommended' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + name: mergedeep + version: 1.3.4 + sha256: 70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl + name: propcache + version: 0.5.2 + sha256: e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl - name: pillow - version: 12.2.0 - sha256: f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421 +- pypi: https://files.pythonhosted.org/packages/2c/fa/65fcae2ed62f84ab72cf89536c7c3217a156e71a2c111b1305ab6f0690e2/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: sqlalchemy + version: 2.0.49 + sha256: 3bb9ec6436a820a4c006aad1ac351f12de2f2dbdaad171692ee457a02429b672 + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/2d/5b/e1deebf88ff431b01b7406ca3583ab2bbb90972bbe1c568732e49c844f7e/numpy-2.4.4-cp312-cp312-win_amd64.whl + name: numpy + version: 2.4.4 + sha256: b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: sqlalchemy + version: 2.0.49 + sha256: 685e93e9c8f399b0c96a624799820176312f5ceef958c0f88215af4013d29066 + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: msgpack + version: 1.1.2 + sha256: 180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl + name: arviz-plots + version: 1.1.0 + sha256: 5c7ab5b0c7c29cda6ddb5e04c699c70285fe68a76d2b1b42302c69a85742adde + requires_dist: + - arviz-base>=1.1,<1.2 + - arviz-stats[xarray]>=1.1,<1.2 + - bokeh>=3.4 ; extra == 'bokeh' + - sphinx-book-theme ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx>=6 ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'doc' + - plotly<6 ; extra == 'doc' + - matplotlib>=3.9 ; extra == 'matplotlib' + - plotly>=5.19 ; extra == 'plotly' + - webcolors ; extra == 'plotly' + - hypothesis ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - h5netcdf[h5py] ; extra == 'test' + - kaleido ; extra == 'test' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl + name: python-discovery + version: 1.3.0 + sha256: 441d9ced3dfce36e113beb35ca302c71c7ef06f3c0f9c227a0b9bb3bd49b9e9f + requires_dist: + - filelock>=3.15.4 + - platformdirs>=4.3.6,<5 + - furo>=2025.12.19 ; extra == 'docs' + - sphinx-autodoc-typehints>=3.6.3 ; extra == 'docs' + - sphinx>=9.1 ; extra == 'docs' + - sphinxcontrib-mermaid>=2 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'testing' + - coverage>=7.5.4 ; extra == 'testing' + - pytest-mock>=3.14 ; extra == 'testing' + - pytest>=8.3.5 ; extra == 'testing' + - setuptools>=75.1 ; extra == 'testing' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + name: mkdocstrings-python + version: 2.0.3 + sha256: 0b83513478bdfd803ff05aa43e9b1fca9dd22bcd9471f09ca6257f009bc5ee12 + requires_dist: + - mkdocstrings>=0.30 + - mkdocs-autorefs>=1.4 + - griffelib>=2.0 + - typing-extensions>=4.0 ; python_full_version < '3.11' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: matplotlib + version: 3.10.9 + sha256: 34cf8167e023ad956c15f36302911d5406bd99a9862c1a8499ea6f7c0e015dc2 requires_dist: - - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx>=8.2 ; extra == 'docs' - - sphinx-autobuild ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - arro3-compute ; extra == 'test-arrow' - - arro3-core ; extra == 'test-arrow' - - nanoarrow ; extra == 'test-arrow' - - pyarrow ; extra == 'test-arrow' - - check-manifest ; extra == 'tests' - - coverage>=7.4.2 ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma>=5 ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - pytest-xdist ; extra == 'tests' - - trove-classifiers>=2024.10.12 ; extra == 'tests' - - defusedxml ; extra == 'xmp' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.23 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=3 + - python-dateutil>=2.7 + - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' + - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' + - setuptools-scm>=7,<10 ; extra == 'dev' + - setuptools>=64 ; extra == 'dev' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl - name: pip - version: 26.1.1 - sha256: 99cb1c2899893b075ff56e4ed0af55669a955b49ad7fb8d8603ecdaf4ed653fb +- pypi: https://files.pythonhosted.org/packages/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl + name: chardet + version: 7.4.3 + sha256: 4b2799bd58e7245cfa8d4ab2e8ad1d76a5c3a5b1f32318eb6acca4c69a3e7101 requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda - sha256: 506c9330b8dc5ae98f4c32629fa59fa40e6bdd42a681c48d2f9554693dd01156 - md5: d57ef7cb7ad6b5d62cef8b9bdf1d400b - depends: - - ipykernel >=6 - - jupyter_client >=7 - - jupyter_server >=2.4 - - msgspec >=0.18 - - python >=3.10 - - returns >=0.23 - - tomli >=2 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pixi-kernel?source=hash-mapping - size: 39509 - timestamp: 1764156429044 -- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda - sha256: 8f29915c172f1f7f4f7c9391cd5dac3ebf5d13745c8b7c8006032615246345a5 - md5: 89c0b6d1793601a2a3a3f7d2d3d8b937 - depends: - - python >=3.10 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/platformdirs?source=hash-mapping - size: 25862 - timestamp: 1775741140609 -- pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - name: plopp - version: 26.4.2 - sha256: 5cab99bb0905ce08a1d1d7d82f0f64cee7d594269ec1bd01a8a361bd14ab7bff +- pypi: https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: matplotlib + version: 3.10.9 + sha256: ae20801130378b82d647ff5047c07316295b68dc054ca6b3c13519d0ea624285 requires_dist: - - lazy-loader>=0.4 - - matplotlib>=3.8 - - scipp>=25.8.0 ; extra == 'scipp' - - plopp[scipp] ; extra == 'all' - - ipympl>0.8.4 ; extra == 'all' - - pythreejs>=2.4.1 ; extra == 'all' - - mpltoolbox>=24.6.0 ; extra == 'all' - - ipywidgets>=8.1.0 ; extra == 'all' - - graphviz>=0.20.3 ; extra == 'all' - - plopp[scipp] ; extra == 'test' - - graphviz>=0.20.3 ; extra == 'test' - - h5py>=3.12 ; extra == 'test' - - ipympl>=0.8.4 ; extra == 'test' - - ipywidgets>=8.1.0 ; extra == 'test' - - ipykernel>=6.26,<7 ; extra == 'test' - - mpltoolbox>=24.6.0 ; extra == 'test' - - pandas>=2.2.2 ; extra == 'test' - - plotly>=5.15.0 ; extra == 'test' - - pooch>=1.5 ; extra == 'test' - - pyarrow>=13.0.0 ; extra == 'test' - - pytest>=8.0 ; extra == 'test' - - pythreejs>=2.4.1 ; extra == 'test' - - scipy>=1.10.0 ; extra == 'test' - - xarray>=2024.5.0 ; extra == 'test' - - anywidget>=0.9.0 ; extra == 'test' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-py3-none-any.whl - name: plotly - version: 6.7.0 - sha256: ac8aca1c25c663a59b5b9140a549264a5badde2e057d79b8c772ae2920e32ff0 + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.23 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=3 + - python-dateutil>=2.7 + - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' + - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' + - setuptools-scm>=7,<10 ; extra == 'dev' + - setuptools>=64 ; extra == 'dev' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/32/a0/37fb236da6040e337381dd656cafb97d09eacb998c5db3057547f5ffddd9/pycifrw-5.0.1-cp312-cp312-macosx_11_0_arm64.whl + name: pycifrw + version: 5.0.1 + sha256: 2d0464e10abda9890347a95c8c385654c2741fca186df371a5c47c3b4b819866 requires_dist: - - narwhals>=1.15.1 - - packaging - - anywidget ; extra == 'dev' - - build ; extra == 'dev' - - colorcet ; extra == 'dev' - - fiona<=1.9.6 ; python_full_version < '3.9' and extra == 'dev' - - geopandas ; extra == 'dev' - - inflect ; extra == 'dev' - - jupyterlab ; extra == 'dev' - - kaleido>=1.1.0 ; extra == 'dev' - - numpy>=1.22 ; extra == 'dev' - - orjson ; extra == 'dev' - - pandas ; extra == 'dev' - - pdfrw ; extra == 'dev' - - pillow ; extra == 'dev' - - plotly-geo ; extra == 'dev' - - polars[timezone] ; extra == 'dev' - - pyarrow ; extra == 'dev' - - pyshp ; extra == 'dev' - - pytest ; extra == 'dev' - - pytz ; extra == 'dev' - - requests ; extra == 'dev' - - ruff==0.11.12 ; extra == 'dev' - - scikit-image ; extra == 'dev' - - scipy ; extra == 'dev' - - shapely ; extra == 'dev' - - statsmodels ; extra == 'dev' - - vaex ; python_full_version < '3.10' and extra == 'dev' - - xarray ; extra == 'dev' - - build ; extra == 'dev-build' - - jupyterlab ; extra == 'dev-build' - - pytest ; extra == 'dev-build' - - requests ; extra == 'dev-build' - - ruff==0.11.12 ; extra == 'dev-build' - - pytest ; extra == 'dev-core' - - requests ; extra == 'dev-core' - - ruff==0.11.12 ; extra == 'dev-core' - - anywidget ; extra == 'dev-optional' - - build ; extra == 'dev-optional' - - colorcet ; extra == 'dev-optional' - - fiona<=1.9.6 ; python_full_version < '3.9' and extra == 'dev-optional' - - geopandas ; extra == 'dev-optional' - - inflect ; extra == 'dev-optional' - - jupyterlab ; extra == 'dev-optional' - - kaleido>=1.1.0 ; extra == 'dev-optional' - - numpy>=1.22 ; extra == 'dev-optional' - - orjson ; extra == 'dev-optional' - - pandas ; extra == 'dev-optional' - - pdfrw ; extra == 'dev-optional' - - pillow ; extra == 'dev-optional' - - plotly-geo ; extra == 'dev-optional' - - polars[timezone] ; extra == 'dev-optional' - - pyarrow ; extra == 'dev-optional' - - pyshp ; extra == 'dev-optional' - - pytest ; extra == 'dev-optional' - - pytz ; extra == 'dev-optional' - - requests ; extra == 'dev-optional' - - ruff==0.11.12 ; extra == 'dev-optional' - - scikit-image ; extra == 'dev-optional' - - scipy ; extra == 'dev-optional' - - shapely ; extra == 'dev-optional' - - statsmodels ; extra == 'dev-optional' - - vaex ; python_full_version < '3.10' and extra == 'dev-optional' - - xarray ; extra == 'dev-optional' - - numpy>=1.22 ; extra == 'express' - - kaleido>=1.1.0 ; extra == 'kaleido' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl - name: pluggy - version: 1.6.0 - sha256: e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 + - prettytable + - ply + - numpy +- pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-py3-none-any.whl + name: pytest-benchmark + version: 5.2.3 + sha256: bc839726ad20e99aaa0d11a127445457b4219bdb9e80a1afc4b51da7f96b0803 requires_dist: - - pre-commit ; extra == 'dev' - - tox ; extra == 'dev' - - pytest ; extra == 'testing' - - pytest-benchmark ; extra == 'testing' - - coverage ; extra == 'testing' + - pytest>=8.1 + - py-cpuinfo + - aspectlib ; extra == 'aspect' + - pygal ; extra == 'histogram' + - pygaljs ; extra == 'histogram' + - setuptools ; extra == 'histogram' + - elasticsearch ; extra == 'elasticsearch' 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 +- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + name: distlib + version: 0.4.0 + sha256: 9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16 +- pypi: https://files.pythonhosted.org/packages/33/75/98a7eb100dc5cfd20b019046452f08d5e67dfbacc71d8f28763d32426fd3/spglib-2.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: spglib + version: 2.6.0 + sha256: a8e9c34da1e2428c3a8bd4e209e5356d12d454d8ac54120d5ba4a437d3abe7ba requires_dist: - - pywin32 ; platform_python_implementation != 'PyPy' and sys_platform == 'win32' - - paramiko ; extra == 'ssh' + - numpy>=1.20,<3 + - importlib-resources ; python_full_version < '3.10' + - typing-extensions>=4.9.0 ; python_full_version < '3.13' + - pytest ; extra == 'test' + - pyyaml ; extra == 'test' + - sphinx>=7.0 ; extra == 'docs' + - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' + - sphinx-book-theme ; extra == 'docs' + - sphinx-autodoc-typehints ; extra == 'docs' + - myst-parser>=2.0 ; extra == 'docs' + - linkify-it-py ; extra == 'docs' + - sphinx-tippy ; extra == 'docs' + - spglib[test] ; extra == 'test-cov' + - pytest-cov ; extra == 'test-cov' + - spglib[test] ; extra == 'test-benchmark' + - pytest-benchmark ; extra == 'test-benchmark' + - spglib[test] ; extra == 'dev' + - pre-commit ; extra == 'dev' + - spglib[docs] ; extra == 'doc' + - spglib[test] ; extra == 'testing' 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' - sha256: 096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce -- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl - name: pooch - version: 1.9.0 - sha256: f265597baa9f760d25ceb29d0beb8186c243d6607b0f60b83ecf14078dbc703b +- 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: - - platformdirs>=2.5.0 - - packaging>=20.0 - - requests>=2.19.0 - - tqdm>=4.41.0,<5.0.0 ; extra == 'progress' - - paramiko>=2.7.0 ; extra == 'sftp' - - xxhash>=1.4.3 ; extra == 'xxhash' - - pytest-httpserver ; extra == 'test' - - pytest-localftpserver ; extra == 'test' + - 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/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz + name: diffpy-pdffit2 + version: 1.6.0 + sha256: 11a65466f8790f5ac7ae45f2f3fc0d5d116d156d274bcfc079df653123d080e2 + requires_dist: + - diffpy-structure + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + name: tokenize-rt + version: 6.2.0 + sha256: a152bf4f249c847a66497a4a95f63376ed68ac6abf092a2f7cfb29d044ecff44 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl - name: pre-commit - version: 4.6.0 - sha256: e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b +- pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + name: ruff + version: 0.15.12 + sha256: c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/34/23/35c7aea1274aef7525bdd2dc92f710bdde6d11652239d71d1ec450067939/coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl + name: coverage + version: 7.14.0 + sha256: 829994cfe1aeb773ca27bf246d4badc1e764893e3bfb98fff820fcecd1ca4662 requires_dist: - - cfgv>=2.0.0 - - identify>=1.0.0 - - nodeenv>=0.11.1 - - pyyaml>=5.1 - - virtualenv>=20.10.0 + - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl - name: prettytable - version: 3.17.0 - sha256: aad69b294ddbe3e1f95ef8886a060ed1666a0b83018bbf56295f6f226c43d287 +- pypi: https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl + name: msgpack + version: 1.1.2 + sha256: 446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl + name: backrefs + version: '7.0' + sha256: ca42ce6a49ace3d75684dfa9937f3373902a63284ecb385ce36d15e5dcb41c12 requires_dist: - - wcwidth - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-lazy-fixtures ; extra == 'tests' - requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda - sha256: 4d7ec90d4f9c1f3b4a50623fefe4ebba69f651b102b373f7c0e9dbbfa43d495c - md5: a11ab1f31af799dd93c3a39881528884 - depends: - - python >=3.10 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/prometheus-client?source=hash-mapping - size: 57113 - timestamp: 1775771465170 -- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - sha256: 4817651a276016f3838957bfdf963386438c70761e9faec7749d411635979bae - md5: edb16f14d920fb3faf17f5ce582942d6 - depends: - - python >=3.10 - - wcwidth - constrains: - - prompt_toolkit 3.0.52 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/prompt-toolkit?source=hash-mapping - size: 273927 - timestamp: 1756321848365 -- pypi: https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: propcache - version: 0.5.2 - sha256: 6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: propcache - version: 0.5.2 - sha256: e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl - name: propcache - version: 0.5.2 - sha256: e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl - name: propcache - version: 0.5.2 - sha256: d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42 - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl - name: propcache - version: 0.5.2 - sha256: 81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl - name: propcache - version: 0.5.2 - sha256: 97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539 + - regex ; extra == 'extras' requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda - sha256: d834fd656133c9e4eaf63ffe9a117c7d0917d86d89f7d64073f4e3a0020bd8a7 - md5: dd94c506b119130aef5a9382aed648e7 - depends: - - python - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil?source=hash-mapping - size: 225545 - timestamp: 1769678155334 -- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda - sha256: f15574ed6c8c8ed8c15a0c5a00102b1efe8b867c0bd286b498cd98d95bd69ae5 - md5: 4f225a966cfee267a79c5cb6382bd121 - depends: - - python - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - - python_abi 3.14.* *_cp314 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil?source=hash-mapping - size: 231303 - timestamp: 1769678156552 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda - sha256: 6d0e21c76436374635c074208cfeee62a94d3c37d0527ad67fd8a7615e546a05 - md5: fd856899666759403b3c16dcba2f56ff - depends: - - python - - __osx >=11.0 - - python 3.12.* *_cpython - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil?source=hash-mapping - size: 239031 - timestamp: 1769678393511 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda - sha256: e0f31c053eb11803d63860c213b2b1b57db36734f5f84a3833606f7c91fedff9 - md5: fc4c7ab223873eee32080d51600ce7e7 - depends: - - python - - __osx >=11.0 - - python 3.14.* *_cp314 - - python_abi 3.14.* *_cp314 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil?source=hash-mapping - size: 245502 - timestamp: 1769678303655 -- conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py312he5662c2_0.conda - sha256: edffc84c001a05b996b5f8607c8164432754e86ec9224e831cd00ebabdec04e7 - md5: a2724c93b745fc7861948eb8b9f6679a - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil?source=hash-mapping - size: 242769 - timestamp: 1769678170631 -- conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda - sha256: 17c8274ce5a32c9793f73a5a0094bd6188f3a13026a93147655143d4df034214 - md5: fd539ac231820f64066839251aa9fa48 - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.14.* *_cp314 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil?source=hash-mapping - size: 249950 - timestamp: 1769678167309 -- conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - sha256: a7713dfe30faf17508ec359e0bc7e0983f5d94682492469bd462cdaae9c64d83 - md5: 7d9daffbb8d8e0af0f769dbbcd173a54 - depends: - - python >=3.9 - license: ISC - purls: - - pkg:pypi/ptyprocess?source=hash-mapping - size: 19457 - timestamp: 1733302371990 -- conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - sha256: 71bd24600d14bb171a6321d523486f6a06f855e75e547fa0cb2a0953b02047f0 - md5: 3bfdfb8dbcdc4af1ae3f9a8eb3948f04 - depends: - - python >=3.9 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pure-eval?source=hash-mapping - size: 16668 - timestamp: 1733569518868 -- pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl - name: py - version: 1.11.0 - sha256: 607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378 - requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' -- pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - name: py-cpuinfo - version: 9.0.0 - sha256: 859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5 -- pypi: https://files.pythonhosted.org/packages/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl - name: py3dmol - version: 2.5.4 - sha256: 32806726b5310524a2b5bfee320737f7feef635cafc945c991062806daa9e43a - requires_dist: - - ipython ; extra == 'ipython' -- pypi: https://files.pythonhosted.org/packages/28/55/5733807f4af131ea6194309ac0f43eb5b05463c676d036ef948f3143c1f2/pycifrw-5.0.1-cp312-cp312-win_amd64.whl - name: pycifrw - version: 5.0.1 - sha256: 9d2939cce3bded805f02beda5a6aea62eb95951d59a1b99d73aa3463052fe4fe +- pypi: https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl + name: fonttools + version: 4.62.1 + sha256: fa1d16210b6b10a826d71bed68dd9ec24a9e218d5a5e2797f37c573e7ec215ca requires_dist: - - prettytable - - ply - - numpy -- pypi: https://files.pythonhosted.org/packages/32/a0/37fb236da6040e337381dd656cafb97d09eacb998c5db3057547f5ffddd9/pycifrw-5.0.1-cp312-cp312-macosx_11_0_arm64.whl - name: pycifrw - version: 5.0.1 - sha256: 2d0464e10abda9890347a95c8c385654c2741fca186df371a5c47c3b4b819866 + - lxml>=4.0 ; extra == 'lxml' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - zopfli>=0.1.4 ; extra == 'woff' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' + - lz4>=1.7.4.2 ; extra == 'graphite' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' + - pycairo ; extra == 'interpolatable' + - matplotlib ; extra == 'plot' + - sympy ; extra == 'symfont' + - xattr ; sys_platform == 'darwin' and extra == 'type1' + - skia-pathops>=0.5.0 ; extra == 'pathops' + - uharfbuzz>=0.45.0 ; extra == 'repacker' + - lxml>=4.0 ; extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' + - pycairo ; extra == 'all' + - matplotlib ; extra == 'all' + - sympy ; extra == 'all' + - xattr ; sys_platform == 'darwin' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.45.0 ; extra == 'all' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl + name: pandas + version: 3.0.3 + sha256: 3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5 requires_dist: - - prettytable - - ply - - numpy -- pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz - name: pycifrw - version: 5.0.1 - sha256: e636b80be6a2be15b215e69ecec0c0a784ebcbfed8b1e3bac4bcc6e6ba9a75e0 + - numpy>=1.26.0 ; python_full_version < '3.14' + - numpy>=2.3.3 ; python_full_version >= '3.14' + - python-dateutil>=2.8.2 + - tzdata ; sys_platform == 'win32' + - tzdata ; sys_platform == 'emscripten' + - hypothesis>=6.116.0 ; extra == 'test' + - pytest>=8.3.4 ; extra == 'test' + - pytest-xdist>=3.6.1 ; extra == 'test' + - pyarrow>=13.0.0 ; extra == 'pyarrow' + - bottleneck>=1.4.2 ; extra == 'performance' + - numba>=0.60.0 ; extra == 'performance' + - numexpr>=2.10.2 ; extra == 'performance' + - scipy>=1.14.1 ; extra == 'computation' + - xarray>=2024.10.0 ; extra == 'computation' + - fsspec>=2024.10.0 ; extra == 'fss' + - s3fs>=2024.10.0 ; extra == 'aws' + - gcsfs>=2024.10.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.5 ; extra == 'excel' + - python-calamine>=0.3.0 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.2.0 ; extra == 'excel' + - pyarrow>=13.0.0 ; extra == 'parquet' + - pyarrow>=13.0.0 ; extra == 'feather' + - pyiceberg>=0.8.1 ; extra == 'iceberg' + - tables>=3.10.1 ; extra == 'hdf5' + - pyreadstat>=1.2.8 ; extra == 'spss' + - sqlalchemy>=2.0.36 ; extra == 'postgresql' + - psycopg2>=2.9.10 ; extra == 'postgresql' + - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.36 ; extra == 'mysql' + - pymysql>=1.1.1 ; extra == 'mysql' + - sqlalchemy>=2.0.36 ; extra == 'sql-other' + - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' + - beautifulsoup4>=4.12.3 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'xml' + - matplotlib>=3.9.3 ; extra == 'plot' + - jinja2>=3.1.5 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.4.2 ; extra == 'clipboard' + - zstandard>=0.23.0 ; extra == 'compression' + - pytz>=2020.1 ; extra == 'timezone' + - adbc-driver-postgresql>=1.2.0 ; extra == 'all' + - adbc-driver-sqlite>=1.2.0 ; extra == 'all' + - beautifulsoup4>=4.12.3 ; extra == 'all' + - bottleneck>=1.4.2 ; extra == 'all' + - fastparquet>=2024.11.0 ; extra == 'all' + - fsspec>=2024.10.0 ; extra == 'all' + - gcsfs>=2024.10.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.116.0 ; extra == 'all' + - jinja2>=3.1.5 ; extra == 'all' + - lxml>=5.3.0 ; extra == 'all' + - matplotlib>=3.9.3 ; extra == 'all' + - numba>=0.60.0 ; extra == 'all' + - numexpr>=2.10.2 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.5 ; extra == 'all' + - psycopg2>=2.9.10 ; extra == 'all' + - pyarrow>=13.0.0 ; extra == 'all' + - pyiceberg>=0.8.1 ; extra == 'all' + - pymysql>=1.1.1 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.8 ; extra == 'all' + - pytest>=8.3.4 ; extra == 'all' + - pytest-xdist>=3.6.1 ; extra == 'all' + - python-calamine>=0.3.0 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.4.2 ; extra == 'all' + - scipy>=1.14.1 ; extra == 'all' + - s3fs>=2024.10.0 ; extra == 'all' + - sqlalchemy>=2.0.36 ; extra == 'all' + - tables>=3.10.1 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2024.10.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.2.0 ; extra == 'all' + - zstandard>=0.23.0 ; extra == 'all' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl + name: lmfit + version: 1.3.4 + sha256: afce1593b42324d37ae2908249b0c55445e2f4c1a0474ff706a8e2f7b5d949fa requires_dist: - - prettytable - - ply - - numpy -- pypi: https://files.pythonhosted.org/packages/ae/61/3c1ea8c10bf4f6bf83c33a7f5b4a3143f4cc1f979859dec5498b6cc31900/pycifrw-5.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - name: pycifrw - version: 5.0.1 - sha256: 379801e71509d0f9c59b56edc5ceb6600796eaf2b84ee5e0f5a256c76542047d + - asteval>=1.0 + - numpy>=1.24 + - scipy>=1.10.0 + - uncertainties>=3.2.2 + - dill>=0.3.4 + - build ; extra == 'dev' + - check-wheel-contents ; extra == 'dev' + - flake8-pyproject ; extra == 'dev' + - pre-commit ; extra == 'dev' + - twine ; extra == 'dev' + - cairosvg ; extra == 'doc' + - corner ; extra == 'doc' + - emcee>=3.0.0 ; extra == 'doc' + - ipykernel ; extra == 'doc' + - jupyter-sphinx>=0.2.4 ; extra == 'doc' + - matplotlib ; extra == 'doc' + - numdifftools ; extra == 'doc' + - pandas ; extra == 'doc' + - pillow ; extra == 'doc' + - pycairo ; sys_platform == 'win32' and extra == 'doc' + - sphinx ; extra == 'doc' + - sphinx-gallery>=0.10 ; extra == 'doc' + - sphinxcontrib-svg2pdfconverter ; extra == 'doc' + - sympy ; extra == 'doc' + - coverage ; extra == 'test' + - flaky ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - lmfit[dev,doc,test] ; extra == 'all' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + name: xraydb + version: 4.5.8 + sha256: 2215baafa6a03d00d0254a94525aafc6493c8c285e4ac4477fbd6271b25e6a51 requires_dist: - - prettytable - - ply - - numpy -- pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz - name: pycifstar - version: 0.3.0 - sha256: 5892fdf16c83372ee5f32557127d5f36e14b0bbe520883a4e2e70365382f70ed -- pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl - name: pycodestyle - version: 2.14.0 - sha256: dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d + - numpy>=1.19 + - scipy>=1.6 + - sqlalchemy>=2.0.1 + - platformdirs + - build ; extra == 'dev' + - twine ; extra == 'dev' + - sphinx ; extra == 'doc' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - coverage ; extra == 'test' + - xraydb[dev,doc,test] ; extra == 'all' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 - md5: 12c566707c80111f9799308d9e265aef - depends: - - python >=3.9 - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pycparser?source=hash-mapping - size: 110100 - timestamp: 1733195786147 -- pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl - name: pydantic - version: 2.13.4 - sha256: 45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba +- pypi: https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl + name: pip + version: 26.1.1 + sha256: 99cb1c2899893b075ff56e4ed0af55669a955b49ad7fb8d8603ecdaf4ed653fb + requires_python: '>=3.10' +- 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: - - annotated-types>=0.6.0 - - pydantic-core==2.46.4 - - typing-extensions>=4.14.1 - - typing-inspection>=0.4.2 - - email-validator>=2.0.0 ; extra == 'email' - - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' + - prompt-toolkit>=2.0,<4.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.whl + name: h5py + version: 3.16.0 + sha256: fa48993a0b799737ba7fd21e2350fa0a60701e58180fae9f2de834bc39a147ab + requires_dist: + - numpy>=1.21.2 + requires_python: '>=3.10' +- 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/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl - name: pydantic-core - version: 2.46.4 - sha256: 962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f +- pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + name: backrefs + version: '7.0' + sha256: a6448b28180e3ca01134c9cf09dcebafad8531072e09903c5451748a05f24bc9 requires_dist: - - typing-extensions>=4.14.1 - requires_python: '>=3.9' + - regex ; extra == 'extras' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl + name: widgetsnbextension + version: 4.0.15 + sha256: 8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/3f/d0/7b958df957e4827837b590944008f0b28078f552b451f7407b4b3d54f574/asciichartpy-1.5.25-py2.py3-none-any.whl + name: asciichartpy + version: 1.5.25 + sha256: 33c417a3c8ef7d0a11b98eb9ea6dd9b2c1b17559e539b207a17d26d4302d0258 + requires_dist: + - setuptools + - flake8 ; extra == 'qa' +- pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl + name: typer + version: 0.25.1 + sha256: 75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89 + requires_dist: + - click>=8.2.1 + - shellingham>=1.3.0 + - rich>=13.8.0 + - annotated-doc>=0.0.2 + requires_python: '>=3.10' - pypi: https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl name: pydantic-core version: 2.46.4 @@ -10375,1421 +9599,1826 @@ packages: requires_dist: - typing-extensions>=4.14.1 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - name: pydantic-core - version: 2.46.4 - sha256: 926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce +- pypi: https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl + name: matplotlib + version: 3.10.9 + sha256: 97e35e8d39ccc85859095e01a53847432ba9a53ddf7986f7a54a11b73d0e143f requires_dist: - - typing-extensions>=4.14.1 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - name: pydantic-core - version: 2.46.4 - sha256: 7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.23 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=3 + - python-dateutil>=2.7 + - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' + - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' + - setuptools-scm>=7,<10 ; extra == 'dev' + - setuptools>=64 ; extra == 'dev' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: yarl + version: 1.23.0 + sha256: 1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 requires_dist: - - typing-extensions>=4.14.1 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl - name: pydantic-core - version: 2.46.4 - sha256: 23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462 + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/42/d9/27b13bc9419bf5dae02905b348f16ca827646cd76244ddd326f1a8139a6a/cyclebane-24.10.0-py3-none-any.whl + name: cyclebane + version: 24.10.0 + sha256: 902dd318667e4a222afc270cc5bc72c67d5d6047d2e0e1c36018885fb80f5e5d requires_dist: - - typing-extensions>=4.14.1 - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl - name: pydantic-core - version: 2.46.4 - sha256: 811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac + - networkx + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + name: mpmath + version: 1.3.0 + sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c 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 + - pytest>=4.6 ; extra == 'develop' + - pycodestyle ; extra == 'develop' + - pytest-cov ; extra == 'develop' + - codecov ; extra == 'develop' + - wheel ; extra == 'develop' + - sphinx ; extra == 'docs' + - gmpy2>=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' + - pytest>=4.6 ; extra == 'tests' +- pypi: https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: pillow + version: 12.2.0 + sha256: 62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780 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' + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - arro3-compute ; extra == 'test-arrow' + - arro3-core ; extra == 'test-arrow' + - nanoarrow ; extra == 'test-arrow' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma>=5 ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - defusedxml ; extra == 'xmp' requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 - md5: 16c18772b340887160c79a6acc022db0 - depends: - - python >=3.10 - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/pygments?source=hash-mapping - size: 893031 - timestamp: 1774796815820 -- pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl - name: pymdown-extensions - version: 10.21.2 - sha256: 5c0fd2a2bea14eb39af8ff284f1066d898ab2187d81b889b75d46d4348c01638 +- pypi: https://files.pythonhosted.org/packages/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: scipp + version: 26.3.1 + sha256: 2ef08ba8d83542807f9f9833ba8f01583215c1629693bfadb1d6508cbdeb335c requires_dist: - - markdown>=3.6 - - pyyaml - - pygments>=2.19.1 ; extra == 'extra' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py312h19bbe71_0.conda - sha256: b015f430fe9ea2c53e14be13639f1b781f68deaa5ae74cd8c1d07720890cd02a - md5: c65d7abdc9e60fd3af0ed852591adf1b - depends: - - __osx >=11.0 - - libffi >=3.5.2,<3.6.0a0 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - - setuptools - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyobjc-core?source=hash-mapping - size: 476750 - timestamp: 1763151865523 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda - sha256: df5af268c5a74b7160d772c263ece6f43257faff571783443e34b5f1d5a61cf2 - md5: 75a84fc8337557347252cc4fd3ba2a93 - depends: - - __osx >=11.0 - - libffi >=3.5.2,<3.6.0a0 - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python_abi 3.14.* *_cp314 - - setuptools - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyobjc-core?source=hash-mapping - size: 483374 - timestamp: 1763151489724 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py312h1de3e18_0.conda - sha256: 3710f5ae09c2ea77ba4d82cc51e876d9fc009b878b197a40d3c6347c09ae7d7c - md5: f0bae1b67ece138378923e340b940051 - depends: - - __osx >=11.0 - - libffi >=3.5.2,<3.6.0a0 - - pyobjc-core 12.1.* - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping - size: 377723 - timestamp: 1763160705325 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda - sha256: aa76ee4328d0514d7c1c455dcd2d3b547db1c59797e54ce0a3f27de5b970e508 - md5: 4219bb3408016e22316cf8b443b5ef93 - depends: - - __osx >=11.0 - - libffi >=3.5.2,<3.6.0a0 - - pyobjc-core 12.1.* - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping - size: 374792 - timestamp: 1763160601898 -- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - name: pyparsing - version: 3.3.2 - sha256: 850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d + - numpy>=2 + - pytest ; extra == 'test' + - matplotlib ; extra == 'test' + - beautifulsoup4 ; extra == 'test' + - ipython ; extra == 'test' + - h5py ; extra == 'extra' + - scipy>=1.7.0 ; extra == 'extra' + - graphviz ; extra == 'extra' + - pooch ; extra == 'extra' + - plopp ; extra == 'extra' + - matplotlib ; extra == 'extra' + - scipp[extra] ; extra == 'all' + - ipympl ; extra == 'all' + - ipython ; extra == 'all' + - ipywidgets ; extra == 'all' + - jupyterlab ; extra == 'all' + - jupyterlab-widgets ; extra == 'all' + - jupyter-nbextensions-configurator ; extra == 'all' + - nodejs ; extra == 'all' + - pythreejs ; extra == 'all' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/44/7b/537a61906eac58d94131273084d21d4eb219f5453f0ed30de3aca580a2b4/scipp-26.3.1-cp312-cp312-macosx_14_0_arm64.whl + name: scipp + version: 26.3.1 + sha256: 2608ba21e2c550abe864598e8cfffe22d7e7be70ff9f9b03d44868e353b241c9 requires_dist: - - railroad-diagrams ; extra == 'diagrams' - - jinja2 ; extra == 'diagrams' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - name: pyproject-hooks - version: 1.2.0 - sha256: 9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913 + - numpy>=2 + - pytest ; extra == 'test' + - matplotlib ; extra == 'test' + - beautifulsoup4 ; extra == 'test' + - ipython ; extra == 'test' + - h5py ; extra == 'extra' + - scipy>=1.7.0 ; extra == 'extra' + - graphviz ; extra == 'extra' + - pooch ; extra == 'extra' + - plopp ; extra == 'extra' + - matplotlib ; extra == 'extra' + - scipp[extra] ; extra == 'all' + - ipympl ; extra == 'all' + - ipython ; extra == 'all' + - ipywidgets ; extra == 'all' + - jupyterlab ; extra == 'all' + - jupyterlab-widgets ; extra == 'all' + - jupyter-nbextensions-configurator ; extra == 'all' + - nodejs ; extra == 'all' + - pythreejs ; extra == 'all' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/46/b4/0887c88ddfaba1d7140ea335144eb904af97550786ee58bdb295ff10d255/crysfml-0.6.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: crysfml + version: 0.6.2 + sha256: 8274d3c1ac37444d779b7819e752cba03ba3029953fed61479e4537225b3ee99 + requires_dist: + - numpy + requires_python: '>=3.11,<3.15' +- pypi: https://files.pythonhosted.org/packages/47/9e/fd90114059175cac64e4fafa9bf3ac20584384d66de40793ae2e2f26f3bb/sqlalchemy-2.0.49-cp312-cp312-win_amd64.whl + name: sqlalchemy + version: 2.0.49 + sha256: 618a308215b6cececb6240b9abde545e3acdabac7ae3e1d4e666896bf5ba44b4 + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - sha256: d016e04b0e12063fbee4a2d5fbb9b39a8d191b5a0042f0b8459188aedeabb0ca - md5: e2fd202833c4a981ce8a65974fe4abd1 - depends: - - __win - - python >=3.9 - - win_inet_pton - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pysocks?source=hash-mapping - size: 21784 - timestamp: 1733217448189 -- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 - md5: 461219d1a5bd61342293efa2c0c90eac - depends: - - __unix - - python >=3.9 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pysocks?source=hash-mapping - size: 21085 - timestamp: 1733217331982 -- pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl - name: pytest - version: 9.0.3 - sha256: 2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9 +- pypi: https://files.pythonhosted.org/packages/47/d4/dbacced3953544b9a93088cc10ef2b596d348c983d5c67a404fa41ec51ba/fonttools-4.62.1-cp312-cp312-macosx_10_13_universal2.whl + name: fonttools + version: 4.62.1 + sha256: 90365821debbd7db678809c7491ca4acd1e0779b9624cdc6ddaf1f31992bf974 requires_dist: - - colorama>=0.4 ; sys_platform == 'win32' - - exceptiongroup>=1 ; python_full_version < '3.11' - - iniconfig>=1.0.1 - - packaging>=22 - - pluggy>=1.5,<2 - - pygments>=2.7.2 - - tomli>=1 ; python_full_version < '3.11' - - argcomplete ; extra == 'dev' - - attrs>=19.2 ; extra == 'dev' - - hypothesis>=3.56 ; extra == 'dev' - - mock ; extra == 'dev' - - requests ; extra == 'dev' - - setuptools ; extra == 'dev' - - xmlschema ; extra == 'dev' + - lxml>=4.0 ; extra == 'lxml' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - zopfli>=0.1.4 ; extra == 'woff' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' + - lz4>=1.7.4.2 ; extra == 'graphite' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' + - pycairo ; extra == 'interpolatable' + - matplotlib ; extra == 'plot' + - sympy ; extra == 'symfont' + - xattr ; sys_platform == 'darwin' and extra == 'type1' + - skia-pathops>=0.5.0 ; extra == 'pathops' + - uharfbuzz>=0.45.0 ; extra == 'repacker' + - lxml>=4.0 ; extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' + - pycairo ; extra == 'all' + - matplotlib ; extra == 'all' + - sympy ; extra == 'all' + - xattr ; sys_platform == 'darwin' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.45.0 ; extra == 'all' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-py3-none-any.whl - name: pytest-benchmark - version: 5.2.3 - sha256: bc839726ad20e99aaa0d11a127445457b4219bdb9e80a1afc4b51da7f96b0803 +- pypi: https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl + name: kiwisolver + version: 1.5.0 + sha256: 0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/49/b3/2de412451330756aaaa72d27131db6dde23995efe62c941184e15242a5fa/sqlalchemy-2.0.49-cp312-cp312-macosx_11_0_arm64.whl + name: sqlalchemy + version: 2.0.49 + sha256: 4bbccb45260e4ff1b7db0be80a9025bb1e6698bdb808b83fff0000f7a90b2c0b requires_dist: - - pytest>=8.1 - - py-cpuinfo - - aspectlib ; extra == 'aspect' - - pygal ; extra == 'histogram' - - pygaljs ; extra == 'histogram' - - setuptools ; extra == 'histogram' - - elasticsearch ; extra == 'elasticsearch' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl - name: pytest-cov - version: 7.1.0 - sha256: a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + name: dask + version: 2026.3.0 + sha256: be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d requires_dist: - - coverage[toml]>=7.10.6 - - pluggy>=1.2 - - pytest>=7 - - process-tests ; extra == 'testing' - - pytest-xdist ; extra == 'testing' - - virtualenv ; extra == 'testing' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl - name: pytest-xdist - version: 3.8.0 - sha256: 202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88 + - click>=8.1 + - cloudpickle>=3.0.0 + - fsspec>=2021.9.0 + - packaging>=20.0 + - partd>=1.4.0 + - pyyaml>=5.3.1 + - toolz>=0.12.0 + - importlib-metadata>=4.13.0 ; python_full_version < '3.12' + - numpy>=1.24 ; extra == 'array' + - dask[array] ; extra == 'dataframe' + - pandas>=2.0 ; extra == 'dataframe' + - pyarrow>=16.0 ; extra == 'dataframe' + - 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' + - pyarrow>=16.0 ; extra == 'complete' + - lz4>=4.3.2 ; extra == 'complete' + - pandas[test] ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-rerunfailures ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - pre-commit ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl + name: scipy + version: 1.17.1 + sha256: 3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19 requires_dist: - - execnet>=2.1 - - pytest>=7.0.0 - - filelock ; extra == 'testing' - - psutil>=3.0 ; extra == 'psutil' - - setproctitle ; extra == 'setproctitle' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda - sha256: a44655c1c3e1d43ed8704890a91e12afd68130414ea2c0872e154e5633a13d7e - md5: 7eccb41177e15cc672e1babe9056018e - depends: - - __glibc >=2.17,<3.0.a0 - - bzip2 >=1.0.8,<2.0a0 - - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.4,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - libgcc >=14 - - liblzma >=5.8.2,<6.0a0 - - libnsl >=2.0.1,<2.1.0a0 - - libsqlite >=3.51.2,<4.0a0 - - libuuid >=2.41.3,<3.0a0 - - libxcrypt >=4.4.36 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.5,<4.0a0 - - readline >=8.3,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - constrains: - - python_abi 3.12.* *_cp312 - license: Python-2.0 - purls: [] - size: 31608571 - timestamp: 1772730708989 -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda - build_number: 100 - sha256: dec247c5badc811baa34d6085df9d0465535883cf745e22e8d79092ad54a3a7b - md5: a443f87920815d41bfe611296e507995 - depends: - - __glibc >=2.17,<3.0.a0 - - bzip2 >=1.0.8,<2.0a0 - - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.5,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - libgcc >=14 - - liblzma >=5.8.2,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.52.0,<4.0a0 - - libuuid >=2.42,<3.0a0 - - libzlib >=1.3.2,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.6,<4.0a0 - - python_abi 3.14.* *_cp314 - - readline >=8.3,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - purls: [] - size: 36705460 - timestamp: 1775614357822 - python_site_packages_path: lib/python3.14/site-packages -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda - sha256: e658e647a4a15981573d6018928dec2c448b10c77c557c29872043ff23c0eb6a - md5: 8e7608172fa4d1b90de9a745c2fd2b81 - depends: - - __osx >=11.0 - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.4,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.2,<6.0a0 - - libsqlite >=3.51.2,<4.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.5,<4.0a0 - - readline >=8.3,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - constrains: - - python_abi 3.12.* *_cp312 - license: Python-2.0 - purls: [] - size: 12127424 - timestamp: 1772730755512 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda - build_number: 100 - sha256: 27e7d6cbe021f37244b643f06a98e46767255f7c2907108dd3736f042757ddad - md5: e1bc5a3015a4bbeb304706dba5a32b7f - depends: - - __osx >=11.0 - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.5,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.2,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.52.0,<4.0a0 - - libzlib >=1.3.2,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.6,<4.0a0 - - python_abi 3.14.* *_cp314 - - readline >=8.3,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - purls: [] - size: 13533346 - timestamp: 1775616188373 - python_site_packages_path: lib/python3.14/site-packages -- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.13-h0159041_0_cpython.conda - sha256: a02b446d8b7b167b61733a3de3be5de1342250403e72a63b18dac89e99e6180e - md5: 2956dff38eb9f8332ad4caeba941cfe7 - depends: - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.4,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.2,<6.0a0 - - libsqlite >=3.51.2,<4.0a0 - - libzlib >=1.3.1,<2.0a0 - - openssl >=3.5.5,<4.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - python_abi 3.12.* *_cp312 - license: Python-2.0 - purls: [] - size: 15840187 - timestamp: 1772728877265 -- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda - build_number: 100 - sha256: e258d626b0ba778abb319f128de4c1211306fe86fe0803166817b1ce2514c920 - md5: 40b6a8f438afb5e7b314cc5c4a43cd84 - depends: - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.5,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.2,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.52.0,<4.0a0 - - libzlib >=1.3.2,<2.0a0 - - openssl >=3.5.6,<4.0a0 - - python_abi 3.14.* *_cp314 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - purls: [] - size: 18055445 - timestamp: 1775615317758 - python_site_packages_path: Lib/site-packages -- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 - md5: 5b8d21249ff20967101ffa321cab24e8 - depends: - - python >=3.9 - - six >=1.5 - - python - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/python-dateutil?source=hash-mapping - size: 233310 - timestamp: 1751104122689 -- pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - name: python-discovery - version: 1.3.0 - sha256: 441d9ced3dfce36e113beb35ca302c71c7ef06f3c0f9c227a0b9bb3bd49b9e9f + - numpy>=1.26.4,<2.7 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.10.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/4c/65/b4b86e5fa07543bfbbcdc6c9f7f9f561e66a5f3539992e3009973f2b1314/jupytext-1.19.2-py3-none-any.whl + name: jupytext + version: 1.19.2 + sha256: 8a31e896c7e9215841783aade24336e945543057e1c2d7f00b22f9e870348688 requires_dist: - - filelock>=3.15.4 - - platformdirs>=4.3.6,<5 - - furo>=2025.12.19 ; extra == 'docs' - - sphinx-autodoc-typehints>=3.6.3 ; extra == 'docs' - - sphinx>=9.1 ; extra == 'docs' - - sphinxcontrib-mermaid>=2 ; extra == 'docs' - - covdefaults>=2.3 ; extra == 'testing' - - coverage>=7.5.4 ; extra == 'testing' - - pytest-mock>=3.14 ; extra == 'testing' - - pytest>=8.3.5 ; extra == 'testing' - - setuptools>=75.1 ; extra == 'testing' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl - name: python-engineio - version: 4.13.1 - sha256: f32ad10589859c11053ad7d9bb3c9695cdf862113bfb0d20bc4d890198287399 + - markdown-it-py>=1.0 + - mdit-py-plugins + - nbformat + - packaging + - pyyaml + - tomli ; python_full_version < '3.11' + - autopep8 ; extra == 'dev' + - black ; extra == 'dev' + - flake8 ; extra == 'dev' + - gitpython ; extra == 'dev' + - ipykernel ; extra == 'dev' + - isort ; extra == 'dev' + - jupyter-fs[fs]>=1.0 ; extra == 'dev' + - jupyter-server!=2.11 ; extra == 'dev' + - marimo>=0.17.6,<=0.19.4 ; extra == 'dev' + - nbconvert ; extra == 'dev' + - pre-commit ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-asyncio ; extra == 'dev' + - pytest-cov>=2.6.1 ; extra == 'dev' + - pytest-randomly ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-gallery>=0.8 ; extra == 'dev' + - myst-parser ; extra == 'docs' + - sphinx ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pytest ; extra == 'test' + - pytest-asyncio ; extra == 'test' + - pytest-randomly ; extra == 'test' + - pytest-xdist ; extra == 'test' + - black ; extra == 'test-cov' + - ipykernel ; extra == 'test-cov' + - jupyter-server!=2.11 ; extra == 'test-cov' + - nbconvert ; extra == 'test-cov' + - pytest ; extra == 'test-cov' + - pytest-asyncio ; extra == 'test-cov' + - pytest-cov>=2.6.1 ; extra == 'test-cov' + - pytest-randomly ; extra == 'test-cov' + - pytest-xdist ; extra == 'test-cov' + - autopep8 ; extra == 'test-external' + - black ; extra == 'test-external' + - flake8 ; extra == 'test-external' + - gitpython ; extra == 'test-external' + - ipykernel ; extra == 'test-external' + - isort ; extra == 'test-external' + - jupyter-fs[fs]>=1.0 ; extra == 'test-external' + - jupyter-server!=2.11 ; extra == 'test-external' + - marimo>=0.17.6,<=0.19.4 ; extra == 'test-external' + - nbconvert ; extra == 'test-external' + - pre-commit ; extra == 'test-external' + - pytest ; extra == 'test-external' + - pytest-asyncio ; extra == 'test-external' + - pytest-randomly ; extra == 'test-external' + - pytest-xdist ; extra == 'test-external' + - sphinx ; extra == 'test-external' + - sphinx-gallery>=0.8 ; extra == 'test-external' + - black ; extra == 'test-functional' + - pytest ; extra == 'test-functional' + - pytest-asyncio ; extra == 'test-functional' + - pytest-randomly ; extra == 'test-functional' + - pytest-xdist ; extra == 'test-functional' + - black ; extra == 'test-integration' + - ipykernel ; extra == 'test-integration' + - jupyter-server!=2.11 ; extra == 'test-integration' + - nbconvert ; extra == 'test-integration' + - pytest ; extra == 'test-integration' + - pytest-asyncio ; extra == 'test-integration' + - pytest-randomly ; extra == 'test-integration' + - pytest-xdist ; extra == 'test-integration' + - bash-kernel ; extra == 'test-ui' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/4c/fe/4fb3a0805bd5165da5ebf858da7cc01cce8061674106d2cf5bdab32cbfde/greenlet-3.5.0-cp312-cp312-win_amd64.whl + name: greenlet + version: 3.5.0 + sha256: d4d9f0624c775f2dfc56ba54d515a8c771044346852a918b405914f6b19d7fd8 requires_dist: - - simple-websocket>=0.10.0 - - requests>=2.21.0 ; extra == 'client' - - websocket-client>=0.54.0 ; extra == 'client' - - aiohttp>=3.11 ; extra == 'asyncio-client' - - tox ; extra == 'dev' - sphinx ; extra == 'docs' - furo ; extra == 'docs' - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - sha256: df9aa74e9e28e8d1309274648aac08ec447a92512c33f61a8de0afa9ce32ebe8 - md5: 23029aae904a2ba587daba708208012f - depends: - - python >=3.9 - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/fastjsonschema?source=hash-mapping - size: 244628 - timestamp: 1755304154927 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - sha256: 97327b9509ae3aae28d27217a5d7bd31aff0ab61a02041e9c6f98c11d8a53b29 - md5: 32780d6794b8056b78602103a04e90ef - depends: - - cpython 3.12.13.* - - python_abi * *_cp312 - license: Python-2.0 - purls: [] - size: 46449 - timestamp: 1772728979370 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda - sha256: 36ff7984e4565c85149e64f8206303d412a0652e55cf806dcb856903fa056314 - md5: e4e60721757979d01d3964122f674959 - depends: - - cpython 3.14.4.* - - python_abi * *_cp314 - license: Python-2.0 - purls: [] - size: 49806 - timestamp: 1775614307464 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda - sha256: 1c55116c22512cef7b01d55ae49697707f2c1fd829407183c19817e2d300fd8d - md5: 1cd2f3e885162ee1366312bd1b1677fd - depends: - - python >=3.10 - - typing_extensions - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/python-json-logger?source=hash-mapping - size: 18969 - timestamp: 1777318679482 -- pypi: https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl - name: python-socketio - version: 5.16.1 - sha256: a3eb1702e92aa2f2b5d3ba00261b61f062cce51f1cfb6900bf3ab4d1934d2d35 + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.whl + name: chardet + version: 7.4.3 + sha256: acc46d1b8b7d5783216afe15db56d1c179b9a40e5a1558bc13164c4fd20674c4 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl + name: simple-websocket + version: 1.1.0 + sha256: 4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c requires_dist: - - bidict>=0.21.0 - - python-engineio>=4.11.0 - - requests>=2.21.0 ; extra == 'client' - - websocket-client>=0.54.0 ; extra == 'client' - - aiohttp>=3.4 ; extra == 'asyncio-client' + - wsproto - tox ; extra == 'dev' + - flake8 ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' - sphinx ; extra == 'docs' + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl + name: contourpy + version: 1.3.3 + sha256: 556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6 + requires_dist: + - numpy>=1.25 - furo ; extra == 'docs' - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - sha256: e943f9c15a6bdba2e1b9f423ab913b3f6b02197b0ef9f8e6b7464d78b59965b9 - md5: f6ad7450fc21e00ecc23812baed6d2e4 - depends: - - python >=3.10 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/tzdata?source=hash-mapping - size: 146639 - timestamp: 1777068997932 -- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - build_number: 8 - sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 - md5: c3efd25ac4d74b1584d2f7a57195ddf1 - constrains: - - python 3.12.* *_cpython - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 6958 - timestamp: 1752805918820 -- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - build_number: 8 - sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 - md5: 0539938c55b6b1a59b560e843ad864a4 - constrains: - - python 3.14.* *_cp314 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 6989 - timestamp: 1752805904792 -- pypi: https://files.pythonhosted.org/packages/d8/8b/e2bbeb42068f0c48899e8eddd34902afc0f7429d4d2a152d2dc2670dc661/pythreejs-2.4.2-py3-none-any.whl - name: pythreejs - version: 2.4.2 - sha256: 8418807163ad91f4df53b58c4e991b26214852a1236f28f1afeaadf99d095818 + - sphinx>=7.2 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - bokeh ; extra == 'bokeh' + - selenium ; extra == 'bokeh' + - contourpy[bokeh,docs] ; extra == 'mypy' + - bokeh ; extra == 'mypy' + - docutils-stubs ; extra == 'mypy' + - mypy==1.17.0 ; extra == 'mypy' + - types-pillow ; extra == 'mypy' + - contourpy[test-no-images] ; extra == 'test' + - matplotlib ; extra == 'test' + - pillow ; extra == 'test' + - pytest ; extra == 'test-no-images' + - pytest-cov ; extra == 'test-no-images' + - pytest-rerunfailures ; extra == 'test-no-images' + - pytest-xdist ; extra == 'test-no-images' + - wurlitzer ; extra == 'test-no-images' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + name: pluggy + version: 1.6.0 + sha256: e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 requires_dist: - - ipywidgets>=7.2.1 - - ipydatawidgets>=1.1.1 - - numpy - - traitlets - - sphinx>=1.5 ; extra == 'docs' - - nbsphinx>=0.2.13 ; extra == 'docs' - - nbsphinx-link ; extra == 'docs' - - sphinx-rtd-theme ; extra == 'docs' - - scipy ; extra == 'examples' - - matplotlib ; extra == 'examples' - - scikit-image ; extra == 'examples' - - ipywebrtc ; extra == 'examples' - - nbval ; extra == 'test' - - pytest-check-links ; extra == 'test' - - numpy>=1.14 ; extra == 'test' + - pre-commit ; extra == 'dev' + - tox ; extra == 'dev' + - pytest ; extra == 'testing' + - pytest-benchmark ; extra == 'testing' + - coverage ; extra == 'testing' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl + name: sqlalchemy + version: 2.0.49 + sha256: 233088b4b99ebcbc5258c755a097aa52fbf90727a03a5a80781c4b9c54347a2e + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + name: ipywidgets + version: 8.1.8 + sha256: ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e + requires_dist: + - comm>=0.1.3 + - ipython>=6.1.0 + - traitlets>=4.3.1 + - widgetsnbextension~=4.0.14 + - jupyterlab-widgets~=3.0.15 + - jsonschema ; extra == 'test' + - ipykernel ; extra == 'test' + - pytest>=3.6.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytz ; extra == 'test' requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py312h829343e_1.conda - sha256: a7505522048dad63940d06623f07eb357b9b65510a8d23ff32b99add05aac3a1 - md5: 64cbe4ecbebe185a2261d3f298a60cde - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.12.* *_cp312 - license: PSF-2.0 - license_family: PSF - purls: - - pkg:pypi/pywin32?source=hash-mapping - size: 6684490 - timestamp: 1756487136116 -- conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda - sha256: 6918a8067f296f3c65d43e84558170c9e6c3f4dd735cfe041af41a7fdba7b171 - md5: 2d7b7ba21e8a8ced0eca553d4d53f773 - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.14.* *_cp314 - license: PSF-2.0 - license_family: PSF - purls: - - pkg:pypi/pywin32?source=hash-mapping - size: 6713155 - timestamp: 1756487145487 -- conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py312h275cf98_1.conda - sha256: 61cc6c2c712ab4d2b8e7a73d884ef8d3262cb80cc93a4aa074e8b08aa7ddd648 - md5: 66255d136bd0daa41713a334db41d9f0 - depends: - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - - winpty - license: MIT - license_family: MIT - purls: - - pkg:pypi/pywinpty?source=hash-mapping - size: 215371 - timestamp: 1759557609855 -- conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda - sha256: 048e20641da680aedaab285640a2aca56b7b5baf7a18f8f164f2796e13628c1f - md5: dd84e8748bd3c85a5c751b0576488080 - depends: - - python >=3.14.0rc3,<3.15.0a0 - - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - - winpty - license: MIT - license_family: MIT - purls: - - pkg:pypi/pywinpty?source=hash-mapping - size: 216325 - timestamp: 1759557436167 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda - sha256: cb142bfd92f6e55749365ddc244294fa7b64db6d08c45b018ff1c658907bfcbf - md5: 15878599a87992e44c059731771591cb - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - yaml >=0.2.5,<0.3.0a0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 198293 - timestamp: 1770223620706 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda - sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d - md5: 2035f68f96be30dc60a5dfd7452c7941 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - - yaml >=0.2.5,<0.3.0a0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 202391 - timestamp: 1770223462836 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda - sha256: 737959262d03c9c305618f2d48c7f1691fb996f14ae420bfd05932635c99f873 - md5: 95a5f0831b5e0b1075bbd80fcffc52ac - depends: - - __osx >=11.0 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - - yaml >=0.2.5,<0.3.0a0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 187278 - timestamp: 1770223990452 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda - sha256: 95f385f9606e30137cf0b5295f63855fd22223a4cf024d306cf9098ea1c4a252 - md5: dcf51e564317816cb8d546891019b3ab - depends: - - __osx >=11.0 - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python_abi 3.14.* *_cp314 - - yaml >=0.2.5,<0.3.0a0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 189475 - timestamp: 1770223788648 -- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py312h05f76fc_1.conda - sha256: 1cab6cbd6042b2a1d8ee4d6b4ec7f36637a41f57d2f5c5cf0c12b7c4ce6a62f6 - md5: 9f6ebef672522cb9d9a6257215ca5743 - depends: - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - yaml >=0.2.5,<0.3.0a0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 179738 - timestamp: 1770223468771 -- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda - sha256: a2aff34027aa810ff36a190b75002d2ff6f9fbef71ec66e567616ac3a679d997 - md5: 0cd9b88826d0f8db142071eb830bce56 - depends: - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - yaml >=0.2.5,<0.3.0a0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 181257 - timestamp: 1770223460931 -- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl - name: pyyaml-env-tag - version: '1.1' - sha256: 17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 +- pypi: https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: aiohttp + version: 3.13.5 + sha256: b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: pandas + version: 3.0.3 + sha256: 9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a + requires_dist: + - numpy>=1.26.0 ; python_full_version < '3.14' + - numpy>=2.3.3 ; python_full_version >= '3.14' + - python-dateutil>=2.8.2 + - tzdata ; sys_platform == 'win32' + - tzdata ; sys_platform == 'emscripten' + - hypothesis>=6.116.0 ; extra == 'test' + - pytest>=8.3.4 ; extra == 'test' + - pytest-xdist>=3.6.1 ; extra == 'test' + - pyarrow>=13.0.0 ; extra == 'pyarrow' + - bottleneck>=1.4.2 ; extra == 'performance' + - numba>=0.60.0 ; extra == 'performance' + - numexpr>=2.10.2 ; extra == 'performance' + - scipy>=1.14.1 ; extra == 'computation' + - xarray>=2024.10.0 ; extra == 'computation' + - fsspec>=2024.10.0 ; extra == 'fss' + - s3fs>=2024.10.0 ; extra == 'aws' + - gcsfs>=2024.10.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.5 ; extra == 'excel' + - python-calamine>=0.3.0 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.2.0 ; extra == 'excel' + - pyarrow>=13.0.0 ; extra == 'parquet' + - pyarrow>=13.0.0 ; extra == 'feather' + - pyiceberg>=0.8.1 ; extra == 'iceberg' + - tables>=3.10.1 ; extra == 'hdf5' + - pyreadstat>=1.2.8 ; extra == 'spss' + - sqlalchemy>=2.0.36 ; extra == 'postgresql' + - psycopg2>=2.9.10 ; extra == 'postgresql' + - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.36 ; extra == 'mysql' + - pymysql>=1.1.1 ; extra == 'mysql' + - sqlalchemy>=2.0.36 ; extra == 'sql-other' + - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' + - beautifulsoup4>=4.12.3 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'xml' + - matplotlib>=3.9.3 ; extra == 'plot' + - jinja2>=3.1.5 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.4.2 ; extra == 'clipboard' + - zstandard>=0.23.0 ; extra == 'compression' + - pytz>=2020.1 ; extra == 'timezone' + - adbc-driver-postgresql>=1.2.0 ; extra == 'all' + - adbc-driver-sqlite>=1.2.0 ; extra == 'all' + - beautifulsoup4>=4.12.3 ; extra == 'all' + - bottleneck>=1.4.2 ; extra == 'all' + - fastparquet>=2024.11.0 ; extra == 'all' + - fsspec>=2024.10.0 ; extra == 'all' + - gcsfs>=2024.10.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.116.0 ; extra == 'all' + - jinja2>=3.1.5 ; extra == 'all' + - lxml>=5.3.0 ; extra == 'all' + - matplotlib>=3.9.3 ; extra == 'all' + - numba>=0.60.0 ; extra == 'all' + - numexpr>=2.10.2 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.5 ; extra == 'all' + - psycopg2>=2.9.10 ; extra == 'all' + - pyarrow>=13.0.0 ; extra == 'all' + - pyiceberg>=0.8.1 ; extra == 'all' + - pymysql>=1.1.1 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.8 ; extra == 'all' + - pytest>=8.3.4 ; extra == 'all' + - pytest-xdist>=3.6.1 ; extra == 'all' + - python-calamine>=0.3.0 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.4.2 ; extra == 'all' + - scipy>=1.14.1 ; extra == 'all' + - s3fs>=2024.10.0 ; extra == 'all' + - sqlalchemy>=2.0.36 ; extra == 'all' + - tables>=3.10.1 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2024.10.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.2.0 ; extra == 'all' + - zstandard>=0.23.0 ; extra == 'all' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/58/e0/f1871f520c359e4e3a2eb7437c9e7e792bb6c356414e8617937561167caf/pycifrw-5.0.1.tar.gz + name: pycifrw + version: 5.0.1 + sha256: e636b80be6a2be15b215e69ecec0c0a784ebcbfed8b1e3bac4bcc6e6ba9a75e0 requires_dist: - - pyyaml + - prettytable + - ply + - numpy +- pypi: https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl + name: frozenlist + version: 1.8.0 + sha256: 3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0 requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda - noarch: python - sha256: be66c1f85c3b48137200d62c12d918f4f8ad329423daef04fed292818efd3c28 - md5: 082985717303dab433c976986c674b35 - depends: - - python - - libgcc >=14 - - libstdcxx >=14 - - __glibc >=2.17,<3.0.a0 - - zeromq >=4.3.5,<4.4.0a0 - - _python_abi3_support 1.* - - cpython >=3.12 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pyzmq?source=hash-mapping - size: 211567 - timestamp: 1771716961404 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda - noarch: python - sha256: 2f31f799a46ed75518fae0be75ecc8a1b84360dbfd55096bc2fe8bd9c797e772 - md5: 2f6b79700452ef1e91f45a99ab8ffe5a - depends: - - python - - libcxx >=19 - - __osx >=11.0 - - _python_abi3_support 1.* - - cpython >=3.12 - - zeromq >=4.3.5,<4.4.0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pyzmq?source=hash-mapping - size: 191641 - timestamp: 1771717073430 -- conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda - noarch: python - sha256: d84bcc19a945ca03d1fd794be3e9896ab6afc9f691d58d9c2da514abe584d4df - md5: eb1ec67a70b4d479f7dd76e6c8fe7575 - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - zeromq >=4.3.5,<4.3.6.0a0 - - _python_abi3_support 1.* - - cpython >=3.12 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pyzmq?source=hash-mapping - size: 183235 - timestamp: 1771716967192 -- 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 +- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + name: mkdocs-material-extensions + version: 1.3.1 + sha256: adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/5b/69/93b34728cc386efdde0c342f8c680b9187dea7beb7adaf6b58a0713be101/mpld3-0.5.12-py3-none-any.whl + name: mpld3 + version: 0.5.12 + sha256: bea31799a4041029a906f53f2662bbf1c49903e0c0bc712b412354158ec7cf54 requires_dist: - - prompt-toolkit>=2.0,<4.0 + - jinja2 + - matplotlib +- pypi: https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl + name: watchdog + version: 6.0.0 + sha256: 6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl + name: scippnexus + version: 26.1.1 + sha256: 899a0a5e71291b7809d902c17b6c74addf5a805397eabcec557491ff74eead12 + requires_dist: + - scipp>=24.2.0 + - scipy>=1.10.0 + - h5py>=3.12 + - pytest>=7.0 ; extra == 'test' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl + name: pillow + version: 12.2.0 + sha256: 7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5 + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - arro3-compute ; extra == 'test-arrow' + - arro3-core ; extra == 'test-arrow' + - nanoarrow ; extra == 'test-arrow' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma>=5 ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pydantic-core + version: 2.46.4 + sha256: 926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/61/2b/e260d50e64690d2a9e405d52ccd18a63c286c5088937dd0107cb23eb3195/diffpy_utils-3.7.2-py3-none-any.whl + name: diffpy-utils + version: 3.7.2 + sha256: 6100600736791a8e4638e3dd476704f4dabe3cab75bcb5c60c83c16a2032519a + requires_dist: + - numpy + - xraydb + - scipy + requires_python: '>=3.10,<3.15' +- pypi: https://files.pythonhosted.org/packages/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl + name: propcache + version: 0.5.2 + sha256: d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl + name: propcache + version: 0.5.2 + sha256: 81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl + name: scippneutron + version: 26.5.0 + sha256: e9cfad09b974867c6dc2a175cd2e575e06eaa951b2409e9ef863db237853bf99 + requires_dist: + - python-dateutil>=2.8 + - email-validator>=2 + - h5py>=3.12 + - lazy-loader>=0.4 + - mpltoolbox>=24.6.0 + - numpy>=1.20 + - plopp>=26.4.1 + - pydantic>=2 + - scipp>=25.8.0 + - scippnexus>=23.11.0 + - scipy>=1.7.0 + - scipp[all]>=25.8.0 ; extra == 'all' + - pooch>=1.5 ; extra == 'all' + - hypothesis>=6.100 ; extra == 'test' + - ipympl>0.9.0 ; extra == 'test' + - ipykernel>6.30 ; extra == 'test' + - pace-neutrons>=0.3 ; extra == 'test' + - pooch>=1.5 ; extra == 'test' + - psutil>=5.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-xdist>=3.0 ; extra == 'test' + - pythreejs>=2.4.1 ; extra == 'test' + - sciline>=25.1.0 ; extra == 'test' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl + name: propcache + version: 0.5.2 + sha256: 97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/64/a8/c09fbe44b12fa919c5bfe0afb71e60d1231a7dc93405e54c30496c57c9d3/arviz-1.1.0-py3-none-any.whl + name: arviz + version: 1.1.0 + sha256: 87ebd21ce052f30d21f932b4166fc31b91c0bc7443f8da7fed3518b342267010 + requires_dist: + - arviz-base>=1.1.0,<1.2.0 + - arviz-stats[xarray]>=1.1.0,<1.2.0 + - arviz-plots>=1.1.0,<1.2.0 + - arviz-plots[bokeh] ; extra == 'bokeh' + - build ; extra == 'check' + - pre-commit ; extra == 'check' + - h5netcdf ; extra == 'doc' + - h5py ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - matplotlib ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - pydata-sphinx-theme>=0.13 ; extra == 'doc' + - sphinx>=5 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - sphinx-notfound-page ; extra == 'doc' + - sphinxcontrib-youtube ; extra == 'doc' + - sphinx-togglebutton ; extra == 'doc' + - sphobjinv ; extra == 'doc' + - arviz-base[h5netcdf] ; extra == 'h5netcdf' + - arviz-plots[matplotlib] ; extra == 'matplotlib' + - arviz-base[netcdf4] ; extra == 'netcdf4' + - arviz-plots[plotly] ; extra == 'plotly' + - pytest ; extra == 'test' + - arviz-base[zarr] ; extra == 'zarr' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: msgpack + version: 1.1.2 + sha256: 372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42 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 - sha256: 632cc032364a6f8bb1010a2f6a12d0f14bc7e5ede76585ef29dc0cecf4cd8859 +- pypi: https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: pandas + version: 3.0.3 + sha256: 6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9 requires_dist: - - mando>=0.6,<0.8 - - colorama==0.4.1 ; python_full_version < '3.5' - - colorama>=0.4.1 ; python_full_version >= '3.5' - - tomli>=2.0.1 ; extra == 'toml' -- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 - md5: d7d95fc8287ea7bf33e0e7116d2b95ec - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - ncurses >=6.5,<7.0a0 - license: GPL-3.0-only - license_family: GPL - purls: [] - size: 345073 - timestamp: 1765813471974 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 - md5: f8381319127120ce51e081dce4865cf4 - depends: - - __osx >=11.0 - - ncurses >=6.5,<7.0a0 - license: GPL-3.0-only - license_family: GPL - purls: [] - size: 313930 - timestamp: 1765813902568 -- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 - md5: 870293df500ca7e18bedefa5838a22ab - depends: - - attrs >=22.2.0 - - python >=3.10 - - rpds-py >=0.7.0 - - typing_extensions >=4.4.0 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/referencing?source=hash-mapping - size: 51788 - timestamp: 1760379115194 -- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - sha256: 7f2c24dd3bd3c104a1d2c9a10ead5ed6758b0976b74f972cfe9c19884ccc4241 - md5: 9659f587a8ceacc21864260acd02fc67 - depends: - - python >=3.10 - - certifi >=2023.5.7 - - charset-normalizer >=2,<4 - - idna >=2.5,<4 - - urllib3 >=1.26,<3 - - python - constrains: - - chardet >=3.0.2,<8 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/requests?source=hash-mapping - size: 63728 - timestamp: 1777030058920 -- conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - sha256: 3b45efeae771f1a20307b36ecdb3a8911a89c05382836b50c62b0a99d8d3dfd8 - md5: da94ff04d97ec5efc42cbe5da3c43a84 - depends: - - python >=3.11 - - typing_extensions >=4.0,<5.0 - - python - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/returns?source=hash-mapping - size: 100559 - timestamp: 1776176903101 -- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - sha256: 2e4372f600490a6e0b3bac60717278448e323cab1c0fecd5f43f7c56535a99c5 - md5: 36de09a8d3e5d5e6f4ee63af49e59706 - depends: - - python >=3.9 - - six - license: MIT - license_family: MIT - purls: - - pkg:pypi/rfc3339-validator?source=hash-mapping - size: 10209 - timestamp: 1733600040800 -- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - sha256: 2a5b495a1de0f60f24d8a74578ebc23b24aa53279b1ad583755f223097c41c37 - md5: 912a71cc01012ee38e6b90ddd561e36f - depends: - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/rfc3986-validator?source=hash-mapping - size: 7818 - timestamp: 1598024297745 -- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - sha256: 70001ac24ee62058557783d9c5a7bbcfd97bd4911ef5440e3f7a576f9e43bc92 - md5: 7234f99325263a5af6d4cd195035e8f2 - depends: - - python >=3.9 - - lark >=1.2.2 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/rfc3987-syntax?source=hash-mapping - size: 22913 - timestamp: 1752876729969 -- pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl - name: rich - version: 15.0.0 - sha256: 33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb + - numpy>=1.26.0 ; python_full_version < '3.14' + - numpy>=2.3.3 ; python_full_version >= '3.14' + - python-dateutil>=2.8.2 + - tzdata ; sys_platform == 'win32' + - tzdata ; sys_platform == 'emscripten' + - hypothesis>=6.116.0 ; extra == 'test' + - pytest>=8.3.4 ; extra == 'test' + - pytest-xdist>=3.6.1 ; extra == 'test' + - pyarrow>=13.0.0 ; extra == 'pyarrow' + - bottleneck>=1.4.2 ; extra == 'performance' + - numba>=0.60.0 ; extra == 'performance' + - numexpr>=2.10.2 ; extra == 'performance' + - scipy>=1.14.1 ; extra == 'computation' + - xarray>=2024.10.0 ; extra == 'computation' + - fsspec>=2024.10.0 ; extra == 'fss' + - s3fs>=2024.10.0 ; extra == 'aws' + - gcsfs>=2024.10.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.5 ; extra == 'excel' + - python-calamine>=0.3.0 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.2.0 ; extra == 'excel' + - pyarrow>=13.0.0 ; extra == 'parquet' + - pyarrow>=13.0.0 ; extra == 'feather' + - pyiceberg>=0.8.1 ; extra == 'iceberg' + - tables>=3.10.1 ; extra == 'hdf5' + - pyreadstat>=1.2.8 ; extra == 'spss' + - sqlalchemy>=2.0.36 ; extra == 'postgresql' + - psycopg2>=2.9.10 ; extra == 'postgresql' + - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.36 ; extra == 'mysql' + - pymysql>=1.1.1 ; extra == 'mysql' + - sqlalchemy>=2.0.36 ; extra == 'sql-other' + - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' + - beautifulsoup4>=4.12.3 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'xml' + - matplotlib>=3.9.3 ; extra == 'plot' + - jinja2>=3.1.5 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.4.2 ; extra == 'clipboard' + - zstandard>=0.23.0 ; extra == 'compression' + - pytz>=2020.1 ; extra == 'timezone' + - adbc-driver-postgresql>=1.2.0 ; extra == 'all' + - adbc-driver-sqlite>=1.2.0 ; extra == 'all' + - beautifulsoup4>=4.12.3 ; extra == 'all' + - bottleneck>=1.4.2 ; extra == 'all' + - fastparquet>=2024.11.0 ; extra == 'all' + - fsspec>=2024.10.0 ; extra == 'all' + - gcsfs>=2024.10.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.116.0 ; extra == 'all' + - jinja2>=3.1.5 ; extra == 'all' + - lxml>=5.3.0 ; extra == 'all' + - matplotlib>=3.9.3 ; extra == 'all' + - numba>=0.60.0 ; extra == 'all' + - numexpr>=2.10.2 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.5 ; extra == 'all' + - psycopg2>=2.9.10 ; extra == 'all' + - pyarrow>=13.0.0 ; extra == 'all' + - pyiceberg>=0.8.1 ; extra == 'all' + - pymysql>=1.1.1 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.8 ; extra == 'all' + - pytest>=8.3.4 ; extra == 'all' + - pytest-xdist>=3.6.1 ; extra == 'all' + - python-calamine>=0.3.0 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.4.2 ; extra == 'all' + - scipy>=1.14.1 ; extra == 'all' + - s3fs>=2024.10.0 ; extra == 'all' + - sqlalchemy>=2.0.36 ; extra == 'all' + - tables>=3.10.1 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2024.10.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.2.0 ; extra == 'all' + - zstandard>=0.23.0 ; extra == 'all' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/66/3e/868e5c3364b6cee19ff3e1a122194fa4ce51def02c61023970442162859e/yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: yarl + version: 1.23.0 + sha256: a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 + requires_dist: + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + name: pandas + version: 3.0.3 + sha256: bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f + requires_dist: + - numpy>=1.26.0 ; python_full_version < '3.14' + - numpy>=2.3.3 ; python_full_version >= '3.14' + - python-dateutil>=2.8.2 + - tzdata ; sys_platform == 'win32' + - tzdata ; sys_platform == 'emscripten' + - hypothesis>=6.116.0 ; extra == 'test' + - pytest>=8.3.4 ; extra == 'test' + - pytest-xdist>=3.6.1 ; extra == 'test' + - pyarrow>=13.0.0 ; extra == 'pyarrow' + - bottleneck>=1.4.2 ; extra == 'performance' + - numba>=0.60.0 ; extra == 'performance' + - numexpr>=2.10.2 ; extra == 'performance' + - scipy>=1.14.1 ; extra == 'computation' + - xarray>=2024.10.0 ; extra == 'computation' + - fsspec>=2024.10.0 ; extra == 'fss' + - s3fs>=2024.10.0 ; extra == 'aws' + - gcsfs>=2024.10.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.5 ; extra == 'excel' + - python-calamine>=0.3.0 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.2.0 ; extra == 'excel' + - pyarrow>=13.0.0 ; extra == 'parquet' + - pyarrow>=13.0.0 ; extra == 'feather' + - pyiceberg>=0.8.1 ; extra == 'iceberg' + - tables>=3.10.1 ; extra == 'hdf5' + - pyreadstat>=1.2.8 ; extra == 'spss' + - sqlalchemy>=2.0.36 ; extra == 'postgresql' + - psycopg2>=2.9.10 ; extra == 'postgresql' + - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.36 ; extra == 'mysql' + - pymysql>=1.1.1 ; extra == 'mysql' + - sqlalchemy>=2.0.36 ; extra == 'sql-other' + - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' + - beautifulsoup4>=4.12.3 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'xml' + - matplotlib>=3.9.3 ; extra == 'plot' + - jinja2>=3.1.5 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.4.2 ; extra == 'clipboard' + - zstandard>=0.23.0 ; extra == 'compression' + - pytz>=2020.1 ; extra == 'timezone' + - adbc-driver-postgresql>=1.2.0 ; extra == 'all' + - adbc-driver-sqlite>=1.2.0 ; extra == 'all' + - beautifulsoup4>=4.12.3 ; extra == 'all' + - bottleneck>=1.4.2 ; extra == 'all' + - fastparquet>=2024.11.0 ; extra == 'all' + - fsspec>=2024.10.0 ; extra == 'all' + - gcsfs>=2024.10.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.116.0 ; extra == 'all' + - jinja2>=3.1.5 ; extra == 'all' + - lxml>=5.3.0 ; extra == 'all' + - matplotlib>=3.9.3 ; extra == 'all' + - numba>=0.60.0 ; extra == 'all' + - numexpr>=2.10.2 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.5 ; extra == 'all' + - psycopg2>=2.9.10 ; extra == 'all' + - pyarrow>=13.0.0 ; extra == 'all' + - pyiceberg>=0.8.1 ; extra == 'all' + - pymysql>=1.1.1 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.8 ; extra == 'all' + - pytest>=8.3.4 ; extra == 'all' + - pytest-xdist>=3.6.1 ; extra == 'all' + - python-calamine>=0.3.0 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.4.2 ; extra == 'all' + - scipy>=1.14.1 ; extra == 'all' + - s3fs>=2024.10.0 ; extra == 'all' + - sqlalchemy>=2.0.36 ; extra == 'all' + - tables>=3.10.1 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2024.10.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.2.0 ; extra == 'all' + - zstandard>=0.23.0 ; extra == 'all' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/69/d1/705e6c19b437a4105bf3b9ae7945fcfc3ad2abb73d14bae0a3f2d58b305b/arviz_base-1.1.0-py3-none-any.whl + name: arviz-base + version: 1.1.0 + sha256: 4f97016f697751038f45d144331a1830c921f0ebc2739d5df343120fba453e83 requires_dist: - - ipywidgets>=7.5.1,<9 ; extra == 'jupyter' - - markdown-it-py>=2.2.0 - - pygments>=2.13.0,<3.0.0 - requires_python: '>=3.9.0' -- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py312h868fb18_0.conda - sha256: 62f46e85caaba30b459da7dfcf3e5488ca24fd11675c33ce4367163ab191a42c - md5: 3ffc5a3572db8751c2f15bacf6a0e937 - depends: - - python - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python_abi 3.12.* *_cp312 - constrains: - - __glibc >=2.17 - license: MIT - license_family: MIT - purls: - - pkg:pypi/rpds-py?source=hash-mapping - size: 383750 - timestamp: 1764543174231 -- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda - sha256: e53b0cbf3b324eaa03ca1fe1a688fdf4ab42cea9c25270b0a7307d8aaaa4f446 - md5: c1c368b5437b0d1a68f372ccf01cb133 - depends: - - python - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - - python_abi 3.14.* *_cp314 - constrains: - - __glibc >=2.17 - license: MIT - license_family: MIT - purls: - - pkg:pypi/rpds-py?source=hash-mapping - size: 376121 - timestamp: 1764543122774 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py312h6ef9ec0_0.conda - sha256: ea06f6f66b1bea97244c36fd2788ccd92fd1fb06eae98e469dd95ee80831b057 - md5: a7cfbbdeb93bb9a3f249bc4c3569cd4c - depends: - - python - - __osx >=11.0 - - python 3.12.* *_cpython - - python_abi 3.12.* *_cp312 - constrains: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/rpds-py?source=hash-mapping - size: 358853 - timestamp: 1764543161524 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda - sha256: e161dd97403b8b8a083d047369a5cf854557dba1204d29e2f0250f5ac4403925 - md5: 76a4f88d1b7748c477abf3c341edc64c - depends: - - python - - __osx >=11.0 - - python 3.14.* *_cp314 - - python_abi 3.14.* *_cp314 - constrains: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/rpds-py?source=hash-mapping - size: 350976 - timestamp: 1764543169524 -- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py312hdabe01f_0.conda - sha256: faad05e6df2fc15e3ae06fdd71a36e17ff25364777aa4c40f2ec588740d64091 - md5: 2c51baeda0a355b0a5e7b6acb28cf02d - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.12.* *_cp312 - license: MIT - license_family: MIT - purls: - - pkg:pypi/rpds-py?source=hash-mapping - size: 243577 - timestamp: 1764543069837 -- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda - sha256: e4435368c5c25076dc0f5918ba531c5a92caee8e0e2f9912ef6810049cf00db2 - md5: e86531e278ad304438e530953cd55d14 - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/rpds-py?source=hash-mapping - size: 235780 - timestamp: 1764543046065 -- pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl - name: ruff - version: 0.15.12 - sha256: c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl - name: ruff - version: 0.15.12 - sha256: fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5 - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - name: ruff - version: 0.15.12 - sha256: 83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0 - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - name: sciline - version: 25.11.1 - sha256: 13c378287b8157e819b9b67d7e973c65bc6bdc545a3602d18204c365b0c336f9 + - numpy>=2 + - xarray>=2024.11.0 + - typing-extensions>=3.10 + - lazy-loader>=0.4 + - build ; extra == 'check' + - pre-commit ; extra == 'check' + - docstub==0.4 ; extra == 'check' + - mypy ; extra == 'check' + - pre-commit ; extra == 'ci' + - cloudpickle ; extra == 'ci' + - sphinx-book-theme ; extra == 'doc' + - myst-parser[linkify] ; extra == 'doc' + - myst-nb ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - numpydoc ; extra == 'doc' + - sphinx>=5 ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - jupyter-sphinx ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'doc' + - h5netcdf[h5py] ; extra == 'h5netcdf' + - netcdf4 ; extra == 'netcdf4' + - xarray!=2025.8.0 ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - scipy ; extra == 'test' + - zarr ; extra == 'zarr' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/69/ff/6699e7b71e60d3049eb2bdcbc95ee3f35707b2b0e48f32e9e63d3ce30c08/coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: coverage + version: 7.14.0 + sha256: ca3d9cf2c32b521bd9518385608787fa86f38daf993695307531822c3430ed67 + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl + name: h5py + version: 3.16.0 + sha256: 8c1eff849cdd53cbc73c214c30ebdb6f1bb8b64790b4b4fc36acdb5e43570210 + requires_dist: + - numpy>=1.21.2 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: frozenlist + version: 1.8.0 + sha256: 494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-win_amd64.whl + name: fonttools + version: 4.62.1 + sha256: 1eecc128c86c552fb963fe846ca4e011b1be053728f798185a1687502f6d398e + requires_dist: + - lxml>=4.0 ; extra == 'lxml' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - zopfli>=0.1.4 ; extra == 'woff' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' + - lz4>=1.7.4.2 ; extra == 'graphite' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' + - pycairo ; extra == 'interpolatable' + - matplotlib ; extra == 'plot' + - sympy ; extra == 'symfont' + - xattr ; sys_platform == 'darwin' and extra == 'type1' + - skia-pathops>=0.5.0 ; extra == 'pathops' + - uharfbuzz>=0.45.0 ; extra == 'repacker' + - lxml>=4.0 ; extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' + - pycairo ; extra == 'all' + - matplotlib ; extra == 'all' + - sympy ; extra == 'all' + - xattr ; sys_platform == 'darwin' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.45.0 ; extra == 'all' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6c/25/4f103d1bedb3593718713b3f743df7b3ff3fc68d36d6666c30265ef59c8a/ase-3.28.0-py3-none-any.whl + name: ase + 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' + - pytest-xdist>=3.2.0 ; extra == 'test' + - spglib>=1.9 ; extra == 'spglib' + - mypy ; extra == 'lint' + - ruff ; extra == 'lint' + - types-docutils ; extra == 'lint' + - types-pymysql ; extra == 'lint' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + name: mkdocstrings + version: 1.0.4 + sha256: 63464b4b29053514f32a1dbbf604e52876d5e638111b0c295ab7ed3cac73ca9b requires_dist: - - cyclebane>=24.6.0 - - pytest ; extra == 'test' - - pytest-randomly>=3 ; extra == 'test' - - dask ; extra == 'test' - - graphviz ; extra == 'test' - - jsonschema ; extra == 'test' - - numpy ; extra == 'test' - - pandas ; extra == 'test' - - pydantic ; extra == 'test' - - rich ; extra == 'test' - - rich ; extra == 'progress' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/0f/0e/0eb94e64f5badef67f11fe1e448dde2a44f00940d8949f4adf71d560552e/scipp-26.3.1-cp314-cp314-macosx_14_0_arm64.whl - name: scipp - version: 26.3.1 - sha256: 1f103f6c5a33b08773206c613fe2dd9c02585f5c4e44b77311c54b7828a758ed + - jinja2>=3.1 + - markdown>=3.6 + - markupsafe>=1.1 + - mkdocs>=1.6 + - mkdocs-autorefs>=1.4 + - pymdown-extensions>=6.3 + - mkdocstrings-crystal>=0.3.4 ; extra == 'crystal' + - mkdocstrings-python-legacy>=0.2.1 ; extra == 'python-legacy' + - mkdocstrings-python>=1.16.2 ; extra == 'python' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl + name: msgpack + version: 1.1.2 + sha256: 9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/6f/0c/8297c8d978c919ad6318011631a6123082d5da940da5f8612e75a247d739/diffpy_pdffit2-1.6.0-cp312-cp312-win_amd64.whl + name: diffpy-pdffit2 + version: 1.6.0 + sha256: 6c7865218f78effeeb8374fb62a5aef2b084264da96e77c03160aa411d33c2a0 requires_dist: - - numpy>=2 - - pytest ; extra == 'test' - - matplotlib ; extra == 'test' - - beautifulsoup4 ; extra == 'test' - - ipython ; extra == 'test' - - h5py ; extra == 'extra' - - scipy>=1.7.0 ; extra == 'extra' - - graphviz ; extra == 'extra' - - pooch ; extra == 'extra' - - plopp ; extra == 'extra' - - matplotlib ; extra == 'extra' - - scipp[extra] ; extra == 'all' - - ipympl ; extra == 'all' - - ipython ; extra == 'all' - - ipywidgets ; extra == 'all' - - jupyterlab ; extra == 'all' - - jupyterlab-widgets ; extra == 'all' - - jupyter-nbextensions-configurator ; extra == 'all' - - nodejs ; extra == 'all' - - pythreejs ; extra == 'all' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/1a/1f/86b4d15221096cb5500bcd73bf350745749e3ba056cdd7a7f75f126f154e/scipp-26.3.1-cp312-cp312-win_amd64.whl - name: scipp - version: 26.3.1 - sha256: 8b036876edf7895d17644f59711037d2d7d9ad048b1a503200646d8229fb1ad7 + - diffpy-structure + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/71/d6/48f5b9e44e2e760855d7b489b1317cd7620e82dcb73197961e5cc1391348/mdit_py_plugins-0.6.0-py3-none-any.whl + name: mdit-py-plugins + version: 0.6.0 + sha256: f7e7a25d8b616fee99cb1e330da73451d11a8061baf39bb9663ab9ce0e005b90 requires_dist: - - numpy>=2 - - pytest ; extra == 'test' - - matplotlib ; extra == 'test' - - beautifulsoup4 ; extra == 'test' - - ipython ; extra == 'test' - - h5py ; extra == 'extra' - - scipy>=1.7.0 ; extra == 'extra' - - graphviz ; extra == 'extra' - - pooch ; extra == 'extra' - - plopp ; extra == 'extra' - - matplotlib ; extra == 'extra' - - scipp[extra] ; extra == 'all' - - ipympl ; extra == 'all' - - ipython ; extra == 'all' - - ipywidgets ; extra == 'all' - - jupyterlab ; extra == 'all' - - jupyterlab-widgets ; extra == 'all' - - jupyter-nbextensions-configurator ; extra == 'all' - - nodejs ; extra == 'all' - - pythreejs ; extra == 'all' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/1e/e7/cd78635d0ece7e4d3393f2c1d2ebabf6ff4bd615da142891b1d42ad58abf/scipp-26.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: scipp - version: 26.3.1 - sha256: 7525c843f673ef5461d229095054a701aeb3233db29af137fdf4bbf0884ad9d4 + - markdown-it-py>=2.0.0,<5.0.0 + - pre-commit ; extra == 'code-style' + - myst-parser ; extra == 'rtd' + - sphinx-book-theme ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + - pytest-timeout ; extra == 'testing' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + name: partd + version: 1.4.2 + sha256: 978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f requires_dist: - - numpy>=2 - - pytest ; extra == 'test' - - matplotlib ; extra == 'test' - - beautifulsoup4 ; extra == 'test' - - ipython ; extra == 'test' - - h5py ; extra == 'extra' - - scipy>=1.7.0 ; extra == 'extra' - - graphviz ; extra == 'extra' - - pooch ; extra == 'extra' - - plopp ; extra == 'extra' - - matplotlib ; extra == 'extra' - - scipp[extra] ; extra == 'all' - - ipympl ; extra == 'all' - - ipython ; extra == 'all' - - ipywidgets ; extra == 'all' - - jupyterlab ; extra == 'all' - - jupyterlab-widgets ; extra == 'all' - - jupyter-nbextensions-configurator ; extra == 'all' - - nodejs ; extra == 'all' - - pythreejs ; extra == 'all' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - name: scipp - version: 26.3.1 - sha256: 26291c0a882b9d5aac868c6d6f2508b79baa821ed30060a22c50620dbcce9e75 + - locket + - toolz + - numpy>=1.20.0 ; extra == 'complete' + - pandas>=1.3 ; extra == 'complete' + - pyzmq ; extra == 'complete' + - blosc ; extra == 'complete' + requires_python: '>=3.9' +- 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: - - numpy>=2 + - jinja2 + - pyyaml - pytest ; extra == 'test' - - matplotlib ; extra == 'test' - - beautifulsoup4 ; extra == 'test' - - ipython ; extra == 'test' - - h5py ; extra == 'extra' - - scipy>=1.7.0 ; extra == 'extra' - - graphviz ; extra == 'extra' - - pooch ; extra == 'extra' - - plopp ; extra == 'extra' - - matplotlib ; extra == 'extra' - - scipp[extra] ; extra == 'all' - - ipympl ; extra == 'all' - - ipython ; extra == 'all' - - ipywidgets ; extra == 'all' - - jupyterlab ; extra == 'all' - - jupyterlab-widgets ; extra == 'all' - - jupyter-nbextensions-configurator ; extra == 'all' - - nodejs ; extra == 'all' - - pythreejs ; extra == 'all' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/43/fe/ad0ecbe2393cb690a4b3100a8fea47ecfdb49f6e06f40cf2f626635adc0c/scipp-26.3.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: scipp - version: 26.3.1 - sha256: 2ef08ba8d83542807f9f9833ba8f01583215c1629693bfadb1d6508cbdeb335c + - pytest-cov ; extra == 'test' +- pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + name: mike + version: 2.2.0 + sha256: e1f4981c1152eec7c2490a3401142292cc47d686194188416db2648fdfe1d040 + requires_dist: + - jinja2>=2.7 + - mkdocs~=1.0 + - pyparsing>=3.0 + - pyyaml>=5.1 + - pyyaml-env-tag + - verspec + - importlib-metadata ; python_full_version < '3.10' + - importlib-resources ; python_full_version < '3.10' + - coverage ; extra == 'dev' + - flake8-quotes ; extra == 'dev' + - flake8>=3.0 ; extra == 'dev' + - shtab ; extra == 'dev' + - coverage ; extra == 'test' + - flake8-quotes ; extra == 'test' + - flake8>=3.0 ; extra == 'test' + - shtab ; extra == 'test' +- pypi: https://files.pythonhosted.org/packages/78/3c/2a612b95ddbb9a6bdcb47b7a93c4884f74c6ff22356b2f7b213b16e65c35/pycifstar-0.3.0.tar.gz + name: pycifstar + version: 0.3.0 + sha256: 5892fdf16c83372ee5f32557127d5f36e14b0bbe520883a4e2e70365382f70ed +- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + name: annotated-types + version: 0.7.0 + sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 + requires_dist: + - typing-extensions>=4.0.0 ; python_full_version < '3.9' + requires_python: '>=3.8' +- 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/7b/67/b1944235474aac3f0b0e1b232ce49547f9f9461ca4b943df1b88da5d3f1d/bumps-1.0.4-py3-none-any.whl + name: bumps + version: 1.0.4 + sha256: 78b8cfaf9fbcbf2fd77f6d4a2f8c906b0e03a794804ba6caf64d56d6f6cce4d4 + requires_dist: + - numpy + - scipy + - h5py + - dill + - cloudpickle + - matplotlib + - blinker + - aiohttp + - python-socketio + - plotly + - mpld3 + - msgpack + - uncertainties + - build ; extra == 'dev' + - pre-commit ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - ruff ; extra == 'dev' + - wheel ; extra == 'dev' + - setuptools ; extra == 'dev' + - sphinx ; extra == 'dev' + - versioningit ; extra == 'dev' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl + name: trove-classifiers + version: 2026.5.7.17 + sha256: 5ec0800de5e2ddbd7c663cb4c0c15328f132dc168813897c18866c5c7b93db33 +- pypi: https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl + name: contourpy + version: 1.3.3 + sha256: cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd requires_dist: - - numpy>=2 - - pytest ; extra == 'test' + - numpy>=1.25 + - furo ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - bokeh ; extra == 'bokeh' + - selenium ; extra == 'bokeh' + - contourpy[bokeh,docs] ; extra == 'mypy' + - bokeh ; extra == 'mypy' + - docutils-stubs ; extra == 'mypy' + - mypy==1.17.0 ; extra == 'mypy' + - types-pillow ; extra == 'mypy' + - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' - - beautifulsoup4 ; extra == 'test' - - ipython ; extra == 'test' - - h5py ; extra == 'extra' - - scipy>=1.7.0 ; extra == 'extra' - - graphviz ; extra == 'extra' - - pooch ; extra == 'extra' - - plopp ; extra == 'extra' - - matplotlib ; extra == 'extra' - - scipp[extra] ; extra == 'all' - - ipympl ; extra == 'all' - - ipython ; extra == 'all' - - ipywidgets ; extra == 'all' - - jupyterlab ; extra == 'all' - - jupyterlab-widgets ; extra == 'all' - - jupyter-nbextensions-configurator ; extra == 'all' - - nodejs ; extra == 'all' - - pythreejs ; extra == 'all' + - pillow ; extra == 'test' + - pytest ; extra == 'test-no-images' + - pytest-cov ; extra == 'test-no-images' + - pytest-rerunfailures ; extra == 'test-no-images' + - pytest-xdist ; extra == 'test-no-images' + - wurlitzer ; extra == 'test-no-images' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/44/7b/537a61906eac58d94131273084d21d4eb219f5453f0ed30de3aca580a2b4/scipp-26.3.1-cp312-cp312-macosx_14_0_arm64.whl - name: scipp - version: 26.3.1 - sha256: 2608ba21e2c550abe864598e8cfffe22d7e7be70ff9f9b03d44868e353b241c9 +- pypi: https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl + name: multidict + version: 6.7.1 + sha256: fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19 requires_dist: - - numpy>=2 - - pytest ; extra == 'test' - - matplotlib ; extra == 'test' - - beautifulsoup4 ; extra == 'test' - - ipython ; extra == 'test' - - h5py ; extra == 'extra' - - scipy>=1.7.0 ; extra == 'extra' - - graphviz ; extra == 'extra' - - pooch ; extra == 'extra' - - plopp ; extra == 'extra' - - matplotlib ; extra == 'extra' - - scipp[extra] ; extra == 'all' - - ipympl ; extra == 'all' - - ipython ; extra == 'all' - - ipywidgets ; extra == 'all' - - jupyterlab ; extra == 'all' - - jupyterlab-widgets ; extra == 'all' - - jupyter-nbextensions-configurator ; extra == 'all' - - nodejs ; extra == 'all' - - pythreejs ; extra == 'all' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/63/9f/724f66a48309dd97a2ff58f491d6ffd925f35d1278a5e55dc9a5ac6a156b/scippneutron-26.5.0-py3-none-any.whl - name: scippneutron - version: 26.5.0 - sha256: e9cfad09b974867c6dc2a175cd2e575e06eaa951b2409e9ef863db237853bf99 + - typing-extensions>=4.1.0 ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + name: pre-commit + version: 4.6.0 + sha256: e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b requires_dist: - - python-dateutil>=2.8 - - email-validator>=2 - - h5py>=3.12 - - lazy-loader>=0.4 - - mpltoolbox>=24.6.0 - - numpy>=1.20 - - plopp>=26.4.1 - - pydantic>=2 - - scipp>=25.8.0 - - scippnexus>=23.11.0 - - scipy>=1.7.0 - - scipp[all]>=25.8.0 ; extra == 'all' - - pooch>=1.5 ; extra == 'all' - - hypothesis>=6.100 ; extra == 'test' - - ipympl>0.9.0 ; extra == 'test' - - ipykernel>6.30 ; extra == 'test' - - pace-neutrons>=0.3 ; extra == 'test' - - pooch>=1.5 ; extra == 'test' - - psutil>=5.0 ; extra == 'test' - - pytest>=7.0 ; extra == 'test' - - pytest-xdist>=3.0 ; extra == 'test' - - pythreejs>=2.4.1 ; extra == 'test' - - sciline>=25.1.0 ; extra == 'test' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/5c/01/6cb4d63c6b6933be4b7945b2f64638336420f04ea71ca5b9a7539c008bc5/scippnexus-26.1.1-py3-none-any.whl - name: scippnexus - version: 26.1.1 - sha256: 899a0a5e71291b7809d902c17b6c74addf5a805397eabcec557491ff74eead12 + - cfgv>=2.0.0 + - identify>=1.0.0 + - nodeenv>=0.11.1 + - pyyaml>=5.1 + - virtualenv>=20.10.0 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + name: filelock + version: 3.29.0 + sha256: 96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl + name: rich + version: 15.0.0 + sha256: 33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb requires_dist: - - scipp>=24.2.0 - - scipy>=1.10.0 - - h5py>=3.12 + - ipywidgets>=7.5.1,<9 ; extra == 'jupyter' + - markdown-it-py>=2.2.0 + - pygments>=2.13.0,<3.0.0 + requires_python: '>=3.9.0' +- pypi: https://files.pythonhosted.org/packages/82/d0/26c81ffbe588f936d05f395da34046c66322e8067c9fd331c788c4f682f2/diffpy_pdffit2-1.6.0-cp314-cp314-win_amd64.whl + name: diffpy-pdffit2 + version: 1.6.0 + sha256: dc4b5c57c5bcdac4983ff3ec33a960b0f45b3d8d0e20f44347f533861b890c2a + requires_dist: + - diffpy-structure + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/85/19/93853133df2cb371083285ef6a93982a0173e7a233b0f61373ba9fd30eb2/coverage-7.14.0-cp312-cp312-win_amd64.whl + name: coverage + version: 7.14.0 + sha256: 70390b0da32cb90b501953716302906e8bcce087cb283e70d8c97729f22e92b2 + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + name: docstripy + version: 0.7.2 + sha256: c4ba35de6c1b1c51f7afad4a46d8953aad55dce1a490d198f7e98c8c63efefda + requires_dist: + - nbformat + requires_python: '>=3.7' +- 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/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + name: mkdocs-get-deps + 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/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + name: cloudpickle + version: 3.1.2 + sha256: 9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + name: nodeenv + version: 1.10.0 + sha256: 5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pydantic-core + version: 2.46.4 + sha256: 7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/8a/06/2c1bd1ee9eee3e65b0b6395dcf960e71b11576995eae3b4ab9ec63d89bea/essreduce-26.4.1-py3-none-any.whl + name: essreduce + version: 26.4.1 + sha256: 1758a18fffca9c7c2a6fa9547cf87bf45f9d52fc3ccbdffcf7524f71bc060424 + requires_dist: + - sciline>=25.11.0 + - scipp>=26.3.1 + - scippneutron>=25.11.1 + - scippnexus>=25.6.0 + - graphviz>=0.20 ; extra == 'test' + - ipywidgets>=8.1 ; extra == 'test' + - matplotlib>=3.10.7 ; extra == 'test' + - numba>=0.63 ; extra == 'test' + - pooch>=1.9.0 ; extra == 'test' - pytest>=7.0 ; extra == 'test' + - scipy>=1.14 ; extra == 'test' + - tof>=25.12.0 ; extra == 'test' + - autodoc-pydantic ; extra == 'docs' + - graphviz>=0.20 ; extra == 'docs' + - ipykernel ; extra == 'docs' + - ipython!=8.7.0 ; extra == 'docs' + - ipywidgets>=8.1 ; extra == 'docs' + - myst-parser ; extra == 'docs' + - nbsphinx ; extra == 'docs' + - numba>=0.63 ; extra == 'docs' + - plopp ; extra == 'docs' + - pydata-sphinx-theme>=0.14 ; extra == 'docs' + - sphinx>=7 ; extra == 'docs' + - sphinx-autodoc-typehints ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-design ; extra == 'docs' + - tof>=25.12.0 ; extra == 'docs' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: scipy - version: 1.17.1 - sha256: 02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458 +- pypi: https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl + name: lazy-loader + version: '0.5' + sha256: ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005 + requires_dist: + - packaging + - pytest>=8.0 ; extra == 'test' + - pytest-cov>=5.0 ; extra == 'test' + - coverage[toml]>=7.2 ; extra == 'test' + - pre-commit==4.3.0 ; extra == 'lint' + - changelist==0.5 ; extra == 'dev' + - spin==0.15 ; extra == 'dev' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl + name: msgpack + version: 1.1.2 + sha256: 1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl + name: traittypes + version: 0.2.3 + sha256: 49016082ce740d6556d9bb4672ee2d899cd14f9365f17cbb79d5d96b47096d4e + requires_dist: + - traitlets>=4.2.2 + - numpy ; extra == 'test' + - pandas ; extra == 'test' + - xarray ; extra == 'test' + - pytest ; extra == 'test' +- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl + name: uncertainties + version: 3.2.3 + sha256: 313353900d8f88b283c9bad81e7d2b2d3d4bcc330cbace35403faaed7e78890a requires_dist: - - numpy>=1.26.4,<2.7 - - pytest>=8.0.0 ; extra == 'test' + - numpy ; extra == 'arrays' + - pytest ; extra == 'test' + - pytest-codspeed ; extra == 'test' - pytest-cov ; extra == 'test' - - pytest-timeout ; extra == 'test' - - pytest-xdist ; extra == 'test' - - asv ; extra == 'test' - - mpmath ; extra == 'test' - - gmpy2 ; extra == 'test' - - threadpoolctl ; extra == 'test' - - scikit-umfpack ; extra == 'test' - - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' - - array-api-strict>=2.3.1 ; extra == 'test' - - cython ; extra == 'test' - - meson ; extra == 'test' - - ninja ; sys_platform != 'emscripten' and extra == 'test' - - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' - - intersphinx-registry ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - scipy ; extra == 'test' + - sphinx ; extra == 'doc' - sphinx-copybutton ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' - - numpydoc ; extra == 'doc' - - jupytext ; extra == 'doc' - - myst-nb>=1.2.0 ; extra == 'doc' - - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' - - jupyterlite-pyodide-kernel ; extra == 'doc' - - linkify-it-py ; extra == 'doc' - - tabulate ; extra == 'doc' - - click<8.3.0 ; extra == 'dev' - - spin ; extra == 'dev' - - mypy==1.10.0 ; extra == 'dev' - - typing-extensions ; extra == 'dev' - - types-psutil ; extra == 'dev' - - pycodestyle ; extra == 'dev' - - ruff>=0.12.0 ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - name: scipy - version: 1.17.1 - sha256: eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118 + - python-docs-theme ; extra == 'doc' + - uncertainties[arrays,doc,test] ; extra == 'all' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/8f/82/b54e646be7b938fcbdda10030c6533bd2bb1a59930a1381cc83d6050a49c/spglib-2.6.0-cp312-cp312-win_amd64.whl + name: spglib + version: 2.6.0 + sha256: 86d0fd355689e58becd2cda609b03c3a0d9ad9d6f761cefd08b970db6f314eae requires_dist: - - numpy>=1.26.4,<2.7 - - pytest>=8.0.0 ; extra == 'test' + - numpy>=1.20,<3 + - importlib-resources ; python_full_version < '3.10' + - typing-extensions>=4.9.0 ; python_full_version < '3.13' + - pytest ; extra == 'test' + - pyyaml ; extra == 'test' + - sphinx>=7.0 ; extra == 'docs' + - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' + - sphinx-book-theme ; extra == 'docs' + - sphinx-autodoc-typehints ; extra == 'docs' + - myst-parser>=2.0 ; extra == 'docs' + - linkify-it-py ; extra == 'docs' + - sphinx-tippy ; extra == 'docs' + - spglib[test] ; extra == 'test-cov' + - pytest-cov ; extra == 'test-cov' + - spglib[test] ; extra == 'test-benchmark' + - pytest-benchmark ; extra == 'test-benchmark' + - spglib[test] ; extra == 'dev' + - pre-commit ; extra == 'dev' + - spglib[docs] ; extra == 'doc' + - spglib[test] ; extra == 'testing' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + name: paginate + version: 0.5.7 + sha256: b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591 + requires_dist: + - pytest ; extra == 'dev' + - tox ; extra == 'dev' + - black ; extra == 'lint' +- pypi: https://files.pythonhosted.org/packages/90/ad/cba91b3bcf04073e4d1655a5c1710ef3f457f56f7d1b79dcc3d72f4dd912/plotly-6.7.0-py3-none-any.whl + name: plotly + version: 6.7.0 + sha256: ac8aca1c25c663a59b5b9140a549264a5badde2e057d79b8c772ae2920e32ff0 + requires_dist: + - narwhals>=1.15.1 + - packaging + - anywidget ; extra == 'dev' + - build ; extra == 'dev' + - colorcet ; extra == 'dev' + - fiona<=1.9.6 ; python_full_version < '3.9' and extra == 'dev' + - geopandas ; extra == 'dev' + - inflect ; extra == 'dev' + - jupyterlab ; extra == 'dev' + - kaleido>=1.1.0 ; extra == 'dev' + - numpy>=1.22 ; extra == 'dev' + - orjson ; extra == 'dev' + - pandas ; extra == 'dev' + - pdfrw ; extra == 'dev' + - pillow ; extra == 'dev' + - plotly-geo ; extra == 'dev' + - polars[timezone] ; extra == 'dev' + - pyarrow ; extra == 'dev' + - pyshp ; extra == 'dev' + - pytest ; extra == 'dev' + - pytz ; extra == 'dev' + - requests ; extra == 'dev' + - ruff==0.11.12 ; extra == 'dev' + - scikit-image ; extra == 'dev' + - scipy ; extra == 'dev' + - shapely ; extra == 'dev' + - statsmodels ; extra == 'dev' + - vaex ; python_full_version < '3.10' and extra == 'dev' + - xarray ; extra == 'dev' + - build ; extra == 'dev-build' + - jupyterlab ; extra == 'dev-build' + - pytest ; extra == 'dev-build' + - requests ; extra == 'dev-build' + - ruff==0.11.12 ; extra == 'dev-build' + - pytest ; extra == 'dev-core' + - requests ; extra == 'dev-core' + - ruff==0.11.12 ; extra == 'dev-core' + - anywidget ; extra == 'dev-optional' + - build ; extra == 'dev-optional' + - colorcet ; extra == 'dev-optional' + - fiona<=1.9.6 ; python_full_version < '3.9' and extra == 'dev-optional' + - geopandas ; extra == 'dev-optional' + - inflect ; extra == 'dev-optional' + - jupyterlab ; extra == 'dev-optional' + - kaleido>=1.1.0 ; extra == 'dev-optional' + - numpy>=1.22 ; extra == 'dev-optional' + - orjson ; extra == 'dev-optional' + - pandas ; extra == 'dev-optional' + - pdfrw ; extra == 'dev-optional' + - pillow ; extra == 'dev-optional' + - plotly-geo ; extra == 'dev-optional' + - polars[timezone] ; extra == 'dev-optional' + - pyarrow ; extra == 'dev-optional' + - pyshp ; extra == 'dev-optional' + - pytest ; extra == 'dev-optional' + - pytz ; extra == 'dev-optional' + - requests ; extra == 'dev-optional' + - ruff==0.11.12 ; extra == 'dev-optional' + - scikit-image ; extra == 'dev-optional' + - scipy ; extra == 'dev-optional' + - shapely ; extra == 'dev-optional' + - statsmodels ; extra == 'dev-optional' + - vaex ; python_full_version < '3.10' and extra == 'dev-optional' + - xarray ; extra == 'dev-optional' + - numpy>=1.22 ; extra == 'express' + - kaleido>=1.1.0 ; extra == 'kaleido' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/91/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl + name: greenlet + version: 3.5.0 + sha256: 3bc59be3945ae9750b9e7d45067d01ae3fe90ea5f9ade99239dabdd6e28a5033 + requires_dist: + - sphinx ; extra == 'docs' + - furo ; extra == 'docs' + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl + name: graphviz + version: '0.21' + sha256: 54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42 + requires_dist: + - build ; extra == 'dev' + - wheel ; extra == 'dev' + - twine ; extra == 'dev' + - flake8 ; extra == 'dev' + - flake8-pyproject ; extra == 'dev' + - pep8-naming ; extra == 'dev' + - tox>=3 ; extra == 'dev' + - pytest>=7,<8.1 ; extra == 'test' + - pytest-mock>=3 ; extra == 'test' - pytest-cov ; extra == 'test' - - pytest-timeout ; extra == 'test' - - pytest-xdist ; extra == 'test' - - asv ; extra == 'test' - - mpmath ; extra == 'test' - - gmpy2 ; extra == 'test' - - threadpoolctl ; extra == 'test' - - scikit-umfpack ; extra == 'test' - - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' - - array-api-strict>=2.3.1 ; extra == 'test' - - cython ; extra == 'test' - - meson ; extra == 'test' - - ninja ; sys_platform != 'emscripten' and extra == 'test' - - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' - - intersphinx-registry ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' - - numpydoc ; extra == 'doc' - - jupytext ; extra == 'doc' - - myst-nb>=1.2.0 ; extra == 'doc' - - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' - - jupyterlite-pyodide-kernel ; extra == 'doc' - - linkify-it-py ; extra == 'doc' - - tabulate ; extra == 'doc' - - click<8.3.0 ; extra == 'dev' - - spin ; extra == 'dev' - - mypy==1.10.0 ; extra == 'dev' - - typing-extensions ; extra == 'dev' - - types-psutil ; extra == 'dev' - - pycodestyle ; extra == 'dev' - - ruff>=0.12.0 ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' + - coverage ; extra == 'test' + - sphinx>=5,<7 ; extra == 'docs' + - sphinx-autodoc-typehints ; extra == 'docs' + - sphinx-rtd-theme>=0.2.5 ; extra == 'docs' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + name: typeguard + version: 4.5.1 + sha256: 44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 + requires_dist: + - importlib-metadata>=3.6 ; python_full_version < '3.10' + - typing-extensions>=4.14.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl + name: numpy + version: 2.4.4 + sha256: 2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl - name: scipy - version: 1.17.1 - sha256: 3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19 +- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + name: radon + version: 6.0.1 + sha256: 632cc032364a6f8bb1010a2f6a12d0f14bc7e5ede76585ef29dc0cecf4cd8859 + requires_dist: + - mando>=0.6,<0.8 + - colorama==0.4.1 ; python_full_version < '3.5' + - colorama>=0.4.1 ; python_full_version >= '3.5' + - tomli>=2.0.1 ; extra == 'toml' +- pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + name: identify + version: 2.6.19 + sha256: 20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a + requires_dist: + - ukkonen ; extra == 'license' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/96/5d/0c59079aa7ef34980a5925a06a90ad2b7c94e486c194b3527d557cabb042/cryspy-0.11.0-py3-none-any.whl + name: cryspy + version: 0.11.0 + sha256: 0b650655a0fbdc3cfcb28826c2ab9fbc5f491e32e1ea9a47d9b75976cd43f26f requires_dist: - - numpy>=1.26.4,<2.7 - - pytest>=8.0.0 ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-timeout ; extra == 'test' - - pytest-xdist ; extra == 'test' - - asv ; extra == 'test' - - mpmath ; extra == 'test' - - gmpy2 ; extra == 'test' - - threadpoolctl ; extra == 'test' - - scikit-umfpack ; extra == 'test' - - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' - - array-api-strict>=2.3.1 ; extra == 'test' - - cython ; extra == 'test' - - meson ; extra == 'test' - - ninja ; sys_platform != 'emscripten' and extra == 'test' - - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' - - intersphinx-registry ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' - - numpydoc ; extra == 'doc' - - jupytext ; extra == 'doc' - - myst-nb>=1.2.0 ; extra == 'doc' - - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' - - jupyterlite-pyodide-kernel ; extra == 'doc' - - linkify-it-py ; extra == 'doc' - - tabulate ; extra == 'doc' - - click<8.3.0 ; extra == 'dev' - - spin ; extra == 'dev' - - mypy==1.10.0 ; extra == 'dev' - - typing-extensions ; extra == 'dev' - - types-psutil ; extra == 'dev' - - pycodestyle ; extra == 'dev' - - ruff>=0.12.0 ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' + - numpy + - scipy + - pycifstar + - matplotlib +- pypi: https://files.pythonhosted.org/packages/97/37/ce5c3ef2595dac2be35039f7b91a0691ef643aa3d954815b3b51e026e0ab/crysfml-0.6.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: crysfml + version: 0.6.2 + sha256: e18ff9ea04b0b823dbc1558afb974bd5b66f3ce13f9e18b25adedfcfde1a59a4 + requires_dist: + - numpy + requires_python: '>=3.11,<3.15' +- pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: numpy + version: 2.4.4 + sha256: 27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl - name: scipy - version: 1.17.1 - sha256: 41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87 +- pypi: https://files.pythonhosted.org/packages/98/ba/fc20faf5b2bb04615fa906f8daecfe896e6f7a56b34debd93c4a4d63e6e5/copier-9.15.0-py3-none-any.whl + name: copier + version: 9.15.0 + sha256: 0f59c2ea36df42f3ded85c091c3f1e2c8d3814b537504f0abc8c2e508f7e013d requires_dist: - - numpy>=1.26.4,<2.7 - - pytest>=8.0.0 ; extra == 'test' + - 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/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl + name: asteval + version: 1.0.8 + sha256: 6c64385c6ff859a474953c124987c7ee8354d781c76509b2c598741c4d1d28e9 + requires_dist: + - build ; extra == 'dev' + - twine ; extra == 'dev' + - sphinx ; extra == 'doc' + - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - - pytest-timeout ; extra == 'test' - - pytest-xdist ; extra == 'test' - - asv ; extra == 'test' - - mpmath ; extra == 'test' - - gmpy2 ; extra == 'test' - - threadpoolctl ; extra == 'test' - - scikit-umfpack ; extra == 'test' - - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' - - array-api-strict>=2.3.1 ; extra == 'test' - - cython ; extra == 'test' - - meson ; extra == 'test' - - ninja ; sys_platform != 'emscripten' and extra == 'test' - - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' - - intersphinx-registry ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' - - numpydoc ; extra == 'doc' - - jupytext ; extra == 'doc' - - myst-nb>=1.2.0 ; extra == 'doc' - - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' - - jupyterlite-pyodide-kernel ; extra == 'doc' - - linkify-it-py ; extra == 'doc' - - tabulate ; extra == 'doc' - - click<8.3.0 ; extra == 'dev' - - spin ; extra == 'dev' - - mypy==1.10.0 ; extra == 'dev' - - typing-extensions ; extra == 'dev' - - types-psutil ; extra == 'dev' - - pycodestyle ; extra == 'dev' - - ruff>=0.12.0 ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' + - coverage ; extra == 'test' + - asteval[dev,doc,test] ; extra == 'all' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl + name: bidict + version: 0.23.1 + sha256: 5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + name: tabulate + version: 0.10.0 + sha256: f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 + requires_dist: + - wcwidth ; extra == 'widechars' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl + name: kiwisolver + version: 1.5.0 + sha256: ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9b/8a/99c8b3c3888c5c474c08dbfd7c8899786de9604b727fcefb055b42c84bba/fonttools-4.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: fonttools + version: 4.62.1 + sha256: 149f7d84afca659d1a97e39a4778794a2f83bf344c5ee5134e09995086cc2392 + requires_dist: + - lxml>=4.0 ; extra == 'lxml' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - zopfli>=0.1.4 ; extra == 'woff' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode' + - lz4>=1.7.4.2 ; extra == 'graphite' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' + - pycairo ; extra == 'interpolatable' + - matplotlib ; extra == 'plot' + - sympy ; extra == 'symfont' + - xattr ; sys_platform == 'darwin' and extra == 'type1' + - skia-pathops>=0.5.0 ; extra == 'pathops' + - uharfbuzz>=0.45.0 ; extra == 'repacker' + - lxml>=4.0 ; extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' + - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' + - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' + - pycairo ; extra == 'all' + - matplotlib ; extra == 'all' + - sympy ; extra == 'all' + - xattr ; sys_platform == 'darwin' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.45.0 ; extra == 'all' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl + name: aiohttp + version: 3.13.5 + sha256: 756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/9b/fd/e5ecca1e78c05106d98028114f5c00d3eddb41207686b2b7de3e477b0e22/numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl + name: numpy + version: 2.4.4 + sha256: 8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.whl - name: scipy - version: 1.17.1 - sha256: cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086 +- pypi: https://files.pythonhosted.org/packages/9c/2f/4c5af01fd1a7506a1d5375403d68925eac70289229492db5aa68b58103d8/chardet-7.4.3-cp312-cp312-macosx_11_0_arm64.whl + name: chardet + version: 7.4.3 + sha256: 29af5999f654e8729d251f1724a62b538b1262d9292cccaefddf8a02aae1ef6a + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + name: pytest-cov + version: 7.1.0 + sha256: a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 requires_dist: - - numpy>=1.26.4,<2.7 - - pytest>=8.0.0 ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-timeout ; extra == 'test' - - pytest-xdist ; extra == 'test' - - asv ; extra == 'test' - - mpmath ; extra == 'test' - - gmpy2 ; extra == 'test' - - threadpoolctl ; extra == 'test' - - scikit-umfpack ; extra == 'test' - - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' - - array-api-strict>=2.3.1 ; extra == 'test' - - cython ; extra == 'test' - - meson ; extra == 'test' - - ninja ; sys_platform != 'emscripten' and extra == 'test' - - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - coverage[toml]>=7.10.6 + - pluggy>=1.2 + - pytest>=7 + - process-tests ; extra == 'testing' + - pytest-xdist ; extra == 'testing' + - virtualenv ; extra == 'testing' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + name: autopep8 + version: 2.3.2 + sha256: ce8ad498672c845a0c3de2629c15b635ec2b05ef8177a6e7c91c74f3e9b51128 + requires_dist: + - pycodestyle>=2.12.0 + - tomli ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl + name: networkx + version: 3.6.1 + sha256: d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762 + requires_dist: + - asv ; extra == 'benchmarking' + - virtualenv ; extra == 'benchmarking' + - numpy>=1.25 ; extra == 'default' + - scipy>=1.11.2 ; extra == 'default' + - matplotlib>=3.8 ; extra == 'default' + - pandas>=2.0 ; extra == 'default' + - pre-commit>=4.1 ; extra == 'developer' + - mypy>=1.15 ; extra == 'developer' + - sphinx>=8.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.16 ; extra == 'doc' + - sphinx-gallery>=0.18 ; extra == 'doc' + - numpydoc>=1.8.0 ; extra == 'doc' + - pillow>=10 ; extra == 'doc' + - texext>=0.6.7 ; extra == 'doc' + - myst-nb>=1.1 ; extra == 'doc' - intersphinx-registry ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' - - numpydoc ; extra == 'doc' - - jupytext ; extra == 'doc' - - myst-nb>=1.2.0 ; extra == 'doc' - - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' - - jupyterlite-pyodide-kernel ; extra == 'doc' - - linkify-it-py ; extra == 'doc' - - tabulate ; extra == 'doc' - - click<8.3.0 ; extra == 'dev' - - spin ; extra == 'dev' - - mypy==1.10.0 ; extra == 'dev' - - typing-extensions ; extra == 'dev' - - types-psutil ; extra == 'dev' - - pycodestyle ; extra == 'dev' - - ruff>=0.12.0 ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl + - osmnx>=2.0.0 ; extra == 'example' + - momepy>=0.7.2 ; extra == 'example' + - contextily>=1.6 ; extra == 'example' + - seaborn>=0.13 ; extra == 'example' + - cairocffi>=1.7 ; extra == 'example' + - igraph>=0.11 ; extra == 'example' + - scikit-learn>=1.5 ; extra == 'example' + - iplotx>=0.9.0 ; extra == 'example' + - lxml>=4.6 ; extra == 'extra' + - pygraphviz>=1.14 ; extra == 'extra' + - pydot>=3.0.1 ; extra == 'extra' + - sympy>=1.10 ; extra == 'extra' + - build>=0.10 ; extra == 'release' + - twine>=4.0 ; extra == 'release' + - wheel>=0.40 ; extra == 'release' + - changelist==0.5 ; extra == 'release' + - pytest>=7.2 ; extra == 'test' + - pytest-cov>=4.0 ; extra == 'test' + - pytest-xdist>=3.0 ; extra == 'test' + - pytest-mpl ; extra == 'test-extras' + - pytest-randomly ; extra == 'test-extras' + requires_python: '>=3.11,!=3.14.1' +- pypi: https://files.pythonhosted.org/packages/9e/e9/1a19e42cd43cc1365e127db6aae85e1c671da1d9a5d746f4d34a50edb577/h5py-3.16.0-cp312-cp312-manylinux_2_28_x86_64.whl + name: h5py + version: 3.16.0 + sha256: dfc21898ff025f1e8e67e194965a95a8d4754f452f83454538f98f8a3fcb207e + requires_dist: + - numpy>=1.21.2 + requires_python: '>=3.10' +- 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/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl + name: frozenlist + version: 1.8.0 + sha256: 4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl + name: sympy + version: 1.14.0 + sha256: e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 + requires_dist: + - mpmath>=1.1.0,<1.4 + - pytest>=7.1.0 ; extra == 'dev' + - hypothesis>=6.70.0 ; extra == 'dev' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl name: scipy version: 1.17.1 - sha256: 3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b + sha256: 41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87 requires_dist: - numpy>=1.26.4,<2.7 - pytest>=8.0.0 ; extra == 'test' @@ -11830,956 +11459,1230 @@ packages: - ruff>=0.12.0 ; extra == 'dev' - cython-lint>=0.12.2 ; extra == 'dev' requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda - sha256: 8fc024bf1a7b99fc833b131ceef4bef8c235ad61ecb95a71a6108be2ccda63e8 - md5: b70e2d44e6aa2beb69ba64206a16e4c6 - depends: - - __osx - - pyobjc-framework-cocoa - - python >=3.10 - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/send2trash?source=hash-mapping - size: 22519 - timestamp: 1770937603551 -- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda - sha256: 305446a0b018f285351300463653d3d3457687270e20eda37417b12ee386ef76 - md5: 6ac53f3fff2c416d63511843a04646fa - depends: - - __win - - pywin32 - - python >=3.10 - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/send2trash?source=hash-mapping - size: 22864 - timestamp: 1770937641143 -- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda - sha256: 59656f6b2db07229351dfb3a859c35e57cc8e8bcbc86d4e501bff881a6f771f1 - md5: 28eb91468df04f655a57bcfbb35fc5c5 - depends: - - __linux - - python >=3.10 - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/send2trash?source=hash-mapping - size: 24108 - timestamp: 1770937597662 -- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - sha256: 82088a6e4daa33329a30bc26dc19a98c7c1d3f05c0f73ce9845d4eab4924e9e1 - md5: 8e194e7b992f99a5015edbd4ebd38efd - depends: - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/setuptools?source=hash-mapping - size: 639697 - timestamp: 1773074868565 -- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - name: shellingham - version: 1.5.4 - sha256: 7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl - name: simple-websocket - version: 1.1.0 - sha256: 4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c +- pypi: https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl + name: kiwisolver + version: 1.5.0 + sha256: d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl + name: ply + version: '3.11' + sha256: 096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce +- pypi: https://files.pythonhosted.org/packages/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: greenlet + version: 3.5.0 + sha256: 8f52a464e4ed91780bdfbbdd2b97197f3accaa629b98c200f4dffada759f3ae7 requires_dist: - - wsproto - - tox ; extra == 'dev' - - flake8 ; extra == 'dev' - - pytest ; extra == 'dev' - - pytest-cov ; extra == 'dev' - sphinx ; extra == 'docs' - requires_python: '>=3.6' -- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d - md5: 3339e3b65d58accf4ca4fb8748ab16b3 - depends: - - python >=3.9 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/six?source=hash-mapping - size: 18455 - timestamp: 1753199211006 -- 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' -- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad - md5: 03fe290994c5e4ec17293cfb6bdce520 - depends: - - python >=3.10 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/sniffio?source=hash-mapping - size: 15698 - timestamp: 1762941572482 -- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - sha256: 23b71ecf089967d2900126920e7f9ff18cdcef82dbff3e2f54ffa360243a17ac - md5: 18de09b20462742fe093ba39185d9bac - depends: - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/soupsieve?source=hash-mapping - size: 38187 - timestamp: 1769034509657 -- 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/33/75/98a7eb100dc5cfd20b019046452f08d5e67dfbacc71d8f28763d32426fd3/spglib-2.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - name: spglib - version: 2.6.0 - sha256: a8e9c34da1e2428c3a8bd4e209e5356d12d454d8ac54120d5ba4a437d3abe7ba - requires_dist: - - numpy>=1.20,<3 - - importlib-resources ; python_full_version < '3.10' - - typing-extensions>=4.9.0 ; python_full_version < '3.13' - - pytest ; extra == 'test' - - pyyaml ; extra == 'test' - - sphinx>=7.0 ; extra == 'docs' - - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' - - sphinx-book-theme ; extra == 'docs' - - sphinx-autodoc-typehints ; extra == 'docs' - - myst-parser>=2.0 ; extra == 'docs' - - linkify-it-py ; extra == 'docs' - - sphinx-tippy ; extra == 'docs' - - spglib[test] ; extra == 'test-cov' - - pytest-cov ; extra == 'test-cov' - - spglib[test] ; extra == 'test-benchmark' - - pytest-benchmark ; extra == 'test-benchmark' - - spglib[test] ; extra == 'dev' - - pre-commit ; extra == 'dev' - - spglib[docs] ; extra == 'doc' - - spglib[test] ; extra == 'testing' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/8f/82/b54e646be7b938fcbdda10030c6533bd2bb1a59930a1381cc83d6050a49c/spglib-2.6.0-cp312-cp312-win_amd64.whl - name: spglib - version: 2.6.0 - sha256: 86d0fd355689e58becd2cda609b03c3a0d9ad9d6f761cefd08b970db6f314eae + - furo ; extra == 'docs' + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl + name: varname + version: 1.0.0 + sha256: 1125bfe981c3bbbe56988f5cb85fdcd7cad923b153283c2d464aea8b4c833d51 requires_dist: - - numpy>=1.20,<3 - - importlib-resources ; python_full_version < '3.10' - - typing-extensions>=4.9.0 ; python_full_version < '3.13' - - pytest ; extra == 'test' - - pyyaml ; extra == 'test' - - sphinx>=7.0 ; extra == 'docs' - - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' - - sphinx-book-theme ; extra == 'docs' - - sphinx-autodoc-typehints ; extra == 'docs' - - myst-parser>=2.0 ; extra == 'docs' - - linkify-it-py ; extra == 'docs' - - sphinx-tippy ; extra == 'docs' - - spglib[test] ; extra == 'test-cov' - - pytest-cov ; extra == 'test-cov' - - spglib[test] ; extra == 'test-benchmark' - - pytest-benchmark ; extra == 'test-benchmark' - - spglib[test] ; extra == 'dev' - - pre-commit ; extra == 'dev' - - spglib[docs] ; extra == 'doc' - - spglib[test] ; extra == 'testing' + - executing>=2.1 + - typing-extensions>=4.13 ; python_full_version < '3.10' + - asttokens==3.* ; extra == 'all' + - pure-eval==0.* ; extra == 'all' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/bd/8c/d4907ad4f6bdc5bf79462d8767728713a7b316918a7444df372958a0e417/spglib-2.6.0-cp312-cp312-macosx_11_0_arm64.whl - name: spglib - version: 2.6.0 - sha256: 83ea2e90addc7232017c793a32d94b47bc68040c595671d1cbb836ede4349510 +- pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + name: verspec + version: 0.1.0 + sha256: 741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31 requires_dist: - - numpy>=1.20,<3 - - importlib-resources ; python_full_version < '3.10' - - typing-extensions>=4.9.0 ; python_full_version < '3.13' + - coverage ; extra == 'test' + - flake8>=3.7 ; extra == 'test' + - mypy ; extra == 'test' + - pretend ; extra == 'test' - pytest ; extra == 'test' - - pyyaml ; extra == 'test' - - sphinx>=7.0 ; extra == 'docs' - - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' - - sphinx-book-theme ; extra == 'docs' - - sphinx-autodoc-typehints ; extra == 'docs' - - myst-parser>=2.0 ; extra == 'docs' - - linkify-it-py ; extra == 'docs' - - sphinx-tippy ; extra == 'docs' - - spglib[test] ; extra == 'test-cov' - - pytest-cov ; extra == 'test-cov' - - spglib[test] ; extra == 'test-benchmark' - - pytest-benchmark ; extra == 'test-benchmark' - - spglib[test] ; extra == 'dev' - - pre-commit ; extra == 'dev' - - spglib[docs] ; extra == 'doc' - - spglib[test] ; extra == 'testing' +- pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl + name: wsproto + version: 1.3.2 + sha256: 61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584 + requires_dist: + - h11>=0.16.0,<1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: frozenlist + version: 1.8.0 + sha256: cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz - name: spglib - version: 2.6.0 - sha256: d66eda2ba00a1e14fd96ec9c3b4dbf8ab0fb3f124643e35785c71ee455b408eb +- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + name: mkdocs-markdownextradata-plugin + version: 0.2.6 + sha256: 34dd40870781784c75809596b2d8d879da783815b075336d541de1f150c94242 requires_dist: - - numpy>=1.20,<3 - - importlib-resources ; python_full_version < '3.10' - - typing-extensions>=4.9.0 ; python_full_version < '3.13' - - pytest ; extra == 'test' - - pyyaml ; extra == 'test' - - sphinx>=7.0 ; extra == 'docs' - - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' - - sphinx-book-theme ; extra == 'docs' - - sphinx-autodoc-typehints ; extra == 'docs' - - myst-parser>=2.0 ; extra == 'docs' - - linkify-it-py ; extra == 'docs' - - sphinx-tippy ; extra == 'docs' - - spglib[test] ; extra == 'test-cov' - - pytest-cov ; extra == 'test-cov' - - spglib[test] ; extra == 'test-benchmark' - - pytest-benchmark ; extra == 'test-benchmark' - - spglib[test] ; extra == 'dev' - - pre-commit ; extra == 'dev' - - spglib[docs] ; extra == 'doc' - - spglib[test] ; extra == 'testing' + - mkdocs + - pyyaml + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl + name: yarl + version: 1.23.0 + sha256: 63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 + requires_dist: + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl + name: multidict + version: 6.7.1 + sha256: b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7 + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/2c/fa/65fcae2ed62f84ab72cf89536c7c3217a156e71a2c111b1305ab6f0690e2/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: sqlalchemy - version: 2.0.49 - sha256: 3bb9ec6436a820a4c006aad1ac351f12de2f2dbdaad171692ee457a02429b672 +- pypi: https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl + name: python-engineio + version: 4.13.1 + sha256: f32ad10589859c11053ad7d9bb3c9695cdf862113bfb0d20bc4d890198287399 requires_dist: - - importlib-metadata ; python_full_version < '3.8' - - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' - - typing-extensions>=4.6.0 - - greenlet>=1 ; extra == 'asyncio' - - mypy>=0.910 ; extra == 'mypy' - - pyodbc ; extra == 'mssql' - - pymssql ; extra == 'mssql-pymssql' - - pyodbc ; extra == 'mssql-pyodbc' - - mysqlclient>=1.4.0 ; extra == 'mysql' - - mysql-connector-python ; extra == 'mysql-connector' - - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' - - cx-oracle>=8 ; extra == 'oracle' - - oracledb>=1.0.1 ; extra == 'oracle-oracledb' - - psycopg2>=2.7 ; extra == 'postgresql' - - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' - - greenlet>=1 ; extra == 'postgresql-asyncpg' - - asyncpg ; extra == 'postgresql-asyncpg' - - psycopg2-binary ; extra == 'postgresql-psycopg2binary' - - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' - - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' - - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' - - pymysql ; extra == 'pymysql' - - greenlet>=1 ; extra == 'aiomysql' - - aiomysql>=0.2.0 ; extra == 'aiomysql' - - greenlet>=1 ; extra == 'aioodbc' - - aioodbc ; extra == 'aioodbc' - - greenlet>=1 ; extra == 'asyncmy' - - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' - - greenlet>=1 ; extra == 'aiosqlite' - - aiosqlite ; extra == 'aiosqlite' - - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' - - sqlcipher3-binary ; extra == 'sqlcipher' + - simple-websocket>=0.10.0 + - requests>=2.21.0 ; extra == 'client' + - websocket-client>=0.54.0 ; extra == 'client' + - aiohttp>=3.11 ; extra == 'asyncio-client' + - tox ; extra == 'dev' + - sphinx ; extra == 'docs' + - furo ; extra == 'docs' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + name: ruff + version: 0.15.12 + sha256: fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5 requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: sqlalchemy - version: 2.0.49 - sha256: 685e93e9c8f399b0c96a624799820176312f5ceef958c0f88215af4013d29066 +- pypi: https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl + name: aiohttp + version: 3.13.5 + sha256: 110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 requires_dist: - - importlib-metadata ; python_full_version < '3.8' - - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' - - typing-extensions>=4.6.0 - - greenlet>=1 ; extra == 'asyncio' - - mypy>=0.910 ; extra == 'mypy' - - pyodbc ; extra == 'mssql' - - pymssql ; extra == 'mssql-pymssql' - - pyodbc ; extra == 'mssql-pyodbc' - - mysqlclient>=1.4.0 ; extra == 'mysql' - - mysql-connector-python ; extra == 'mysql-connector' - - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' - - cx-oracle>=8 ; extra == 'oracle' - - oracledb>=1.0.1 ; extra == 'oracle-oracledb' - - psycopg2>=2.7 ; extra == 'postgresql' - - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' - - greenlet>=1 ; extra == 'postgresql-asyncpg' - - asyncpg ; extra == 'postgresql-asyncpg' - - psycopg2-binary ; extra == 'postgresql-psycopg2binary' - - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' - - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' - - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' - - pymysql ; extra == 'pymysql' - - greenlet>=1 ; extra == 'aiomysql' - - aiomysql>=0.2.0 ; extra == 'aiomysql' - - greenlet>=1 ; extra == 'aioodbc' - - aioodbc ; extra == 'aioodbc' - - greenlet>=1 ; extra == 'asyncmy' - - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' - - greenlet>=1 ; extra == 'aiosqlite' - - aiosqlite ; extra == 'aiosqlite' - - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' - - sqlcipher3-binary ; extra == 'sqlcipher' + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl + name: matplotlib + version: 3.10.9 + sha256: 336b9acc64d309063126edcdaca00db9373af3c476bb94388fe9c5a53ad13e6f + requires_dist: + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.23 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=3 + - python-dateutil>=2.7 + - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' + - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' + - setuptools-scm>=7,<10 ; extra == 'dev' + - setuptools>=64 ; extra == 'dev' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + name: execnet + version: 2.1.2 + sha256: 67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec + requires_dist: + - hatch ; extra == 'testing' + - pre-commit ; extra == 'testing' + - pytest ; extra == 'testing' + - tox ; extra == 'testing' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + name: jupyterlab-widgets + version: 3.0.16 + sha256: 45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8 requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/47/9e/fd90114059175cac64e4fafa9bf3ac20584384d66de40793ae2e2f26f3bb/sqlalchemy-2.0.49-cp312-cp312-win_amd64.whl - name: sqlalchemy - version: 2.0.49 - sha256: 618a308215b6cececb6240b9abde545e3acdabac7ae3e1d4e666896bf5ba44b4 +- pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl + name: pydantic-core + version: 2.46.4 + sha256: 23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462 requires_dist: - - importlib-metadata ; python_full_version < '3.8' - - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' - - typing-extensions>=4.6.0 - - greenlet>=1 ; extra == 'asyncio' - - mypy>=0.910 ; extra == 'mypy' - - pyodbc ; extra == 'mssql' - - pymssql ; extra == 'mssql-pymssql' - - pyodbc ; extra == 'mssql-pyodbc' - - mysqlclient>=1.4.0 ; extra == 'mysql' - - mysql-connector-python ; extra == 'mysql-connector' - - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' - - cx-oracle>=8 ; extra == 'oracle' - - oracledb>=1.0.1 ; extra == 'oracle-oracledb' - - psycopg2>=2.7 ; extra == 'postgresql' - - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' - - greenlet>=1 ; extra == 'postgresql-asyncpg' - - asyncpg ; extra == 'postgresql-asyncpg' - - psycopg2-binary ; extra == 'postgresql-psycopg2binary' - - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' - - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' - - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' - - pymysql ; extra == 'pymysql' - - greenlet>=1 ; extra == 'aiomysql' - - aiomysql>=0.2.0 ; extra == 'aiomysql' - - greenlet>=1 ; extra == 'aioodbc' - - aioodbc ; extra == 'aioodbc' - - greenlet>=1 ; extra == 'asyncmy' - - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' - - greenlet>=1 ; extra == 'aiosqlite' - - aiosqlite ; extra == 'aiosqlite' - - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' - - sqlcipher3-binary ; extra == 'sqlcipher' - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/49/b3/2de412451330756aaaa72d27131db6dde23995efe62c941184e15242a5fa/sqlalchemy-2.0.49-cp312-cp312-macosx_11_0_arm64.whl - name: sqlalchemy - version: 2.0.49 - sha256: 4bbccb45260e4ff1b7db0be80a9025bb1e6698bdb808b83fff0000f7a90b2c0b + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl + name: kiwisolver + version: 1.5.0 + sha256: f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + name: click + version: 8.3.3 + sha256: a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613 requires_dist: - - importlib-metadata ; python_full_version < '3.8' - - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' - - typing-extensions>=4.6.0 - - greenlet>=1 ; extra == 'asyncio' - - mypy>=0.910 ; extra == 'mypy' - - pyodbc ; extra == 'mssql' - - pymssql ; extra == 'mssql-pymssql' - - pyodbc ; extra == 'mssql-pyodbc' - - mysqlclient>=1.4.0 ; extra == 'mysql' - - mysql-connector-python ; extra == 'mysql-connector' - - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' - - cx-oracle>=8 ; extra == 'oracle' - - oracledb>=1.0.1 ; extra == 'oracle-oracledb' - - psycopg2>=2.7 ; extra == 'postgresql' - - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' - - greenlet>=1 ; extra == 'postgresql-asyncpg' - - asyncpg ; extra == 'postgresql-asyncpg' - - psycopg2-binary ; extra == 'postgresql-psycopg2binary' - - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' - - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' - - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' - - pymysql ; extra == 'pymysql' - - greenlet>=1 ; extra == 'aiomysql' - - aiomysql>=0.2.0 ; extra == 'aiomysql' - - greenlet>=1 ; extra == 'aioodbc' - - aioodbc ; extra == 'aioodbc' - - greenlet>=1 ; extra == 'asyncmy' - - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' - - greenlet>=1 ; extra == 'aiosqlite' - - aiosqlite ; extra == 'aiosqlite' - - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' - - sqlcipher3-binary ; extra == 'sqlcipher' - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl - name: sqlalchemy - version: 2.0.49 - sha256: 233088b4b99ebcbc5258c755a097aa52fbf90727a03a5a80781c4b9c54347a2e + - colorama ; sys_platform == 'win32' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ae/61/3c1ea8c10bf4f6bf83c33a7f5b4a3143f4cc1f979859dec5498b6cc31900/pycifrw-5.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pycifrw + version: 5.0.1 + sha256: 379801e71509d0f9c59b56edc5ceb6600796eaf2b84ee5e0f5a256c76542047d requires_dist: - - importlib-metadata ; python_full_version < '3.8' - - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' - - typing-extensions>=4.6.0 - - greenlet>=1 ; extra == 'asyncio' - - mypy>=0.910 ; extra == 'mypy' - - pyodbc ; extra == 'mssql' - - pymssql ; extra == 'mssql-pymssql' - - pyodbc ; extra == 'mssql-pyodbc' - - mysqlclient>=1.4.0 ; extra == 'mysql' - - mysql-connector-python ; extra == 'mysql-connector' - - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' - - cx-oracle>=8 ; extra == 'oracle' - - oracledb>=1.0.1 ; extra == 'oracle-oracledb' - - psycopg2>=2.7 ; extra == 'postgresql' - - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' - - greenlet>=1 ; extra == 'postgresql-asyncpg' - - asyncpg ; extra == 'postgresql-asyncpg' - - psycopg2-binary ; extra == 'postgresql-psycopg2binary' - - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' - - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' - - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' - - pymysql ; extra == 'pymysql' - - greenlet>=1 ; extra == 'aiomysql' - - aiomysql>=0.2.0 ; extra == 'aiomysql' - - greenlet>=1 ; extra == 'aioodbc' - - aioodbc ; extra == 'aioodbc' - - greenlet>=1 ; extra == 'asyncmy' - - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' - - greenlet>=1 ; extra == 'aiosqlite' - - aiosqlite ; extra == 'aiosqlite' - - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' - - sqlcipher3-binary ; extra == 'sqlcipher' - requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl - name: sqlalchemy - version: 2.0.49 - sha256: 77641d299179c37b89cf2343ca9972c88bb6eef0d5fc504a2f86afd15cd5adf5 + - prettytable + - ply + - numpy +- pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl + name: sciline + version: 25.11.1 + sha256: 13c378287b8157e819b9b67d7e973c65bc6bdc545a3602d18204c365b0c336f9 requires_dist: - - importlib-metadata ; python_full_version < '3.8' - - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' - - typing-extensions>=4.6.0 - - greenlet>=1 ; extra == 'asyncio' - - mypy>=0.910 ; extra == 'mypy' - - pyodbc ; extra == 'mssql' - - pymssql ; extra == 'mssql-pymssql' - - pyodbc ; extra == 'mssql-pyodbc' - - mysqlclient>=1.4.0 ; extra == 'mysql' - - mysql-connector-python ; extra == 'mysql-connector' - - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' - - cx-oracle>=8 ; extra == 'oracle' - - oracledb>=1.0.1 ; extra == 'oracle-oracledb' - - psycopg2>=2.7 ; extra == 'postgresql' - - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' - - greenlet>=1 ; extra == 'postgresql-asyncpg' - - asyncpg ; extra == 'postgresql-asyncpg' - - psycopg2-binary ; extra == 'postgresql-psycopg2binary' - - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' - - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' - - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' - - pymysql ; extra == 'pymysql' - - greenlet>=1 ; extra == 'aiomysql' - - aiomysql>=0.2.0 ; extra == 'aiomysql' - - greenlet>=1 ; extra == 'aioodbc' - - aioodbc ; extra == 'aioodbc' - - greenlet>=1 ; extra == 'asyncmy' - - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' - - greenlet>=1 ; extra == 'aiosqlite' - - aiosqlite ; extra == 'aiosqlite' - - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' - - sqlcipher3-binary ; extra == 'sqlcipher' + - cyclebane>=24.6.0 + - pytest ; extra == 'test' + - pytest-randomly>=3 ; extra == 'test' + - dask ; extra == 'test' + - graphviz ; extra == 'test' + - jsonschema ; extra == 'test' + - numpy ; extra == 'test' + - pandas ; extra == 'test' + - pydantic ; extra == 'test' + - rich ; extra == 'test' + - rich ; extra == 'progress' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/b0/3e/a6497e1c2c9bc6ed2b79e0f2d31a4ce509fd2a9eed4e4f7ac63eda8113cb/gemmi-0.7.5-cp312-cp312-macosx_11_0_arm64.whl + name: gemmi + version: 0.7.5 + sha256: 5682920985109c6a08616ae9aae080f8b46a9714534dc864b535e3e6d203d5b8 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b0/42/c84efcc1d4caebafb1ecd8be4643f39c85c47a80fe254d92b8b43b1eadaf/h5py-3.16.0-cp312-cp312-macosx_11_0_arm64.whl + name: h5py + version: 3.16.0 + sha256: 42b012933a83e1a558c673176676a10ce2fd3759976a0fedee1e672d1e04fc9d + requires_dist: + - numpy>=1.21.2 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl + name: chardet + version: 7.4.3 + sha256: b95c934b9ad59e2ba8abb9be49df70d3ad1b0d95d864b9fdb7588d4fa8bd921c + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl + name: virtualenv + version: 21.3.1 + sha256: d1a71cf58f2f9228fff23a1f6ec15d39785c6b32e03658d104974247145edd35 + requires_dist: + - distlib>=0.3.7,<1 + - filelock>=3.24.2,<4 ; python_full_version >= '3.10' + - filelock>=3.16.1,<=3.19.1 ; python_full_version < '3.10' + - importlib-metadata>=6.6 ; python_full_version < '3.8' + - platformdirs>=3.9.1,<5 + - python-discovery>=1.2.2 + - typing-extensions>=4.13.2 ; python_full_version < '3.11' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + name: mdurl + version: 0.1.2 + sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - sha256: 570da295d421661af487f1595045760526964f41471021056e993e73089e9c41 - md5: b1b505328da7a6b246787df4b5a49fbc - depends: - - asttokens - - executing - - pure_eval - - python >=3.9 - license: MIT - license_family: MIT - purls: - - pkg:pypi/stack-data?source=hash-mapping - size: 26988 - timestamp: 1733569565672 -- pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl - name: sympy - version: 1.14.0 - sha256: e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 +- pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + name: jupyterquiz + version: 2.9.6.4 + sha256: f8c4418f6c827454523fc882a30d744b585cb58ac1ae277769c3059d04fc272b +- pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl + name: markdown-it-py + version: 4.2.0 + sha256: 9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a + requires_dist: + - mdurl~=0.1 + - psutil ; extra == 'benchmarking' + - pytest ; extra == 'benchmarking' + - pytest-benchmark ; extra == 'benchmarking' + - commonmark~=0.9 ; extra == 'compare' + - markdown~=3.4 ; extra == 'compare' + - mistletoe~=1.0 ; extra == 'compare' + - mistune~=3.0 ; extra == 'compare' + - panflute~=2.3 ; extra == 'compare' + - markdown-it-pyrs ; extra == 'compare' + - linkify-it-py>=1,<3 ; extra == 'linkify' + - mdit-py-plugins>=0.5.0 ; extra == 'plugins' + - gprof2dot ; extra == 'profiling' + - mdit-py-plugins>=0.5.0 ; extra == 'rtd' + - myst-parser ; extra == 'rtd' + - pyyaml ; extra == 'rtd' + - sphinx ; extra == 'rtd' + - sphinx-copybutton ; extra == 'rtd' + - sphinx-design ; extra == 'rtd' + - sphinx-book-theme~=1.0 ; extra == 'rtd' + - jupyter-sphinx ; extra == 'rtd' + - ipykernel ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + - pytest-timeout ; extra == 'testing' + - requests ; extra == 'testing' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b4/5e/bf11645aebb9af7d8d35927c40d3855816a0855c799e8156eeca8d632c90/diffpy_structure-3.4.0-py3-none-any.whl + name: diffpy-structure + version: 3.4.0 + sha256: bd0f06a96635d80316f51ebc0a08003bdeb2cb48c9bb18cbed1455ac60645e48 requires_dist: - - mpmath>=1.1.0,<1.4 - - pytest>=7.1.0 ; extra == 'dev' - - hypothesis>=6.70.0 ; extra == 'dev' + - numpy + - pycifrw + - diffpy-utils + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl + name: watchdog + version: 6.0.0 + sha256: 20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl - name: tabulate - version: 0.10.0 - sha256: f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 +- pypi: https://files.pythonhosted.org/packages/b7/18/4880dd762e40cd360c1bf06e890c5a97b997e91cb324602b1a19950ad5ce/matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl + name: matplotlib + version: 3.10.9 + sha256: 41cb28c2bd769aa3e98322c6ab09854cbcc52ab69d2759d681bba3e327b2b320 requires_dist: - - wcwidth ; extra == 'widechars' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.23 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=3 + - python-dateutil>=2.7 + - meson-python>=0.13.1,<0.17.0 ; extra == 'dev' + - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev' + - setuptools-scm>=7,<10 ; extra == 'dev' + - setuptools>=64 ; extra == 'dev' requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-ha3553a1_1.conda - sha256: 5ff149ba6832bf4ded4b43bf0a41cde7be814802a95070553176c087f65b2a01 - md5: 34aa94d586fe95fa121966c0d4e73cf4 - depends: - - libhwloc >=2.12.2,<2.12.3.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: Apache-2.0 - license_family: APACHE - purls: [] - size: 156910 - timestamp: 1777976465531 -- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda - sha256: b375e8df0d5710717c31e7c8e93c025c37fa3504aea325c7a55509f64e5d4340 - md5: e43ca10d61e55d0a8ec5d8c62474ec9e - depends: - - __win - - pywinpty >=1.1.0 - - python >=3.10 - - tornado >=6.1.0 - - python - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/terminado?source=hash-mapping - size: 23665 - timestamp: 1766513806974 -- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - sha256: 6b6727a13d1ca6a23de5e6686500d0669081a117736a87c8abf444d60c1e40eb - md5: 17b43cee5cc84969529d5d0b0309b2cb - depends: - - __unix - - ptyprocess - - python >=3.10 - - tornado >=6.1.0 - - python - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/terminado?source=hash-mapping - size: 24749 - timestamp: 1766513766867 -- conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - sha256: cad582d6f978276522f84bd209a5ddac824742fe2d452af6acf900f8650a73a2 - md5: f1acf5fdefa8300de697982bcb1761c9 - depends: - - python >=3.5 - - webencodings >=0.4 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/tinycss2?source=hash-mapping - size: 28285 - timestamp: 1729802975370 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac - md5: cffd3bdd58090148f4cfcd831f4b26ab - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libzlib >=1.3.1,<2.0a0 - constrains: - - xorg-libx11 >=1.8.12,<2.0a0 - license: TCL - license_family: BSD - purls: [] - size: 3301196 - timestamp: 1769460227866 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 - md5: a9d86bc62f39b94c4661716624eb21b0 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: TCL - license_family: BSD - purls: [] - size: 3127137 - timestamp: 1769460817696 -- conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - sha256: 0e79810fae28f3b69fe7391b0d43f5474d6bd91d451d5f2bde02f55ae481d5e3 - md5: 0481bfd9814bf525bd4b3ee4b51494c4 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: TCL - license_family: BSD - purls: [] - size: 3526350 - timestamp: 1769460339384 -- pypi: https://files.pythonhosted.org/packages/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl - name: tof - version: 26.3.0 - sha256: e89783a072b05fdb53d9e76fbf919dc8935e75e118fdaf17ca5cc33727ef002b +- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + name: validate-pyproject + version: '0.25' + sha256: f9d05e2686beff82f9ea954f582306b036ced3d3feb258c1110f2c2a495b1981 requires_dist: - - plopp>=23.10.0 - - pooch>=1.5.0 - - scipp>=25.1.0 - - lazy-loader>=0.3 - - pytest>=8.0 ; extra == 'test' - - scippneutron>=24.12.0 ; extra == 'test' + - fastjsonschema>=2.16.2,<=3 + - packaging>=24.2 ; extra == 'all' + - trove-classifiers>=2021.10.20 ; extra == 'all' + - tomli>=1.2.1 ; python_full_version < '3.11' and extra == 'all' + - validate-pyproject-schema-store ; extra == 'store' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl + name: frozenlist + version: 1.8.0 + sha256: 34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl + name: pandas + version: 3.0.3 + sha256: c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc + requires_dist: + - numpy>=1.26.0 ; python_full_version < '3.14' + - numpy>=2.3.3 ; python_full_version >= '3.14' + - python-dateutil>=2.8.2 + - tzdata ; sys_platform == 'win32' + - tzdata ; sys_platform == 'emscripten' + - hypothesis>=6.116.0 ; extra == 'test' + - pytest>=8.3.4 ; extra == 'test' + - pytest-xdist>=3.6.1 ; extra == 'test' + - pyarrow>=13.0.0 ; extra == 'pyarrow' + - bottleneck>=1.4.2 ; extra == 'performance' + - numba>=0.60.0 ; extra == 'performance' + - numexpr>=2.10.2 ; extra == 'performance' + - scipy>=1.14.1 ; extra == 'computation' + - xarray>=2024.10.0 ; extra == 'computation' + - fsspec>=2024.10.0 ; extra == 'fss' + - s3fs>=2024.10.0 ; extra == 'aws' + - gcsfs>=2024.10.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.5 ; extra == 'excel' + - python-calamine>=0.3.0 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.2.0 ; extra == 'excel' + - pyarrow>=13.0.0 ; extra == 'parquet' + - pyarrow>=13.0.0 ; extra == 'feather' + - pyiceberg>=0.8.1 ; extra == 'iceberg' + - tables>=3.10.1 ; extra == 'hdf5' + - pyreadstat>=1.2.8 ; extra == 'spss' + - sqlalchemy>=2.0.36 ; extra == 'postgresql' + - psycopg2>=2.9.10 ; extra == 'postgresql' + - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.36 ; extra == 'mysql' + - pymysql>=1.1.1 ; extra == 'mysql' + - sqlalchemy>=2.0.36 ; extra == 'sql-other' + - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' + - beautifulsoup4>=4.12.3 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'xml' + - matplotlib>=3.9.3 ; extra == 'plot' + - jinja2>=3.1.5 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.4.2 ; extra == 'clipboard' + - zstandard>=0.23.0 ; extra == 'compression' + - pytz>=2020.1 ; extra == 'timezone' + - adbc-driver-postgresql>=1.2.0 ; extra == 'all' + - adbc-driver-sqlite>=1.2.0 ; extra == 'all' + - beautifulsoup4>=4.12.3 ; extra == 'all' + - bottleneck>=1.4.2 ; extra == 'all' + - fastparquet>=2024.11.0 ; extra == 'all' + - fsspec>=2024.10.0 ; extra == 'all' + - gcsfs>=2024.10.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.116.0 ; extra == 'all' + - jinja2>=3.1.5 ; extra == 'all' + - lxml>=5.3.0 ; extra == 'all' + - matplotlib>=3.9.3 ; extra == 'all' + - numba>=0.60.0 ; extra == 'all' + - numexpr>=2.10.2 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.5 ; extra == 'all' + - psycopg2>=2.9.10 ; extra == 'all' + - pyarrow>=13.0.0 ; extra == 'all' + - pyiceberg>=0.8.1 ; extra == 'all' + - pymysql>=1.1.1 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.8 ; extra == 'all' + - pytest>=8.3.4 ; extra == 'all' + - pytest-xdist>=3.6.1 ; extra == 'all' + - python-calamine>=0.3.0 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.4.2 ; extra == 'all' + - scipy>=1.14.1 ; extra == 'all' + - s3fs>=2024.10.0 ; extra == 'all' + - sqlalchemy>=2.0.36 ; extra == 'all' + - tables>=3.10.1 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2024.10.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.2.0 ; extra == 'all' + - zstandard>=0.23.0 ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl - name: tokenize-rt - version: 6.2.0 - sha256: a152bf4f249c847a66497a4a95f63376ed68ac6abf092a2f7cfb29d044ecff44 +- pypi: https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl + name: dnspython + version: 2.8.0 + sha256: 01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af + requires_dist: + - black>=25.1.0 ; extra == 'dev' + - coverage>=7.0 ; extra == 'dev' + - flake8>=7 ; extra == 'dev' + - hypercorn>=0.17.0 ; extra == 'dev' + - mypy>=1.17 ; extra == 'dev' + - pylint>=3 ; extra == 'dev' + - pytest-cov>=6.2.0 ; extra == 'dev' + - pytest>=8.4 ; extra == 'dev' + - quart-trio>=0.12.0 ; extra == 'dev' + - sphinx-rtd-theme>=3.0.0 ; extra == 'dev' + - sphinx>=8.2.0 ; extra == 'dev' + - twine>=6.1.0 ; extra == 'dev' + - wheel>=0.45.0 ; extra == 'dev' + - cryptography>=45 ; extra == 'dnssec' + - h2>=4.2.0 ; extra == 'doh' + - httpcore>=1.0.0 ; extra == 'doh' + - httpx>=0.28.0 ; extra == 'doh' + - aioquic>=1.2.0 ; extra == 'doq' + - idna>=3.10 ; extra == 'idna' + - 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/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl + name: pillow + version: 12.2.0 + sha256: 80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - arro3-compute ; extra == 'test-arrow' + - arro3-core ; extra == 'test-arrow' + - nanoarrow ; extra == 'test-arrow' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma>=5 ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + name: pyproject-hooks + version: 1.2.0 + sha256: 9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/bd/8c/d4907ad4f6bdc5bf79462d8767728713a7b316918a7444df372958a0e417/spglib-2.6.0-cp312-cp312-macosx_11_0_arm64.whl + name: spglib + version: 2.6.0 + sha256: 83ea2e90addc7232017c793a32d94b47bc68040c595671d1cbb836ede4349510 + requires_dist: + - numpy>=1.20,<3 + - importlib-resources ; python_full_version < '3.10' + - typing-extensions>=4.9.0 ; python_full_version < '3.13' + - pytest ; extra == 'test' + - pyyaml ; extra == 'test' + - sphinx>=7.0 ; extra == 'docs' + - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' + - sphinx-book-theme ; extra == 'docs' + - sphinx-autodoc-typehints ; extra == 'docs' + - myst-parser>=2.0 ; extra == 'docs' + - linkify-it-py ; extra == 'docs' + - sphinx-tippy ; extra == 'docs' + - spglib[test] ; extra == 'test-cov' + - pytest-cov ; extra == 'test-cov' + - spglib[test] ; extra == 'test-benchmark' + - pytest-benchmark ; extra == 'test-benchmark' + - spglib[test] ; extra == 'dev' + - pre-commit ; extra == 'dev' + - spglib[docs] ; extra == 'doc' + - spglib[test] ; extra == 'testing' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd - md5: b5325cf06a000c5b14970462ff5e4d58 - depends: - - python >=3.10 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomli?source=hash-mapping - size: 21561 - timestamp: 1774492402955 -- 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 +- pypi: https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: aiohttp + version: 3.13.5 + sha256: 241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda - sha256: 4629b1c9139858fb08bb357df917ffc12e4d284c57ff389806bb3ae476ef4e0a - md5: 2b37798adbc54fd9e591d24679d2133a - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/tornado?source=hash-mapping - size: 859665 - timestamp: 1774358032165 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda - sha256: ed8d06093ff530a2dae9ed1e51eb6f908fbfd171e8b62f4eae782d67b420be5a - md5: dc1ff1e915ab35a06b6fa61efae73ab5 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/tornado?source=hash-mapping - size: 912476 - timestamp: 1774358032579 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda - sha256: 29edd36311b4a810a9e6208437bdbedb28c9ac15221caf812cb5c5cf48375dca - md5: 02cce5319b0f1317d9642dcb2e475379 - depends: - - __osx >=11.0 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/tornado?source=hash-mapping - size: 859155 - timestamp: 1774358568476 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda - sha256: 4ccc4a20d676c0ba85adee9c99015bec7f5b685df0cf8006e34573f1d6c2ce75 - md5: 3f81f8b2fe2c26a82c0abf57ab2b9610 - depends: - - __osx >=11.0 - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python_abi 3.14.* *_cp314 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/tornado?source=hash-mapping - size: 910845 - timestamp: 1774358965067 -- conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py312he06e257_0.conda - sha256: 1220c986664e9e8662e660dc64dd97ed823926b1ba05175771408cf1d6a46dd2 - md5: c6c66a64da3d2953c83ed2789a7f4bdb - depends: - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/tornado?source=hash-mapping - size: 859726 - timestamp: 1774358173994 -- conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda - sha256: 49d64837dd02475903479ca47b82669bd6c9f7e6afde61860c6f3f2bd57d8a03 - md5: 87b1215adf7f0ba1fb9250af9fc668e1 - depends: - - python >=3.14,<3.15.0a0 - - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: Apache-2.0 - license_family: Apache - purls: - - pkg:pypi/tornado?source=hash-mapping - size: 914835 - timestamp: 1774358183098 -- conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.0-pyhcf101f3_0.conda - sha256: dfb681579be59c2e790c95f7f49b7529a9b0511d6385ad276e3c8988cbd54d2c - md5: 4bada6a6d908a27262af8ebddf4f7492 - depends: - - python >=3.10 - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/traitlets?source=hash-mapping - size: 115165 - timestamp: 1778074251714 -- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl - name: traittypes - version: 0.2.3 - sha256: 49016082ce740d6556d9bb4672ee2d899cd14f9365f17cbb79d5d96b47096d4e +- pypi: https://files.pythonhosted.org/packages/bf/34/1fe99124be59579ebd24316522e1da780979c856977b142c0dcd878b0a2d/spglib-2.6.0.tar.gz + name: spglib + version: 2.6.0 + sha256: d66eda2ba00a1e14fd96ec9c3b4dbf8ab0fb3f124643e35785c71ee455b408eb + requires_dist: + - numpy>=1.20,<3 + - importlib-resources ; python_full_version < '3.10' + - typing-extensions>=4.9.0 ; python_full_version < '3.13' + - pytest ; extra == 'test' + - pyyaml ; extra == 'test' + - sphinx>=7.0 ; extra == 'docs' + - sphinxcontrib-bibtex>=2.5 ; extra == 'docs' + - sphinx-book-theme ; extra == 'docs' + - sphinx-autodoc-typehints ; extra == 'docs' + - myst-parser>=2.0 ; extra == 'docs' + - linkify-it-py ; extra == 'docs' + - sphinx-tippy ; extra == 'docs' + - spglib[test] ; extra == 'test-cov' + - pytest-cov ; extra == 'test-cov' + - spglib[test] ; extra == 'test-benchmark' + - pytest-benchmark ; extra == 'test-benchmark' + - spglib[test] ; extra == 'dev' + - pre-commit ; extra == 'dev' + - spglib[docs] ; extra == 'doc' + - spglib[test] ; extra == 'testing' + requires_python: '>=3.9' +- 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: - - traitlets>=4.2.2 - - numpy ; extra == 'test' - - pandas ; extra == 'test' - - xarray ; extra == 'test' + - 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' -- pypi: https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl - name: trove-classifiers - version: 2026.5.7.17 - sha256: 5ec0800de5e2ddbd7c663cb4c0c15328f132dc168813897c18866c5c7b93db33 -- pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl - name: typeguard - version: 4.5.1 - sha256: 44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/bf/e1/9e8e09ab8fc5c77f228e3271188dc4f569d12692548c42bff81b1fbba5e1/easydiffraction-0.16.0-py3-none-any.whl + name: easydiffraction + version: 0.16.0 + sha256: 2691a1e175974ca79e0ec3c219d92b77f277c38fb3b0b8d25f6f7e99696bf70f requires_dist: - - importlib-metadata>=3.6 ; python_full_version < '3.10' - - typing-extensions>=4.14.0 + - asciichartpy + - asteval + - bumps + - colorama + - crysfml + - cryspy + - darkdetect + - dfo-ls + - diffpy-pdffit2 + - diffpy-utils + - essdiffraction + - gemmi + - lmfit + - numpy + - pandas + - plotly + - pooch + - py3dmol + - rich + - scipy + - sympy + - tabulate + - typeguard + - typer + - uncertainties + - varname + - build ; extra == 'dev' + - copier ; extra == 'dev' + - docstripy ; 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-benchmark ; 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' + requires_python: '>=3.12' +- 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/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: chardet + version: 7.4.3 + sha256: 6e3bd9f936e04bae89c254262af08d9e5b98f805175ba1e29d454e6cba3107b7 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: kiwisolver + version: 1.5.0 + sha256: bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/c4/6d/82e65254354ba651dc966775270a9bbc02414a3eb3f1704e6c87dab2ea83/essdiffraction-26.5.1-py3-none-any.whl + name: essdiffraction + version: 26.5.1 + sha256: 8a6c779078c71be250714619214069221ab7968a69580d4e4d3f4b3e9a1a53ad + requires_dist: + - dask>=2022.1.0 + - essreduce>=26.4.0 + - graphviz + - numpy>=2 + - plopp>=26.2.0 + - pythreejs>=2.4.1 + - sciline>=25.4.1 + - scipp>=25.11.0 + - scippneutron>=26.3.0 + - scippnexus>=23.12.0 + - tof>=25.12.0 + - ncrystal[cif]>=4.1.0 + - spglib!=2.7 + - pandas>=2.1.2 ; extra == 'test' + - pooch>=1.5 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - ipywidgets>=8.1.7 ; extra == 'test' + - autodoc-pydantic ; extra == 'docs' + - ipykernel ; extra == 'docs' + - ipympl ; extra == 'docs' + - ipython!=8.7.0 ; extra == 'docs' + - myst-parser ; extra == 'docs' + - nbsphinx ; extra == 'docs' + - pandas ; extra == 'docs' + - pooch ; extra == 'docs' + - pydata-sphinx-theme>=0.14 ; extra == 'docs' + - sphinx ; extra == 'docs' + - sphinx-autodoc-typehints ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-design ; extra == 'docs' + - sphinxcontrib-bibtex ; extra == 'docs' + - pyarrow ; extra == 'docs' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + name: mkdocs-plugin-inline-svg + version: 0.1.0 + sha256: a5aab2d98a19b24019f8e650f54fc647c2f31e7d0e36fc5cf2d2161acc0ea49a + requires_dist: + - mkdocs + requires_python: '>=3.5' +- pypi: https://files.pythonhosted.org/packages/c7/6b/6c02f55c2ce2f137ccca0986be7dd89bea31d5bee4346b4377fa3b8586df/ncrystal_core-4.4.2-py3-none-win_amd64.whl + name: ncrystal-core + version: 4.4.2 + sha256: 9b28a90b63849e6a3a807a0a59f7c2ee57e4c64f5643b2dcb6a798ac8ccf666a + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/c7/a0/5ff05d1919ca249508012cad89f08fdc6cfbdaa15b41651c5fe6dffaf1d3/dfo_ls-1.6.5-py3-none-any.whl + name: dfo-ls + version: 1.6.5 + sha256: d147d42e471e240f9abf8bc38351a88f555ea6a8fcfd83119bbbf93c36f75ab2 + requires_dist: + - setuptools + - numpy + - scipy>=1.11 + - pandas + - pytest ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-rtd-theme ; extra == 'dev' + - trustregion>=1.1 ; extra == 'trustregion' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl - name: typer - version: 0.25.1 - sha256: 75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89 +- pypi: https://files.pythonhosted.org/packages/c7/e1/68c2256b69a314eba133673377ba9118c356f6342a0c02b61de449cf2bf2/narwhals-2.21.0-py3-none-any.whl + name: narwhals + version: 2.21.0 + sha256: 1e6617d0fca68ae1fda29e5397c4eaacd3ffc9fffe6bcd6ded0c690475e853be requires_dist: - - click>=8.2.1 - - shellingham>=1.3.0 - - rich>=13.8.0 - - annotated-doc>=0.0.2 + - cudf-cu12>=24.10.0 ; extra == 'cudf' + - dask[dataframe]>=2024.8 ; extra == 'dask' + - duckdb>=1.1 ; extra == 'duckdb' + - ibis-framework>=6.0.0 ; extra == 'ibis' + - packaging ; extra == 'ibis' + - pyarrow-hotfix ; extra == 'ibis' + - rich ; extra == 'ibis' + - modin ; extra == 'modin' + - pandas>=1.1.3 ; extra == 'pandas' + - polars>=0.20.4 ; extra == 'polars' + - pyarrow>=13.0.0 ; extra == 'pyarrow' + - pyspark>=3.5.0 ; extra == 'pyspark' + - pyspark[connect]>=3.5.0 ; extra == 'pyspark-connect' + - duckdb>=1.1 ; extra == 'sql' + - sqlparse ; extra == 'sql' + - sqlframe>=3.22.0,!=3.39.3 ; extra == 'sqlframe' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c7/ea/7988934c8e3e3418aa043f70421817df28d06aef50bfd85f5ad3ec6e70f1/ncrystal_core-4.4.2-py3-none-macosx_11_0_arm64.whl + name: ncrystal-core + version: 4.4.2 + sha256: b7e6101a6850aa18cf441825214381614db444ffcba648de8266fe1c4d1024ce + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + name: pytest-xdist + version: 3.8.0 + sha256: 202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88 + requires_dist: + - execnet>=2.1 + - pytest>=7.0.0 + - filelock ; extra == 'testing' + - psutil>=3.0 ; extra == 'psutil' + - setproctitle ; extra == 'setproctitle' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + name: iniconfig + version: 2.3.0 + sha256: f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c - md5: edd329d7d3a4ab45dcf905899a7a6115 - depends: - - typing_extensions ==4.15.0 pyhcf101f3_0 - license: PSF-2.0 - license_family: PSF - purls: [] - size: 91383 - timestamp: 1756220668932 -- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - name: typing-inspection - version: 0.4.2 - sha256: 4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 +- pypi: https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: contourpy + version: 1.3.3 + sha256: 4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1 + requires_dist: + - numpy>=1.25 + - furo ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - bokeh ; extra == 'bokeh' + - selenium ; extra == 'bokeh' + - contourpy[bokeh,docs] ; extra == 'mypy' + - bokeh ; extra == 'mypy' + - docutils-stubs ; extra == 'mypy' + - mypy==1.17.0 ; extra == 'mypy' + - types-pillow ; extra == 'mypy' + - contourpy[test-no-images] ; extra == 'test' + - matplotlib ; extra == 'test' + - pillow ; extra == 'test' + - pytest ; extra == 'test-no-images' + - pytest-cov ; extra == 'test-no-images' + - pytest-rerunfailures ; extra == 'test-no-images' + - pytest-xdist ; extra == 'test-no-images' + - wurlitzer ; extra == 'test-no-images' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl + name: pillow + version: 12.2.0 + sha256: 4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150 requires_dist: - - typing-extensions>=4.12.0 - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 - md5: 0caa1af407ecff61170c9437a808404d - depends: - - python >=3.10 - - python - license: PSF-2.0 - license_family: PSF - purls: - - pkg:pypi/typing-extensions?source=hash-mapping - size: 51692 - timestamp: 1756220668932 -- conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - sha256: 3088d5d873411a56bf988eee774559335749aed6f6c28e07bf933256afb9eb6c - md5: f6d7aa696c67756a650e91e15e88223c - depends: - - python >=3.9 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/typing-utils?source=hash-mapping - size: 15183 - timestamp: 1733331395943 -- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c - md5: ad659d0a2b3e47e38d829aa8cad2d610 - license: LicenseRef-Public-Domain - purls: [] - size: 119135 - timestamp: 1767016325805 -- conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 - md5: 71b24316859acd00bdb8b38f5e2ce328 - constrains: - - vc14_runtime >=14.29.30037 - - vs2015_runtime >=14.29.30037 - license: LicenseRef-MicrosoftWindowsSDK10 - purls: [] - size: 694692 - timestamp: 1756385147981 -- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - name: uncertainties - version: 3.2.3 - sha256: 313353900d8f88b283c9bad81e7d2b2d3d4bcc330cbace35403faaed7e78890a + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - arro3-compute ; extra == 'test-arrow' + - arro3-core ; extra == 'test-arrow' + - nanoarrow ; extra == 'test-arrow' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma>=5 ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl + name: pandas + version: 3.0.3 + sha256: b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4 requires_dist: - - numpy ; extra == 'arrays' - - pytest ; extra == 'test' - - pytest-codspeed ; extra == 'test' - - pytest-cov ; extra == 'test' - - scipy ; extra == 'test' - - sphinx ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - python-docs-theme ; extra == 'doc' - - uncertainties[arrays,doc,test] ; extra == 'all' - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - sha256: e0eb6c8daf892b3056f08416a96d68b0a358b7c46b99c8a50481b22631a4dfc0 - md5: e7cb0f5745e4c5035a460248334af7eb - depends: - - python >=3.9 - license: MIT - license_family: MIT - purls: - - pkg:pypi/uri-template?source=hash-mapping - size: 23990 - timestamp: 1733323714454 -- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 - md5: cbb88288f74dbe6ada1c6c7d0a97223e - depends: - - backports.zstd >=1.0.0 - - brotli-python >=1.2.0 - - h2 >=4,<5 - - pysocks >=1.5.6,<2.0,!=1.5.7 - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/urllib3?source=hash-mapping - size: 103560 - timestamp: 1778188657149 -- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl - name: validate-pyproject - version: '0.25' - sha256: f9d05e2686beff82f9ea954f582306b036ced3d3feb258c1110f2c2a495b1981 + - numpy>=1.26.0 ; python_full_version < '3.14' + - numpy>=2.3.3 ; python_full_version >= '3.14' + - python-dateutil>=2.8.2 + - tzdata ; sys_platform == 'win32' + - tzdata ; sys_platform == 'emscripten' + - hypothesis>=6.116.0 ; extra == 'test' + - pytest>=8.3.4 ; extra == 'test' + - pytest-xdist>=3.6.1 ; extra == 'test' + - pyarrow>=13.0.0 ; extra == 'pyarrow' + - bottleneck>=1.4.2 ; extra == 'performance' + - numba>=0.60.0 ; extra == 'performance' + - numexpr>=2.10.2 ; extra == 'performance' + - scipy>=1.14.1 ; extra == 'computation' + - xarray>=2024.10.0 ; extra == 'computation' + - fsspec>=2024.10.0 ; extra == 'fss' + - s3fs>=2024.10.0 ; extra == 'aws' + - gcsfs>=2024.10.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.5 ; extra == 'excel' + - python-calamine>=0.3.0 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.2.0 ; extra == 'excel' + - pyarrow>=13.0.0 ; extra == 'parquet' + - pyarrow>=13.0.0 ; extra == 'feather' + - pyiceberg>=0.8.1 ; extra == 'iceberg' + - tables>=3.10.1 ; extra == 'hdf5' + - pyreadstat>=1.2.8 ; extra == 'spss' + - sqlalchemy>=2.0.36 ; extra == 'postgresql' + - psycopg2>=2.9.10 ; extra == 'postgresql' + - adbc-driver-postgresql>=1.2.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.36 ; extra == 'mysql' + - pymysql>=1.1.1 ; extra == 'mysql' + - sqlalchemy>=2.0.36 ; extra == 'sql-other' + - adbc-driver-postgresql>=1.2.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=1.2.0 ; extra == 'sql-other' + - beautifulsoup4>=4.12.3 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'html' + - lxml>=5.3.0 ; extra == 'xml' + - matplotlib>=3.9.3 ; extra == 'plot' + - jinja2>=3.1.5 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.4.2 ; extra == 'clipboard' + - zstandard>=0.23.0 ; extra == 'compression' + - pytz>=2020.1 ; extra == 'timezone' + - adbc-driver-postgresql>=1.2.0 ; extra == 'all' + - adbc-driver-sqlite>=1.2.0 ; extra == 'all' + - beautifulsoup4>=4.12.3 ; extra == 'all' + - bottleneck>=1.4.2 ; extra == 'all' + - fastparquet>=2024.11.0 ; extra == 'all' + - fsspec>=2024.10.0 ; extra == 'all' + - gcsfs>=2024.10.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.116.0 ; extra == 'all' + - jinja2>=3.1.5 ; extra == 'all' + - lxml>=5.3.0 ; extra == 'all' + - matplotlib>=3.9.3 ; extra == 'all' + - numba>=0.60.0 ; extra == 'all' + - numexpr>=2.10.2 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.5 ; extra == 'all' + - psycopg2>=2.9.10 ; extra == 'all' + - pyarrow>=13.0.0 ; extra == 'all' + - pyiceberg>=0.8.1 ; extra == 'all' + - pymysql>=1.1.1 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.8 ; extra == 'all' + - pytest>=8.3.4 ; extra == 'all' + - pytest-xdist>=3.6.1 ; extra == 'all' + - python-calamine>=0.3.0 ; extra == 'all' + - pytz>=2020.1 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.4.2 ; extra == 'all' + - scipy>=1.14.1 ; extra == 'all' + - s3fs>=2024.10.0 ; extra == 'all' + - sqlalchemy>=2.0.36 ; extra == 'all' + - tables>=3.10.1 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2024.10.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.2.0 ; extra == 'all' + - zstandard>=0.23.0 ; extra == 'all' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl + name: sqlalchemy + version: 2.0.49 + sha256: 77641d299179c37b89cf2343ca9972c88bb6eef0d5fc504a2f86afd15cd5adf5 requires_dist: - - fastjsonschema>=2.16.2,<=3 - - packaging>=24.2 ; extra == 'all' - - trove-classifiers>=2021.10.20 ; extra == 'all' - - tomli>=1.2.1 ; python_full_version < '3.11' and extra == 'all' - - validate-pyproject-schema-store ; extra == 'store' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/a4/39/3a0ae5b0edb66e61bb0e8bc53a503495cba5892297ae21faf6ba0525e681/varname-1.0.0-py3-none-any.whl - name: varname - version: 1.0.0 - sha256: 1125bfe981c3bbbe56988f5cb85fdcd7cad923b153283c2d464aea8b4c833d51 + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.whl + name: scipy + version: 1.17.1 + sha256: cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086 requires_dist: - - executing>=2.1 - - typing-extensions>=4.13 ; python_full_version < '3.10' - - asttokens==3.* ; extra == 'all' - - pure-eval==0.* ; extra == 'all' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - sha256: 9dc40c2610a6e6727d635c62cced5ef30b7b30123f5ef67d6139e23d21744b3a - md5: 1e610f2416b6acdd231c5f573d754a0f - depends: - - vc14_runtime >=14.44.35208 - track_features: - - vc14 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 19356 - timestamp: 1767320221521 -- conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - sha256: 02732f953292cce179de9b633e74928037fa3741eb5ef91c3f8bae4f761d32a5 - md5: 37eb311485d2d8b2c419449582046a42 - depends: - - ucrt >=10.0.20348.0 - - vcomp14 14.44.35208 h818238b_34 - constrains: - - vs2015_runtime 14.44.35208.* *_34 - license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime - license_family: Proprietary - purls: [] - size: 683233 - timestamp: 1767320219644 -- conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - sha256: 878d5d10318b119bd98ed3ed874bd467acbe21996e1d81597a1dbf8030ea0ce6 - md5: 242d9f25d2ae60c76b38a5e42858e51d - depends: - - ucrt >=10.0.20348.0 - constrains: - - vs2015_runtime 14.44.35208.* *_34 - license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime - license_family: Proprietary - purls: [] - size: 115235 - timestamp: 1767320173250 -- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl - name: versioningit - version: 3.3.0 - sha256: 23b1db3c4756cded9bd6b0ddec6643c261e3d0c471707da3e0b230b81ce53e4b + - numpy>=1.26.4,<2.7 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.10.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + name: colorama + version: 0.4.6 + sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + name: mando + version: 0.7.1 + sha256: 26ef1d70928b6057ee3ca12583d73c63e05c49de8972d620c278a7b206581a8a requires_dist: - - importlib-metadata>=3.6 ; python_full_version < '3.10' - - packaging>=17.1 - - tomli>=1.2,<3.0 ; python_full_version < '3.11' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - name: verspec - version: 0.1.0 - sha256: 741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31 + - six + - argparse ; python_full_version < '2.7' + - funcsigs ; python_full_version < '3.3' + - rst2ansi ; extra == 'restructuredtext' +- pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + name: pytest + version: 9.0.3 + sha256: 2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9 requires_dist: - - coverage ; extra == 'test' - - flake8>=3.7 ; extra == 'test' - - mypy ; extra == 'test' - - pretend ; extra == 'test' + - colorama>=0.4 ; sys_platform == 'win32' + - exceptiongroup>=1 ; python_full_version < '3.11' + - iniconfig>=1.0.1 + - packaging>=22 + - pluggy>=1.5,<2 + - pygments>=2.7.2 + - tomli>=1 ; python_full_version < '3.11' + - argcomplete ; extra == 'dev' + - attrs>=19.2 ; extra == 'dev' + - hypothesis>=3.56 ; extra == 'dev' + - mock ; extra == 'dev' + - requests ; extra == 'dev' + - setuptools ; extra == 'dev' + - xmlschema ; extra == 'dev' + 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/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl + name: fsspec + version: 2026.4.0 + sha256: 11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2 + requires_dist: + - adlfs ; extra == 'abfs' + - adlfs ; extra == 'adl' + - pyarrow>=1 ; extra == 'arrow' + - dask ; extra == 'dask' + - distributed ; extra == 'dask' + - pre-commit ; extra == 'dev' + - ruff>=0.5 ; extra == 'dev' + - numpydoc ; extra == 'doc' + - sphinx ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - yarl ; extra == 'doc' + - dropbox ; extra == 'dropbox' + - dropboxdrivefs ; extra == 'dropbox' + - requests ; extra == 'dropbox' + - adlfs ; extra == 'full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' + - dask ; extra == 'full' + - distributed ; extra == 'full' + - dropbox ; extra == 'full' + - dropboxdrivefs ; extra == 'full' + - fusepy ; extra == 'full' + - gcsfs>2024.2.0 ; extra == 'full' + - libarchive-c ; extra == 'full' + - ocifs ; extra == 'full' + - panel ; extra == 'full' + - paramiko ; extra == 'full' + - pyarrow>=1 ; extra == 'full' + - pygit2 ; extra == 'full' + - requests ; extra == 'full' + - s3fs>2024.2.0 ; extra == 'full' + - smbprotocol ; extra == 'full' + - tqdm ; extra == 'full' + - fusepy ; extra == 'fuse' + - gcsfs>2024.2.0 ; extra == 'gcs' + - pygit2 ; extra == 'git' + - requests ; extra == 'github' + - gcsfs ; extra == 'gs' + - panel ; extra == 'gui' + - pyarrow>=1 ; extra == 'hdfs' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' + - libarchive-c ; extra == 'libarchive' + - ocifs ; extra == 'oci' + - s3fs>2024.2.0 ; extra == 's3' + - paramiko ; extra == 'sftp' + - smbprotocol ; extra == 'smb' + - paramiko ; extra == 'ssh' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test' + - numpy ; extra == 'test' - pytest ; extra == 'test' -- pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - name: virtualenv - version: 21.3.1 - sha256: d1a71cf58f2f9228fff23a1f6ec15d39785c6b32e03658d104974247145edd35 + - pytest-asyncio!=0.22.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-recording ; extra == 'test' + - pytest-rerunfailures ; extra == 'test' + - requests ; extra == 'test' + - aiobotocore>=2.5.4,<3.0.0 ; extra == 'test-downstream' + - dask[dataframe,test] ; extra == 'test-downstream' + - moto[server]>4,<5 ; extra == 'test-downstream' + - pytest-timeout ; extra == 'test-downstream' + - xarray ; extra == 'test-downstream' + - adlfs ; extra == 'test-full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test-full' + - backports-zstd ; python_full_version < '3.14' and extra == 'test-full' + - cloudpickle ; extra == 'test-full' + - dask ; extra == 'test-full' + - distributed ; extra == 'test-full' + - dropbox ; extra == 'test-full' + - dropboxdrivefs ; extra == 'test-full' + - fastparquet ; extra == 'test-full' + - fusepy ; extra == 'test-full' + - gcsfs ; extra == 'test-full' + - jinja2 ; extra == 'test-full' + - kerchunk ; extra == 'test-full' + - libarchive-c ; extra == 'test-full' + - lz4 ; extra == 'test-full' + - notebook ; extra == 'test-full' + - numpy ; extra == 'test-full' + - ocifs ; extra == 'test-full' + - pandas<3.0.0 ; extra == 'test-full' + - panel ; extra == 'test-full' + - paramiko ; extra == 'test-full' + - pyarrow ; extra == 'test-full' + - pyarrow>=1 ; extra == 'test-full' + - pyftpdlib ; extra == 'test-full' + - pygit2 ; extra == 'test-full' + - pytest ; extra == 'test-full' + - pytest-asyncio!=0.22.0 ; extra == 'test-full' + - pytest-benchmark ; extra == 'test-full' + - pytest-cov ; extra == 'test-full' + - pytest-mock ; extra == 'test-full' + - pytest-recording ; extra == 'test-full' + - pytest-rerunfailures ; extra == 'test-full' + - python-snappy ; extra == 'test-full' + - requests ; extra == 'test-full' + - smbprotocol ; extra == 'test-full' + - tqdm ; extra == 'test-full' + - urllib3 ; extra == 'test-full' + - zarr ; extra == 'test-full' + - zstandard ; python_full_version < '3.14' and extra == 'test-full' + - tqdm ; extra == 'tqdm' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + name: pycodestyle + version: 2.14.0 + sha256: dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: coverage + version: 7.14.0 + sha256: 5ebb8f4614a3787d567e610bbfdf96a4798dd69a1afb1bd8ad228d4111fe6ff3 requires_dist: - - distlib>=0.3.7,<1 - - filelock>=3.24.2,<4 ; python_full_version >= '3.10' - - filelock>=3.16.1,<=3.19.1 ; python_full_version < '3.10' - - importlib-metadata>=6.6 ; python_full_version < '3.8' - - platformdirs>=3.9.1,<5 - - python-discovery>=1.2.2 - - typing-extensions>=4.13.2 ; python_full_version < '3.11' - requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl - name: watchdog - version: 6.0.0 - sha256: 6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d8/8b/e2bbeb42068f0c48899e8eddd34902afc0f7429d4d2a152d2dc2670dc661/pythreejs-2.4.2-py3-none-any.whl + name: pythreejs + version: 2.4.2 + sha256: 8418807163ad91f4df53b58c4e991b26214852a1236f28f1afeaadf99d095818 requires_dist: - - pyyaml>=3.10 ; extra == 'watchmedo' - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - name: watchdog - version: 6.0.0 - sha256: 20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 + - ipywidgets>=7.2.1 + - ipydatawidgets>=1.1.1 + - numpy + - traitlets + - sphinx>=1.5 ; extra == 'docs' + - nbsphinx>=0.2.13 ; extra == 'docs' + - nbsphinx-link ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - scipy ; extra == 'examples' + - matplotlib ; extra == 'examples' + - scikit-image ; extra == 'examples' + - ipywebrtc ; extra == 'examples' + - nbval ; extra == 'test' + - pytest-check-links ; extra == 'test' + - numpy>=1.14 ; extra == 'test' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl + name: pillow + version: 12.2.0 + sha256: f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421 requires_dist: - - pyyaml>=3.10 ; extra == 'watchmedo' - requires_python: '>=3.9' + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx>=8.2 ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' + - arro3-compute ; extra == 'test-arrow' + - arro3-core ; extra == 'test-arrow' + - nanoarrow ; extra == 'test-arrow' + - pyarrow ; extra == 'test-arrow' + - check-manifest ; extra == 'tests' + - coverage>=7.4.2 ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma>=5 ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + - trove-classifiers>=2024.10.12 ; extra == 'tests' + - defusedxml ; extra == 'xmp' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + name: cfgv + version: 3.5.0 + sha256: a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl + name: scipy + version: 1.17.1 + sha256: 3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b + requires_dist: + - numpy>=1.26.4,<2.7 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.10.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.11' - pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz name: watchdog version: 6.0.0 @@ -12787,6 +12690,11 @@ packages: requires_dist: - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + name: locket + version: 1.0.0 + sha256: b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl name: watchdog version: 6.0.0 @@ -12794,80 +12702,6 @@ packages: requires_dist: - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda - sha256: 1ee2d8384972ecbf8630ce8a3ea9d16858358ad3e8566675295e66996d5352da - md5: eb9538b8e55069434a18547f43b96059 - depends: - - python >=3.10 - license: MIT - license_family: MIT - purls: - - pkg:pypi/wcwidth?source=hash-mapping - size: 82917 - timestamp: 1777744489106 -- conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - sha256: 21f6c8a20fe050d09bfda3fb0a9c3493936ce7d6e1b3b5f8b01319ee46d6c6f6 - md5: 6639b6b0d8b5a284f027a2003669aa65 - depends: - - python >=3.10 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/webcolors?source=hash-mapping - size: 18987 - timestamp: 1761899393153 -- conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - sha256: 19ff205e138bb056a46f9e3839935a2e60bd1cf01c8241a5e172a422fed4f9c6 - md5: 2841eb5bfc75ce15e9a0054b98dcd64d - depends: - - python >=3.9 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/webencodings?source=hash-mapping - size: 15496 - timestamp: 1733236131358 -- conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - sha256: 42a2b61e393e61cdf75ced1f5f324a64af25f347d16c60b14117393a98656397 - md5: 2f1ed718fcd829c184a6d4f0f2e07409 - depends: - - python >=3.10 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/websocket-client?source=hash-mapping - size: 61391 - timestamp: 1759928175142 -- pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl - name: widgetsnbextension - version: 4.0.15 - sha256: 8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366 - requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - sha256: 93807369ab91f230cf9e6e2a237eaa812492fe00face5b38068735858fba954f - md5: 46e441ba871f524e2b067929da3051c2 - depends: - - __win - - python >=3.9 - license: LicenseRef-Public-Domain - purls: - - pkg:pypi/win-inet-pton?source=hash-mapping - size: 9555 - timestamp: 1733130678956 -- conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 - sha256: 9df10c5b607dd30e05ba08cbd940009305c75db242476f4e845ea06008b0a283 - md5: 1cee351bf20b830d991dbe0bc8cd7dfe - license: MIT - license_family: MIT - purls: [] - size: 1176306 -- pypi: https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl - name: wsproto - version: 1.3.2 - sha256: 61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584 - requires_dist: - - h11>=0.16.0,<1 - requires_python: '>=3.10' - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl name: xarray version: 2026.4.0 @@ -12916,132 +12750,235 @@ packages: - types-setuptools ; extra == 'types' - types-xlrd ; extra == 'types' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/19/d4/225027a913621a879b429a043674aa35220e6ce67785acad4f7bd0c4ff33/xarray_einstats-0.10.0-py3-none-any.whl - name: xarray-einstats - version: 0.10.0 - sha256: fa3169b46cee29092db820d8bbc203148bada4fc970ee75e62cbf3dd7c5a8945 +- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + name: typing-inspection + version: 0.4.2 + sha256: 4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 requires_dist: - - numpy>=2.0 - - scipy>=1.13 - - xarray>=2024.2.0 - - furo ; extra == 'doc' - - myst-parser[linkify] ; extra == 'doc' - - myst-nb ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - numpydoc ; extra == 'doc' - - sphinx>=5 ; extra == 'doc' - - jupyter-sphinx ; extra == 'doc' - - sphinx-design ; extra == 'doc' - - watermark ; extra == 'doc' - - matplotlib ; extra == 'doc' - - sphinx-togglebutton ; extra == 'doc' - - einops ; extra == 'einops' - - numba>=0.55 ; extra == 'numba' - - hypothesis ; extra == 'test' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - packaging ; extra == 'test' - - scipy>=1.15 ; extra == 'test' - - preliz>=0.19 ; extra == 'test' - requires_python: '>=3.12' -- pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl - name: xraydb - version: 4.5.8 - sha256: 2215baafa6a03d00d0254a94525aafc6493c8c285e4ac4477fbd6271b25e6a51 + - typing-extensions>=4.12.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-py3-none-any.whl + name: ncrystal-python + version: 4.4.2 + sha256: f419318d088fade6bcff1e39e15baf6fe69fcf5306dd681fca1106d1f63a89ce + requires_dist: + - numpy>=1.22 + requires_python: '>=3.8' +- 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 + sha256: 80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4 + requires_dist: + - dnspython>=2.0.0 + - idna>=2.0.0 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + name: markdown + version: 3.10.2 + sha256: e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36 requires_dist: - - numpy>=1.19 - - scipy>=1.6 - - sqlalchemy>=2.0.1 - - platformdirs - - build ; extra == 'dev' - - twine ; extra == 'dev' - - sphinx ; extra == 'doc' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - coverage ; extra == 'test' - - xraydb[dev,doc,test] ; extra == 'all' + - coverage ; extra == 'testing' + - pyyaml ; extra == 'testing' + - mkdocs>=1.6 ; extra == 'docs' + - mkdocs-nature>=0.6 ; extra == 'docs' + - mdx-gh-links>=0.2 ; extra == 'docs' + - mkdocstrings[python]>=0.28.3 ; extra == 'docs' + - mkdocs-gen-files ; extra == 'docs' + - mkdocs-section-index ; extra == 'docs' + - mkdocs-literate-nav ; extra == 'docs' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + name: py-cpuinfo + version: 9.0.0 + sha256: 859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5 +- pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl + name: multidict + version: 6.7.1 + sha256: 5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad - md5: a77f85f77be52ff59391544bfe73390a - depends: - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - license: MIT - license_family: MIT - purls: [] - size: 85189 - timestamp: 1753484064210 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - sha256: b03433b13d89f5567e828ea9f1a7d5c5d697bf374c28a4168d71e9464f5dafac - md5: 78a0fe9e9c50d2c381e8ee47e3ea437d - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: [] - size: 83386 - timestamp: 1753484079473 -- conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - sha256: 80ee68c1e7683a35295232ea79bcc87279d31ffeda04a1665efdb43cbd50a309 - md5: 433699cba6602098ae8957a323da2664 - depends: - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - license: MIT - license_family: MIT - purls: [] - size: 63944 - timestamp: 1753484092156 -- pypi: https://files.pythonhosted.org/packages/19/2a/725ecc166d53438bc88f76822ed4b1e3b10756e790bafd7b523fe97c322d/yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl - name: yarl - version: 1.23.0 - sha256: 13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 +- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + name: shellingham + version: 1.5.4 + sha256: 7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl + name: plopp + version: 26.4.2 + sha256: 5cab99bb0905ce08a1d1d7d82f0f64cee7d594269ec1bd01a8a361bd14ab7bff requires_dist: - - idna>=2.0 - - multidict>=4.0 - - propcache>=0.2.1 + - lazy-loader>=0.4 + - matplotlib>=3.8 + - scipp>=25.8.0 ; extra == 'scipp' + - plopp[scipp] ; extra == 'all' + - ipympl>0.8.4 ; extra == 'all' + - pythreejs>=2.4.1 ; extra == 'all' + - mpltoolbox>=24.6.0 ; extra == 'all' + - ipywidgets>=8.1.0 ; extra == 'all' + - graphviz>=0.20.3 ; extra == 'all' + - plopp[scipp] ; extra == 'test' + - graphviz>=0.20.3 ; extra == 'test' + - h5py>=3.12 ; extra == 'test' + - ipympl>=0.8.4 ; extra == 'test' + - ipywidgets>=8.1.0 ; extra == 'test' + - ipykernel>=6.26,<7 ; extra == 'test' + - mpltoolbox>=24.6.0 ; extra == 'test' + - pandas>=2.2.2 ; extra == 'test' + - plotly>=5.15.0 ; extra == 'test' + - pooch>=1.5 ; extra == 'test' + - pyarrow>=13.0.0 ; extra == 'test' + - pytest>=8.0 ; extra == 'test' + - pythreejs>=2.4.1 ; extra == 'test' + - scipy>=1.10.0 ; extra == 'test' + - xarray>=2024.5.0 ; extra == 'test' + - anywidget>=0.9.0 ; extra == 'test' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: gemmi + version: 0.7.5 + sha256: bdc67ad4a7fc420974ab3102f7f6ad1517fa0c3d9f2f7561e42e5f7017635242 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: chardet + version: 7.4.3 + sha256: 9a4904dd5f071b7a7d7f50b4a67a86db3c902d243bf31708f1d5cde2f68239cb requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl - name: yarl - version: 1.23.0 - sha256: 23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 +- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl + name: cycler + version: 0.12.1 + sha256: 85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 requires_dist: - - idna>=2.0 - - multidict>=4.0 - - propcache>=0.2.1 + - ipython ; extra == 'docs' + - matplotlib ; extra == 'docs' + - numpydoc ; extra == 'docs' + - sphinx ; extra == 'docs' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-xdist ; extra == 'tests' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: kiwisolver + version: 1.5.0 + sha256: 80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: yarl - version: 1.23.0 - sha256: 1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 +- pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: ruff + version: 0.15.12 + sha256: 83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/e8/88/5a431cd1ea7587408a66947384b39beb2ab2bcc1c87b7c4082f05036719f/gemmi-0.7.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: gemmi + version: 0.7.5 + sha256: 217bb9ac9da7c90704026dacfc0a0652a38f4df1e318225d8f35c75f1f8c7ebf + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + name: nbmake + version: 1.5.5 + sha256: c6fbe6e48b60cacac14af40b38bf338a3b88f47f085c54ac5b8639ff0babaf4b requires_dist: - - idna>=2.0 - - multidict>=4.0 - - propcache>=0.2.1 + - ipykernel>=5.4.0 + - nbclient>=0.6.6 + - nbformat>=5.0.4 + - pygments>=2.7.3 + - pytest>=6.1.0 + requires_python: '>=3.8.0' +- pypi: https://files.pythonhosted.org/packages/eb/f2/53be7a4ba5816e13c39be0f728facac4bcb39cf4903ceeec54b006511c8f/gemmi-0.7.5-cp312-cp312-win_amd64.whl + name: gemmi + version: 0.7.5 + sha256: a1fdb6f72006495b5119e3a8bb5c3185efa708b785bd4a5ce4397ef7abb3fec7 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ee/8c/83087ebc47ab0396ce092363001fa37c17153119ee282700c0713a195853/prettytable-3.17.0-py3-none-any.whl + name: prettytable + version: 3.17.0 + sha256: aad69b294ddbe3e1f95ef8886a060ed1666a0b83018bbf56295f6f226c43d287 + requires_dist: + - wcwidth + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-lazy-fixtures ; extra == 'tests' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/66/3e/868e5c3364b6cee19ff3e1a122194fa4ce51def02c61023970442162859e/yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: yarl - version: 1.23.0 - sha256: a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 +- pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl + name: h5py + version: 3.16.0 + sha256: e4360f15875a532bc7b98196c7592ed4fc92672a57c0a621355961cafb17a6dd requires_dist: - - idna>=2.0 - - multidict>=4.0 - - propcache>=0.2.1 + - numpy>=1.21.2 requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl - name: yarl - version: 1.23.0 - sha256: 63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 +- pypi: https://files.pythonhosted.org/packages/f1/2c/3850985d4c64048dec7b826f8a803e135b52b11b4c81c9cd4326b1ca15ab/ncrystal_core-4.4.2-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: ncrystal-core + version: 4.4.2 + sha256: d0d9c47cd017b7cefc52dde50546d7c151bfdd75d345e42e2b3e74ab5fe83c62 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl + name: multidict + version: 6.7.1 + sha256: 0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1 + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f1/5b/e63c877c4c94382b66de5045e08ec8cd960e8a4d22f0d62a4dfb1f9e5ac6/ipydatawidgets-4.3.5-py2.py3-none-any.whl + name: ipydatawidgets + version: 4.3.5 + sha256: d590cdb7c364f2f6ab346f20b9d2dd661d27a834ef7845bc9d7113118f05ec87 + requires_dist: + - ipywidgets>=7.0.0 + - numpy + - traittypes>=0.2.0 + - sphinx ; extra == 'docs' + - recommonmark ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pytest>=4 ; extra == 'test' + - pytest-cov ; extra == 'test' + - nbval>=0.9.2 ; extra == 'test' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + name: pathspec + version: 1.1.1 + sha256: a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 + requires_dist: + - hyperscan>=0.7 ; extra == 'hyperscan' + - typing-extensions>=4 ; extra == 'optional' + - google-re2>=1.1 ; extra == 're2' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl + name: darkdetect + version: 0.8.0 + sha256: a7509ccf517eaad92b31c214f593dbcf138ea8a43b2935406bbd565e15527a85 + requires_dist: + - pyobjc-framework-cocoa ; sys_platform == 'darwin' and extra == 'macos-listener' + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: multidict + version: 6.7.1 + sha256: bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961 + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl + name: coverage + version: 7.14.0 + sha256: ba3b8390db29296dbbf49e91b6fe08f990743a90c8f447ba4c2ffc29670dfa63 requires_dist: - - idna>=2.0 - - multidict>=4.0 - - propcache>=0.2.1 + - tomli ; python_full_version <= '3.11' and extra == 'toml' requires_python: '>=3.10' +- 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/f5/57/2a154a69d6642860300bf8eb205d13131104991f2b1065bbb9075ac5c32e/tof-26.3.0-py3-none-any.whl + name: tof + version: 26.3.0 + sha256: e89783a072b05fdb53d9e76fbf919dc8935e75e118fdaf17ca5cc33727ef002b + requires_dist: + - plopp>=23.10.0 + - pooch>=1.5.0 + - scipp>=25.1.0 + - lazy-loader>=0.3 + - pytest>=8.0 ; extra == 'test' + - scippneutron>=24.12.0 ; extra == 'test' + requires_python: '>=3.11' - pypi: https://files.pythonhosted.org/packages/f5/be/25216a49daeeb7af2bec0db22d5e7df08ed1d7c9f65d78b14f3b74fd72fc/yarl-1.23.0-cp312-cp312-win_amd64.whl name: yarl version: 1.23.0 @@ -13051,91 +12988,148 @@ packages: - multidict>=4.0 - propcache>=0.2.1 requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda - sha256: 325d370b28e2b9cc1f765c5b4cdb394c91a5d958fbd15da1a14607a28fee09f6 - md5: 755b096086851e1193f3b10347415d7c - depends: - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - - libstdcxx >=14 - - krb5 >=1.22.2,<1.23.0a0 - - libsodium >=1.0.21,<1.0.22.0a0 - license: MPL-2.0 - license_family: MOZILLA - purls: [] - size: 311150 - timestamp: 1772476812121 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda - sha256: 2705360c72d4db8de34291493379ffd13b09fd594d0af20c9eefa8a3f060d868 - md5: e85dcd3bde2b10081cdcaeae15797506 - depends: - - __osx >=11.0 - - libcxx >=19 - - krb5 >=1.22.2,<1.23.0a0 - - libsodium >=1.0.21,<1.0.22.0a0 - license: MPL-2.0 - license_family: MOZILLA - purls: [] - size: 245246 - timestamp: 1772476886668 -- conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda - sha256: b8568dfde46edf3455458912ea6ffb760e4456db8230a0cf34ecbc557d3c275f - md5: 1ab0237036bfb14e923d6107473b0021 - depends: - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - libsodium >=1.0.21,<1.0.22.0a0 - - krb5 >=1.22.2,<1.23.0a0 - license: MPL-2.0 - license_family: MOZILLA - purls: [] - size: 265665 - timestamp: 1772476832995 -- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - sha256: 523616c0530d305d2216c2b4a8dfd3872628b60083255b89c5e0d8c42e738cca - md5: e1c36c6121a7c9c76f2f148f1e83b983 - depends: - - python >=3.10 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/zipp?source=hash-mapping - size: 24461 - timestamp: 1776131454755 -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 - md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 - depends: - - __glibc >=2.17,<3.0.a0 - - libzlib >=1.3.1,<2.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 601375 - timestamp: 1764777111296 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 - md5: ab136e4c34e97f34fb621d2592a393d8 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 433413 - timestamp: 1764777166076 -- conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - sha256: 368d8628424966fd8f9c8018326a9c779e06913dd39e646cf331226acc90e5b2 - md5: 053b84beec00b71ea8ff7a4f84b55207 - depends: - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - libzlib >=1.3.1,<2.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 388453 - timestamp: 1764777142545 +- pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + name: py + version: 1.11.0 + sha256: 607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' +- pypi: https://files.pythonhosted.org/packages/f7/00/bbca25f8a2372465cdf93138c1e1e38dff045fb0afef1488f395d0afcb3b/ncrystal-4.4.2-py3-none-any.whl + name: ncrystal + version: 4.4.2 + sha256: e02fa7d743addc3fbea23287737a88b8d01192450fdca51554d3f9032fe4617c + requires_dist: + - ncrystal-core==4.4.2 + - ncrystal-python==4.4.2 + - spglib>=2.1.0 ; extra == 'composer' + - ase>=3.23.0 ; extra == 'cif' + - gemmi>=0.6.1 ; extra == 'cif' + - spglib>=2.1.0 ; extra == 'cif' + - endf-parserpy>=0.14.3 ; extra == 'endf' + - matplotlib>=3.6.0 ; extra == 'plot' + - ase>=3.23.0 ; extra == 'all' + - endf-parserpy>=0.14.3 ; extra == 'all' + - gemmi>=0.6.1 ; extra == 'all' + - matplotlib>=3.6.0 ; extra == 'all' + - spglib>=2.1.0 ; extra == 'all' + - pyyaml>=6.0.0 ; extra == 'devel' + - ase>=3.23.0 ; extra == 'devel' + - cppcheck ; extra == 'devel' + - endf-parserpy>=0.14.3 ; extra == 'devel' + - gemmi>=0.6.1 ; extra == 'devel' + - matplotlib>=3.6.0 ; extra == 'devel' + - mpmath>=1.3.0 ; extra == 'devel' + - numpy>=1.22 ; extra == 'devel' + - pybind11>=2.11.0 ; extra == 'devel' + - ruff>=0.8.1 ; extra == 'devel' + - simple-build-system>=1.6.0 ; extra == 'devel' + - spglib>=2.1.0 ; extra == 'devel' + - tomli>=2.0.0 ; python_full_version < '3.11' and extra == 'devel' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + name: pymdown-extensions + version: 10.21.2 + sha256: 5c0fd2a2bea14eb39af8ff284f1066d898ab2187d81b889b75d46d4348c01638 + requires_dist: + - markdown>=3.6 + - pyyaml + - pygments>=2.19.1 ; extra == 'extra' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + name: ghp-import + version: 2.1.0 + sha256: 8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 + requires_dist: + - python-dateutil>=2.8.1 + - twine ; extra == 'dev' + - markdown ; extra == 'dev' + - flake8 ; extra == 'dev' + - wheel ; extra == 'dev' +- pypi: https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl + name: coverage + version: 7.14.0 + sha256: 45e0f79d8351fa76e256716df91eab12890d32678b9590df7ae1042e4bd4cf5d + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl + name: numpy + version: 2.4.4 + sha256: 715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + name: dunamai + version: 1.26.1 + sha256: 2727d939c5b4257cb01ea404372803b477f5176e5a347c43beaf89cd5072e853 + requires_dist: + - importlib-metadata>=1.6.0 ; python_full_version < '3.8' + - packaging>=20.9 + requires_python: '>=3.5' +- 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/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + name: aiosignal + version: 1.4.0 + sha256: 053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e + requires_dist: + - frozenlist>=1.1.0 + - typing-extensions>=4.2 ; python_full_version < '3.13' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl + name: pydantic-core + version: 2.46.4 + sha256: 811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl + name: pydantic + version: 2.13.4 + sha256: 45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba + requires_dist: + - annotated-types>=0.6.0 + - pydantic-core==2.46.4 + - typing-extensions>=4.14.1 + - typing-inspection>=0.4.2 + - email-validator>=2.0.0 ; extra == 'email' + - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl + name: contourpy + version: 1.3.3 + sha256: cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77 + requires_dist: + - numpy>=1.25 + - furo ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - bokeh ; extra == 'bokeh' + - selenium ; extra == 'bokeh' + - contourpy[bokeh,docs] ; extra == 'mypy' + - bokeh ; extra == 'mypy' + - docutils-stubs ; extra == 'mypy' + - mypy==1.17.0 ; extra == 'mypy' + - types-pillow ; extra == 'mypy' + - contourpy[test-no-images] ; extra == 'test' + - matplotlib ; extra == 'test' + - pillow ; extra == 'test' + - pytest ; extra == 'test-no-images' + - pytest-cov ; extra == 'test-no-images' + - pytest-rerunfailures ; extra == 'test-no-images' + - pytest-xdist ; extra == 'test-no-images' + - wurlitzer ; extra == 'test-no-images' + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: multidict + version: 6.7.1 + sha256: 7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709 + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ff/1c/a28b27effb13a381fe077ea3e3e78f6debd6315f2b3edff67bbb93d0ef51/gemmi-0.7.5-cp314-cp314-win_amd64.whl + name: gemmi + version: 0.7.5 + sha256: 419c36d9ea0f28dda0ff0d6db17035170d0888ca78aff82a0f9f604613aec58f + requires_python: '>=3.9' From e2c913b07236a9bfd44ada25799442f37a4f7217 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 08:31:29 +0200 Subject: [PATCH 087/106] Add correlation-based limits to posterior pair plots --- src/easydiffraction/display/plotting.py | 141 +++++++++++++++++++++--- 1 file changed, 125 insertions(+), 16 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 7e351abb..fc09f82e 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -77,7 +77,7 @@ class PosteriorPairPlotStyleEnum(StrEnum): DEFAULT_CORRELATION_THRESHOLD: float | None = None -DEFAULT_CORRELATION_MAX_PARAMETERS = 5 +DEFAULT_CORRELATION_MAX_PARAMETERS = 6 EXPECTED_COVAR_NDIM = 2 DEFAULT_RESIDUAL_HEIGHT_FRACTION = 0.25 DEFAULT_BRAGG_PEAKS_HEIGHT_FRACTION = 0.10 @@ -210,6 +210,7 @@ class _PosteriorPairsContext: parameter_names: list[str] labels: list[str] annotation_labels: list[str] + title: str density_samples: np.ndarray scatter_samples: np.ndarray show_contours: bool @@ -726,6 +727,7 @@ def plot_param_correlations( threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, precision: int = 2, *, + max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, show_diagonal: bool = True, ) -> None: """ @@ -744,11 +746,14 @@ def plot_param_correlations( threshold : float | None, default=DEFAULT_CORRELATION_THRESHOLD Minimum absolute off-diagonal correlation required for a parameter to be shown. When omitted, an automatic cutoff is - chosen so the displayed matrix stays at or below ``5 x 5`` - parameters when possible. Set to ``0`` to show the full - matrix. + chosen so the displayed matrix stays at or below + ``max_parameters x max_parameters`` when possible. Set to + ``0`` to show the full matrix. precision : int, default=2 Number of decimal places to show in the table fallback. + max_parameters : int, default=DEFAULT_CORRELATION_MAX_PARAMETERS + Maximum number of parameters to display when ``threshold`` + is omitted. Ignored when ``threshold`` is provided. show_diagonal : bool, default=True Whether to retain blank diagonal cells in the displayed lower-triangle matrix. @@ -760,14 +765,16 @@ def plot_param_correlations( corr_df, resolved_threshold = self._resolve_correlation_filter( corr_df, threshold=threshold, + max_parameters=max_parameters, ) if corr_df is None: return corr_df = self._mask_correlation_lower_triangle(corr_df) - title = 'Refined parameter correlation matrix' - if resolved_threshold > 0: - title += f' with |correlation| >= {resolved_threshold:.2f}' + title = self._correlation_filtered_title( + 'Refined parameter correlation matrix', + resolved_threshold, + ) is_graphical = self._backend._supports_graphical_heatmap display_corr_df, row_numbers, col_numbers = self._trim_correlation_display_dataframe( @@ -802,21 +809,44 @@ def _resolve_correlation_filter( corr_df: pd.DataFrame, *, threshold: float | None, + max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, + min_parameters: int = 1, ) -> tuple[pd.DataFrame | None, float]: """Return a filtered matrix and effective threshold.""" if threshold is not None: filtered_corr_df = cls._filter_correlation_dataframe(corr_df, threshold=threshold) return filtered_corr_df, float(threshold) + validated_max_parameters = cls._validated_max_parameter_count( + max_parameters, + minimum=min_parameters, + ) return cls._auto_filtered_correlation_dataframe( corr_df, - max_parameters=DEFAULT_CORRELATION_MAX_PARAMETERS, + max_parameters=validated_max_parameters, + min_parameters=min_parameters, ) + @staticmethod + def _validated_max_parameter_count( + max_parameters: int, + *, + minimum: int, + ) -> int: + """Return a validated parameter-count limit.""" + if not isinstance(max_parameters, int) or isinstance(max_parameters, bool): + msg = 'max_parameters must be an integer.' + raise ValueError(msg) + if max_parameters < minimum: + msg = f'max_parameters must be at least {minimum}.' + raise ValueError(msg) + return max_parameters + @staticmethod def _auto_filtered_correlation_dataframe( corr_df: pd.DataFrame, *, max_parameters: int, + min_parameters: int = 1, ) -> tuple[pd.DataFrame, float]: """Return an auto-limited matrix for default display.""" if corr_df.shape[0] <= max_parameters: @@ -827,7 +857,7 @@ def _auto_filtered_correlation_dataframe( positive_values = np.unique(abs_corr[abs_corr > 0.0]) for candidate in np.sort(positive_values): keep_mask = (abs_corr >= candidate).any(axis=0) - if 0 < int(keep_mask.sum()) <= max_parameters: + if min_parameters <= int(keep_mask.sum()) <= max_parameters: labels = corr_df.index[keep_mask] return corr_df.loc[labels, labels], float(candidate) @@ -840,10 +870,20 @@ def _auto_filtered_correlation_dataframe( labels = corr_df.index[top_indices] return corr_df.loc[labels, labels], 0.0 + @staticmethod + def _correlation_filtered_title(base_title: str, threshold: float) -> str: + """Return a plot title with a correlation cutoff.""" + if threshold <= 0: + return base_title + return f'{base_title} with |correlation| β‰₯ {threshold:.2f}' + def plot_posterior_pairs( self, parameters: list[object] | None = None, style: PosteriorPairPlotStyleEnum | str = 'auto', + *, + threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, + max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, ) -> None: """ Plot posterior pair relationships for sampled parameters. @@ -852,14 +892,29 @@ def plot_posterior_pairs( ---------- parameters : list[object] | None, default=None Optional subset of sampled parameters to include. When - ``None``, all sampled parameters are shown. + provided, ``threshold`` and ``max_parameters`` are ignored. style : PosteriorPairPlotStyleEnum | str, default='auto' Pair-plot rendering mode. Defaults to ``'auto'``. ``'auto'`` keeps contours for compact plots and disables them for wide grids. ``'fast'`` always skips contours. ``'full'`` always renders contours. + threshold : float | None, default=DEFAULT_CORRELATION_THRESHOLD + Minimum absolute off-diagonal correlation required for a + parameter to be auto-selected. When omitted, an automatic + cutoff keeps the plot at or below ``max_parameters`` + parameters when possible. Set to ``0`` to show all sampled + parameters. + max_parameters : int, default=DEFAULT_CORRELATION_MAX_PARAMETERS + Maximum number of parameters to auto-select when + ``parameters`` is omitted and ``threshold`` is ``None``. + Must be at least ``2``. """ - plot = self._build_posterior_pairs_plot(parameters=parameters, style=style) + plot = self._build_posterior_pairs_plot( + parameters=parameters, + style=style, + threshold=threshold, + max_parameters=max_parameters, + ) if plot is None: return self._show_plot_figure(plot) @@ -1233,6 +1288,8 @@ def _build_posterior_pairs_plot( *, parameters: list[object] | None, style: PosteriorPairPlotStyleEnum | str = 'auto', + threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, + max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, ) -> object | None: """ Build a Plotly posterior pair plot. @@ -1243,6 +1300,10 @@ def _build_posterior_pairs_plot( Optional subset of sampled parameters to include. style : PosteriorPairPlotStyleEnum | str, default='auto' Posterior pair-plot rendering mode. Defaults to ``'auto'``. + threshold : float | None, default=DEFAULT_CORRELATION_THRESHOLD + Absolute-correlation cutoff for auto-selected parameters. + max_parameters : int, default=DEFAULT_CORRELATION_MAX_PARAMETERS + Maximum number of auto-selected parameters. Returns ------- @@ -1250,7 +1311,12 @@ def _build_posterior_pairs_plot( Plotly figure, or ``None`` when posterior plotting is unavailable. """ - context = self._posterior_pairs_context(parameters, style=style) + context = self._posterior_pairs_context( + parameters, + style=style, + threshold=threshold, + max_parameters=max_parameters, + ) if context is None: return None @@ -1291,6 +1357,8 @@ def _posterior_pairs_context( parameters: list[object] | None, *, style: PosteriorPairPlotStyleEnum | str = 'auto', + threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, + max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, ) -> _PosteriorPairsContext | None: """Return the resolved inputs for a posterior pair plot.""" posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() @@ -1299,9 +1367,11 @@ def _posterior_pairs_context( plot_style = self._validated_posterior_pair_plot_style(style) - parameter_names = self._resolve_posterior_parameter_names( + parameter_names, resolved_threshold = self._resolved_posterior_pair_parameter_names( fit_results=fit_results, parameters=parameters, + threshold=threshold, + max_parameters=max_parameters, ) if parameter_names is None: return None @@ -1339,6 +1409,7 @@ def _posterior_pairs_context( parameter_names=parameter_names, labels=self._posterior_plot_labels(fit_results, parameter_names), annotation_labels=self._posterior_pair_axis_title_labels(parameter_names), + title=self._correlation_filtered_title('Posterior pair plot', resolved_threshold), density_samples=density_samples, scatter_samples=scatter_samples, show_contours=show_contours, @@ -1351,6 +1422,38 @@ def _posterior_pairs_context( ), ) + def _resolved_posterior_pair_parameter_names( + self, + *, + fit_results: object, + parameters: list[object] | None, + threshold: float | None, + max_parameters: int, + ) -> tuple[list[str] | None, float]: + """Return pair-plot names and the effective cutoff.""" + parameter_names = self._resolve_posterior_parameter_names( + fit_results=fit_results, + parameters=parameters, + ) + if parameter_names is None: + return None, 0.0 + if parameters is not None: + return parameter_names, 0.0 + + corr_df = self._posterior_correlation_dataframe(fit_results) + if corr_df is None: + return parameter_names, 0.0 + + filtered_corr_df, resolved_threshold = self._resolve_correlation_filter( + corr_df.loc[parameter_names, parameter_names], + threshold=threshold, + max_parameters=max_parameters, + min_parameters=MIN_POSTERIOR_PARAMETER_COUNT, + ) + if filtered_corr_df is None: + return None, 0.0 + return list(filtered_corr_df.index), resolved_threshold + def _posterior_pair_axis_ranges( self, *, @@ -1730,10 +1833,13 @@ def _square_matrix_title_annotation( } @staticmethod - def _posterior_pair_title_annotation(annotation_labels: list[str]) -> dict[str, object]: + def _posterior_pair_title_annotation( + title: str, + annotation_labels: list[str], + ) -> dict[str, object]: """Return the outer title annotation for the pair plot.""" return Plotter._square_matrix_title_annotation( - 'Posterior pair plot', + title, annotation_labels, ) @@ -1801,7 +1907,10 @@ def _finalize_posterior_pairs_figure( margin=self._posterior_pair_layout_margin(context.annotation_labels), bargap=0.05, annotations=[ - self._posterior_pair_title_annotation(context.annotation_labels), + self._posterior_pair_title_annotation( + context.title, + context.annotation_labels, + ), *subplot_title_annotations, ], shapes=subplot_border_shapes, From 09da4695af26086f893b4f35c64745a939c48a50 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 09:25:43 +0200 Subject: [PATCH 088/106] Improve posterior summary plot styling --- src/easydiffraction/display/plotting.py | 37 +++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index fc09f82e..dbd360b5 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -2059,6 +2059,13 @@ def _plot_axis_frame_color(self) -> str: return axis_frame_color() return PlotlyPlotter._axis_frame_color() + def _plot_legend_background_color(self) -> str: + """Return the shared legend background for Plotly plots.""" + legend_background_color = getattr(self._backend, '_legend_background_color', None) + if callable(legend_background_color): + return legend_background_color() + return PlotlyPlotter._legend_background_color() + def _posterior_contour_traces( self, *, @@ -3222,6 +3229,7 @@ def _plot_posterior_predictive_summary( ) -> None: """Render posterior predictive summaries using Plotly.""" go = __import__('plotly.graph_objects', fromlist=['Figure', 'Scatter']) + axis_frame_color = self._plot_axis_frame_color() fig = go.Figure() if show_band: @@ -3298,11 +3306,36 @@ def _plot_posterior_predictive_summary( 'text': f"Posterior predictive for experiment πŸ”¬ '{expt_name}'", 'font': {'size': POSTERIOR_PAIR_TITLE_FONT_SIZE}, }, + margin={ + 'autoexpand': True, + 'r': 30, + 't': 40, + 'b': 45, + }, + legend={ + 'bgcolor': self._plot_legend_background_color(), + 'xanchor': 'right', + 'x': 1.0, + 'yanchor': 'top', + 'y': 1.0, + }, xaxis_title=axes_labels[0], yaxis_title=axes_labels[1], ) - fig.update_xaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) - fig.update_yaxes(title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}) + fig.update_xaxes( + title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + showline=True, + linecolor=axis_frame_color, + mirror=True, + zeroline=False, + ) + fig.update_yaxes( + title_font={'size': POSTERIOR_PAIR_AXIS_TITLE_FONT_SIZE}, + showline=True, + linecolor=axis_frame_color, + mirror=True, + zeroline=False, + ) self._show_plot_figure(fig) def _filtered_posterior_predictive_summary( From 1bb174bbc785f23e20f6a9969ffd464079aaf766 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 09:25:57 +0200 Subject: [PATCH 089/106] Add single-crystal posterior predictive scatter plot --- src/easydiffraction/display/plotting.py | 166 +++++++++++++++++- .../easydiffraction/display/test_plotting.py | 15 ++ 2 files changed, 174 insertions(+), 7 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index dbd360b5..836b6130 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -835,7 +835,7 @@ def _validated_max_parameter_count( """Return a validated parameter-count limit.""" if not isinstance(max_parameters, int) or isinstance(max_parameters, bool): msg = 'max_parameters must be an integer.' - raise ValueError(msg) + raise TypeError(msg) if max_parameters < minimum: msg = f'max_parameters must be at least {minimum}.' raise ValueError(msg) @@ -949,7 +949,7 @@ def plot_posterior_predictive( x: object | None = None, ) -> None: """ - Plot posterior predictive curves for a powder experiment. + Plot posterior predictive checks for supported experiments. Parameters ---------- @@ -958,13 +958,15 @@ def plot_posterior_predictive( style : str, default='band' ``'band'`` shows the 95% credible interval, ``'draws'`` shows sampled predictive curves, and ``'band+draws'`` shows - both together. + both together. Single-crystal plots currently render only + the interval-based reflection check. x_min : float | None, default=None Lower bound for the x-axis range. x_max : float | None, default=None Upper bound for the x-axis range. show_residual : bool | None, default=None - Whether to include the residual row in the composite plot. + Whether to include the residual row in supported powder + composite plots. x : object | None, default=None Optional explicit x-axis data to override stored values. @@ -989,9 +991,6 @@ def plot_posterior_predictive( self._update_project_categories(expt_name) experiment = self._project.experiments[expt_name] x_axis, _, sample_form, scattering_type, _ = self._resolve_x_axis(experiment.type, x) - if sample_form != SampleFormEnum.POWDER: - log.warning('Posterior predictive plots currently support powder experiments only.') - return plot_options = _MeasVsCalcPlotOptions( x_min=x_min, @@ -1000,6 +999,21 @@ def plot_posterior_predictive( x=x, ) + if sample_form == SampleFormEnum.SINGLE_CRYSTAL: + self._plot_single_crystal_posterior_predictive( + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + scattering_type=scattering_type, + plot_options=plot_options, + style=style, + ) + return + + if sample_form != SampleFormEnum.POWDER: + log.warning('Posterior predictive plots currently support powder experiments only.') + return + if scattering_type == ScatteringTypeEnum.BRAGG: self._plot_posterior_predictive_data( experiment=experiment, @@ -1020,6 +1034,87 @@ def plot_posterior_predictive( style=style, ) + def _plot_single_crystal_posterior_predictive( + self, + *, + experiment: object, + expt_name: str, + x_axis: object, + scattering_type: object, + plot_options: _MeasVsCalcPlotOptions, + style: str, + ) -> None: + """Render a single-crystal posterior predictive scatter plot.""" + if scattering_type != ScatteringTypeEnum.BRAGG: + log.warning( + 'Single-crystal posterior predictive plots currently support ' + 'Bragg data only.' + ) + return + if x_axis not in {XAxisType.INTENSITY_CALC, 'intensity_calc'}: + log.warning( + 'Single-crystal posterior predictive plots currently support ' + "x='intensity_calc' only." + ) + return + if plot_options.show_residual: + log.warning( + 'Posterior predictive residuals are unavailable for ' + 'single-crystal plots; ignoring show_residual=True.' + ) + if style != 'band': + log.warning( + 'Single-crystal posterior predictive plots currently support ' + 'style="band" only; rendering the 95% interval.' + ) + + summary = self._get_or_build_posterior_predictive_summary( + experiment=experiment, + expt_name=expt_name, + x_axis=x_axis, + include_draws=False, + ) + if summary is None: + return + + pattern = intensity_category_for(experiment) + y_meas_raw = getattr(pattern, 'intensity_meas', None) + if y_meas_raw is None: + log.warning(f'No measured data available for experiment {expt_name}.') + return + y_meas = np.asarray(y_meas_raw, dtype=float) + if y_meas.shape != np.asarray(summary.map_prediction).shape: + log.warning( + 'Single-crystal posterior predictive values do not match the ' + 'measured reflection array shape.' + ) + return + + y_meas_su_raw = getattr(pattern, 'intensity_meas_su', None) + if y_meas_su_raw is None: + log.warning(f'No measurement uncertainties for experiment {expt_name}') + y_meas_su = np.zeros_like(y_meas) + else: + y_meas_su = np.asarray(y_meas_su_raw, dtype=float) + if y_meas_su.shape != y_meas.shape: + log.warning( + 'Single-crystal posterior predictive uncertainties do not ' + 'match the measured reflection array shape.' + ) + return + + self._plot_single_crystal_posterior_predictive_summary( + expt_name=expt_name, + summary=summary, + y_meas=y_meas, + y_meas_su=y_meas_su, + axes_labels=self._get_axes_labels( + SampleFormEnum.SINGLE_CRYSTAL, + ScatteringTypeEnum.BRAGG, + XAxisType.INTENSITY_CALC, + ), + ) + def _plot_non_bragg_posterior_predictive( self, *, @@ -3338,6 +3433,63 @@ def _plot_posterior_predictive_summary( ) self._show_plot_figure(fig) + def _plot_single_crystal_posterior_predictive_summary( + self, + *, + expt_name: str, + summary: PosteriorPredictiveSummary, + y_meas: np.ndarray, + y_meas_su: np.ndarray, + axes_labels: list[str], + ) -> None: + """Render single-crystal posterior predictive checks.""" + if summary.lower_95 is None or summary.upper_95 is None: + log.warning( + 'Single-crystal posterior predictive plots require 95% ' + 'predictive intervals.' + ) + return + + map_prediction = np.asarray(summary.map_prediction, dtype=float) + lower_95 = np.asarray(summary.lower_95, dtype=float) + upper_95 = np.asarray(summary.upper_95, dtype=float) + if lower_95.shape != map_prediction.shape or upper_95.shape != map_prediction.shape: + log.warning( + 'Single-crystal posterior predictive interval arrays have ' + 'invalid shapes.' + ) + return + + go = __import__('plotly.graph_objects', fromlist=['Figure']) + trace = PlotlyPlotter._get_single_crystal_trace( + x_calc=map_prediction, + y_meas=y_meas, + y_meas_su=y_meas_su, + ) + trace.error_x = { + 'type': 'data', + 'array': np.maximum(0.0, upper_95 - map_prediction), + 'arrayminus': np.maximum(0.0, map_prediction - lower_95), + 'visible': True, + } + trace.customdata = np.column_stack((lower_95, upper_95, y_meas_su)) + trace.hovertemplate = ( + 'Predicted IΒ²: %{x:,.2f}
' + '95% interval: [%{customdata[0]:,.2f}, %{customdata[1]:,.2f}]
' + 'Measured IΒ²: %{y:,.2f}
' + 'su(IΒ²meas): %{customdata[2]:,.2f}' + ) + + fig = go.Figure( + data=[trace], + layout=PlotlyPlotter._get_layout( + f"Posterior predictive reflection check for experiment πŸ”¬ '{expt_name}'", + axes_labels, + shapes=[PlotlyPlotter._get_diagonal_shape()], + ), + ) + self._show_plot_figure(fig) + def _filtered_posterior_predictive_summary( self, *, diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 889e805a..16786b19 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -615,6 +615,7 @@ def test_plot_posterior_predictive_summary_uses_consistent_labels_and_styles(mon from easydiffraction.display.plotting import POSTERIOR_INTERVAL_95_FILL_COLOR from easydiffraction.display.plotting import POSTERIOR_POINT_ESTIMATE_LINE_DASH from easydiffraction.display.plotting import Plotter + from easydiffraction.display.plotters.plotly import PlotlyPlotter captured: dict[str, object] = {} @@ -648,6 +649,20 @@ def test_plot_posterior_predictive_summary_uses_consistent_labels_and_styles(mon assert measured_trace.legendrank == 10 assert max_posterior_trace.legendrank == 20 assert max_posterior_trace.line.dash == POSTERIOR_POINT_ESTIMATE_LINE_DASH + assert fig.layout.legend.x == 1.0 + assert fig.layout.legend.y == 1.0 + assert fig.layout.legend.bgcolor == PlotlyPlotter._legend_background_color() + assert fig.layout.margin.r == 30 + assert fig.layout.margin.t == 40 + assert fig.layout.margin.b == 45 + assert fig.layout.xaxis.showline is True + assert fig.layout.xaxis.mirror is True + assert fig.layout.xaxis.zeroline is False + assert fig.layout.xaxis.linecolor == PlotlyPlotter._axis_frame_color() + assert fig.layout.yaxis.showline is True + assert fig.layout.yaxis.mirror is True + assert fig.layout.yaxis.zeroline is False + assert fig.layout.yaxis.linecolor == PlotlyPlotter._axis_frame_color() @pytest.mark.parametrize( From 72a99ec9c3e0214e293d13f2d928dde78d0dc05c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 09:36:58 +0200 Subject: [PATCH 090/106] Add Tb2TiO7 Bayesian tutorial --- docs/docs/tutorials/ed-22.ipynb | 427 ++++++++++++++++++++++++ docs/docs/tutorials/ed-22.py | 144 ++++++++ docs/docs/tutorials/index.md | 7 + docs/mkdocs.yml | 1 + src/easydiffraction/display/plotting.py | 11 +- 5 files changed, 582 insertions(+), 8 deletions(-) create mode 100644 docs/docs/tutorials/ed-22.ipynb create mode 100644 docs/docs/tutorials/ed-22.py diff --git a/docs/docs/tutorials/ed-22.ipynb b/docs/docs/tutorials/ed-22.ipynb new file mode 100644 index 00000000..64561a9c --- /dev/null +++ b/docs/docs/tutorials/ed-22.ipynb @@ -0,0 +1,427 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": { + "tags": [ + "hide-in-docs" + ] + }, + "outputs": [], + "source": [ + "# Check whether easydiffraction is installed; install it if needed.\n", + "# Required for remote environments such as Google Colab.\n", + "import importlib.util\n", + "\n", + "if importlib.util.find_spec('easydiffraction') is None:\n", + " %pip install easydiffraction" + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "# Deterministic and Bayesian Refinement: Tb2TiO7, HEiDi\n", + "\n", + "This tutorial demonstrates a practical two-stage workflow for single-crystal\n", + "diffraction analysis with EasyDiffraction.\n", + "\n", + "In the first stage, we run a fast local refinement to obtain a sensible\n", + "point estimate and parameter uncertainties. In the second stage, we use\n", + "these refined values to define fit bounds and then sample the posterior\n", + "distribution with BUMPS-DREAM.\n", + "\n", + "The example uses constant-wavelength neutron single-crystal diffraction data\n", + "for Tb2TiO7 measured on HEiDi at FRM II." + ] + }, + { + "cell_type": "markdown", + "id": "2", + "metadata": {}, + "source": [ + "## Import Library" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "import easydiffraction as ed" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": {}, + "source": [ + "## Step 1: Create a Project Container" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "project = ed.Project()" + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": {}, + "source": [ + "## Step 2: Build the Structural Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "structure_path = ed.download_data(id=20, destination='data')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "project.structures.add_from_cif_path(structure_path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "structure = project.structures['tbti']" + ] + }, + { + "cell_type": "markdown", + "id": "10", + "metadata": {}, + "source": [ + "## Step 3: Define the Diffraction Experiment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = ed.download_data(id=19, destination='data')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "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": "13", + "metadata": {}, + "outputs": [], + "source": [ + "experiment = project.experiments['heidi']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.linked_crystal.id = 'tbti'\n", + "experiment.linked_crystal.scale = 1.0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.instrument.setup_wavelength = 0.793" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16", + "metadata": {}, + "outputs": [], + "source": [ + "experiment.extinction.mosaicity = 35000\n", + "experiment.extinction.radius = 10" + ] + }, + { + "cell_type": "markdown", + "id": "17", + "metadata": {}, + "source": [ + "## Step 4: Run an Initial Local Refinement" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18", + "metadata": {}, + "outputs": [], + "source": [ + "structure.atom_sites['O1'].fract_x.free = True\n", + "\n", + "structure.atom_sites['Ti'].occupancy.free = False\n", + "structure.atom_sites['O1'].occupancy.free = False\n", + "structure.atom_sites['O2'].occupancy.free = False\n", + "\n", + "structure.atom_sites['Tb'].adp_iso.free = True\n", + "structure.atom_sites['Ti'].adp_iso.free = True\n", + "structure.atom_sites['O1'].adp_iso.free = True\n", + "structure.atom_sites['O2'].adp_iso.free = True" + ] + }, + { + "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": [ + "project.analysis.fit.show_minimizer_types()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.display.fit_results()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_param_correlations()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_meas_vs_calc(expt_name='heidi')" + ] + }, + { + "cell_type": "markdown", + "id": "25", + "metadata": {}, + "source": [ + "## Step 5: Prepare for Bayesian Sampling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.display.free_params()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27", + "metadata": {}, + "outputs": [], + "source": [ + "for param in project.free_parameters:\n", + " param.set_fit_bounds_from_uncertainty(multiplier=1.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.display.free_params()" + ] + }, + { + "cell_type": "markdown", + "id": "29", + "metadata": {}, + "source": [ + "## Step 6: Configure and Run BUMPS-DREAM" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.fit.show_minimizer_types()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.fit.minimizer_type = 'bumps (dream)'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.fit.minimizer.steps = 500" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "33", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34", + "metadata": {}, + "outputs": [], + "source": [ + "project.analysis.display.fit_results()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_param_correlations()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_posterior_pairs()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37", + "metadata": {}, + "outputs": [], + "source": [ + "for param in project.free_parameters:\n", + " project.display.plotter.plot_param_distribution(param)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38", + "metadata": {}, + "outputs": [], + "source": [ + "project.display.plotter.plot_posterior_predictive(expt_name='heidi')" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "main_language": "python", + "notebook_metadata_filter": "-all" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/docs/tutorials/ed-22.py b/docs/docs/tutorials/ed-22.py new file mode 100644 index 00000000..22cd3f49 --- /dev/null +++ b/docs/docs/tutorials/ed-22.py @@ -0,0 +1,144 @@ +# %% [markdown] +# # Deterministic and Bayesian Refinement: Tb2TiO7, HEiDi +# +# This tutorial demonstrates a practical two-stage workflow for single-crystal +# diffraction analysis with EasyDiffraction. +# +# In the first stage, we run a fast local refinement to obtain a sensible +# point estimate and parameter uncertainties. In the second stage, we use +# these refined values to define fit bounds and then sample the posterior +# distribution with BUMPS-DREAM. +# +# The example uses constant-wavelength neutron single-crystal diffraction data +# for Tb2TiO7 measured on HEiDi at FRM II. + +# %% [markdown] +# ## Import Library + +# %% +import easydiffraction as ed + +# %% [markdown] +# ## Step 1: Create a Project Container + +# %% +project = ed.Project() + +# %% [markdown] +# ## Step 2: Build the Structural Model + +# %% +structure_path = ed.download_data(id=20, destination='data') + +# %% +project.structures.add_from_cif_path(structure_path) + +# %% +structure = project.structures['tbti'] + +# %% [markdown] +# ## Step 3: Define the Diffraction Experiment + +# %% +data_path = ed.download_data(id=19, destination='data') + +# %% +project.experiments.add_from_data_path( + name='heidi', + data_path=data_path, + sample_form='single crystal', + beam_mode='constant wavelength', + radiation_probe='neutron', +) + +# %% +experiment = project.experiments['heidi'] + +# %% +experiment.linked_crystal.id = 'tbti' +experiment.linked_crystal.scale = 1.0 + +# %% +experiment.instrument.setup_wavelength = 0.793 + +# %% +experiment.extinction.mosaicity = 35000 +experiment.extinction.radius = 10 + +# %% [markdown] +# ## Step 4: Run an Initial Local Refinement + +# %% +structure.atom_sites['O1'].fract_x.free = True + +structure.atom_sites['Ti'].occupancy.free = False +structure.atom_sites['O1'].occupancy.free = False +structure.atom_sites['O2'].occupancy.free = False + +structure.atom_sites['Tb'].adp_iso.free = True +structure.atom_sites['Ti'].adp_iso.free = True +structure.atom_sites['O1'].adp_iso.free = True +structure.atom_sites['O2'].adp_iso.free = True + +# %% +experiment.linked_crystal.scale.free = True +experiment.extinction.radius.free = True + +# %% +project.analysis.fit.show_minimizer_types() + +# %% +project.analysis.fit() + +# %% +project.analysis.display.fit_results() + +# %% +project.display.plotter.plot_param_correlations() + +# %% +project.display.plotter.plot_meas_vs_calc(expt_name='heidi') + +# %% [markdown] +# ## Step 5: Prepare for Bayesian Sampling + +# %% +project.analysis.display.free_params() + +# %% +for param in project.free_parameters: + param.set_fit_bounds_from_uncertainty(multiplier=1.5) + +# %% +project.analysis.display.free_params() + +# %% [markdown] +# ## Step 6: Configure and Run BUMPS-DREAM + +# %% +project.analysis.fit.show_minimizer_types() + +# %% +project.analysis.fit.minimizer_type = 'bumps (dream)' + +# %% +project.analysis.fit.minimizer.steps = 500 + +# %% +project.analysis.fit() + +# %% +project.analysis.display.fit_results() + +# %% +project.display.plotter.plot_param_correlations() + +# %% +project.display.plotter.plot_posterior_pairs() + +# %% +for param in project.free_parameters: + project.display.plotter.plot_param_distribution(param) + +# %% +project.display.plotter.plot_posterior_predictive(expt_name='heidi') diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md index 18c2e143..1f4c82f0 100644 --- a/docs/docs/tutorials/index.md +++ b/docs/docs/tutorials/index.md @@ -106,6 +106,13 @@ The tutorials are organized into the following categories: tutorial covers the use of Markov Chain Monte Carlo (MCMC) sampling to explore the posterior distribution of the refined parameters, providing insights into parameter uncertainties and correlations. +- [Tb2TiO7 Bayesian](ed-22.ipynb) – Demonstrates how to perform a + Bayesian analysis of the Tb2TiO7 crystal structure using constant + wavelength neutron single crystal diffraction data from HEiDi at FRM + II. This tutorial covers the use of Markov Chain Monte Carlo (MCMC) + sampling to explore the posterior distribution of the refined + parameters, providing insights into parameter uncertainties and + correlations. ## Workshops & Schools diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 42294197..50eb7449 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -218,6 +218,7 @@ nav: - BEER McStas: tutorials/ed-20.ipynb - Bayesian Analysis: - LBCO Bayesian: tutorials/ed-21.ipynb + - Co2SiO4 Bayesian: tutorials/ed-22.ipynb - Workshops & Schools: - DMSC Summer School: tutorials/ed-13.ipynb - API Reference: diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 836b6130..3082897a 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -1047,8 +1047,7 @@ def _plot_single_crystal_posterior_predictive( """Render a single-crystal posterior predictive scatter plot.""" if scattering_type != ScatteringTypeEnum.BRAGG: log.warning( - 'Single-crystal posterior predictive plots currently support ' - 'Bragg data only.' + 'Single-crystal posterior predictive plots currently support Bragg data only.' ) return if x_axis not in {XAxisType.INTENSITY_CALC, 'intensity_calc'}: @@ -3445,8 +3444,7 @@ def _plot_single_crystal_posterior_predictive_summary( """Render single-crystal posterior predictive checks.""" if summary.lower_95 is None or summary.upper_95 is None: log.warning( - 'Single-crystal posterior predictive plots require 95% ' - 'predictive intervals.' + 'Single-crystal posterior predictive plots require 95% predictive intervals.' ) return @@ -3454,10 +3452,7 @@ def _plot_single_crystal_posterior_predictive_summary( lower_95 = np.asarray(summary.lower_95, dtype=float) upper_95 = np.asarray(summary.upper_95, dtype=float) if lower_95.shape != map_prediction.shape or upper_95.shape != map_prediction.shape: - log.warning( - 'Single-crystal posterior predictive interval arrays have ' - 'invalid shapes.' - ) + log.warning('Single-crystal posterior predictive interval arrays have invalid shapes.') return go = __import__('plotly.graph_objects', fromlist=['Figure']) From 6b6f6220fa29c8f76da83ff0795e8dca87f0c424 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 09:49:50 +0200 Subject: [PATCH 091/106] Set default correlation and pair-plot limit to six --- src/easydiffraction/display/plotting.py | 15 +++-- .../easydiffraction/display/test_plotting.py | 66 +++++++++++-------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 3082897a..1206a0a3 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -809,13 +809,15 @@ def _resolve_correlation_filter( corr_df: pd.DataFrame, *, threshold: float | None, - max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, + max_parameters: int | None = DEFAULT_CORRELATION_MAX_PARAMETERS, min_parameters: int = 1, ) -> tuple[pd.DataFrame | None, float]: """Return a filtered matrix and effective threshold.""" if threshold is not None: filtered_corr_df = cls._filter_correlation_dataframe(corr_df, threshold=threshold) return filtered_corr_df, float(threshold) + if max_parameters is None: + return corr_df, 0.0 validated_max_parameters = cls._validated_max_parameter_count( max_parameters, minimum=min_parameters, @@ -1383,7 +1385,7 @@ def _build_posterior_pairs_plot( parameters: list[object] | None, style: PosteriorPairPlotStyleEnum | str = 'auto', threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, - max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, + max_parameters: int | None = None, ) -> object | None: """ Build a Plotly posterior pair plot. @@ -1396,8 +1398,9 @@ def _build_posterior_pairs_plot( Posterior pair-plot rendering mode. Defaults to ``'auto'``. threshold : float | None, default=DEFAULT_CORRELATION_THRESHOLD Absolute-correlation cutoff for auto-selected parameters. - max_parameters : int, default=DEFAULT_CORRELATION_MAX_PARAMETERS - Maximum number of auto-selected parameters. + max_parameters : int | None, default=None + Maximum number of auto-selected parameters. ``None`` keeps + the full posterior parameter set. Returns ------- @@ -1452,7 +1455,7 @@ def _posterior_pairs_context( *, style: PosteriorPairPlotStyleEnum | str = 'auto', threshold: float | None = DEFAULT_CORRELATION_THRESHOLD, - max_parameters: int = DEFAULT_CORRELATION_MAX_PARAMETERS, + max_parameters: int | None = None, ) -> _PosteriorPairsContext | None: """Return the resolved inputs for a posterior pair plot.""" posterior_samples, fit_results = self._get_posterior_samples_and_fit_results() @@ -1522,7 +1525,7 @@ def _resolved_posterior_pair_parameter_names( fit_results: object, parameters: list[object] | None, threshold: float | None, - max_parameters: int, + max_parameters: int | None, ) -> tuple[list[str] | None, float]: """Return pair-plot names and the effective cutoff.""" parameter_names = self._resolve_posterior_parameter_names( diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 16786b19..3b434c8d 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -1714,7 +1714,7 @@ class Project: assert len(fig.layout.shapes) == 15 -def test_plot_param_correlations_limits_default_table_to_five_parameters(monkeypatch): +def test_plot_param_correlations_limits_default_table_to_six_parameters(monkeypatch): from easydiffraction.display.plotting import Plotter from easydiffraction.display.tables import TableRenderer @@ -1778,38 +1778,50 @@ class Project: '3', '4', '5', + '6', + ] + assert list(df.index) == [0, 1, 2, 3, 4, 5] + assert list(df.iloc[:, 0]) == [ + 'phase.scale', + 'phase.cell.length_a', + 'phase.background', + 'phase.profile.u', + 'phase.profile.v', + 'phase.profile.w', ] - assert list(df.index) == [0, 1, 2, 3, 4] - assert df.iloc[0, 0] == 'phase.scale' assert df.iloc[0, 1] == '' - assert df.iloc[0, 2] == '' - assert df.iloc[0, 3] == '' - assert df.iloc[0, 4] == '' - assert df.iloc[0, 5] == '' - assert df.iloc[1, 0] == 'phase.cell.length_a' assert _strip_markup(df.iloc[1, 1]).strip() == '0.95' - assert df.iloc[1, 2] == '' - assert df.iloc[1, 3] == '' - assert df.iloc[1, 4] == '' - assert df.iloc[1, 5] == '' - assert df.iloc[2, 0] == 'phase.background' - assert df.iloc[2, 1] == '' assert _strip_markup(df.iloc[2, 2]).strip() == '0.94' - assert df.iloc[2, 3] == '' - assert df.iloc[2, 4] == '' - assert df.iloc[2, 5] == '' - assert df.iloc[3, 0] == 'phase.profile.u' - assert df.iloc[3, 1] == '' - assert df.iloc[3, 2] == '' assert _strip_markup(df.iloc[3, 3]).strip() == '0.93' - assert df.iloc[3, 4] == '' - assert df.iloc[3, 5] == '' - assert df.iloc[4, 0] == 'phase.profile.v' - assert df.iloc[4, 1] == '' - assert df.iloc[4, 2] == '' - assert df.iloc[4, 3] == '' assert _strip_markup(df.iloc[4, 4]).strip() == '0.92' - assert df.iloc[4, 5] == '' + assert _strip_markup(df.iloc[5, 5]).strip() == '0.91' + assert df.iloc[5, 6] == '' + + +def test_plot_posterior_pairs_uses_default_max_parameter_limit(monkeypatch): + from easydiffraction.display.plotting import DEFAULT_CORRELATION_MAX_PARAMETERS + from easydiffraction.display.plotting import Plotter + + captured: dict[str, object] = {} + + plotter = Plotter() + + def fake_build(self, *, parameters, style, threshold, max_parameters): + captured['parameters'] = parameters + captured['style'] = style + captured['threshold'] = threshold + captured['max_parameters'] = max_parameters + return object() + + monkeypatch.setattr(Plotter, '_build_posterior_pairs_plot', fake_build) + monkeypatch.setattr(Plotter, '_show_plot_figure', lambda self, figure: None) + + plotter.plot_posterior_pairs() + + assert captured['parameters'] is None + assert captured['style'] == 'auto' + assert captured['threshold'] is None + assert captured['max_parameters'] == DEFAULT_CORRELATION_MAX_PARAMETERS def test_plot_param_correlations_shows_full_table_when_threshold_is_zero(monkeypatch): From 7d3341b19c70503d66cf97fc2d1fe0ed93b92c8e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 13:30:22 +0200 Subject: [PATCH 092/106] Bump copier template to v0.11.3 --- .copier-answers.yml | 2 +- CONTRIBUTING.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index b7376e06..c1c59d2a 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,6 +1,6 @@ # WARNING: Do not edit this file manually. # Any changes will be overwritten by Copier. -_commit: v0.11.2-5-gd120259 +_commit: v0.11.3 _src_path: gh:easyscience/templates app_docs_url: https://easyscience.github.io/diffraction-app app_doi: 10.5281/zenodo.18163581 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e8dc420f..9e5b93cf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -249,6 +249,12 @@ or to run only Python linting checks: pixi run py-lint-check ``` +To add missing license headers: + +```bash +pixi run spdx-add +``` + Some formatting issues can be fixed automatically: ```bash From 2f1f65f8621007f70d84f1a33dc20eab88db9e0c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 13:39:30 +0200 Subject: [PATCH 093/106] Update tutorials --- docs/docs/tutorials/ed-21.ipynb | 2 +- docs/docs/tutorials/ed-21.py | 2 +- docs/docs/tutorials/ed-22.ipynb | 2 +- docs/docs/tutorials/ed-22.py | 2 +- docs/docs/tutorials/index.json | 14 ++++++++++++++ docs/docs/tutorials/index.md | 12 ++++++------ docs/mkdocs.yml | 6 +++--- 7 files changed, 27 insertions(+), 13 deletions(-) diff --git a/docs/docs/tutorials/ed-21.ipynb b/docs/docs/tutorials/ed-21.ipynb index d2a23c71..405bc858 100644 --- a/docs/docs/tutorials/ed-21.ipynb +++ b/docs/docs/tutorials/ed-21.ipynb @@ -24,7 +24,7 @@ "id": "1", "metadata": {}, "source": [ - "# Deterministic and Bayesian Refinement: LBCO, HRPT\n", + "# Bayesian Analysis: LBCO, HRPT\n", "\n", "This tutorial demonstrates a practical two-stage workflow for powder\n", "diffraction analysis with EasyDiffraction.\n", diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index ccfdb965..fe0cf405 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -1,5 +1,5 @@ # %% [markdown] -# # Deterministic and Bayesian Refinement: LBCO, HRPT +# # Bayesian Analysis: LBCO, HRPT # # This tutorial demonstrates a practical two-stage workflow for powder # diffraction analysis with EasyDiffraction. diff --git a/docs/docs/tutorials/ed-22.ipynb b/docs/docs/tutorials/ed-22.ipynb index 64561a9c..cc880314 100644 --- a/docs/docs/tutorials/ed-22.ipynb +++ b/docs/docs/tutorials/ed-22.ipynb @@ -24,7 +24,7 @@ "id": "1", "metadata": {}, "source": [ - "# Deterministic and Bayesian Refinement: Tb2TiO7, HEiDi\n", + "# Bayesian Analysis: Tb2TiO7, HEiDi\n", "\n", "This tutorial demonstrates a practical two-stage workflow for single-crystal\n", "diffraction analysis with EasyDiffraction.\n", diff --git a/docs/docs/tutorials/ed-22.py b/docs/docs/tutorials/ed-22.py index 22cd3f49..68f447d2 100644 --- a/docs/docs/tutorials/ed-22.py +++ b/docs/docs/tutorials/ed-22.py @@ -1,5 +1,5 @@ # %% [markdown] -# # Deterministic and Bayesian Refinement: Tb2TiO7, HEiDi +# # Bayesian Analysis: Tb2TiO7, HEiDi # # This tutorial demonstrates a practical two-stage workflow for single-crystal # diffraction analysis with EasyDiffraction. diff --git a/docs/docs/tutorials/index.json b/docs/docs/tutorials/index.json index dcd0cb87..40145a15 100644 --- a/docs/docs/tutorials/index.json +++ b/docs/docs/tutorials/index.json @@ -131,5 +131,19 @@ "title": "Instrument calibration: BEER at ESS", "description": "Instrument calibration of BEER at ESS using neutron powder diffraction data simulated with McStas", "level": "intermediate" + }, + "21": { + "url": "https://easyscience.github.io/diffraction-lib/{version}/tutorials/ed-21/ed-21.ipynb", + "original_name": "", + "title": "Bayesian Analysis: LBCO, HRPT", + "description": "Bayesian analysis of the La0.5Ba0.5CoO3 crystal structure - Markov Chain Monte Carlo (MCMC) sampling.", + "level": "advanced" + }, + "22": { + "url": "https://easyscience.github.io/diffraction-lib/{version}/tutorials/ed-22/ed-22.ipynb", + "original_name": "", + "title": "Bayesian Analysis: Tb2TiO7, HEiDi", + "description": "Bayesian analysis of the Tb2TiO7 crystal structure - Markov Chain Monte Carlo (MCMC) sampling.", + "level": "advanced" } } diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md index 1f4c82f0..a11c73e6 100644 --- a/docs/docs/tutorials/index.md +++ b/docs/docs/tutorials/index.md @@ -106,13 +106,13 @@ The tutorials are organized into the following categories: tutorial covers the use of Markov Chain Monte Carlo (MCMC) sampling to explore the posterior distribution of the refined parameters, providing insights into parameter uncertainties and correlations. -- [Tb2TiO7 Bayesian](ed-22.ipynb) – Demonstrates how to perform a - Bayesian analysis of the Tb2TiO7 crystal structure using constant - wavelength neutron single crystal diffraction data from HEiDi at FRM - II. This tutorial covers the use of Markov Chain Monte Carlo (MCMC) - sampling to explore the posterior distribution of the refined +- [Tb2TiO7 Bayesian](ed-22.ipynb) – Another example of a Bayesian + analysis. This tutorial focuses on the Tb2TiO7 crystal structure using + constant wavelength neutron single crystal diffraction data from HEiDi + at FRM II. Similar to the LBCO Bayesian tutorial, it covers the use of + MCMC sampling to explore the posterior distribution of the refined parameters, providing insights into parameter uncertainties and - correlations. + correlations in the context of single crystal diffraction data. ## Workshops & Schools diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 50eb7449..16091a5d 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -218,7 +218,7 @@ nav: - BEER McStas: tutorials/ed-20.ipynb - Bayesian Analysis: - LBCO Bayesian: tutorials/ed-21.ipynb - - Co2SiO4 Bayesian: tutorials/ed-22.ipynb + - Tb2TiO7 Bayesian: tutorials/ed-22.ipynb - Workshops & Schools: - DMSC Summer School: tutorials/ed-13.ipynb - API Reference: @@ -234,5 +234,5 @@ nav: - project: api-reference/project.md - summary: api-reference/summary.md - utils: api-reference/utils.md - - Command-Line Interface: - - Command-Line Interface: cli/index.md + - Command-Line: + - Command-Line: cli/index.md From 213a63ca835b32ee6d0e0e477eff2a7952b00270 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 19:24:57 +0200 Subject: [PATCH 094/106] Adjust posterior pair plot margins and title shift --- src/easydiffraction/display/plotting.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 1206a0a3..7f737f2b 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -158,14 +158,14 @@ class PosteriorPairPlotStyleEnum(StrEnum): POSTERIOR_PAIR_TITLE_FONT_SIZE = PLOTLY_TITLE_FONT_SIZE POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 16 POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS = 10 -POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS = 8 +POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS = 12 POSTERIOR_PAIR_GUIDE_LINE_COLOR = 'rgba(125, 140, 173, 0.18)' POSTERIOR_PAIR_FIXED_ASPECT_RATIO = '1 / 1' POSTERIOR_PAIR_FIXED_ASPECT_META_KEY = 'fixed_aspect_wrapper' -POSTERIOR_PAIR_LEFT_MARGIN_PIXELS = 58 -POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS = 10 -POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 26 -POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 24 +POSTERIOR_PAIR_LEFT_MARGIN_PIXELS = 40 +POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS = 24 +POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 40 +POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 40 POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS = 18 POSTERIOR_PAIR_SAMPLE_MARKER_SIZE = 6 POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE = 6 @@ -1944,7 +1944,7 @@ def _posterior_pair_title_annotation( def _square_matrix_title_left_shift(annotation_labels: list[str]) -> int: """Return the title shift that cancels left margin.""" extra_margin = Plotter._posterior_pair_extra_axis_title_margin(annotation_labels) - return POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + extra_margin + return max(0, POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + extra_margin - 14) @staticmethod def _square_matrix_gap_data_width(n_parameters: int) -> float: From 156ec249d390c1a8dcefd5ef9d8a94da9c6e614c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 19:28:00 +0200 Subject: [PATCH 095/106] Generalize pair-plot layout to square matrix --- src/easydiffraction/display/plotting.py | 76 +++++++++++++------------ 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 7f737f2b..758831c7 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -158,15 +158,16 @@ class PosteriorPairPlotStyleEnum(StrEnum): POSTERIOR_PAIR_TITLE_FONT_SIZE = PLOTLY_TITLE_FONT_SIZE POSTERIOR_PAIR_Y_TITLE_XSHIFT_PIXELS = 16 POSTERIOR_PAIR_X_TITLE_YSHIFT_PIXELS = 10 -POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS = 12 +SQUARE_MATRIX_TITLE_YSHIFT_PIXELS = 12 POSTERIOR_PAIR_GUIDE_LINE_COLOR = 'rgba(125, 140, 173, 0.18)' -POSTERIOR_PAIR_FIXED_ASPECT_RATIO = '1 / 1' -POSTERIOR_PAIR_FIXED_ASPECT_META_KEY = 'fixed_aspect_wrapper' -POSTERIOR_PAIR_LEFT_MARGIN_PIXELS = 40 -POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS = 24 -POSTERIOR_PAIR_TOP_MARGIN_PIXELS = 40 -POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS = 40 -POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS = 18 +SQUARE_MATRIX_FIXED_ASPECT_RATIO = '1 / 1' +SQUARE_MATRIX_FIXED_ASPECT_META_KEY = 'fixed_aspect_wrapper' +SQUARE_MATRIX_LEFT_MARGIN_PIXELS = 40 +SQUARE_MATRIX_RIGHT_MARGIN_PIXELS = 24 +SQUARE_MATRIX_TOP_MARGIN_PIXELS = 40 +SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS = 40 +SQUARE_MATRIX_AXIS_TITLE_LINE_HEIGHT_PIXELS = 18 +SQUARE_MATRIX_TITLE_LEFT_PADDING_PIXELS = 14 POSTERIOR_PAIR_SAMPLE_MARKER_SIZE = 6 POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE = 6 @@ -1505,7 +1506,7 @@ def _posterior_pairs_context( fit_results=fit_results, parameter_names=parameter_names, labels=self._posterior_plot_labels(fit_results, parameter_names), - annotation_labels=self._posterior_pair_axis_title_labels(parameter_names), + annotation_labels=self._square_matrix_axis_title_labels(parameter_names), title=self._correlation_filtered_title('Posterior pair plot', resolved_threshold), density_samples=density_samples, scatter_samples=scatter_samples, @@ -1923,7 +1924,7 @@ def _square_matrix_title_annotation( 'y': 1.0, 'yref': 'paper', 'yanchor': 'bottom', - 'yshift': POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS, + 'yshift': SQUARE_MATRIX_TITLE_YSHIFT_PIXELS, 'text': title, 'font': {'size': POSTERIOR_PAIR_TITLE_FONT_SIZE}, 'showarrow': False, @@ -1942,9 +1943,14 @@ def _posterior_pair_title_annotation( @staticmethod def _square_matrix_title_left_shift(annotation_labels: list[str]) -> int: - """Return the title shift that cancels left margin.""" - extra_margin = Plotter._posterior_pair_extra_axis_title_margin(annotation_labels) - return max(0, POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + extra_margin - 14) + """Return the title shift relative to the shared left margin.""" + extra_margin = Plotter._square_matrix_extra_axis_title_margin(annotation_labels) + return max( + 0, + SQUARE_MATRIX_LEFT_MARGIN_PIXELS + + extra_margin + - SQUARE_MATRIX_TITLE_LEFT_PADDING_PIXELS, + ) @staticmethod def _square_matrix_gap_data_width(n_parameters: int) -> float: @@ -1980,12 +1986,12 @@ def _square_matrix_layout_meta( annotation_labels: list[str], ) -> dict[str, object]: """Return wrapper metadata for square matrix plots.""" - margins = cls._posterior_pair_layout_margin(annotation_labels) + margins = cls._square_matrix_layout_margin(annotation_labels) plot_size = cls._square_matrix_target_plot_size_pixels(n_parameters) aspect_width = round(plot_size + int(margins['l']) + int(margins['r'])) aspect_height = round(plot_size + int(margins['t']) + int(margins['b'])) return { - POSTERIOR_PAIR_FIXED_ASPECT_META_KEY: { + SQUARE_MATRIX_FIXED_ASPECT_META_KEY: { 'aspect_ratio': f'{aspect_width} / {aspect_height}', } } @@ -2001,7 +2007,7 @@ def _finalize_posterior_pairs_figure( """Apply final layout settings to the posterior pair plot.""" fig.update_layout( autosize=True, - margin=self._posterior_pair_layout_margin(context.annotation_labels), + margin=self._square_matrix_layout_margin(context.annotation_labels), bargap=0.05, annotations=[ self._posterior_pair_title_annotation( @@ -2026,30 +2032,30 @@ def _finalize_posterior_pairs_figure( ) @staticmethod - def _posterior_pair_layout_margin(annotation_labels: list[str]) -> dict[str, int | bool]: - """Return outer margins sized for multiline pair-plot labels.""" - extra_margin = Plotter._posterior_pair_extra_axis_title_margin(annotation_labels) + def _square_matrix_layout_margin(annotation_labels: list[str]) -> dict[str, int | bool]: + """Return outer margins sized for multiline matrix labels.""" + extra_margin = Plotter._square_matrix_extra_axis_title_margin(annotation_labels) return { 'autoexpand': False, - 'l': POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + extra_margin, - 'r': POSTERIOR_PAIR_RIGHT_MARGIN_PIXELS, - 't': POSTERIOR_PAIR_TOP_MARGIN_PIXELS, - 'b': POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + extra_margin, + 'l': SQUARE_MATRIX_LEFT_MARGIN_PIXELS + extra_margin, + 'r': SQUARE_MATRIX_RIGHT_MARGIN_PIXELS, + 't': SQUARE_MATRIX_TOP_MARGIN_PIXELS, + 'b': SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS + extra_margin, } @staticmethod - def _posterior_pair_extra_axis_title_margin(annotation_labels: list[str]) -> int: + def _square_matrix_extra_axis_title_margin(annotation_labels: list[str]) -> int: """Return extra margin needed for multiline axis labels.""" if not annotation_labels: return 0 max_line_count = max( - Plotter._posterior_pair_axis_title_line_count(label) for label in annotation_labels + Plotter._square_matrix_axis_title_line_count(label) for label in annotation_labels ) - return max(0, max_line_count - 1) * POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS + return max(0, max_line_count - 1) * SQUARE_MATRIX_AXIS_TITLE_LINE_HEIGHT_PIXELS @staticmethod - def _posterior_pair_axis_title_line_count(label: str) -> int: + def _square_matrix_axis_title_line_count(label: str) -> int: """Return the number of display lines in one axis title.""" if not label: return 1 @@ -3862,15 +3868,15 @@ def _posterior_plot_labels( return labels @staticmethod - def _posterior_pair_axis_title_labels( + def _square_matrix_axis_title_labels( parameter_names: list[str], ) -> list[str]: - """Return compact multiline labels for pair-plot axes.""" - return [Plotter._posterior_pair_axis_title_label(name) for name in parameter_names] + """Return compact multiline labels for square-matrix axes.""" + return [Plotter._square_matrix_axis_title_label(name) for name in parameter_names] @staticmethod - def _posterior_pair_axis_title_label(unique_name: str) -> str: - """Return one compact multiline axis title for a pair plot.""" + def _square_matrix_axis_title_label(unique_name: str) -> str: + """Return one compact multiline axis title.""" normalized_name = unique_name.strip() if not normalized_name or '.' not in normalized_name: return normalized_name @@ -4113,8 +4119,8 @@ def _build_correlation_heatmap_plot( go = __import__('plotly.graph_objects', fromlist=['Figure', 'Heatmap']) context = _CorrelationHeatmapContext( corr_df=corr_df, - row_labels=self._posterior_pair_axis_title_labels(corr_df.index.tolist()), - col_labels=self._posterior_pair_axis_title_labels(corr_df.columns.tolist()), + row_labels=self._square_matrix_axis_title_labels(corr_df.index.tolist()), + col_labels=self._square_matrix_axis_title_labels(corr_df.columns.tolist()), threshold=threshold, precision=precision, ) @@ -4155,7 +4161,7 @@ def _build_correlation_heatmap_plot( fig.update_layout( autosize=True, - margin=self._posterior_pair_layout_margin([ + margin=self._square_matrix_layout_margin([ *context.row_labels, *context.col_labels, ]), From 006ca6ae8fddb4b4ed14ed608838d75ee4e0aff8 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 20:28:00 +0200 Subject: [PATCH 096/106] Switch DREAM defaults and refine Bayesian fit displays --- .../analysis/fit_helpers/bayesian.py | 2 +- .../analysis/minimizers/bumps_dream.py | 41 +++++++++++++-- src/easydiffraction/core/variable.py | 4 +- src/easydiffraction/display/plotting.py | 2 +- .../analysis/fit_helpers/test_bayesian.py | 4 +- .../analysis/minimizers/test_bumps_dream.py | 17 +++++- .../easydiffraction/core/test_parameters.py | 19 +++++++ .../easydiffraction/display/test_plotting.py | 52 +++++++++++-------- 8 files changed, 108 insertions(+), 33 deletions(-) diff --git a/src/easydiffraction/analysis/fit_helpers/bayesian.py b/src/easydiffraction/analysis/fit_helpers/bayesian.py index aa087fcb..e10d9c69 100644 --- a/src/easydiffraction/analysis/fit_helpers/bayesian.py +++ b/src/easydiffraction/analysis/fit_helpers/bayesian.py @@ -527,7 +527,7 @@ def _format_sampler_settings(sampler_settings: dict[str, object]) -> str | None: parts = [ f'{key}={sampler_settings[key]}' - for key in ('random_seed', 'steps', 'burn', 'thin', 'pop', 'samples') + for key in ('steps', 'burn', 'thin', 'pop', 'init', 'samples') if key in sampler_settings ] return ', '.join(parts) if parts else None diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index cc141d32..5c1681b6 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -37,13 +37,12 @@ DEFAULT_THIN = 1 DEFAULT_POP = 4 DEFAULT_PARALLEL = 0 -DEFAULT_INIT = DreamPopulationInitializationEnum.EPS +DEFAULT_INIT = DreamPopulationInitializationEnum.LHS DEFAULT_ALPHA = 0.0 DEFAULT_OUTLIER_TEST = 'none' DEFAULT_TRIM = False MAX_RANDOM_SEED = int(np.iinfo(np.uint32).max) -BURN_IN_PROGRESS_POINTS = 5 -SAMPLING_PROGRESS_POINTS = 20 +TOTAL_PROGRESS_POINTS = 25 DREAM_SAMPLE_ARRAY_NDIM = 3 DREAM_DRIVER_FAILURES = (ArithmeticError, RuntimeError, TypeError, ValueError) @@ -92,15 +91,19 @@ def __init__( self._n_parameters = n_parameters self._total_generations = max(1, total_generations) self._burn_steps = max(0, burn_steps) + burn_target_count, sampling_target_count = self._phase_progress_point_counts( + total_generations=self._total_generations, + burn_steps=self._burn_steps, + ) self._burn_targets = self._progress_targets( start=1, stop=self._burn_steps, - target_count=BURN_IN_PROGRESS_POINTS, + target_count=burn_target_count, ) self._sampling_targets = self._progress_targets( start=self._burn_steps + 1, stop=self._total_generations, - target_count=SAMPLING_PROGRESS_POINTS, + target_count=sampling_target_count, ) self._next_burn_target_index = 0 self._next_sampling_target_index = 0 @@ -175,6 +178,34 @@ def _progress_targets( unique_targets.append(stop) return unique_targets + @staticmethod + def _phase_progress_point_counts( + *, + total_generations: int, + burn_steps: int, + ) -> tuple[int, int]: + """Return proportional burn and sampling progress counts.""" + total_points = min(TOTAL_PROGRESS_POINTS, max(1, total_generations)) + burn_generations = min(max(0, burn_steps), total_generations) + sampling_generations = max(total_generations - burn_generations, 0) + + if burn_generations == 0: + return 0, total_points + if sampling_generations == 0: + return total_points, 0 + + burn_target_count = round(total_points * burn_generations / total_generations) + burn_target_count = min( + max(burn_target_count, 1), + burn_generations, + total_points - 1, + ) + sampling_target_count = min( + max(total_points - burn_target_count, 1), + sampling_generations, + ) + return burn_target_count, sampling_target_count + def _should_report(self, generation: int) -> bool: """Return whether the current generation should be rendered.""" clamped_generation = min(max(1, generation), self._total_generations) diff --git a/src/easydiffraction/core/variable.py b/src/easydiffraction/core/variable.py index a09f502f..4e0fb499 100644 --- a/src/easydiffraction/core/variable.py +++ b/src/easydiffraction/core/variable.py @@ -429,7 +429,7 @@ def fit_max(self, v: float) -> None: def set_fit_bounds_from_uncertainty( self, - multiplier: float = 8.0, + multiplier: float = 4.0, *, clip_to_limits: bool = True, ) -> None: @@ -438,7 +438,7 @@ def set_fit_bounds_from_uncertainty( Parameters ---------- - multiplier : float, default=8.0 + multiplier : float, default=4.0 Positive finite factor applied symmetrically to the current parameter uncertainty. clip_to_limits : bool, default=True diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 758831c7..a7d6ece5 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -2360,7 +2360,7 @@ def _posterior_distribution_context( parameter_name=parameter_name, values=samples[:, 0], label=label, - title=f'Posterior distribution: {label}', + title=f'Posterior distribution: {parameter_name}', summary=self._posterior_summary_by_name(fit_results).get(parameter_name), ) diff --git a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py index 5fcfbf1a..3b641e6d 100644 --- a/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py +++ b/tests/unit/easydiffraction/analysis/fit_helpers/test_bayesian.py @@ -157,6 +157,7 @@ def test_bayesian_fit_results_display_results_prints_sampler_and_convergence(cap 'burn': 50, 'thin': 1, 'pop': 4, + 'init': 'lhs', 'samples': 3200, }, convergence_diagnostics={ @@ -191,8 +192,9 @@ def test_bayesian_fit_results_display_results_prints_sampler_and_convergence(cap assert 'Sampler status: DREAM sampling completed' in out assert 'Sampler: dream' in out assert 'Sampler completed: yes' in out - assert 'random_seed=1313900679' in out assert 'steps=200' in out + assert 'init=lhs' in out + assert 'random_seed=1313900679' not in out assert 'status=failed' in out assert 'max_r_hat=1.107' in out assert 'min_ess_bulk=125.9' in out diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py index 9ac35b57..5c3dd60b 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py @@ -49,10 +49,25 @@ def test_type_info_and_default_init(): minimizer = BumpsDreamMinimizer() assert minimizer.type_info.tag == MinimizerTypeEnum.BUMPS_DREAM - assert minimizer.init is DreamPopulationInitializationEnum.EPS + assert minimizer.init is DreamPopulationInitializationEnum.LHS assert minimizer.steps == 1000 +def test_dream_progress_monitor_allocates_rows_by_phase_ratio(): + from easydiffraction.analysis.minimizers.bumps_dream import _DreamProgressMonitor + + monitor = _DreamProgressMonitor( + tracker=MagicMock(), + n_points=100, + n_parameters=3, + total_generations=100, + burn_steps=40, + ) + + assert len(monitor._burn_targets) == 10 + assert len(monitor._sampling_targets) == 15 + + def test_init_accepts_enum_or_string_and_rejects_invalid(): from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum diff --git a/tests/unit/easydiffraction/core/test_parameters.py b/tests/unit/easydiffraction/core/test_parameters.py index 0a4c95cc..a6c5b7ad 100644 --- a/tests/unit/easydiffraction/core/test_parameters.py +++ b/tests/unit/easydiffraction/core/test_parameters.py @@ -123,6 +123,25 @@ def test_parameter_set_fit_bounds_from_uncertainty_sets_bounds_and_returns_none( assert np.isclose(p.fit_max, 3.0) +def test_parameter_set_fit_bounds_from_uncertainty_uses_default_multiplier(): + from easydiffraction.core.validation import AttributeSpec + from easydiffraction.core.variable import Parameter + from easydiffraction.io.cif.handler import CifHandler + + p = Parameter( + name='default_multiplier', + value_spec=AttributeSpec(default=0.0), + cif_handler=CifHandler(names=['_param.default_multiplier']), + ) + p.value = 2.0 + p.uncertainty = 0.25 + + p.set_fit_bounds_from_uncertainty() + + assert np.isclose(p.fit_min, 1.0) + assert np.isclose(p.fit_max, 3.0) + + def test_parameter_set_fit_bounds_from_uncertainty_clips_to_physical_limits(): from easydiffraction.core.validation import AttributeSpec from easydiffraction.core.validation import DataTypes diff --git a/tests/unit/easydiffraction/display/test_plotting.py b/tests/unit/easydiffraction/display/test_plotting.py index 3b434c8d..c0ef1615 100644 --- a/tests/unit/easydiffraction/display/test_plotting.py +++ b/tests/unit/easydiffraction/display/test_plotting.py @@ -307,12 +307,12 @@ def test_correlation_from_posterior_samples_returns_labeled_dataframe(): def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): - from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_HOVER_MARKER_SIZE from easydiffraction.display.plotting import POSTERIOR_PAIR_SAMPLE_MARKER_SIZE from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_FONT_SIZE - from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS - from easydiffraction.display.plotting import POSTERIOR_PAIR_TOP_MARGIN_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_TITLE_YSHIFT_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_TOP_MARGIN_PIXELS plotter, _, _ = _make_bayesian_plotter_fixture() @@ -346,15 +346,15 @@ def test_build_posterior_pairs_plot_hides_diagonal_ticks_and_uses_annotations(): 'twotheta_offset', ] assert figure.layout.annotations[0].font.size == POSTERIOR_PAIR_TITLE_FONT_SIZE - assert figure.layout.annotations[0].yshift == POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS + assert figure.layout.annotations[0].yshift == SQUARE_MATRIX_TITLE_YSHIFT_PIXELS assert figure.layout.annotations[0].xshift == -plotter._square_matrix_title_left_shift([ 'length_a', 'broad_gauss_u', 'broad_gauss_v', 'twotheta_offset', ]) - assert figure.layout.margin.t == POSTERIOR_PAIR_TOP_MARGIN_PIXELS - assert figure.layout.margin.b == POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + assert figure.layout.margin.t == SQUARE_MATRIX_TOP_MARGIN_PIXELS + assert figure.layout.margin.b == SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS subplot = figure.get_subplot(1, 1) bottom_subplot = figure.get_subplot(4, 1) assert subplot.yaxis.showticklabels is False @@ -431,8 +431,8 @@ def test_build_posterior_pairs_plot_sign_colors_contours_and_marginals(): def test_build_posterior_pairs_plot_formats_dotted_axis_titles_multiline(): - from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS - from easydiffraction.display.plotting import POSTERIOR_PAIR_LEFT_MARGIN_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_LEFT_MARGIN_PIXELS plotter, fit_results, _ = _make_bayesian_plotter_fixture() dotted_parameter_names = [ @@ -452,8 +452,8 @@ def test_build_posterior_pairs_plot_formats_dotted_axis_titles_multiline(): assert 'hrpt.
peak.
broad_gauss_u' in annotation_texts assert 'hrpt.
instrument.
twotheta_offset' in annotation_texts assert all('None broad_gauss_u' not in text for text in annotation_texts) - assert figure.layout.margin.l > POSTERIOR_PAIR_LEFT_MARGIN_PIXELS - assert figure.layout.margin.b > POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + assert figure.layout.margin.l > SQUARE_MATRIX_LEFT_MARGIN_PIXELS + assert figure.layout.margin.b > SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS def test_build_posterior_pairs_plot_uses_full_names_in_hovertemplates(): @@ -753,20 +753,28 @@ class Experiment: def test_build_param_distribution_plot_accepts_unique_name_string(): - plotter, _, _ = _make_bayesian_plotter_fixture() + plotter, fit_results, posterior_samples = _make_bayesian_plotter_fixture() + unique_name = 'phase.cell.length_a' + posterior_samples.parameter_names[0] = unique_name + fit_results.parameters[0].unique_name = unique_name + fit_results.posterior_parameter_summaries[0].unique_name = unique_name - figure = plotter._build_param_distribution_plot('length_a') + figure = plotter._build_param_distribution_plot(unique_name) - assert figure.layout.title.text == 'Posterior distribution: length_a' + assert figure.layout.title.text == f'Posterior distribution: {unique_name}' def test_build_param_distribution_plot_accepts_user_facing_label_string(): - plotter, fit_results, _ = _make_bayesian_plotter_fixture() + plotter, fit_results, posterior_samples = _make_bayesian_plotter_fixture() + unique_name = 'phase.cell.length_a' + posterior_samples.parameter_names[0] = unique_name + fit_results.parameters[0].unique_name = unique_name + fit_results.posterior_parameter_summaries[0].unique_name = unique_name fit_results.posterior_parameter_summaries[0].display_name = 'Cell a' figure = plotter._build_param_distribution_plot('Cell a') - assert figure.layout.title.text == 'Posterior distribution: length_a' + assert figure.layout.title.text == f'Posterior distribution: {unique_name}' def test_resolve_posterior_parameter_names_warns_on_ambiguous_label(monkeypatch): @@ -1547,12 +1555,12 @@ def test_plot_param_correlations_renders_plotly_heatmap(monkeypatch): import numpy as np import easydiffraction.display.plotters.plotly as plotly_mod - from easydiffraction.display.plotting import POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS - from easydiffraction.display.plotting import POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_FONT_SIZE - from easydiffraction.display.plotting import POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS - from easydiffraction.display.plotting import POSTERIOR_PAIR_TOP_MARGIN_PIXELS from easydiffraction.display.plotting import Plotter + from easydiffraction.display.plotting import SQUARE_MATRIX_AXIS_TITLE_LINE_HEIGHT_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_TITLE_YSHIFT_PIXELS + from easydiffraction.display.plotting import SQUARE_MATRIX_TOP_MARGIN_PIXELS captured = {} @@ -1617,14 +1625,14 @@ class Project: 'phase.
cell.
length_c', ] assert fig.layout.annotations[0].font.size == POSTERIOR_PAIR_TITLE_FONT_SIZE - assert fig.layout.annotations[0].yshift == POSTERIOR_PAIR_TITLE_YSHIFT_PIXELS + assert fig.layout.annotations[0].yshift == SQUARE_MATRIX_TITLE_YSHIFT_PIXELS assert fig.layout.annotations[0].xshift == -Plotter._square_matrix_title_left_shift([ 'phase.
scale', 'phase.
cell.
length_c', ]) - assert fig.layout.margin.t == POSTERIOR_PAIR_TOP_MARGIN_PIXELS + assert fig.layout.margin.t == SQUARE_MATRIX_TOP_MARGIN_PIXELS assert fig.layout.margin.b == ( - POSTERIOR_PAIR_BOTTOM_MARGIN_PIXELS + 2 * POSTERIOR_PAIR_AXIS_TITLE_LINE_HEIGHT_PIXELS + SQUARE_MATRIX_BOTTOM_MARGIN_PIXELS + 2 * SQUARE_MATRIX_AXIS_TITLE_LINE_HEIGHT_PIXELS ) assert ( fig.layout.meta['fixed_aspect_wrapper']['aspect_ratio'] From 043e7fd27c2b6af9aa2226a8ffa03b52e72cda56 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 20:49:58 +0200 Subject: [PATCH 097/106] Show uncertainty multiplier in pair plot titles --- .../analysis/minimizers/bumps_dream.py | 2 +- src/easydiffraction/core/variable.py | 26 +++++++--- src/easydiffraction/display/plotting.py | 50 ++++++++++++++++++- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/src/easydiffraction/analysis/minimizers/bumps_dream.py b/src/easydiffraction/analysis/minimizers/bumps_dream.py index 5c1681b6..c9af1012 100644 --- a/src/easydiffraction/analysis/minimizers/bumps_dream.py +++ b/src/easydiffraction/analysis/minimizers/bumps_dream.py @@ -31,7 +31,7 @@ from easydiffraction.utils.logging import log DEFAULT_METHOD = 'dream' -DEFAULT_MAX_ITERATIONS = 1000 +DEFAULT_MAX_ITERATIONS = 3000 DEFAULT_BURN_FRACTION = 0.2 DEFAULT_MIN_BURN = 50 DEFAULT_THIN = 1 diff --git a/src/easydiffraction/core/variable.py b/src/easydiffraction/core/variable.py index 4e0fb499..b804889e 100644 --- a/src/easydiffraction/core/variable.py +++ b/src/easydiffraction/core/variable.py @@ -22,6 +22,8 @@ # ====================================================================== +FIT_BOUNDS_FROM_UNCERTAINTY_DEFAULT_MULTIPLIER = 4.0 + class GenericDescriptorBase(GuardedBase): """ @@ -280,6 +282,7 @@ def __init__( self._fit_min = self._fit_min_spec.default self._fit_max_spec = AttributeSpec(data_type=DataTypes.NUMERIC, default=np.inf) self._fit_max = self._fit_max_spec.default + self._fit_bounds_uncertainty_multiplier: float | None = None self._start_value_spec = AttributeSpec(data_type=DataTypes.NUMERIC, default=0.0) self._start_value = self._start_value_spec.default self._constrained_spec = self._BOOL_SPEC_TEMPLATE @@ -414,6 +417,7 @@ def fit_min(self, v: float) -> None: self._fit_min = self._fit_min_spec.validated( v, name=f'{self.unique_name}.fit_min', current=self._fit_min ) + self._fit_bounds_uncertainty_multiplier = None @property def fit_max(self) -> float: @@ -426,10 +430,18 @@ def fit_max(self, v: float) -> None: self._fit_max = self._fit_max_spec.validated( v, name=f'{self.unique_name}.fit_max', current=self._fit_max ) + self._fit_bounds_uncertainty_multiplier = None + + @property + def fit_bounds_uncertainty_multiplier(self) -> float | None: + """ + Multiplier used for uncertainty-derived fit bounds, if known. + """ + return self._fit_bounds_uncertainty_multiplier def set_fit_bounds_from_uncertainty( self, - multiplier: float = 4.0, + multiplier: float = FIT_BOUNDS_FROM_UNCERTAINTY_DEFAULT_MULTIPLIER, *, clip_to_limits: bool = True, ) -> None: @@ -438,7 +450,7 @@ def set_fit_bounds_from_uncertainty( Parameters ---------- - multiplier : float, default=4.0 + multiplier : float, default=FIT_BOUNDS_FROM_UNCERTAINTY_DEFAULT_MULTIPLIER Positive finite factor applied symmetrically to the current parameter uncertainty. clip_to_limits : bool, default=True @@ -459,10 +471,11 @@ def set_fit_bounds_from_uncertainty( msg = f'Cannot set fit bounds for {name}: current value is missing or invalid.' raise ValueError(msg) - if isinstance(multiplier, bool) or not np.isfinite(float(multiplier)): + resolved_multiplier = float(multiplier) + if isinstance(multiplier, bool) or not np.isfinite(resolved_multiplier): msg = 'multiplier must be a positive finite number.' raise ValueError(msg) - if float(multiplier) <= 0: + if resolved_multiplier <= 0: msg = 'multiplier must be a positive finite number.' raise ValueError(msg) @@ -470,8 +483,8 @@ def set_fit_bounds_from_uncertainty( msg = f'Cannot set fit bounds for {name}: uncertainty is missing or invalid.' raise ValueError(msg) - lower = float(value) - float(multiplier) * float(uncertainty) - upper = float(value) + float(multiplier) * float(uncertainty) + lower = float(value) - resolved_multiplier * float(uncertainty) + upper = float(value) + resolved_multiplier * float(uncertainty) if clip_to_limits: physical_lower = float(self._physical_lower_bound()) @@ -490,6 +503,7 @@ def set_fit_bounds_from_uncertainty( self.fit_min = lower self.fit_max = upper + self._fit_bounds_uncertainty_multiplier = resolved_multiplier # ====================================================================== diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index a7d6ece5..65961dd5 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -880,6 +880,47 @@ def _correlation_filtered_title(base_title: str, threshold: float) -> str: return base_title return f'{base_title} with |correlation| β‰₯ {threshold:.2f}' + @staticmethod + def _posterior_pair_title(multiplier: float | None) -> str: + """ + Return the posterior pair title with its displayed bound scale. + """ + if multiplier is None: + return 'Posterior pair plot' + return f'Posterior pair plot in Β±{multiplier:g}Γ—uncertainty region' + + @staticmethod + def _posterior_pair_uncertainty_multiplier( + fit_results: object, + parameter_names: list[str], + ) -> float | None: + """ + Return a shared uncertainty-bound multiplier for a pair plot. + """ + parameters_by_name = { + getattr(parameter, 'unique_name', ''): parameter + for parameter in fit_results.parameters + } + multiplier: float | None = None + + for parameter_name in parameter_names: + parameter = parameters_by_name.get(parameter_name) + if parameter is None: + return None + + current = getattr(parameter, 'fit_bounds_uncertainty_multiplier', None) + if current is None or not np.isfinite(float(current)): + return None + + current_value = float(current) + if multiplier is None: + multiplier = current_value + continue + if not np.isclose(multiplier, current_value): + return None + + return multiplier + def plot_posterior_pairs( self, parameters: list[object] | None = None, @@ -1501,13 +1542,20 @@ def _posterior_pairs_context( selected_samples, max_points=POSTERIOR_PAIR_SCATTER_MAX_POINTS, ) + uncertainty_multiplier = self._posterior_pair_uncertainty_multiplier( + fit_results, + parameter_names, + ) return _PosteriorPairsContext( fit_results=fit_results, parameter_names=parameter_names, labels=self._posterior_plot_labels(fit_results, parameter_names), annotation_labels=self._square_matrix_axis_title_labels(parameter_names), - title=self._correlation_filtered_title('Posterior pair plot', resolved_threshold), + title=self._correlation_filtered_title( + self._posterior_pair_title(uncertainty_multiplier), + resolved_threshold, + ), density_samples=density_samples, scatter_samples=scatter_samples, show_contours=show_contours, From 3db44d1729d9245227772e369a763ee656d50573 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 21:12:53 +0200 Subject: [PATCH 098/106] Refine Bayesian tutorial examples --- docs/docs/tutorials/ed-21.py | 65 +++++++----- docs/docs/tutorials/ed-22.py | 129 +++++++++++++++++++++++- src/easydiffraction/display/plotting.py | 2 +- 3 files changed, 170 insertions(+), 26 deletions(-) diff --git a/docs/docs/tutorials/ed-21.py b/docs/docs/tutorials/ed-21.py index fe0cf405..d91173c3 100644 --- a/docs/docs/tutorials/ed-21.py +++ b/docs/docs/tutorials/ed-21.py @@ -114,13 +114,16 @@ # excluded regions. # %% [markdown] -# #### Download the Measured Data +# Download the measured data from the repository. Alternatively, you +# could use your own data file by providing the path to it instead of +# downloading from the repository. # %% data_path = ed.download_data(id=3, destination='data') # %% [markdown] -# #### Create the Experiment Object +# Create the experiment object and specify the sample form, beam mode, +# and radiation probe. # %% project.experiments.add_from_data_path( @@ -135,7 +138,13 @@ experiment = project.experiments['hrpt'] # %% [markdown] -# #### Set Instrument and Peak-Profile Parameters +# Link the structural phase to the experiment. + +# %% +experiment.linked_phases.create(id='lbco', scale=9.1351) + +# %% [markdown] +# Set instrument and peak profile parameters. # # These values provide the initial instrument description for the local # refinement. Later, a subset of them will be refined. @@ -151,7 +160,7 @@ experiment.peak.broad_lorentz_y = 0.0844 # %% [markdown] -# #### Add Background Points and Excluded Regions +# Add background points and excluded regions. # # The line-segment background is defined by a few anchor points. We also # exclude regions that are not intended to contribute to the fit. @@ -166,12 +175,6 @@ experiment.excluded_regions.create(id='1', start=0, end=10) experiment.excluded_regions.create(id='2', start=100, end=180) -# %% [markdown] -# #### Link the Structural Phase to the Experiment - -# %% -experiment.linked_phases.create(id='lbco', scale=9.1351) - # %% [markdown] # ## Step 4: Run an Initial Local Refinement # @@ -235,15 +238,23 @@ # on the current parameter value and expands them by a chosen multiple of # the reported uncertainty. # -# Default `multiplier` is 8 to give a wide range for the sampler to -# explore, but here we use 3 to speed up the tutorial. +# The default `multiplier` is 4. If the local refinement is very tight, +# or if you expect a broader posterior, increase it explicitly. +# +# Show unset fit bounds before setting them from the local refinement uncertainties. # %% project.analysis.display.free_params() +# %% [markdown] +# Set fit bounds for all free parameters using the default multiplier of +# 4. In this tutorial that means the posterior pair plot will later +# refer to a `Β±4 Γ— uncertainty` region in its title. To use a different +# region, pass another value, for example `multiplier=6`. + # %% for param in project.free_parameters: - param.set_fit_bounds_from_uncertainty(multiplier=3.5) + param.set_fit_bounds_from_uncertainty() # %% [markdown] # Displaying the free parameters again is a convenient way to confirm @@ -263,14 +274,15 @@ # of steps (`steps`) and often the burn-in (`burn`) as well. When # needed, the DREAM API also lets you tune how chains are initialized # through the `init` setting. Other sampler settings such as `thin` and -# `pop` can be adjusted as well. The current EasyDiffraction default -# also uses `parallel=0`, which tells BUMPS DREAM to use all available -# CPUs for population evaluations. +# `pop` can be adjusted as well. The current EasyDiffraction defaults +# use `steps=3000`, `init='lhs'`, and `parallel=0`, which tells +# BUMPS-DREAM to use all available CPUs for population evaluations. # -# The default `steps` value is 1000, and real analyses often need more -# to achieve good convergence and posterior sampling. Here we use a much -# smaller value to keep the tutorial fast, but this is not recommended -# for production analysis. +# The `burn` setting is auto-resolved when left unset. With the default +# `steps=3000` this gives `burn=600`, but if you override `steps` and +# keep `burn=None`, the effective burn-in is recomputed automatically. +# Here we use a much smaller step count to keep the tutorial fast, but +# this is not recommended for production analysis. # %% project.analysis.fit.show_minimizer_types() @@ -279,7 +291,7 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' # %% -project.analysis.fit.minimizer.steps = 100 # lower than the default 1000 +project.analysis.fit.minimizer.steps = 300 # lower than the default 3000 # %% project.analysis.fit() @@ -300,7 +312,10 @@ # - `plot_param_correlations` summarizes pairwise structure in a compact # matrix. # - `plot_posterior_pairs` shows marginal densities on the diagonal and -# posterior contours off-diagonal. +# posterior contours off-diagonal. In this tutorial its title also +# reminds you that the display region follows the `Β±4 Γ— uncertainty` +# bounds defined above, while numeric subplot ranges are omitted to +# keep the grid readable. # %% project.display.plotter.plot_param_correlations() @@ -332,4 +347,8 @@ # after the Bayesian run. # %% -project.display.plotter.plot_posterior_predictive(expt_name='hrpt', x_min=92, x_max=93) +project.display.plotter.plot_posterior_predictive( + expt_name='hrpt', + x_min=92, + x_max=93, +) diff --git a/docs/docs/tutorials/ed-22.py b/docs/docs/tutorials/ed-22.py index 68f447d2..aaa72718 100644 --- a/docs/docs/tutorials/ed-22.py +++ b/docs/docs/tutorials/ed-22.py @@ -11,6 +11,15 @@ # # The example uses constant-wavelength neutron single-crystal diffraction data # for Tb2TiO7 measured on HEiDi at FRM II. +# +# The goal is not only to obtain a good fit, but also to answer Bayesian +# questions such as: +# +# - Which parameter values are most probable? +# - How broad are the credible intervals? +# - Which parameters are strongly correlated? +# - How much uncertainty propagates into the calculated reflection +# intensities? # %% [markdown] # ## Import Library @@ -20,12 +29,21 @@ # %% [markdown] # ## Step 1: Create a Project Container +# +# The project object keeps structures, experiments, fit settings, and +# plotting utilities together in a single place. We will build the full +# workflow inside this object. # %% project = ed.Project() # %% [markdown] # ## Step 2: Build the Structural Model +# +# For this example we start from a CIF file describing the Tb2TiO7 +# pyrochlore structure. Loading the structure from CIF is convenient +# because it preserves a realistic starting +# model without rebuilding the full structure by hand. # %% structure_path = ed.download_data(id=20, destination='data') @@ -38,6 +56,10 @@ # %% [markdown] # ## Step 3: Define the Diffraction Experiment +# +# Next we download the measured reflection data, create a neutron +# single-crystal experiment, and configure the crystal link, +# wavelength, and extinction model. # %% data_path = ed.download_data(id=19, destination='data') @@ -54,10 +76,18 @@ # %% experiment = project.experiments['heidi'] +# %% [markdown] +# Link the crystal structure to the experiment and set its scale factor. + # %% experiment.linked_crystal.id = 'tbti' experiment.linked_crystal.scale = 1.0 +# %% [markdown] +# Set the instrument wavelength and starting extinction parameters. +# These values provide the initial experiment description for the local +# refinement. + # %% experiment.instrument.setup_wavelength = 0.793 @@ -67,6 +97,17 @@ # %% [markdown] # ## Step 4: Run an Initial Local Refinement +# +# Before Bayesian sampling, it is useful to run a deterministic fit. This +# gives us: +# +# - a good point estimate near the best-fit region, +# - uncertainties from the local optimizer, +# - a quick check that the model and experiment are configured +# sensibly. +# +# In this tutorial we refine a small set of structural and extinction +# parameters while keeping occupancies fixed. # %% structure.atom_sites['O1'].fract_x.free = True @@ -84,15 +125,30 @@ experiment.linked_crystal.scale.free = True experiment.extinction.radius.free = True +# %% [markdown] +# We keep using the default LMFIT Levenberg-Marquardt minimizer as a fast local +# optimizer. Its main purpose here is to provide a stable starting point +# and uncertainty estimates for the Bayesian run. + # %% project.analysis.fit.show_minimizer_types() # %% project.analysis.fit() +# %% [markdown] +# The fit-results display summarizes the locally refined values and their +# estimated uncertainties. + # %% project.analysis.display.fit_results() +# %% [markdown] +# The correlation plot shows how strongly the refined parameters move +# together in the local refinement. The measured-vs-calculated plot shows +# how well the refined crystal model reproduces the measured reflection +# intensities. + # %% project.display.plotter.plot_param_correlations() @@ -101,19 +157,60 @@ # %% [markdown] # ## Step 5: Prepare for Bayesian Sampling +# +# DREAM requires finite bounds for the free parameters. Instead of +# setting them manually, we derive them from the uncertainties estimated +# in the local refinement. +# +# The helper method `set_fit_bounds_from_uncertainty` centers the bounds +# on the current parameter value and expands them by a chosen multiple of +# the reported uncertainty. +# +# The default `multiplier` is 4. In this single-crystal tutorial we use +# a tighter value of `1.5` to keep the sampling window closer to the +# locally refined solution. +# +# Show unset fit bounds before setting them from the local refinement +# uncertainties. # %% project.analysis.display.free_params() +# %% [markdown] +# Set fit bounds for all free parameters using `multiplier=1.5`. In this +# tutorial that means the posterior pair plot will later refer to a +# `Β±1.5 Γ— uncertainty` region in its title. To widen the sampling window, +# increase the multiplier explicitly. + # %% for param in project.free_parameters: param.set_fit_bounds_from_uncertainty(multiplier=1.5) +# %% [markdown] +# Displaying the free parameters again is a convenient way to confirm +# that the fit bounds have been assigned as expected before launching the +# sampler. + # %% project.analysis.display.free_params() # %% [markdown] -# ## Step 6: Configure and Run BUMPS-DREAM +# ## Step 6: Configure and Run DREAM +# +# We now switch from the local minimizer to the Bayesian DREAM sampler. +# +# The settings below are intentionally small so the tutorial runs +# quickly. For production analysis you would usually increase the number +# of steps (`steps`) and often the burn-in (`burn`) as well. When +# needed, the DREAM API also lets you tune how chains are initialized +# through the `init` setting. Other sampler settings such as `thin` and +# `pop` can be adjusted as well. The current EasyDiffraction defaults +# use `steps=3000`, `init='lhs'`, and `parallel=0`, which tells +# BUMPS-DREAM to use all available CPUs for population evaluations. +# +# The `burn` setting is auto-resolved when left unset. Here we override +# `steps` with a smaller value to keep the tutorial fast, and the +# effective burn-in is recomputed automatically. # %% project.analysis.fit.show_minimizer_types() @@ -122,23 +219,51 @@ project.analysis.fit.minimizer_type = 'bumps (dream)' # %% -project.analysis.fit.minimizer.steps = 500 +project.analysis.fit.minimizer.steps = 500 # lower than the default 3000 # %% project.analysis.fit() +# %% [markdown] +# ## Step 7: Inspect Bayesian Results +# +# The fit-results display now includes sampler settings, convergence +# diagnostics, committed parameter values, and posterior summary +# statistics. + # %% project.analysis.display.fit_results() +# %% [markdown] +# The correlation and posterior-pair plots are complementary: +# +# - `plot_param_correlations` summarizes pairwise structure in a compact +# matrix. +# - `plot_posterior_pairs` shows marginal densities on the diagonal and +# posterior contours off-diagonal. In this tutorial its title also +# reminds you that the display region follows the `Β±1.5 Γ— uncertainty` +# bounds defined above, while numeric subplot ranges are omitted to +# keep the grid readable. + # %% project.display.plotter.plot_param_correlations() # %% project.display.plotter.plot_posterior_pairs() +# %% [markdown] +# The one-dimensional posterior distributions below make it easier to +# inspect individual parameters in isolation, including asymmetry or +# multimodality. + # %% for param in project.free_parameters: project.display.plotter.plot_param_distribution(param) +# %% [markdown] +# Finally, the posterior predictive plot propagates the sampled +# parameter uncertainty into the calculated single-crystal reflection +# intensities. + # %% project.display.plotter.plot_posterior_predictive(expt_name='heidi') diff --git a/src/easydiffraction/display/plotting.py b/src/easydiffraction/display/plotting.py index 65961dd5..34b0da10 100644 --- a/src/easydiffraction/display/plotting.py +++ b/src/easydiffraction/display/plotting.py @@ -887,7 +887,7 @@ def _posterior_pair_title(multiplier: float | None) -> str: """ if multiplier is None: return 'Posterior pair plot' - return f'Posterior pair plot in Β±{multiplier:g}Γ—uncertainty region' + return f'Posterior pair plot in Β±{multiplier:g} Γ— uncertainty region' # noqa: RUF001 @staticmethod def _posterior_pair_uncertainty_multiplier( From a862edc76ecc95c582957766236d467d92c6d753 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 21:26:58 +0200 Subject: [PATCH 099/106] Shorten fit-bounds multiplier constant name --- src/easydiffraction/core/variable.py | 6 +++--- .../easydiffraction/analysis/minimizers/test_bumps_dream.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/easydiffraction/core/variable.py b/src/easydiffraction/core/variable.py index b804889e..303c5bbe 100644 --- a/src/easydiffraction/core/variable.py +++ b/src/easydiffraction/core/variable.py @@ -22,7 +22,7 @@ # ====================================================================== -FIT_BOUNDS_FROM_UNCERTAINTY_DEFAULT_MULTIPLIER = 4.0 +DEFAULT_FIT_BOUNDS_MULTIPLIER = 4.0 class GenericDescriptorBase(GuardedBase): @@ -441,7 +441,7 @@ def fit_bounds_uncertainty_multiplier(self) -> float | None: def set_fit_bounds_from_uncertainty( self, - multiplier: float = FIT_BOUNDS_FROM_UNCERTAINTY_DEFAULT_MULTIPLIER, + multiplier: float = DEFAULT_FIT_BOUNDS_MULTIPLIER, *, clip_to_limits: bool = True, ) -> None: @@ -450,7 +450,7 @@ def set_fit_bounds_from_uncertainty( Parameters ---------- - multiplier : float, default=FIT_BOUNDS_FROM_UNCERTAINTY_DEFAULT_MULTIPLIER + multiplier : float, default=DEFAULT_FIT_BOUNDS_MULTIPLIER Positive finite factor applied symmetrically to the current parameter uncertainty. clip_to_limits : bool, default=True diff --git a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py index 5c3dd60b..eea9f089 100644 --- a/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py +++ b/tests/unit/easydiffraction/analysis/minimizers/test_bumps_dream.py @@ -50,7 +50,7 @@ def test_type_info_and_default_init(): assert minimizer.type_info.tag == MinimizerTypeEnum.BUMPS_DREAM assert minimizer.init is DreamPopulationInitializationEnum.LHS - assert minimizer.steps == 1000 + assert minimizer.steps == 3000 def test_dream_progress_monitor_allocates_rows_by_phase_ratio(): From 8a21d9424e658d1ca286ddc11a33dad0c5c8693c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 12 May 2026 21:27:23 +0200 Subject: [PATCH 100/106] Bump dependencies --- pixi.lock | 159 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 75 deletions(-) diff --git a/pixi.lock b/pixi.lock index 73f8d611..04890b1c 100644 --- a/pixi.lock +++ b/pixi.lock @@ -73,7 +73,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -146,7 +146,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -192,6 +192,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-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/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl @@ -294,7 +295,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -364,7 +364,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -437,7 +437,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -536,6 +536,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl @@ -638,7 +639,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -704,7 +704,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -776,7 +776,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -868,6 +868,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl @@ -972,7 +973,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -1040,7 +1040,7 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.4.0-py312h90b7ffd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda @@ -1173,7 +1173,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -1220,6 +1220,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/e7/cd78635d0ece7e4d3393f2c1d2ebabf6ff4bd615da142891b1d42ad58abf/scipp-26.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl @@ -1324,7 +1325,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ae/61/3c1ea8c10bf4f6bf83c33a7f5b4a3143f4cc1f979859dec5498b6cc31900/pycifrw-5.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.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/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -1463,7 +1463,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -1491,7 +1491,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py312h4409184_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.4.0-py312h87c4bb7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda @@ -1561,6 +1561,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-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/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl @@ -1666,7 +1667,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b0/3e/a6497e1c2c9bc6ed2b79e0f2d31a4ce509fd2a9eed4e4f7ac63eda8113cb/gemmi-0.7.5-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b0/42/c84efcc1d4caebafb1ecd8be4643f39c85c47a80fe254d92b8b43b1eadaf/h5py-3.16.0-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -1801,7 +1801,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -1829,7 +1829,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.4.0-py312h06d0912_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.5.0-py312h06d0912_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py312he06e257_1.conda @@ -1896,6 +1896,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-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/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl @@ -2001,7 +2002,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -2124,7 +2124,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -2197,7 +2197,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -2243,6 +2243,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-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/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/25/7d/cea3531f77df694ac7f169378250d85f19f69b09a5f4fa45f650837ae7cc/py3dmol-2.5.4-py2.py3-none-any.whl @@ -2345,7 +2346,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -2415,7 +2415,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -2488,7 +2488,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -2587,6 +2587,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1f/7e/c2cfe0bdbec1f5ce2bd92e03311038e1c491dfd54824606f38a61167a3f0/crysfml-0.6.2-cp314-cp314-macosx_14_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-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/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl @@ -2689,7 +2690,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -2755,7 +2755,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -2827,7 +2827,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -2919,6 +2919,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1f/28/3f8aa247d29d010547d52207395cb057ebd0a40b88f64bc1dbac9e17a729/scipp-26.3.1-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl @@ -3023,7 +3024,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/46/661159ad844034ba8b3f4e0516215c41e4ee17db4213d13a82227670764f/sciline-25.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl @@ -3133,7 +3133,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -3206,7 +3206,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -3344,7 +3344,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -3417,7 +3417,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -3585,7 +3585,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda @@ -3657,7 +3657,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 @@ -3863,9 +3863,9 @@ packages: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 35598 timestamp: 1762509505285 -- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.4.0-py312h90b7ffd_0.conda - sha256: e8c83696e6529ac1909a96690c58624bb376312fd0768409380cd9b05e248c9b - md5: 542da724e75cdeef19e29cca23935c25 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.5.0-py312h90b7ffd_0.conda + sha256: a2b08a4e5e549b5f67c38edffd175437e2208547a7e67b5fa5373b67ef419e50 + md5: b31dba71fe091e7201826e57e0f7b261 depends: - python - libgcc >=14 @@ -3874,9 +3874,9 @@ packages: - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 238360 - timestamp: 1777848717715 + - pkg:pypi/backports-zstd?source=compressed-mapping + size: 239928 + timestamp: 1778594049826 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda sha256: 49df13a1bb5e388ca0e4e87022260f9501ed4192656d23dc9d9a1b4bf3787918 md5: 64088dffd7413a2dd557ce837b4cbbdb @@ -4088,6 +4088,7 @@ packages: - liblapacke 3.11.0 7*_openblas - mkl <2027 license: BSD-3-Clause + license_family: BSD purls: [] size: 18716 timestamp: 1778489854108 @@ -4137,6 +4138,7 @@ packages: - blas 2.307 openblas - liblapack 3.11.0 7*_openblas license: BSD-3-Clause + license_family: BSD purls: [] size: 18675 timestamp: 1778489861559 @@ -4871,16 +4873,17 @@ packages: - pkg:pypi/babel?source=hash-mapping size: 7684321 timestamp: 1772555330347 -- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.4.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda noarch: generic - sha256: de1755a35258eb1b59f2288559bbf0b76da60bd2fa6cd6f768ead442f85bd666 - md5: b712198b257f378e9bd8cde277218296 + sha256: a1c97297e867776760489537bc5ae36fa83a154be30e3b79385a39ca4cb058fe + md5: 1133126d840e75287d83947be3fc3e71 depends: - python >=3.14 license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: [] - size: 7546 - timestamp: 1777848733980 + purls: + - pkg:pypi/backports-zstd?source=compressed-mapping + size: 7533 + timestamp: 1778594057496 - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda sha256: bf1e71c3c0a5b024e44ff928225a0874fc3c3356ec1a0b6fe719108e6d1288f6 md5: 5267bef8efea4127aacd1f4e1f149b6e @@ -6028,9 +6031,9 @@ packages: - pkg:pypi/referencing?source=hash-mapping size: 51788 timestamp: 1760379115194 -- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda - sha256: 7f2c24dd3bd3c104a1d2c9a10ead5ed6758b0976b74f972cfe9c19884ccc4241 - md5: 9659f587a8ceacc21864260acd02fc67 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.0-pyhcf101f3_0.conda + sha256: 4487fdb341537e2df47159ed8e546add99080974c52d5b2dc2a710910619115a + md5: a5985537dab1ba7034b5ff4ea22e2fa9 depends: - python >=3.10 - certifi >=2023.5.7 @@ -6044,8 +6047,8 @@ packages: license_family: APACHE purls: - pkg:pypi/requests?source=hash-mapping - size: 63728 - timestamp: 1777030058920 + size: 68658 + timestamp: 1778534036810 - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda sha256: 3b45efeae771f1a20307b36ecdb3a8911a89c05382836b50c62b0a99d8d3dfd8 md5: da94ff04d97ec5efc42cbe5da3c43a84 @@ -6435,9 +6438,9 @@ packages: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 34218 timestamp: 1762509977830 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.4.0-py312h87c4bb7_0.conda - sha256: 7dbd64d3f06622ef8286be6dfceeb8e6008450fb4e6d9309fbb908b12f3937ff - md5: 95a833465ec45ac1e8f2ed1aaba8ec37 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.5.0-py312h87c4bb7_0.conda + sha256: a492dcf07b1c58797b3192f11aef7e3beb18ec91646d6a5acfe5c6e61e66118d + md5: 6ec306e02579965dc9c01092a5f4ce4c depends: - python - __osx >=11.0 @@ -6445,9 +6448,9 @@ packages: - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 239305 - timestamp: 1777848727027 + - pkg:pypi/backports-zstd?source=compressed-mapping + size: 240840 + timestamp: 1778594074672 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda sha256: 6178775a86579d5e8eec6a7ab316c24f1355f6c6ccbe84bb341f342f1eda2440 md5: 311fcf3f6a8c4eb70f912798035edd35 @@ -6628,6 +6631,7 @@ packages: - liblapack 3.11.0 7*_openblas - liblapacke 3.11.0 7*_openblas license: BSD-3-Clause + license_family: BSD purls: [] size: 18783 timestamp: 1778489983152 @@ -6674,6 +6678,7 @@ packages: - liblapack 3.11.0 7*_openblas - liblapacke 3.11.0 7*_openblas license: BSD-3-Clause + license_family: BSD purls: [] size: 18810 timestamp: 1778489991330 @@ -6868,6 +6873,7 @@ packages: - openmp 22.1.5|22.1.5.* - intel-openmp <0.0a0 license: Apache-2.0 WITH LLVM-exception + license_family: APACHE purls: [] size: 285806 timestamp: 1778447786965 @@ -7309,9 +7315,9 @@ packages: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 38653 timestamp: 1762509771011 -- conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.4.0-py312h06d0912_0.conda - sha256: 71caf40c0fdeb11fafaac639e6e6f9120112aa105a7a5e9dfb5b4b06db9ca97a - md5: 77d0a2bdd46dd8d502bb27eb80353fcd +- conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.5.0-py312h06d0912_0.conda + sha256: 55173c22b24fd257851f2967d4b0256172be3455bd5246b6b7a5c21eb0863f98 + md5: 891112b1a79fc9800317c5d56e056a8b depends: - python - vc >=14.3,<15 @@ -7321,9 +7327,9 @@ packages: - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - - pkg:pypi/backports-zstd?source=hash-mapping - size: 237107 - timestamp: 1777848740547 + - pkg:pypi/backports-zstd?source=compressed-mapping + size: 238601 + timestamp: 1778594083648 - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda sha256: 2bb6f384a51929ef2d5d6039fcf6c294874f20aaab2f63ca768cbe462ed4b379 md5: e8e7a6346a9e50d19b4daf41f367366f @@ -7471,6 +7477,7 @@ packages: - liblapacke 3.11.0 7*_mkl - liblapack 3.11.0 7*_mkl license: BSD-3-Clause + license_family: BSD purls: [] size: 68060 timestamp: 1778490352569 @@ -7485,6 +7492,7 @@ packages: - liblapacke 3.11.0 7*_mkl - liblapack 3.11.0 7*_mkl license: BSD-3-Clause + license_family: BSD purls: [] size: 68594 timestamp: 1778490364980 @@ -7660,6 +7668,7 @@ packages: - openmp 22.1.5|22.1.5.* - intel-openmp <0.0a0 license: Apache-2.0 WITH LLVM-exception + license_family: APACHE purls: [] size: 347493 timestamp: 1778448334890 @@ -8785,6 +8794,19 @@ packages: requires_dist: - nbformat requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/20/5b/885f479093f6627669d39b57bc3d4e674da532e1a4b247d473a61d8d2118/virtualenv-21.3.2-py3-none-any.whl + name: virtualenv + version: 21.3.2 + sha256: c58ea748fa50bb2a4367da5ba3d30b02458ed40b4ea888faad94021f3309f764 + requires_dist: + - distlib>=0.3.7,<1 + - filelock>=3.24.2,<4 ; python_full_version >= '3.10' + - filelock>=3.16.1,<=3.19.1 ; python_full_version < '3.10' + - importlib-metadata>=6.6 ; python_full_version < '3.8' + - platformdirs>=3.9.1,<5 + - python-discovery>=1.2.2 + - typing-extensions>=4.13.2 ; python_full_version < '3.11' + requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/20/7a/1c6e3562dfd8950adbb11ffbc65d21e7c89d01a6e4f137fa981056de25c5/gitpython-3.1.50-py3-none-any.whl name: gitpython version: 3.1.50 @@ -11666,19 +11688,6 @@ packages: version: 7.4.3 sha256: b95c934b9ad59e2ba8abb9be49df70d3ad1b0d95d864b9fdb7588d4fa8bd921c requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl - name: virtualenv - version: 21.3.1 - sha256: d1a71cf58f2f9228fff23a1f6ec15d39785c6b32e03658d104974247145edd35 - requires_dist: - - distlib>=0.3.7,<1 - - filelock>=3.24.2,<4 ; python_full_version >= '3.10' - - filelock>=3.16.1,<=3.19.1 ; python_full_version < '3.10' - - importlib-metadata>=6.6 ; python_full_version < '3.8' - - platformdirs>=3.9.1,<5 - - python-discovery>=1.2.2 - - typing-extensions>=4.13.2 ; python_full_version < '3.11' - requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl name: mdurl version: 0.1.2 From d17b4797ededfc7e95056392050afcbf16f5a806 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Wed, 13 May 2026 14:48:02 +0200 Subject: [PATCH 101/106] Add ADR documents --- docs/dev/adr_analysis-cif-fit-state.md | 221 ++++++ .../adr_parameter-correlation-persistence.md | 114 +++ docs/dev/adr_parameter-posterior-summary.md | 684 ++++++++++++++++++ docs/dev/adr_undo-fit.md | 163 +++++ 4 files changed, 1182 insertions(+) create mode 100644 docs/dev/adr_analysis-cif-fit-state.md create mode 100644 docs/dev/adr_parameter-correlation-persistence.md create mode 100644 docs/dev/adr_parameter-posterior-summary.md create mode 100644 docs/dev/adr_undo-fit.md diff --git a/docs/dev/adr_analysis-cif-fit-state.md b/docs/dev/adr_analysis-cif-fit-state.md new file mode 100644 index 00000000..bf4af6f6 --- /dev/null +++ b/docs/dev/adr_analysis-cif-fit-state.md @@ -0,0 +1,221 @@ +# ADR: Analysis CIF Fit State + +**Status:** Proposed +**Date:** 2026-05-13 + +## Context + +`analysis/analysis.cif` currently persists analysis configuration such +as `_fit.minimizer_type`, `_fit.mode`, aliases, constraints, and +joint-fit weights. It does not persist analysis-owned fit state such as +fit bounds, bound provenance, pre-fit scalar snapshots, or latest +fit-status metadata. + +At the same time, parameter CIF serialization already carries the +committed parameter `value`, the current `free` state, and the current +`uncertainty` via CIF bracket notation. That data belongs to the model +and should remain in structure or experiment CIF files. + +The missing piece is analysis-owned fit state: + +- fit controls that apply to parameters during fitting but are not part + of the model itself +- latest fit-status metadata shown by `display.fit_results()` +- deterministic and Bayesian fit metadata that should survive project + reloads and command-line workflows + +This separation matters because: + +- Bayesian plotting after reload needs `fit_min`, `fit_max`, and bound + provenance even when raw posterior arrays are absent +- command-line users need a saved pre-fit starting state to recover from + a poor minimization run +- `analysis.fit_results` already changes by fit type, but its persisted + projection should have a stable analysis-owned home + +The current architecture document still describes fit results as +runtime-only. This ADR proposes a narrower persisted projection of the +latest fit state, not a direct dump of backend runtime objects. + +## Decision + +### 1. `analysis/analysis.cif` becomes the home of analysis-owned fit state + +The analysis CIF file will persist: + +- fit configuration +- aliases and constraints +- joint-fit weights +- per-parameter fit controls owned by analysis +- latest fit-status metadata common to deterministic and Bayesian fits +- fit-type-specific extensions defined in separate ADRs + +Committed parameter values remain in structure or experiment CIF files. +They are not duplicated into `analysis/analysis.cif`. + +### 2. Add a real `_fit_parameter` loop + +Introduce a new analysis-owned loop category: + +```cif +loop_ +_fit_parameter.param_unique_name +_fit_parameter.fit_min +_fit_parameter.fit_max +_fit_parameter.fit_bounds_uncertainty_multiplier +_fit_parameter.start_value +_fit_parameter.start_uncertainty +cosio.atom_site.Co1.adp_iso 0.0000 0.1200 4.0 0.0312 0.0021 +cosio.atom_site.Co2.adp_iso 0.0000 0.1200 4.0 0.0312 0.0021 +``` + +Fields: + +- `param_unique_name` +- `fit_min` +- `fit_max` +- `fit_bounds_uncertainty_multiplier` +- `start_value` +- `start_uncertainty` + +Rationale: + +- `fit_min` and `fit_max` are required to restore deterministic and + Bayesian fit controls faithfully. +- `fit_bounds_uncertainty_multiplier` preserves the provenance of + uncertainty-derived bounds for restored Bayesian plot annotations. +- `start_value` and `start_uncertainty` capture the last committed + pre-fit scalar state and enable fit recovery workflows, especially in + command-line usage. +- `start_uncertainty` preserves a user-visible pre-fit uncertainty + instead of treating it as disposable fit residue. + +### 3. Add a generic `_fit_result` single-item category + +Persist the latest fit-status metadata shared across fit types in a +single analysis-owned category: + +- `result_kind` +- `success` +- `message` +- `iterations` +- `fitting_time` +- `reduced_chi_square` + +Suggested CIF fragment: + +```cif +_fit_result.result_kind deterministic +_fit_result.success yes +_fit_result.message "Fit converged" +_fit_result.iterations 37 +_fit_result.fitting_time 1.82 +_fit_result.reduced_chi_square 1.031 +``` + +`result_kind` distinguishes the latest persisted fit projection, for +example `deterministic` or `bayesian`. + +### 4. Persist only stable fit-status fields here + +The `_fit_result` category is for generic status fields that are stable +across engines and already belong to the result model. + +It should not persist backend runtime objects or arbitrary engine +payloads. + +Metrics such as R-factors shown by `display.fit_results()` are derived +from observed and calculated data and can be recomputed after load when +needed. They do not need to be part of the first persisted fit-state +schema. + +### 5. Fit-type-specific extensions build on this ADR + +This ADR defines the common `analysis.cif` contract for deterministic +and Bayesian fitting. + +Fit-type-specific extensions are layered on top: + +- Bayesian persistence extends this with `_bayesian_*` categories and an + HDF5 sidecar, as described in + `adr_parameter-posterior-summary.md`. +- Future fit-specific summaries should follow the same pattern: generic + shared fields in `_fit_result`, specialized fields in separate + categories. + +### 6. Restore order is analysis-first, fit-type-second + +Load order should be: + +1. standard analysis configuration +2. aliases and constraints +3. joint-fit weights +4. `_fit_parameter` +5. `_fit_result` +6. fit-type-specific extensions such as `_bayesian_*` + +This ensures that generic fit controls are available before restoring +specialized fit summaries. + +### 7. Suggested full `analysis.cif` example + +```cif +_fit.minimizer_type "bumps (dream)" +_fit.mode single + +loop_ +_alias.label +_alias.param_unique_name +biso_Co1 cosio.atom_site.Co1.adp_iso +biso_Co2 cosio.atom_site.Co2.adp_iso + +loop_ +_constraint.expression +"biso_Co2 = biso_Co1" + +loop_ +_fit_parameter.param_unique_name +_fit_parameter.fit_min +_fit_parameter.fit_max +_fit_parameter.fit_bounds_uncertainty_multiplier +_fit_parameter.start_value +_fit_parameter.start_uncertainty +cosio.atom_site.Co1.adp_iso 0.0000 0.1200 4.0 0.0312 0.0021 +cosio.atom_site.Co2.adp_iso 0.0000 0.1200 4.0 0.0312 0.0021 + +_fit_result.result_kind bayesian +_fit_result.success yes +_fit_result.message "Sampler converged" +_fit_result.iterations 3000 +_fit_result.fitting_time 82.4 +_fit_result.reduced_chi_square 1.031 + +# Bayesian-specific extension categories follow here. +``` + +## Consequences + +### Positive + +- `analysis.cif` becomes the single analysis-owned source of fit state. +- Deterministic and Bayesian persistence share one common base schema. +- Fit bounds, bound provenance, and start values survive project + reloads. +- Command-line workflows gain a persisted pre-fit starting state. + +### Trade-offs + +- The architecture document must be updated because fit state is no + longer entirely runtime-only. +- Analysis persistence becomes more stateful and must be kept in sync + with live parameter objects. +- Some existing serializer assumptions will need refactoring so that + `analysis.cif` owns fit metadata rather than individual parameters. + +## Deferred Work + +- Bayesian-specific categories and HDF5 sidecar details remain in + `adr_parameter-posterior-summary.md`. +- Undo semantics for `start_value` and `start_uncertainty` are defined + in a separate ADR. +- Correlation-matrix persistence is defined in a separate ADR. diff --git a/docs/dev/adr_parameter-correlation-persistence.md b/docs/dev/adr_parameter-correlation-persistence.md new file mode 100644 index 00000000..5d7b6888 --- /dev/null +++ b/docs/dev/adr_parameter-correlation-persistence.md @@ -0,0 +1,114 @@ +# ADR: Parameter Correlation Persistence + +**Status:** Proposed +**Date:** 2026-05-13 + +## Context + +`plot_param_correlations()` can currently visualize either: + +- deterministic parameter correlations derived from engine covariance +- Bayesian correlations derived from posterior samples + +After project reload, this correlation information is not available +unless the underlying runtime objects are rebuilt. For Bayesian fits, +full posterior samples may not always be restored. For deterministic +fits, engine covariance is typically not persisted at all. + +The correlation matrix is an analysis-owned summary, not model state. +It therefore belongs in `analysis/analysis.cif`, not in structure or +experiment CIF files. + +## Decision + +### 1. Add a `_fit_parameter_correlation` loop category + +Persist pairwise parameter correlations in a new analysis-owned loop: + +- `source_kind` +- `param_unique_name_i` +- `param_unique_name_j` +- `correlation` + +Suggested example: + +```cif +loop_ +_fit_parameter_correlation.source_kind +_fit_parameter_correlation.param_unique_name_i +_fit_parameter_correlation.param_unique_name_j +_fit_parameter_correlation.correlation +posterior cosio.atom_site.Co1.adp_iso cosio.atom_site.Co2.adp_iso 0.87 +``` + +`source_kind` records how the correlation was obtained, for example: + +- `deterministic` +- `posterior` + +### 2. Store only the upper triangle excluding the diagonal + +Each row stores one unordered parameter pair with +`param_unique_name_i < param_unique_name_j` in a stable ordering. + +The diagonal is omitted because it is always 1.0 and can be rebuilt on +load. + +This keeps the CIF loop compact while remaining lossless for the +correlation matrix. + +### 3. Treat the loop as a summary, not a replacement for raw samples + +For Bayesian fits, `_fit_parameter_correlation` is a persisted summary. +It does not replace posterior samples or posterior pair data. + +This means: + +- correlation heatmaps can be restored from the loop alone +- posterior pair plots still require posterior samples + +### 4. Deterministic and Bayesian fits share the same loop schema + +The same loop category is used for both deterministic and Bayesian fit +results. The distinction is carried by `source_kind`, not by separate +loop names. + +### 5. Suggested restore behavior + +On load: + +- if `_fit_parameter_correlation` is present, correlation summaries are + restored into a lightweight analysis-owned correlation structure +- if it is absent, correlation plots fall back to whatever live runtime + information is available + +### 6. Suggested user-facing behavior + +```python +# Restored from analysis.cif when available +project.display.plotter.plot_param_correlations() +``` + +If only the correlation loop is restored, the user still gets the +correlation heatmap without needing raw posterior samples. + +## Consequences + +### Positive + +- Deterministic and Bayesian correlation summaries survive reload. +- Correlation heatmaps no longer depend entirely on runtime-only data. +- The schema is compact and fit-type-agnostic. + +### Trade-offs + +- The correlation loop is a derived summary, so it must be kept in sync + with the latest fit result. +- Restored correlation data is not enough for posterior pair plots or + predictive summaries. + +## Deferred Work + +- optional storage of covariance matrices in addition to correlations +- multiple named correlation sources for the same saved project +- full correlation restoration for pair-plot density surfaces diff --git a/docs/dev/adr_parameter-posterior-summary.md b/docs/dev/adr_parameter-posterior-summary.md new file mode 100644 index 00000000..5469a2bd --- /dev/null +++ b/docs/dev/adr_parameter-posterior-summary.md @@ -0,0 +1,684 @@ +# ADR: Parameter-Level Posterior Projection and Bayesian Persistence + +**Status:** Proposed +**Date:** 2026-05-13 + +## Context + +`GenericParameter` already stores fit-adjacent helper data such as +`uncertainty`, `fit_min`, and `fit_max`, while `value` remains the +single scalar used by calculations. + +Bayesian DREAM currently keeps posterior state only on +`analysis.fit_results` via `BayesianFitResults`, including +`posterior_samples`, `posterior_parameter_summaries`, +`posterior_predictive`, diagnostics, and sampler settings. The current +architecture document describes this state as runtime-only and not +serialized. + +`analysis.fit_results` already changes by analysis type: deterministic +fits use `FitResults`, while posterior-capable fits such as DREAM use +`BayesianFitResults`. This ADR preserves that result-model split. + +The user-facing need is more local: when a posterior-capable fit has +completed, each parameter should expose a compact Bayesian summary for +inspection without forcing users to traverse `analysis.fit_results`. +At the same time, `parameter.value` must remain the only scalar used by +the live model, minimizer setup, constraints, and category updates. + +There is also a staleness problem. After a manual parameter edit or a +new fit, fit-derived helper data must be cleared or replaced as a +group. Keeping old posterior summaries after the active parameter state +changes would mislead users. + +One more implementation constraint matters: minimizers currently apply +final fitted values through `_set_value_from_minimizer(...)` and then +write `param.uncertainty = ...` directly. If `uncertainty` and +posterior metadata become read-only fit outputs and the public `value` +setter starts clearing stale fit metadata on manual edits, fit-result +application must move to a dedicated internal update path so that valid +fit outputs are installed atomically instead of being cleared +accidentally. + +## Decision + +### 1. Add one optional posterior object to each parameter + +Each `GenericParameter` will gain a read-only +`posterior` property whose default value is `None`. + +This property is convenience metadata only. It does not participate in +calculations. `parameter.value` remains the only scalar used by the +live model. + +### 2. Reuse the existing Bayesian summary container + +Do not add separate flat parameter attributes such as `median`, +`map_estimate`, `interval_95`, `r_hat`, or `ess_bulk`. + +Instead, the parameter-level projection reuses the existing +`PosteriorParameterSummary` object already produced for +`BayesianFitResults`. This keeps one grouped summary shape for display, +inspection, and later persistence. + +The summary object currently provides the right level of detail: + +- `map_estimate` +- `median` +- `uncertainty` +- `interval_68` +- `interval_95` +- `r_hat` +- `ess_bulk` + +`unique_name` and `display_name` remain redundant but acceptable when +the object is attached to a parameter. + +Different communities use different names for this scalar spread term: +`standard deviation`, `estimated standard deviation` (`e.s.d.`), and +`standard uncertainty` (`s.u.` / `su`). The public EasyDiffraction API +selects `uncertainty` as the canonical name because it already matches +the existing parameter API, aligns better with CIF terminology, and can +be used consistently for both deterministic and Bayesian results. For +Bayesian summaries, this `uncertainty` value is computed from the +posterior standard deviation. + +The internal field names stay compact and code-oriented. User-facing +tables, summaries, and plot annotations should use these friendly +labels: + +- `map_estimate` -> `MAP estimate` +- `median` -> `Median` +- `uncertainty` -> `Standard uncertainty` +- `interval_68` -> `68% credible interval` +- `interval_95` -> `95% credible interval` +- `r_hat` -> `R-hat` +- `ess_bulk` -> `Bulk ESS` + +Asymmetric interval information remains explicit through the stored +lower and upper bounds. For example, `parameter.posterior.interval_95` +returns a `(lower, upper)` tuple rather than one symmetric uncertainty +value. + +Example user access: + +```python +param = project.phases['lbco'].cell.length_a + +current_value = param.value +current_uncertainty = param.uncertainty + +if param.posterior is not None: + map_estimate = param.posterior.map_estimate + median = param.posterior.median + uncertainty = param.posterior.uncertainty + low95, high95 = param.posterior.interval_95 + r_hat = param.posterior.r_hat + ess_bulk = param.posterior.ess_bulk +``` + +### 3. Make fit outputs read-only for the user + +`uncertainty` becomes a read-only fit output on the public parameter +API. `posterior` is also read-only. + +Users may inspect these properties, but only internal fit-application +paths may set or clear them. + +This keeps the writable public parameter state focused on user intent: +`value`, `free`, `fit_min`, `fit_max`, and related configuration. + +### 4. Populate it only for posterior-capable fit methods + +Only fit methods that actually produce posterior summaries may populate +`parameter.posterior`. + +At present this means only `bumps (dream)`. + +Do not add a generic minimizer-capability abstraction yet. That would +introduce a new abstraction before there is a second concrete posterior +fit method. When another posterior-capable minimizer exists, the shared +contract can be extracted then. + +### 5. Treat parameter-level posterior data as a projection, not the canonical result + +The canonical Bayesian result remains `analysis.fit_results`. + +`parameter.posterior` is a synchronized projection of the current fit +result for user convenience. It must never be the only place where +Bayesian information lives, because it cannot represent joint posterior +arrays, predictive summaries, or cross-parameter correlations. + +### 6. Clear or replace fit-derived metadata as a group + +Fit-derived helper data on a parameter must be coherent. + +The following policy applies: + +- Manual edit of `parameter.value` clears `parameter.uncertainty` and + `parameter.posterior`. +- A deterministic fit replaces `value` and `uncertainty`, then clears + `posterior`. +- A posterior fit replaces `value`, `uncertainty`, and `posterior` + together. + +Manual user edits of `uncertainty` and `posterior` are not supported, +because both are read-only fit outputs. + +Configuration attributes such as `free`, `fit_min`, `fit_max`, units, +and `fit_bounds_uncertainty_multiplier` are not cleared by this policy. +They are parameter configuration or user intent, not posterior output. + +### 7. Add a dedicated internal fit-application path + +To support the clearing policy above, fit application must not rely on +public setters alone. + +Implementation should add private helpers on `GenericParameter` to set +and clear fit-derived state explicitly, for example: + +- `_set_uncertainty(...)` +- `_set_posterior(...)` +- `_clear_fit_metadata()` +- `_apply_deterministic_fit_update(...)` +- `_apply_posterior_fit_update(...)` + +The exact helper names can be refined during implementation, but the +design requirement is fixed: manual user edits clear stale metadata, +while internal fit application installs fresh metadata atomically. + +### 8. Commit MAP to `parameter.value` after Bayesian fits + +After a posterior-capable fit, `parameter.value` is committed from the +maximum-a-posteriori estimate. + +MAP is chosen because it is a coherent joint point estimate across all +free parameters. Marginal medians remain available on +`parameter.posterior`, but they are summary data rather than the active +live model state. + +### 9. Keep `uncertainty` as a convenience scalar after Bayesian fits + +`parameter.uncertainty` remains a single convenience scalar even after +posterior fits. + +For posterior-capable fits, populate it from posterior standard +deviation and expose it as `uncertainty`. This preserves one scalar API +term across deterministic and Bayesian results while keeping the +calculation itself statistically conventional. + +Asymmetric interval information is not squeezed into +`parameter.uncertainty`; it remains available only via +`parameter.posterior`. + +### 10. Persist canonical Bayesian state at analysis level + +Canonical Bayesian state is owned by `analysis.fit_results`, not by +individual parameters. + +When the active result is a `BayesianFitResults` instance, persistence +must save enough data to restore two distinct capability levels: + +- summary-only restore for parameter inspection and tables +- full restore for posterior plots and predictive plots + +`parameter.posterior` is never serialized as a per-parameter property. +It is always rebuilt from the canonical analysis-level persisted data. + +### 11. Persist fit-control and Bayesian metadata in `analysis/analysis.cif` + +The existing `analysis/analysis.cif` file remains the text metadata +entry point for analysis persistence. + +The persisted fit-control and Bayesian metadata is split into explicit +CIF categories. + +#### 11.1 `_fit_parameter` loop + +Stores analysis-owned per-parameter fit metadata that is not currently +covered by parameter CIF serialization. + +This loop exists because the committed parameter CIF representation +already carries the active `value`, current `free` state, and current +`uncertainty`, but it does not carry fit bounds, bound provenance, or +the pre-fit uncertainty snapshot needed by undo. Those fields are +required for Bayesian plot ranges, pair-plot bound annotations, and +clean fit rollback after project reload. + +Fields: + +- `param_unique_name` +- `fit_min` +- `fit_max` +- `fit_bounds_uncertainty_multiplier` +- `start_value` +- `start_uncertainty` + +`fit_min` and `fit_max` are required for restored Bayesian plotting. +`fit_bounds_uncertainty_multiplier` is required if restored plots should +preserve the uncertainty-derived bound annotation exactly. +`start_value` and `start_uncertainty` are required for clean +cross-session undo. If omitted, restored fit reports may show `N/A` for +`start` and `change`, and undo may need to clear uncertainty as a +compatibility fallback. + +#### 11.2 `_bayesian_result` single item + +Stores one saved Bayesian result header with these fields: + +- `schema_version` +- `sampler_name` +- `point_estimate_name` +- `success` +- `sampler_completed` +- `reduced_chi_square` +- `fitting_time` +- `best_log_posterior` +- `credible_interval_inner` +- `credible_interval_outer` +- `has_posterior_samples` +- `has_posterior_predictive` +- `sidecar_file` + +For the current design, `point_estimate_name` is always `map`. + +#### 11.3 `_bayesian_sampler` single item + +Stores resolved sampler settings actually used for the run: + +- `steps` +- `burn` +- `thin` +- `pop` +- `parallel` +- `init` +- `random_seed` + +This persists the existing runtime `sampler_settings` in an explicit, +schema-driven form rather than as an open-ended key/value mapping. + +#### 11.4 `_bayesian_convergence` single item + +Stores top-level convergence and shape metadata: + +- `converged` +- `max_r_hat` +- `min_ess_bulk` +- `n_draws` +- `n_chains` +- `n_parameters` + +Per-parameter `r_hat` and `ess_bulk` remain in the parameter summary +loop described below. + +#### 11.5 `_bayesian_parameter_posterior` loop + +Stores one canonical posterior summary row per sampled parameter. +These rows are the source used to rebuild `parameter.posterior` on +load. + +Fields: + +- `order_index` +- `unique_name` +- `display_name` +- `map_estimate` +- `median` +- `uncertainty` +- `interval_68_lower` +- `interval_68_upper` +- `interval_95_lower` +- `interval_95_upper` +- `ess_bulk` +- `r_hat` + +`order_index` defines the parameter order used by posterior sample +columns in the sidecar arrays. + +#### 11.6 `_bayesian_predictive_dataset` loop + +Stores one manifest row per persisted posterior predictive summary. + +Fields: + +- `experiment_name` +- `x_axis_name` +- `x_path` +- `map_prediction_path` +- `lower_95_path` +- `upper_95_path` +- `lower_68_path` +- `upper_68_path` +- `draws_path` +- `n_x` +- `n_draws_cached` + +This loop tells the loader which arrays to read from the sidecar file +for each experiment-level predictive summary. + +#### 11.7 Suggested CIF fragments + +The active parameter value remains in the structure or experiment CIF as +it does today, for example: + +```cif +_atom_site_U_iso_or_equiv 0.0319(21) +``` + +Analysis-owned fit-control and Bayesian metadata then lives in +`analysis/analysis.cif`, for example: + +```cif +_fit.minimizer_type "bumps (dream)" +_fit.mode single + +loop_ +_fit_parameter.param_unique_name +_fit_parameter.fit_min +_fit_parameter.fit_max +_fit_parameter.fit_bounds_uncertainty_multiplier +_fit_parameter.start_value +_fit_parameter.start_uncertainty +cosio.atom_site.Co1.adp_iso 0.0000 0.1200 4.0 0.0312 0.0021 +cosio.atom_site.Co2.adp_iso 0.0000 0.1200 4.0 0.0312 0.0021 + +_bayesian_result.schema_version 1 +_bayesian_result.sampler_name dream +_bayesian_result.point_estimate_name map +_bayesian_result.success yes +_bayesian_result.sampler_completed yes +_bayesian_result.reduced_chi_square 1.031 +_bayesian_result.fitting_time 82.4 +_bayesian_result.best_log_posterior -1542.77 +_bayesian_result.credible_interval_inner 0.68 +_bayesian_result.credible_interval_outer 0.95 +_bayesian_result.has_posterior_samples yes +_bayesian_result.has_posterior_predictive yes +_bayesian_result.sidecar_file "bayesian_data.h5" + +_bayesian_sampler.steps 3000 +_bayesian_sampler.burn 600 +_bayesian_sampler.thin 1 +_bayesian_sampler.pop 20 +_bayesian_sampler.parallel 0 +_bayesian_sampler.init lhs +_bayesian_sampler.random_seed 12345 + +_bayesian_convergence.converged yes +_bayesian_convergence.max_r_hat 1.01 +_bayesian_convergence.min_ess_bulk 812.4 +_bayesian_convergence.n_draws 2400 +_bayesian_convergence.n_chains 20 +_bayesian_convergence.n_parameters 2 + +loop_ +_bayesian_parameter_posterior.order_index +_bayesian_parameter_posterior.unique_name +_bayesian_parameter_posterior.display_name +_bayesian_parameter_posterior.map_estimate +_bayesian_parameter_posterior.median +_bayesian_parameter_posterior.uncertainty +_bayesian_parameter_posterior.interval_68_lower +_bayesian_parameter_posterior.interval_68_upper +_bayesian_parameter_posterior.interval_95_lower +_bayesian_parameter_posterior.interval_95_upper +_bayesian_parameter_posterior.ess_bulk +_bayesian_parameter_posterior.r_hat +0 cosio.atom_site.Co1.adp_iso "Co1 ADP" 0.0319 0.0317 0.0021 0.0298 0.0339 0.0278 0.0361 812.4 1.01 +1 cosio.atom_site.Co2.adp_iso "Co2 ADP" 0.0320 0.0318 0.0020 0.0300 0.0338 0.0281 0.0359 830.7 1.00 + +loop_ +_bayesian_predictive_dataset.experiment_name +_bayesian_predictive_dataset.x_axis_name +_bayesian_predictive_dataset.x_path +_bayesian_predictive_dataset.map_prediction_path +_bayesian_predictive_dataset.lower_95_path +_bayesian_predictive_dataset.upper_95_path +_bayesian_predictive_dataset.lower_68_path +_bayesian_predictive_dataset.upper_68_path +_bayesian_predictive_dataset.draws_path +_bayesian_predictive_dataset.n_x +_bayesian_predictive_dataset.n_draws_cached +hrpt ttheta /predictive/hrpt/x /predictive/hrpt/map_prediction /predictive/hrpt/lower_95 /predictive/hrpt/upper_95 /predictive/hrpt/lower_68 /predictive/hrpt/upper_68 /predictive/hrpt/draws 2500 200 +``` + +### 12. Persist bulk arrays in `analysis/bayesian_data.h5` + +Large numerical arrays are stored outside CIF text in a single sidecar +file: + +- `analysis/bayesian_data.h5` + +The sidecar is optional. Summary-only restore remains valid without it. + +HDF5 is selected instead of NPZ because the persisted Bayesian payload +is a structured collection of named datasets with heterogeneous shapes, +optional groups, and potentially large predictive arrays. HDF5 provides +explicit hierarchical storage, dataset metadata, selective reads, and a +better long-term path for compression or chunking. NPZ is simpler, but +it is flatter and less suitable once the saved Bayesian state grows +beyond a small set of arrays. + +#### 12.1 Required core HDF5 dataset paths when posterior samples are saved + +- `posterior_parameter_samples` +- `posterior_log_posterior` +- `posterior_draw_index` + +Expected array shapes: + +- `posterior_parameter_samples`: `(n_draws, n_chains, n_parameters)` +- `posterior_log_posterior`: `(n_draws, n_chains)` when available +- `posterior_draw_index`: `(n_draws,)` when available + +If `posterior_log_posterior` or `posterior_draw_index` are unavailable, +their corresponding header flags remain false and the arrays may be +omitted. + +#### 12.2 Predictive dataset keys + +Posterior predictive arrays are addressed through the +`_bayesian_predictive_dataset` manifest rather than inferred from file +ordering. + +Recommended HDF5 dataset naming is: + +- `predictive____x` +- `predictive____map_prediction` +- `predictive____lower_95` +- `predictive____upper_95` +- `predictive____lower_68` +- `predictive____upper_68` +- `predictive____draws` + +The manifest, not the naming convention, is the source of truth. + +Recommended HDF5 group layout is: + +- `/posterior/parameter_samples` +- `/posterior/log_posterior` +- `/posterior/draw_index` +- `/predictive//x` +- `/predictive//map_prediction` +- `/predictive//lower_95` +- `/predictive//upper_95` +- `/predictive//lower_68` +- `/predictive//upper_68` +- `/predictive//draws` + +The manifest remains the canonical mapping used by the loader, so this +layout is recommended rather than mandatory. + +#### 12.3 What is not persisted in the sidecar + +Do not persist backend-specific runtime objects such as `engine_result`, +the DREAM driver, or ArviZ `InferenceData`. + +Those objects can be rebuilt from canonical saved arrays when needed, +or left unavailable after load. + +### 13. Restore flow and partial-availability policy + +Persistence must support both full and partial restore. + +#### 13.1 Save flow + +When `Project.save()` sees `analysis.fit_results` as a +`BayesianFitResults` instance: + +1. It writes standard analysis configuration to `analysis/analysis.cif`. +2. It appends `_fit_parameter`, `_bayesian_result`, + `_bayesian_sampler`, `_bayesian_convergence`, and + `_bayesian_parameter_posterior`. +3. If posterior predictive summaries are available, it also writes the + `_bayesian_predictive_dataset` manifest. +4. If posterior sample arrays or predictive arrays are available, it + writes `analysis/bayesian_data.h5`. + +#### 13.2 Load flow + +When `Project.load()` restores `analysis/analysis.cif`: + +1. Standard analysis configuration is restored first. +2. If `_fit_parameter` is present, fit bounds, bound provenance, and + optional pre-fit scalar snapshots are restored by matching + `param_unique_name` to live parameters. +3. If Bayesian categories are present, a lightweight + `BayesianFitResults` instance is rebuilt from persisted metadata and + parameter summary rows. +4. `parameter.posterior` is rebuilt by matching summary rows to live + parameters via `unique_name`. +5. `parameter.value` and `parameter.uncertainty` continue to come from + the normal project serialization path; Bayesian restore does not + overwrite them. +6. If `analysis/bayesian_data.h5` exists and matches the manifest, + `posterior_samples` and `posterior_predictive` are restored. +7. If the sidecar is missing or incomplete, the restore degrades to + summary-only mode without failing the whole project load. + +#### 13.3 Partial restore behavior + +The chosen partial-restore policy is: + +- `parameter.posterior` and `display.fit_results()` remain available + from saved metadata and summaries. +- Bayesian-only plots requiring canonical posterior arrays remain + unavailable unless those arrays were restored successfully. +- Missing sidecar data should produce a clear warning, not a hard load + failure. + +Example user access after load: + +```python +project = Project.load('/path/to/project') + +param = project.phases['lbco'].cell.length_a +posterior = param.posterior + +if posterior is not None: + print(posterior.map_estimate) + print(posterior.uncertainty) + print(posterior.interval_68) + +project.analysis.display.fit_results() +``` + +Example plotting behavior after load: + +```python +# Works with summary-only restore +project.analysis.display.fit_results() + +# Requires canonical posterior arrays from analysis/bayesian_data.h5 +project.display.plotter.plot_posterior_pairs() +project.display.plotter.plot_param_distribution(param) +project.display.plotter.plot_posterior_predictive(expt_name='hrpt') +``` + +### 14. Keep parameter posterior data rebuilt, not duplicated + +`parameter.posterior` is always rebuilt from the canonical +`_bayesian_parameter_posterior` loop in `analysis/analysis.cif`. + +Do not serialize posterior summaries again inside each parameter's own +CIF representation. Duplicating the same posterior summary data across +structure and experiment files would create multiple sources of truth. + +## Consequences + +### Positive + +- Users get a compact Bayesian overview directly from each parameter. +- The parameter API stays tidy because posterior helpers are grouped + into one optional object rather than many flat attributes. +- `uncertainty` and posterior metadata become clearly fit-owned rather + than mixed user-editable and fit-editable state. +- `analysis.fit_results` remains the canonical source for full Bayesian + state. +- `analysis/analysis.cif` becomes the home for fit-control metadata + that does not belong in structure or experiment CIF files. +- Bayesian save/load gains a clear split between text metadata in + `analysis/analysis.cif` and bulk numerical arrays in + `analysis/bayesian_data.h5`. +- Partial restore works for summaries even when full posterior arrays + are absent. +- The design matches the current rule that `value` is the only active + scalar used for calculations. + +### Trade-offs + +- `GenericParameter` now holds an optional reference to analysis-derived + metadata. +- Any manual user edit invalidates fit-derived metadata more eagerly + than today. +- `uncertainty` becomes a read-only public property, so fit-result + application code must be updated to use dedicated internal helpers + rather than a mix of `_set_value_from_minimizer(...)` and public + uncertainty assignment. +- Bayesian persistence now spans both CIF metadata and a binary sidecar, + so save/load code must validate consistency between the two. + +## Layering and Ownership + +To keep `core/` free of Bayesian computations, the parameter object must +not compute posterior summaries itself. + +The summary object is created by posterior-capable fit code and then +attached to parameters as already-computed metadata. `core/variable.py` +should avoid eager runtime imports of Bayesian helper modules; a +type-only import is acceptable. + +## Deferred Work + +This ADR now defines persistence for one canonical saved Bayesian run. + +It still defers: + +- support for multiple saved Bayesian runs per project +- plot-ready cache layers beyond canonical posterior and predictive data +- persistence-time compression or chunking strategies beyond the first + HDF5 sidecar implementation +- persistence for future posterior-capable minimizers beyond DREAM +- enabling currently unsupported single-crystal predictive draw plots + +## Implementation Notes + +- The first implementation should only populate + `parameter.posterior` for DREAM. +- Existing `PosteriorParameterSummary` instances should be reused rather + than copied into a second summary type unless implementation reveals a + concrete layering problem that cannot be resolved cleanly. +- `parameter.posterior` should always be rebuilt from restored canonical + Bayesian data rather than serialized redundantly at parameter level. +- The sidecar reader and writer should be isolated behind explicit + serializer helpers instead of being implemented inline in + `Project.save()` and `Project.load()`. + +## Chosen Defaults + +- `parameter.value` remains committed to MAP after posterior fits. +- If a project is loaded without full posterior arrays, restoring only + `parameter.posterior` is acceptable for table display and parameter + inspection. +- Posterior plotting remains unavailable unless the canonical Bayesian + containers needed by those plots are also restored. diff --git a/docs/dev/adr_undo-fit.md b/docs/dev/adr_undo-fit.md new file mode 100644 index 00000000..e2aa46e0 --- /dev/null +++ b/docs/dev/adr_undo-fit.md @@ -0,0 +1,163 @@ +# ADR: Undo Fit + +**Status:** Proposed +**Date:** 2026-05-13 + +## Context + +The new `_fit_parameter.start_value` and +`_fit_parameter.start_uncertainty` fields in `analysis/analysis.cif` +capture the last committed pre-fit scalar state for each fitted +parameter. This is useful when a minimization run produces a poor +result and the user wants to return to the state from immediately +before the fit. + +This need is especially important in command-line workflows, where the +user may save a project after a bad fit and reopen it later expecting a +simple way to roll back to the pre-fit state. + +However, these snapshots alone do not define undo semantics. The API +owner, rollback scope, and interaction with fit-derived metadata must +be explicit. + +## Decision + +### 1. Add an analysis-owned `undo_fit()` operation + +The rollback operation belongs on `Analysis`, for example: + +```python +project.analysis.undo_fit() +``` + +`Analysis` owns the fit lifecycle, fit metadata, and persisted +`analysis.cif` state, so it is the correct owner for this operation. + +### 2. Initial undo scope is scalar rollback plus posterior clear + +The first undo implementation restores each fitted parameter's saved +pre-fit scalar state and clears fit state that belongs only to the +discarded fit. + +It does not attempt to restore every possible runtime detail of the +previous fit result. + +After `undo_fit()`: + +- `parameter.value` is restored from `_fit_parameter.start_value` +- `parameter.uncertainty` is restored from + `_fit_parameter.start_uncertainty` +- `parameter.posterior` is cleared +- `analysis.fit_results` is cleared + +This gives the user a safe, predictable return to the pre-fit visible +parameter state without pretending to restore a full historical result. + +If an older saved project lacks `start_uncertainty`, clearing +`parameter.uncertainty` remains an acceptable compatibility fallback. + +### 3. Undo does not roll back user configuration + +The initial undo operation does not revert: + +- aliases +- constraints +- fit bounds +- minimizer type +- fit mode +- joint-fit weights + +These are analysis configuration, not fit output. + +### 4. Undo is single-level for now + +Only the latest saved pre-fit state is addressable. + +The initial API does not create a stack of historical fits. Supporting +multiple undo levels would require a dedicated snapshot history design +and is deferred. + +### 5. Persisted scalar snapshots are the rollback anchors + +The minimum persisted state required for clean cross-session undo is the +pair of `_fit_parameter.start_value` and +`_fit_parameter.start_uncertainty` defined in +`adr_analysis-cif-fit-state.md`. + +If a parameter has no saved `start_value`, `undo_fit()` leaves that +parameter unchanged. + +If a parameter has no saved `start_uncertainty`, `undo_fit()` may clear +that parameter's uncertainty as a compatibility fallback for older +saved projects. + +### 6. Suggested user flow + +```python +project.analysis.fit() + +# Decide that the latest fit should be discarded. +project.analysis.undo_fit() + +# Save the recovered state if desired. +project.save() +``` + +### 7. Add a top-level `undo-fit` CLI command + +Because command-line recovery is one of the main motivations for this +feature, undo must also be exposed through the existing top-level CLI. + +Suggested command: + +```bash +python -m easydiffraction undo-fit PROJECT_DIR +``` + +This command should: + +- load the saved project from `PROJECT_DIR` +- execute `project.analysis.undo_fit()` +- save the recovered state back to the same project directory by + default +- support `--dry` to perform the rollback in memory without overwriting + project files +- emit a clear message describing whether the latest fit snapshot was + successfully discarded + +Suggested dry-run form: + +```bash +python -m easydiffraction undo-fit PROJECT_DIR --dry +``` + +If the project does not contain a usable undo snapshot, the command +should fail with a clear non-zero exit status instead of silently doing +nothing. + +## Consequences + +### Positive + +- Users gain a simple recovery path after a poor fit. +- The feature works naturally with saved projects and both Python and + command-line workflows. +- The initial scope stays small and does not require full historical + fit snapshots. + +### Trade-offs + +- Undo restores pre-fit scalar parameter state, not a full historical + `fit_results` object. +- Older saved projects that do not carry `start_uncertainty` may still + fall back to clearing uncertainty. +- Multi-level undo remains unsupported. + +## Deferred Work + +- exact restoration of previous posterior-derived projections beyond the + scalar parameter snapshot +- multi-level undo / redo +- user-facing confirmation or preview APIs +- rollback of fit-type-specific persisted summaries beyond parameter + values From 9d03c30d5f26fccd26677c94313f62997bab1bd8 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Wed, 13 May 2026 14:50:39 +0200 Subject: [PATCH 102/106] Improve CI and codecov settings --- .codecov.yml | 26 ++++++ .copier-answers.yml | 2 +- .github/workflows/dashboard.yml | 6 +- codecov.yml | 13 --- docs/dev/adr_analysis-cif-fit-state.md | 3 +- .../adr_parameter-correlation-persistence.md | 4 +- docs/dev/adr_parameter-posterior-summary.md | 79 +++++++++---------- docs/dev/adr_undo-fit.md | 21 +++-- 8 files changed, 83 insertions(+), 71 deletions(-) create mode 100644 .codecov.yml delete mode 100644 codecov.yml diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 00000000..d001c41d --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,26 @@ +# Codecov configuration +# https://docs.codecov.com/docs/codecov-yaml + +github_checks: + annotations: true + +comment: + layout: 'reach, diff, flags, files' + behavior: default + require_changes: false + require_base: false + require_head: true + +coverage: + status: + project: + default: + target: auto + threshold: 1% + # Make project coverage informational (won't block PR) + informational: true + patch: + default: + target: auto + # Require patch coverage but with threshold + threshold: 1% diff --git a/.copier-answers.yml b/.copier-answers.yml index c1c59d2a..009e6acc 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,6 +1,6 @@ # WARNING: Do not edit this file manually. # Any changes will be overwritten by Copier. -_commit: v0.11.3 +_commit: v0.11.4 _src_path: gh:easyscience/templates app_docs_url: https://easyscience.github.io/diffraction-app app_doi: 10.5281/zenodo.18163581 diff --git a/.github/workflows/dashboard.yml b/.github/workflows/dashboard.yml index 9d1f2b0b..573e3086 100644 --- a/.github/workflows/dashboard.yml +++ b/.github/workflows/dashboard.yml @@ -32,9 +32,13 @@ jobs: - name: Set up pixi uses: ./.github/actions/setup-pixi + # Install badgery into the active Pixi environment without modifying + # pixi.toml/pixi.lock. Using `pixi add` here re-solves the whole project + # and rebuilds the local editable package, which can cause intermittent + # Linux CI failures (`Text file busy`, os error 26). - name: Install badgery shell: bash - run: pixi add --pypi --git https://github.com/enhantica/badgery badgery + run: pixi run python -m pip install git+https://github.com/enhantica/badgery - name: Run docstring coverage and code complexity/maintainability checks run: | diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index f62b13ab..00000000 --- a/codecov.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Codecov configuration -# https://docs.codecov.com/docs/codecovyml-reference - -coverage: - status: - project: - default: - # Make project coverage informational (won't block PR) - informational: true - patch: - default: - # Require patch coverage but with threshold - threshold: 1% diff --git a/docs/dev/adr_analysis-cif-fit-state.md b/docs/dev/adr_analysis-cif-fit-state.md index bf4af6f6..c39fc192 100644 --- a/docs/dev/adr_analysis-cif-fit-state.md +++ b/docs/dev/adr_analysis-cif-fit-state.md @@ -137,8 +137,7 @@ and Bayesian fitting. Fit-type-specific extensions are layered on top: - Bayesian persistence extends this with `_bayesian_*` categories and an - HDF5 sidecar, as described in - `adr_parameter-posterior-summary.md`. + HDF5 sidecar, as described in `adr_parameter-posterior-summary.md`. - Future fit-specific summaries should follow the same pattern: generic shared fields in `_fit_result`, specialized fields in separate categories. diff --git a/docs/dev/adr_parameter-correlation-persistence.md b/docs/dev/adr_parameter-correlation-persistence.md index 5d7b6888..9c494908 100644 --- a/docs/dev/adr_parameter-correlation-persistence.md +++ b/docs/dev/adr_parameter-correlation-persistence.md @@ -15,8 +15,8 @@ unless the underlying runtime objects are rebuilt. For Bayesian fits, full posterior samples may not always be restored. For deterministic fits, engine covariance is typically not persisted at all. -The correlation matrix is an analysis-owned summary, not model state. -It therefore belongs in `analysis/analysis.cif`, not in structure or +The correlation matrix is an analysis-owned summary, not model state. It +therefore belongs in `analysis/analysis.cif`, not in structure or experiment CIF files. ## Decision diff --git a/docs/dev/adr_parameter-posterior-summary.md b/docs/dev/adr_parameter-posterior-summary.md index 5469a2bd..dd7999ba 100644 --- a/docs/dev/adr_parameter-posterior-summary.md +++ b/docs/dev/adr_parameter-posterior-summary.md @@ -22,20 +22,20 @@ fits use `FitResults`, while posterior-capable fits such as DREAM use The user-facing need is more local: when a posterior-capable fit has completed, each parameter should expose a compact Bayesian summary for -inspection without forcing users to traverse `analysis.fit_results`. -At the same time, `parameter.value` must remain the only scalar used by -the live model, minimizer setup, constraints, and category updates. +inspection without forcing users to traverse `analysis.fit_results`. At +the same time, `parameter.value` must remain the only scalar used by the +live model, minimizer setup, constraints, and category updates. There is also a staleness problem. After a manual parameter edit or a -new fit, fit-derived helper data must be cleared or replaced as a -group. Keeping old posterior summaries after the active parameter state -changes would mislead users. +new fit, fit-derived helper data must be cleared or replaced as a group. +Keeping old posterior summaries after the active parameter state changes +would mislead users. One more implementation constraint matters: minimizers currently apply final fitted values through `_set_value_from_minimizer(...)` and then -write `param.uncertainty = ...` directly. If `uncertainty` and -posterior metadata become read-only fit outputs and the public `value` -setter starts clearing stale fit metadata on manual edits, fit-result +write `param.uncertainty = ...` directly. If `uncertainty` and posterior +metadata become read-only fit outputs and the public `value` setter +starts clearing stale fit metadata on manual edits, fit-result application must move to a dedicated internal update path so that valid fit outputs are installed atomically instead of being cleared accidentally. @@ -44,12 +44,12 @@ accidentally. ### 1. Add one optional posterior object to each parameter -Each `GenericParameter` will gain a read-only -`posterior` property whose default value is `None`. +Each `GenericParameter` will gain a read-only `posterior` property whose +default value is `None`. This property is convenience metadata only. It does not participate in -calculations. `parameter.value` remains the only scalar used by the -live model. +calculations. `parameter.value` remains the only scalar used by the live +model. ### 2. Reuse the existing Bayesian summary container @@ -256,11 +256,10 @@ Fields: `fit_min` and `fit_max` are required for restored Bayesian plotting. `fit_bounds_uncertainty_multiplier` is required if restored plots should -preserve the uncertainty-derived bound annotation exactly. -`start_value` and `start_uncertainty` are required for clean -cross-session undo. If omitted, restored fit reports may show `N/A` for -`start` and `change`, and undo may need to clear uncertainty as a -compatibility fallback. +preserve the uncertainty-derived bound annotation exactly. `start_value` +and `start_uncertainty` are required for clean cross-session undo. If +omitted, restored fit reports may show `N/A` for `start` and `change`, +and undo may need to clear uncertainty as a compatibility fallback. #### 11.2 `_bayesian_result` single item @@ -313,9 +312,8 @@ loop described below. #### 11.5 `_bayesian_parameter_posterior` loop -Stores one canonical posterior summary row per sampled parameter. -These rows are the source used to rebuild `parameter.posterior` on -load. +Stores one canonical posterior summary row per sampled parameter. These +rows are the source used to rebuild `parameter.posterior` on load. Fields: @@ -514,8 +512,8 @@ layout is recommended rather than mandatory. Do not persist backend-specific runtime objects such as `engine_result`, the DREAM driver, or ArviZ `InferenceData`. -Those objects can be rebuilt from canonical saved arrays when needed, -or left unavailable after load. +Those objects can be rebuilt from canonical saved arrays when needed, or +left unavailable after load. ### 13. Restore flow and partial-availability policy @@ -527,13 +525,12 @@ When `Project.save()` sees `analysis.fit_results` as a `BayesianFitResults` instance: 1. It writes standard analysis configuration to `analysis/analysis.cif`. -2. It appends `_fit_parameter`, `_bayesian_result`, - `_bayesian_sampler`, `_bayesian_convergence`, and - `_bayesian_parameter_posterior`. +2. It appends `_fit_parameter`, `_bayesian_result`, `_bayesian_sampler`, + `_bayesian_convergence`, and `_bayesian_parameter_posterior`. 3. If posterior predictive summaries are available, it also writes the - `_bayesian_predictive_dataset` manifest. + `_bayesian_predictive_dataset` manifest. 4. If posterior sample arrays or predictive arrays are available, it - writes `analysis/bayesian_data.h5`. + writes `analysis/bayesian_data.h5`. #### 13.2 Load flow @@ -541,20 +538,20 @@ When `Project.load()` restores `analysis/analysis.cif`: 1. Standard analysis configuration is restored first. 2. If `_fit_parameter` is present, fit bounds, bound provenance, and - optional pre-fit scalar snapshots are restored by matching - `param_unique_name` to live parameters. + optional pre-fit scalar snapshots are restored by matching + `param_unique_name` to live parameters. 3. If Bayesian categories are present, a lightweight - `BayesianFitResults` instance is rebuilt from persisted metadata and - parameter summary rows. + `BayesianFitResults` instance is rebuilt from persisted metadata and + parameter summary rows. 4. `parameter.posterior` is rebuilt by matching summary rows to live - parameters via `unique_name`. + parameters via `unique_name`. 5. `parameter.value` and `parameter.uncertainty` continue to come from - the normal project serialization path; Bayesian restore does not - overwrite them. + the normal project serialization path; Bayesian restore does not + overwrite them. 6. If `analysis/bayesian_data.h5` exists and matches the manifest, - `posterior_samples` and `posterior_predictive` are restored. + `posterior_samples` and `posterior_predictive` are restored. 7. If the sidecar is missing or incomplete, the restore degrades to - summary-only mode without failing the whole project load. + summary-only mode without failing the whole project load. #### 13.3 Partial restore behavior @@ -615,8 +612,8 @@ structure and experiment files would create multiple sources of truth. than mixed user-editable and fit-editable state. - `analysis.fit_results` remains the canonical source for full Bayesian state. -- `analysis/analysis.cif` becomes the home for fit-control metadata - that does not belong in structure or experiment CIF files. +- `analysis/analysis.cif` becomes the home for fit-control metadata that + does not belong in structure or experiment CIF files. - Bayesian save/load gains a clear split between text metadata in `analysis/analysis.cif` and bulk numerical arrays in `analysis/bayesian_data.h5`. @@ -663,8 +660,8 @@ It still defers: ## Implementation Notes -- The first implementation should only populate - `parameter.posterior` for DREAM. +- The first implementation should only populate `parameter.posterior` + for DREAM. - Existing `PosteriorParameterSummary` instances should be reused rather than copied into a second summary type unless implementation reveals a concrete layering problem that cannot be resolved cleanly. diff --git a/docs/dev/adr_undo-fit.md b/docs/dev/adr_undo-fit.md index e2aa46e0..29974130 100644 --- a/docs/dev/adr_undo-fit.md +++ b/docs/dev/adr_undo-fit.md @@ -8,17 +8,17 @@ The new `_fit_parameter.start_value` and `_fit_parameter.start_uncertainty` fields in `analysis/analysis.cif` capture the last committed pre-fit scalar state for each fitted -parameter. This is useful when a minimization run produces a poor -result and the user wants to return to the state from immediately -before the fit. +parameter. This is useful when a minimization run produces a poor result +and the user wants to return to the state from immediately before the +fit. This need is especially important in command-line workflows, where the user may save a project after a bad fit and reopen it later expecting a simple way to roll back to the pre-fit state. However, these snapshots alone do not define undo semantics. The API -owner, rollback scope, and interaction with fit-derived metadata must -be explicit. +owner, rollback scope, and interaction with fit-derived metadata must be +explicit. ## Decision @@ -88,8 +88,8 @@ If a parameter has no saved `start_value`, `undo_fit()` leaves that parameter unchanged. If a parameter has no saved `start_uncertainty`, `undo_fit()` may clear -that parameter's uncertainty as a compatibility fallback for older -saved projects. +that parameter's uncertainty as a compatibility fallback for older saved +projects. ### 6. Suggested user flow @@ -118,8 +118,7 @@ This command should: - load the saved project from `PROJECT_DIR` - execute `project.analysis.undo_fit()` -- save the recovered state back to the same project directory by - default +- save the recovered state back to the same project directory by default - support `--dry` to perform the rollback in memory without overwriting project files - emit a clear message describing whether the latest fit snapshot was @@ -142,8 +141,8 @@ nothing. - Users gain a simple recovery path after a poor fit. - The feature works naturally with saved projects and both Python and command-line workflows. -- The initial scope stays small and does not require full historical - fit snapshots. +- The initial scope stays small and does not require full historical fit + snapshots. ### Trade-offs From 303a4190d1ee3819417c4ca60b8d782899dc0fe8 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Wed, 13 May 2026 21:18:45 +0200 Subject: [PATCH 103/106] Fix structure factor support for X-ray --- .../analysis/calculators/cryspy.py | 10 +++++-- .../analysis/calculators/test_cryspy.py | 29 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/easydiffraction/analysis/calculators/cryspy.py b/src/easydiffraction/analysis/calculators/cryspy.py index 3c2da252..7bac2738 100644 --- a/src/easydiffraction/analysis/calculators/cryspy.py +++ b/src/easydiffraction/analysis/calculators/cryspy.py @@ -315,13 +315,19 @@ def _powder_refln_core_arrays( try: indices = np.asarray(phase_block['index_hkl'], dtype=int) sin_theta_over_lambda = np.asarray(phase_block['sthovl'], dtype=float) - f_nucl = np.asarray(phase_block['f_nucl']) except KeyError: return None + structure_factor = phase_block.get('f_nucl') + if structure_factor is None: + structure_factor = phase_block.get('f_charge') + if structure_factor is None: + return None + structure_factor = np.asarray(structure_factor) + if indices.shape[0] != EXPECTED_HKL_INDEX_ROWS: return None - return indices, sin_theta_over_lambda, f_nucl + return indices, sin_theta_over_lambda, structure_factor @staticmethod def _powder_refln_d_spacing( diff --git a/tests/unit/easydiffraction/analysis/calculators/test_cryspy.py b/tests/unit/easydiffraction/analysis/calculators/test_cryspy.py index 5fdda3ee..6cebe4c3 100644 --- a/tests/unit/easydiffraction/analysis/calculators/test_cryspy.py +++ b/tests/unit/easydiffraction/analysis/calculators/test_cryspy.py @@ -173,3 +173,32 @@ def test_last_powder_refln_records_reads_tof_time_and_d_spacing(): assert records[0].d_spacing == pytest.approx(3.21) assert records[0].f_calc == pytest.approx(6.0) assert records[0].f_squared_calc == pytest.approx(36.0) + + +def test_last_powder_refln_records_reads_xray_charge_structure_factor(): + from easydiffraction.analysis.calculators.cryspy import CryspyCalculator + from easydiffraction.datablocks.experiment.item.enums import BeamModeEnum + + calculator = CryspyCalculator() + calculator._last_powder_phase_blocks = { + 'phase_exp': { + 'index_hkl': np.array([[1], [1], [1]]), + 'sthovl': np.array([0.2]), + 'ttheta_hkl': np.array([np.pi / 3]), + 'f_charge': np.array([8.0 - 6.0j]), + } + } + structure = SimpleNamespace(name='phase') + experiment = SimpleNamespace( + name='exp', + type=SimpleNamespace(beam_mode=SimpleNamespace(value=BeamModeEnum.CONSTANT_WAVELENGTH)), + ) + + records = calculator.last_powder_refln_records(structure, experiment, phase_id='phase-x') + + assert len(records) == 1 + assert records[0].phase_id == 'phase-x' + assert records[0].two_theta == pytest.approx(60.0) + assert records[0].d_spacing == pytest.approx(2.5) + assert records[0].f_calc == pytest.approx(10.0) + assert records[0].f_squared_calc == pytest.approx(100.0) From ebfa81ff11e2486b1aa7c5c8d7efcfe1f041f156 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Wed, 13 May 2026 22:32:55 +0200 Subject: [PATCH 104/106] Increase integration coverage for Bayesian fit helpers --- .../test_analysis_and_fit_category_support.py | 352 ++++++++++ .../fitting/test_bayesian_helper_support.py | 662 ++++++++++++++++++ .../fitting/test_bayesian_tracker_and_base.py | 451 ++++++++++++ .../fitting/test_bumps_dream_support.py | 559 +++++++++++++++ .../fitting/test_cli_entrypoints.py | 173 +++++ 5 files changed, 2197 insertions(+) create mode 100644 tests/integration/fitting/test_analysis_and_fit_category_support.py create mode 100644 tests/integration/fitting/test_bayesian_helper_support.py create mode 100644 tests/integration/fitting/test_bayesian_tracker_and_base.py create mode 100644 tests/integration/fitting/test_bumps_dream_support.py create mode 100644 tests/integration/fitting/test_cli_entrypoints.py diff --git a/tests/integration/fitting/test_analysis_and_fit_category_support.py b/tests/integration/fitting/test_analysis_and_fit_category_support.py new file mode 100644 index 00000000..f476b0d4 --- /dev/null +++ b/tests/integration/fitting/test_analysis_and_fit_category_support.py @@ -0,0 +1,352 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +import pytest + + +def _make_project(): + class ExpCol: + def __init__(self) -> None: + self._names: list[str] = [] + + @property + def names(self): + return self._names + + @property + def parameters(self): + return [] + + @property + def fittable_parameters(self): + return [] + + @property + def free_parameters(self): + return [] + + class Project: + experiments = ExpCol() + structures = ExpCol() + _varname = 'proj' + verbosity = 'full' + + return Project() + + +def _make_project_with_names(names: list[str]): + class ExpCol: + def __init__(self, names): + self._names = names + + def __len__(self): + return len(self._names) + + @property + def names(self): + return self._names + + @property + def parameters(self): + return [] + + @property + def fittable_parameters(self): + return [] + + @property + def free_parameters(self): + return [] + + class Project: + experiments = ExpCol(names) + structures = ExpCol([]) + _varname = 'proj' + verbosity = 'full' + + return Project() + + +def test_fit_mode_enum_members_default_and_descriptions(): + from easydiffraction.analysis.categories.fit.enums import FitModeEnum + + assert FitModeEnum.SINGLE == 'single' + assert FitModeEnum.JOINT == 'joint' + assert FitModeEnum.SEQUENTIAL == 'sequential' + assert FitModeEnum.default() is FitModeEnum.SINGLE + assert all(member.description() for member in FitModeEnum) + + +def test_fit_instantiation_defaults_and_run_paths(): + from easydiffraction.analysis.categories.fit.default import Fit + import easydiffraction.analysis.categories.fit.default as fit_mod + + fit = Fit() + + assert fit._identity.category_code == 'fit' + assert fit.mode.value == 'single' + assert fit.minimizer_type.value == 'lmfit (leastsq)' + assert fit.minimizer is None + + with pytest.raises( + RuntimeError, + match=r'Fit category is not attached to an Analysis object\.', + ): + fit.run() + + calls: list[tuple[str | None, bool, int | None]] = [] + + class Parent: + fitter = object() + + @staticmethod + def _run_fit( + verbosity: str | None = None, + *, + use_physical_limits: bool = False, + random_seed: int | None = None, + ) -> None: + calls.append((verbosity, use_physical_limits, random_seed)) + + fit._parent = Parent() + fit(verbosity='silent', use_physical_limits=True, random_seed=7) + + assert calls == [('silent', True, 7)] + + class ParentWithMinimizer: + fitter = type('FitterHolder', (), {'minimizer': 'MIN'})() + + fit._parent = ParentWithMinimizer() + assert fit.minimizer == 'MIN' + + shown: list[str] = [] + monkeypatch = pytest.MonkeyPatch() + monkeypatch.setattr(fit_mod.MinimizerFactory, 'show_supported', lambda: shown.append('shown')) + Fit.show_available_minimizers() + monkeypatch.undo() + + assert shown == ['shown'] + + +def test_fit_from_cif_warns_on_invalid_minimizer(monkeypatch): + import easydiffraction.analysis.categories.fit.default as fit_mod + from easydiffraction.analysis.categories.fit.default import Fit + + fit = Fit() + fit._minimizer_type._value = 'bad-minimizer' + + class Parent: + fitter = None + + warnings: list[str] = [] + fit._parent = Parent() + monkeypatch.setattr(fit_mod.CategoryItem, 'from_cif', lambda self, block, idx=0: None) + monkeypatch.setattr( + fit_mod, + 'Fitter', + lambda value: (_ for _ in ()).throw(ValueError('bad minimizer')), + ) + monkeypatch.setattr(fit_mod.log, 'warning', lambda message: warnings.append(message)) + + fit.from_cif(object()) + + assert warnings == ['bad minimizer'] + + +def test_fit_fallback_paths_without_parent_or_project(capsys, monkeypatch): + import easydiffraction.analysis.categories.fit.default as fit_mod + from easydiffraction.analysis.categories.fit.default import Fit + + fit = Fit() + + assert fit.minimizer is None + + fit.show_modes() + out = capsys.readouterr().out + assert 'single' in out + assert 'joint' in out + assert 'sequential' in out + + monkeypatch.setattr(fit_mod.CategoryItem, 'from_cif', lambda self, block, idx=0: None) + fit.from_cif(object()) + + +def test_fit_show_modes_for_single_and_multiple_experiments(capsys): + from easydiffraction.analysis.analysis import Analysis + + single = Analysis(project=_make_project_with_names(['e1'])) + single.fit.show_modes() + out_single = capsys.readouterr().out + assert 'Fit modes' in out_single + assert 'single' in out_single + assert 'joint' not in out_single + + multi = Analysis(project=_make_project_with_names(['e1', 'e2'])) + multi.fit.show_modes() + out_multi = capsys.readouterr().out + assert 'joint' in out_multi + assert 'sequential' in out_multi + + +def test_show_minimizer_types_prints(capsys): + from easydiffraction.analysis.analysis import Analysis + + analysis = Analysis(project=_make_project_with_names([])) + analysis.fit.show_minimizer_types() + out = capsys.readouterr().out + assert 'Minimizer types' in out + assert 'lmfit (leastsq)' in out + + +def test_analysis_help_and_mode_switching(capsys): + from easydiffraction.analysis.analysis import Analysis + + analysis = Analysis(project=_make_project_with_names(['e1', 'e2'])) + assert analysis.fit.mode.value == 'single' + analysis.fit.mode = 'joint' + assert analysis.fit.mode.value == 'joint' + assert len(analysis.joint_fit_experiments) == 0 + + analysis.help() + out = capsys.readouterr().out + assert "Help for 'Analysis'" in out + assert 'fit' in out + assert 'display' in out + assert 'Properties' in out + assert 'Methods' in out + assert 'fit_sequential()' in out + + +def test_display_fit_results_warns_when_no_results(capsys): + from easydiffraction.analysis.analysis import Analysis + + analysis = Analysis(project=_make_project_with_names([])) + analysis.display.fit_results() + out = capsys.readouterr().out + assert 'No fit results available' in out + + +def test_display_fit_results_calls_process_fit_results(monkeypatch): + from easydiffraction.analysis.analysis import Analysis + + process_called = {'called': False, 'args': None} + + def fake_process_fit_results(structures, experiments): + process_called['called'] = True + process_called['args'] = (structures, experiments) + + class Project: + structures = object() + _varname = 'proj' + verbosity = 'full' + + class Experiments: + names: list[str] = [] + + @staticmethod + def values(): + return [] + + @property + def parameters(self): + return [] + + @property + def fittable_parameters(self): + return [] + + @property + def free_parameters(self): + return [] + + experiments = Experiments() + + analysis = Analysis(project=Project()) + analysis.fit_results = object() + monkeypatch.setattr(analysis.fitter, '_process_fit_results', fake_process_fit_results) + + analysis.display.fit_results() + + assert process_called['called'] is True + + +def test_analysis_display_as_cif_and_constraints(monkeypatch, capsys): + import easydiffraction.analysis.analysis as analysis_mod + from easydiffraction.analysis.analysis import Analysis + + analysis = Analysis(project=_make_project()) + rendered: dict[str, str] = {} + + monkeypatch.setattr(analysis_mod, 'render_cif', lambda text: rendered.setdefault('text', text)) + analysis.display.as_cif() + assert 'text' in rendered + + analysis.display.constraints() + assert 'No constraints' in capsys.readouterr().out + + class FakeExpr: + value = 'x = y + 1' + + class FakeConstraint: + expression = FakeExpr() + + analysis.constraints._items = [FakeConstraint()] + captured: dict[str, object] = {} + monkeypatch.setattr(analysis_mod, 'render_table', lambda **kwargs: captured.update(kwargs)) + analysis.display.constraints() + out = capsys.readouterr().out + assert 'User defined constraints' in out + assert captured['columns_data'][0][0] == 'x = y + 1' + + +def test_discover_helpers_and_snapshot_params(): + from easydiffraction.analysis.analysis import Analysis + from easydiffraction.analysis.analysis import _discover_method_rows + from easydiffraction.analysis.analysis import _discover_property_rows + + class Demo: + @property + def alpha(self): + """Alpha property.""" + return 1 + + @property + def beta(self): + """Beta property.""" + return 2 + + @beta.setter + def beta(self, value): + return None + + def do_thing(self): + """Do a thing.""" + + def _private(self): + return None + + property_rows = _discover_property_rows(Demo) + method_rows = _discover_method_rows(Demo) + + assert len(property_rows) == 2 + assert 'alpha' in [row[1] for row in property_rows] + assert next(row for row in property_rows if row[1] == 'beta')[2] == 'βœ“' + assert 'do_thing()' in [row[1] for row in method_rows] + assert '_private()' not in [row[1] for row in method_rows] + + analysis = Analysis(project=_make_project()) + + class FakeParam: + unique_name = 'p1' + value = 1.23 + uncertainty = 0.01 + units = 'A' + + class FakeResults: + parameters = [FakeParam()] + + analysis._snapshot_params('expt1', FakeResults()) + assert analysis._parameter_snapshots['expt1']['p1']['value'] == 1.23 + assert analysis._parameter_snapshots['expt1']['p1']['uncertainty'] == 0.01 diff --git a/tests/integration/fitting/test_bayesian_helper_support.py b/tests/integration/fitting/test_bayesian_helper_support.py new file mode 100644 index 00000000..8a5fed2f --- /dev/null +++ b/tests/integration/fitting/test_bayesian_helper_support.py @@ -0,0 +1,662 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +import numpy as np +import pytest + + +class Identity: + def __init__(self) -> None: + self.datablock_entry_name = 'db' + self.category_code = 'cat' + self.category_entry_name = 'entry' + + +class Param: + def __init__(self, unique_name: str, start: float, value: float, uncertainty: float) -> None: + self._identity = Identity() + self._fit_start_value = start + self.unique_name = unique_name + self.name = unique_name + self.value = value + self.uncertainty = uncertainty + self.units = 'arb' + + +def test_posterior_samples_flatten_and_to_arviz(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + + posterior_samples = PosteriorSamples( + parameter_names=['a', 'b'], + parameter_samples=np.array( + [ + [[1.0, 10.0], [2.0, 20.0]], + [[3.0, 30.0], [4.0, 40.0]], + ], + dtype=float, + ), + log_posterior=np.array([[0.1, 0.2], [0.3, 0.4]], dtype=float), + ) + + flattened = posterior_samples.flattened() + inference_data = posterior_samples.to_arviz() + + assert flattened.shape == (4, 2) + np.testing.assert_allclose(flattened[:, 0], np.array([1.0, 2.0, 3.0, 4.0])) + np.testing.assert_allclose(flattened[:, 1], np.array([10.0, 20.0, 30.0, 40.0])) + assert set(inference_data.posterior.data_vars) == {'a', 'b'} + assert inference_data.posterior['a'].shape == (2, 2) + assert inference_data.sample_stats['lp'].shape == (2, 2) + + +def test_posterior_samples_to_arviz_validates_shapes(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + + posterior_samples = PosteriorSamples( + parameter_names=['a'], + parameter_samples=np.array([1.0, 2.0]), + ) + + with pytest.raises( + ValueError, + match=r'Posterior sample array must have shape \(n_draws, n_chains, n_parameters\)\.', + ): + posterior_samples.to_arviz() + + +def test_posterior_samples_to_arviz_validates_name_and_log_posterior_lengths(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + + wrong_names = PosteriorSamples( + parameter_names=['a'], + parameter_samples=np.ones((2, 2, 2), dtype=float), + ) + with pytest.raises( + ValueError, + match=r'Posterior sample array does not match the parameter name list length\.', + ): + wrong_names.to_arviz() + + wrong_log_posterior = PosteriorSamples( + parameter_names=['a'], + parameter_samples=np.ones((2, 2, 1), dtype=float), + log_posterior=np.ones((3, 2), dtype=float), + ) + with pytest.raises( + ValueError, + match=r'Log-posterior array must match the first two posterior sample axes\.', + ): + wrong_log_posterior.to_arviz() + + +def test_compute_convergence_diagnostics_treats_non_finite_values_as_not_converged( + monkeypatch, +): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.analysis.fit_helpers.bayesian import compute_convergence_diagnostics + + posterior_samples = PosteriorSamples( + parameter_names=['a'], + parameter_samples=np.ones((4, 2, 1), dtype=float), + ) + + fake_dataset = type('FakeDataset', (), {'data_vars': {'a': np.array([np.nan], dtype=float)}}) + + monkeypatch.setattr( + 'easydiffraction.analysis.fit_helpers.bayesian.az.rhat', + lambda inference_data: fake_dataset, + ) + monkeypatch.setattr( + 'easydiffraction.analysis.fit_helpers.bayesian.az.ess', + lambda inference_data, method='bulk': type( + 'FakeDataset', (), {'data_vars': {'a': np.array([4000.0], dtype=float)}} + ), + ) + + diagnostics = compute_convergence_diagnostics(posterior_samples) + + assert diagnostics['converged'] is False + assert diagnostics['r_hat_by_parameter'] == {'a': None} + assert diagnostics['ess_bulk_by_parameter'] == {'a': 4000.0} + assert diagnostics['max_r_hat'] is None + assert diagnostics['min_ess_bulk'] == pytest.approx(4000.0) + + +def test_summarize_posterior_parameters_preserves_order_and_display_names(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.analysis.fit_helpers.bayesian import summarize_posterior_parameters + + posterior_samples = PosteriorSamples( + parameter_names=['beta', 'alpha'], + parameter_samples=np.array( + [ + [[2.0, 1.0], [2.2, 1.2]], + [[1.8, 0.8], [2.1, 1.1]], + ], + dtype=float, + ), + ) + + summaries = summarize_posterior_parameters( + parameter_names=['beta', 'alpha'], + posterior_samples=posterior_samples, + map_values=np.array([2.05, 1.05]), + parameter_display_names=['Beta width', 'Alpha shift'], + convergence_diagnostics={ + 'r_hat_by_parameter': {'beta': 1.02, 'alpha': 1.0}, + 'ess_bulk_by_parameter': {'beta': 120.0, 'alpha': 800.0}, + }, + ) + + assert [summary.unique_name for summary in summaries] == ['beta', 'alpha'] + assert [summary.display_name for summary in summaries] == ['Beta width', 'Alpha shift'] + assert summaries[0].r_hat == pytest.approx(1.02) + assert summaries[0].ess_bulk == pytest.approx(120.0) + assert summaries[1].r_hat == pytest.approx(1.0) + assert summaries[1].ess_bulk == pytest.approx(800.0) + + +def test_summarize_posterior_parameters_validates_display_name_length(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorSamples + from easydiffraction.analysis.fit_helpers.bayesian import summarize_posterior_parameters + + posterior_samples = PosteriorSamples( + parameter_names=['alpha'], + parameter_samples=np.ones((2, 2, 1), dtype=float), + ) + + with pytest.raises( + ValueError, + match=r'Posterior display-name list must match the sampled parameter name list length\.', + ): + summarize_posterior_parameters( + parameter_names=['alpha'], + posterior_samples=posterior_samples, + map_values=np.array([1.0]), + parameter_display_names=['Alpha', 'Extra'], + ) + + +def test_standard_deviations_from_summaries_returns_float_array(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import standard_deviations_from_summaries + + values = standard_deviations_from_summaries([ + PosteriorParameterSummary( + unique_name='a', + display_name='A', + map_value=1.0, + median=1.0, + standard_deviation=0.2, + interval_68=(0.9, 1.1), + interval_95=(0.8, 1.2), + ), + PosteriorParameterSummary( + unique_name='b', + display_name='B', + map_value=2.0, + median=2.0, + standard_deviation=0.3, + interval_68=(1.9, 2.1), + interval_95=(1.8, 2.2), + ), + ]) + + np.testing.assert_allclose(values, np.array([0.2, 0.3])) + assert values.dtype == float + + +def test_bayesian_format_helpers_cover_edge_cases(): + from easydiffraction.analysis.fit_helpers.bayesian import _calculate_fit_quality_metrics + from easydiffraction.analysis.fit_helpers.bayesian import _dataset_to_scalar_dict + from easydiffraction.analysis.fit_helpers.bayesian import _format_bayesian_overall_status + from easydiffraction.analysis.fit_helpers.bayesian import _format_convergence_summary + from easydiffraction.analysis.fit_helpers.bayesian import _format_point_estimate_name + from easydiffraction.analysis.fit_helpers.bayesian import _format_sampler_settings + from easydiffraction.analysis.fit_helpers.bayesian import _maybe_scalar + + dataset = type( + 'FakeDataset', + (), + {'data_vars': {'a': np.array([np.nan], dtype=float), 'b': np.array([3.0], dtype=float)}}, + ) + + assert _maybe_scalar(None) is None + assert _maybe_scalar(float('inf')) is None + assert _maybe_scalar(3.0) == pytest.approx(3.0) + assert _dataset_to_scalar_dict(dataset) == {'a': None, 'b': 3.0} + assert _format_sampler_settings({}) is None + assert ( + _format_sampler_settings({'steps': 10, 'burn': 2, 'samples': 40}) + == 'steps=10, burn=2, samples=40' + ) + assert _format_point_estimate_name('map') == 'Max posterior' + assert _format_point_estimate_name('best_sample') == 'Best Sample' + assert _format_bayesian_overall_status( + success=False, + sampler_completed=False, + convergence_diagnostics={}, + ) == ('❌', 'failed') + assert _format_bayesian_overall_status( + success=True, + sampler_completed=False, + convergence_diagnostics={'converged': False}, + ) == ('⚠️', 'completed with warnings') + assert _format_bayesian_overall_status( + success=True, + sampler_completed=True, + convergence_diagnostics={'converged': True}, + ) == ('βœ…', 'completed') + assert _format_bayesian_overall_status( + success=True, + sampler_completed=False, + convergence_diagnostics={}, + ) == ('βœ…', 'posterior available') + assert _format_convergence_summary({}) is None + assert _format_convergence_summary({ + 'converged': False, + 'max_r_hat': 1.02, + 'min_ess_bulk': 200.0, + 'n_draws': 30, + 'n_chains': 8, + }) == ( + 'status=[red]failed[/red], max_r_hat=[red]1.020[/red], ' + 'min_ess_bulk=[red]200.0[/red], draws=30, chains=8' + ) + + metrics = _calculate_fit_quality_metrics( + y_obs=[10.0, 20.0], + y_calc=[9.5, 19.5], + y_err=[1.0, 1.0], + f_obs=[5.0, 6.0], + f_calc=[5.1, 5.9], + ) + + assert metrics['rf'] is not None + assert metrics['rf2'] is not None + assert metrics['wr'] is not None + assert metrics['br'] is not None + + +def test_bayesian_fit_results_display_results_prints_sampler_and_convergence(capsys, monkeypatch): + from easydiffraction.analysis.fit_helpers.bayesian import BayesianFitResults + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.utils.logging import Logger + + monkeypatch.setattr(Logger, '_reaction', Logger.Reaction.WARN, raising=True) + + results = BayesianFitResults( + success=True, + parameters=[Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05)], + reduced_chi_square=1.2345, + fitting_time=0.9876, + sampler_name='dream', + sampler_completed=True, + sampler_settings={ + 'random_seed': 1313900679, + 'steps': 200, + 'burn': 50, + 'thin': 1, + 'pop': 4, + 'init': 'lhs', + 'samples': 3200, + }, + convergence_diagnostics={ + 'converged': False, + 'max_r_hat': 1.107, + 'min_ess_bulk': 125.9, + 'n_draws': 200, + 'n_chains': 16, + }, + posterior_parameter_summaries=[ + PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.2, + median=1.15, + standard_deviation=0.05, + interval_68=(1.1, 1.2), + interval_95=(1.0, 1.3), + r_hat=1.107, + ess_bulk=125.9, + ) + ], + best_log_posterior=-12.34, + ) + results.message = 'DREAM sampling completed' + + results.display_results(y_obs=[10.0, 20.0], y_calc=[9.5, 19.5]) + + out = capsys.readouterr().out + assert 'Bayesian fit results' in out + assert 'Overall status: completed with warnings' in out + assert 'Sampler status: DREAM sampling completed' in out + assert 'Sampler: dream' in out + assert 'Sampler completed: yes' in out + assert 'steps=200' in out + assert 'init=lhs' in out + assert 'random_seed=1313900679' not in out + assert 'status=failed' in out + assert 'max_r_hat=1.107' in out + assert 'min_ess_bulk=125.9' in out + assert 'Posterior parameter summaries:' in out + assert 'Success: True' not in out + assert 'datablock' in out + assert 'category' in out + assert 'entry' in out + assert '95% interval' in out + assert '68% interval' not in out + assert 'std' not in out + + monkeypatch.setattr(Logger, '_reaction', Logger.Reaction.RAISE, raising=True) + + +def test_render_posterior_summary_table_without_summaries_prints_notice(capsys): + from easydiffraction.analysis.fit_helpers import bayesian + + bayesian._render_posterior_summary_table(parameters=[], posterior_parameter_summaries=[]) + + assert 'No posterior parameter summaries available.' in capsys.readouterr().out + + +def test_build_posterior_summary_row_restores_identifier_columns(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import _build_posterior_summary_row + + parameter = Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05) + summary = PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.2, + median=1.15, + standard_deviation=0.05, + interval_68=(1.1, 1.2), + interval_95=(1.0, 1.3), + r_hat=1.107, + ess_bulk=125.9, + ) + + row = _build_posterior_summary_row(summary, {'a': parameter}) + + assert row == [ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.1500', + '[1.0000, 1.3000]', + '[red]1.107[/red]', + '[red]125.9[/red]', + ] + + +def test_render_committed_parameter_table_places_units_after_parameter(monkeypatch): + from easydiffraction.analysis.fit_helpers import bayesian + + captured: dict[str, object] = {} + + def fake_render_table(*, columns_headers, columns_alignment, columns_data): + captured['columns_headers'] = columns_headers + captured['columns_alignment'] = columns_alignment + captured['columns_data'] = columns_data + + monkeypatch.setattr(bayesian, 'render_table', fake_render_table) + + bayesian._render_committed_parameter_table([ + Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05) + ]) + + assert captured['columns_headers'] == [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'units', + 'start', + 'max posterior', + 'uncertainty', + 'change', + ] + assert captured['columns_alignment'] == [ + 'left', + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'right', + ] + assert captured['columns_data'] == [ + [ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.0000', + '1.2000', + '0.0500', + '20.00 % ↑', + ] + ] + + +def test_render_posterior_summary_table_places_units_after_parameter(monkeypatch): + from easydiffraction.analysis.fit_helpers import bayesian + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + + captured: dict[str, object] = {} + + def fake_render_table(*, columns_headers, columns_alignment, columns_data): + captured['columns_headers'] = columns_headers + captured['columns_alignment'] = columns_alignment + captured['columns_data'] = columns_data + + monkeypatch.setattr(bayesian, 'render_table', fake_render_table) + + bayesian._render_posterior_summary_table( + parameters=[Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05)], + posterior_parameter_summaries=[ + PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.2, + median=1.15, + standard_deviation=0.05, + interval_68=(1.1, 1.2), + interval_95=(1.0, 1.3), + r_hat=1.107, + ess_bulk=125.9, + ) + ], + ) + + assert captured['columns_headers'] == [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'units', + 'median', + '95% interval', + 'r-hat', + 'ess bulk', + ] + assert captured['columns_alignment'] == [ + 'left', + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'right', + ] + assert captured['columns_data'] == [ + [ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.1500', + '[1.0000, 1.3000]', + '[red]1.107[/red]', + '[red]125.9[/red]', + ] + ] + + +def test_posterior_table_notes_split_failed_diagnostics(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import _posterior_table_notes + + notes = _posterior_table_notes([ + PosteriorParameterSummary( + unique_name='a', + display_name='a', + map_value=1.0, + median=1.0, + standard_deviation=0.1, + interval_68=(0.9, 1.1), + interval_95=(0.8, 1.2), + r_hat=1.02, + ess_bulk=100.0, + ) + ]) + + assert len(notes) == 2 + assert 'r-hat' in notes[0] + assert 'ess bulk' in notes[1] + + +def test_bayesian_helpers_cover_non_warning_and_default_display_paths(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.fit_helpers.bayesian import _build_posterior_summary_row + from easydiffraction.analysis.fit_helpers.bayesian import _format_ess_bulk + from easydiffraction.analysis.fit_helpers.bayesian import _format_r_hat + from easydiffraction.analysis.fit_helpers.bayesian import _posterior_table_notes + + summary = PosteriorParameterSummary( + unique_name='missing', + display_name='Missing', + map_value=1.0, + median=1.0, + standard_deviation=0.1, + interval_68=(0.9, 1.1), + interval_95=(0.8, 1.2), + r_hat=1.0, + ess_bulk=500.0, + ) + + row = _build_posterior_summary_row(summary, {}) + + assert row == [ + 'N/A', + 'N/A', + '', + 'Missing', + 'N/A', + '1.0000', + '[0.8000, 1.2000]', + '1.000', + '500.0', + ] + assert _format_r_hat(None) == 'N/A' + assert _format_r_hat(1.0) == '1.000' + assert _format_ess_bulk(None) == 'N/A' + assert _format_ess_bulk(500.0) == '500.0' + assert _posterior_table_notes([]) == [] + assert _posterior_table_notes([summary]) == [] + + +def test_fitresults_display_results_prints_and_table(capsys): + from easydiffraction.analysis.fit_helpers.reporting import FitResults + + params = [Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05)] + + results = FitResults( + success=True, + parameters=params, + reduced_chi_square=1.2345, + fitting_time=0.9876, + ) + + results.display_results( + y_obs=[10.0, 20.0], + y_calc=[9.5, 19.5], + y_err=[1.0, 1.0], + f_obs=[5.0, 6.0], + f_calc=[5.1, 5.9], + ) + + out = capsys.readouterr().out + assert 'Fit results' in out + assert 'Success: True' in out + assert 'reduced χ²' in out + assert 'R-factor (Rf)' in out + assert 'R-factor squared (RfΒ²)' in out + assert 'Weighted R-factor (wR)' in out + assert 'Bragg R-factor (BR)' in out + assert 'Fitted parameters:' in out + assert any(char in out for char in ('β•’', 'β”Œ', '+', '─')) + + +def test_fitresults_display_results_places_units_after_parameter(monkeypatch): + from easydiffraction.analysis.fit_helpers import reporting + + captured: dict[str, object] = {} + + def fake_render_table(*, columns_headers, columns_alignment, columns_data): + captured['columns_headers'] = columns_headers + captured['columns_alignment'] = columns_alignment + captured['columns_data'] = columns_data + + monkeypatch.setattr(reporting, 'render_table', fake_render_table) + + reporting.FitResults( + success=True, + parameters=[Param(unique_name='a', start=1.0, value=1.2, uncertainty=0.05)], + ).display_results() + + assert captured['columns_headers'] == [ + 'datablock', + 'category', + 'entry', + 'parameter', + 'units', + 'start', + 'fitted', + 'uncertainty', + 'change', + ] + assert captured['columns_alignment'] == [ + 'left', + 'left', + 'left', + 'left', + 'left', + 'right', + 'right', + 'right', + 'right', + ] + assert captured['columns_data'] == [ + [ + 'db', + 'cat', + 'entry', + 'a', + 'arb', + '1.0000', + '1.2000', + '0.0500', + '20.00 % ↑', + ] + ] diff --git a/tests/integration/fitting/test_bayesian_tracker_and_base.py b/tests/integration/fitting/test_bayesian_tracker_and_base.py new file mode 100644 index 00000000..f63cb111 --- /dev/null +++ b/tests/integration/fitting/test_bayesian_tracker_and_base.py @@ -0,0 +1,451 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +from dataclasses import dataclass + +import numpy as np +import pytest + + +class DummyParam: + def __init__(self, value: float) -> None: + self.value = value + self.fit_min = -np.inf + self.fit_max = np.inf + self.unique_name = f'param_{value}' + + def _physical_lower_bound(self) -> float: + return -np.inf + + def _physical_upper_bound(self) -> float: + return np.inf + + +def test_tracker_terminal_flow_prints_and_updates_best(monkeypatch, capsys): + import easydiffraction.analysis.fit_helpers.tracking as tracking_mod + from easydiffraction.analysis.fit_helpers.tracking import FitProgressTracker + + monkeypatch.setattr(tracking_mod, 'in_jupyter', lambda: False) + + tracker = FitProgressTracker() + tracker.start_tracking('dummy') + tracker.start_timer() + + tracker.track(np.array([2.0, 1.0]), parameters=[1]) + out = capsys.readouterr().out + assert 'Goodness-of-fit' in out + + tracker.track(np.array([1.9, 1.0]), parameters=[1]) + tracker.track(np.array([0.1, 0.1]), parameters=[1]) + + tracker.stop_timer() + tracker.finish_tracking() + + out = capsys.readouterr().out + assert 'Best goodness-of-fit' in out + assert tracker.best_iteration is not None + + +def test_tracker_sampler_progress_renders_and_completes(monkeypatch, capsys): + import easydiffraction.analysis.fit_helpers.tracking as tracking_mod + from easydiffraction.analysis.fit_helpers.tracking import FitProgressTracker + from easydiffraction.analysis.fit_helpers.tracking import SamplerProgressUpdate + + monkeypatch.setattr(tracking_mod, 'in_jupyter', lambda: False) + + tracker = FitProgressTracker() + tracker.start_tracking('dream', mode='sampling') + tracker.start_timer() + tracker.track_sampler_progress( + SamplerProgressUpdate( + iteration=1, + total_iterations=10, + phase='burn-in', + progress_percent=10.0, + log_posterior=-12.0, + reduced_chi2=5.0, + elapsed_time=0.0, + force_report=True, + ) + ) + tracker.track_sampler_progress( + SamplerProgressUpdate( + iteration=10, + total_iterations=10, + phase='sampling', + progress_percent=100.0, + log_posterior=-3.0, + reduced_chi2=1.0, + elapsed_time=6.0, + force_report=False, + ) + ) + tracker.stop_timer() + tracker.finish_tracking() + + out = capsys.readouterr().out + assert 'Bayesian sampling progress' in out + assert 'Bayesian sampling complete.' in out + assert tracker.best_chi2 == pytest.approx(1.0) + assert tracker.best_iteration == 10 + + +def test_tracker_helper_error_paths_and_short_mode(monkeypatch): + import easydiffraction.analysis.fit_helpers.tracking as tracking_mod + from easydiffraction.analysis.fit_helpers.tracking import FitProgressTracker + from easydiffraction.utils.enums import VerbosityEnum + + monkeypatch.setattr(tracking_mod, 'in_jupyter', lambda: False) + + tracker = FitProgressTracker() + tracker._verbosity = VerbosityEnum.SHORT + tracker.stop_timer() + tracker.start_tracking('dream', mode='sampling') + tracker.finish_tracking() + + with pytest.raises(RuntimeError, match='Sampler progress is unavailable'): + FitProgressTracker()._resolved_final_sampler_progress() + with pytest.raises(RuntimeError, match='Sampler iteration labels require'): + FitProgressTracker()._sampler_iteration_label(1) + + assert FitProgressTracker._rows_match_on_columns(['1', 'a'], ['1', 'b'], (0,)) is True + + +def test_tracker_final_sampler_row_replaces_last_row(monkeypatch): + import easydiffraction.analysis.fit_helpers.tracking as tracking_mod + from easydiffraction.analysis.fit_helpers.tracking import FitProgressTracker + + monkeypatch.setattr(tracking_mod, 'render_table', lambda **kwargs: None) + + tracker = FitProgressTracker() + tracker._tracking_mode = 'sampling' + tracker._sampler_total_iterations = 10 + tracker._last_iteration = 10 + tracker._last_sampler_progress_percent = 100.0 + tracker._last_sampler_log_posterior = -3.0 + tracker._last_sampler_phase = 'sampling' + tracker._last_sampler_elapsed_time = 5.0 + tracker._df_rows = [['10/10', '90.0%', '4.00', '-3.00', 'sampling']] + + tracker.finish_tracking() + + assert tracker._df_rows[-1] == ['10/10', '100.0%', '5.00', '-3.00', 'sampling'] + + +def test_make_display_handle_uses_terminal_live_when_available(monkeypatch): + import easydiffraction.analysis.fit_helpers.tracking as tracking_mod + + class FakeLive: + def __init__(self, *, console, auto_refresh): + self.console = console + self.auto_refresh = auto_refresh + self.started = False + self.stopped = False + + def start(self): + self.started = True + + def stop(self): + self.stopped = True + + monkeypatch.setattr(tracking_mod, 'in_jupyter', lambda: False) + monkeypatch.setattr(tracking_mod, 'Live', FakeLive) + monkeypatch.setattr(tracking_mod.ConsoleManager, 'get', lambda: 'console') + + handle = tracking_mod._make_display_handle() + + assert isinstance(handle, tracking_mod._TerminalLiveHandle) + assert handle._live.console == 'console' + assert handle._live.auto_refresh is True + assert handle._live.started is True + + handle.close() + + assert handle._live.stopped is True + + +def test_tracker_misc_helper_paths(monkeypatch): + import easydiffraction.analysis.fit_helpers.tracking as tracking_mod + from easydiffraction.analysis.fit_helpers.tracking import FitProgressTracker + + render_calls: list[dict[str, object]] = [] + monkeypatch.setattr(tracking_mod, 'render_table', lambda **kwargs: render_calls.append(kwargs)) + monkeypatch.setattr( + tracking_mod, 'calculate_reduced_chi_square', lambda residuals, n_params: 3.0 + ) + + tracker = FitProgressTracker() + tracker._tracking_mode = tracking_mod.TRACKING_MODE_SAMPLER + tracker._previous_chi2 = 5.0 + tracker._best_chi2 = 5.0 + + residuals = np.array([1.0, -1.0], dtype=float) + + assert np.array_equal(tracker.track(residuals, [1.0]), residuals) + assert tracker.best_chi2 == pytest.approx(3.0) + + tracker.start_timer() + tracker.stop_timer() + assert tracker.fitting_time is not None + + tracker.reset() + tracker._tracking_mode = tracking_mod.TRACKING_MODE_SAMPLER + assert tracker._headers() == tracking_mod.SAMPLER_HEADERS + assert tracker._alignments() == tracking_mod.SAMPLER_ALIGNMENTS + assert tracker._current_elapsed_time() is None + assert tracker._format_elapsed_time() == '' + + tracker._replace_last_tracking_row(['1']) + + assert tracker._df_rows == [['1']] + assert len(render_calls) == 1 + + +def test_tracker_final_rows_cover_fallbacks_and_close_suppression(): + import easydiffraction.analysis.fit_helpers.tracking as tracking_mod + from easydiffraction.analysis.fit_helpers.tracking import FitProgressTracker + + tracker = FitProgressTracker() + tracker._tracking_mode = tracking_mod.TRACKING_MODE_SAMPLER + tracker._sampler_total_iterations = 10 + tracker._last_iteration = 8 + tracker._last_sampler_elapsed_time = 2.5 + + assert tracker._final_sampler_tracking_row() == ['8/10', '80.0%', '2.50', '', 'sampling'] + + tracker._tracking_mode = tracking_mod.TRACKING_MODE_FIT + tracker._fitting_time = 1.5 + assert tracker._final_fit_tracking_row() == ['8', '1.50', '', ''] + + class BadHandle: + @staticmethod + def close() -> None: + message = 'boom' + raise RuntimeError(message) + + tracker._display_handle = BadHandle() + tracker._close_display_handle() + + +def test_minimizer_base_fit_flow_and_finalize(): + from easydiffraction.analysis.minimizers.base import MinimizerBase + + @dataclass + class DummyResult: + success: bool = True + + class DummyMinimizer(MinimizerBase): + def __init__(self) -> None: + super().__init__(name='dummy', method='m', max_iterations=5) + self.synced = False + + def _prepare_solver_args(self, parameters): + return {'engine_parameters': {'ok': True}} + + def _run_solver(self, objective_function, **kwargs): + residuals = objective_function(kwargs.get('engine_parameters')) + self.tracker.track(residuals=np.array(residuals), parameters=[1]) + return DummyResult(success=True) + + def _sync_result_to_parameters(self, parameters, raw_result): + self.synced = True + if parameters: + parameters[0].value = 42 + + def _check_success(self, raw_result): + return getattr(raw_result, 'success', False) + + def _compute_residuals( + self, engine_params, parameters, structures, experiments, calculator + ): + assert engine_params == {'ok': True} + return np.array([0.0, 0.0]) + + minimizer = DummyMinimizer() + params = [DummyParam(1.0), DummyParam(2.0)] + objective = minimizer._create_objective_function( + parameters=params, + structures=None, + experiments=None, + calculator=None, + ) + + result = minimizer.fit(parameters=params, objective_function=objective) + + assert result.success is True + assert minimizer.synced is True + assert isinstance(result.parameters, list) + assert result.parameters[0].value == 42 + assert minimizer.tracker.fitting_time is not None + assert minimizer.tracker.fitting_time >= 0.0 + + +def test_minimizer_base_create_objective_function_uses_compute_residuals(): + from easydiffraction.analysis.minimizers.base import MinimizerBase + + class Minimizer(MinimizerBase): + def _prepare_solver_args(self, parameters): + return {} + + def _run_solver(self, objective_function, **kwargs): + return None + + def _sync_result_to_parameters(self, parameters, raw_result): + return None + + def _check_success(self, raw_result): + return True + + def _compute_residuals( + self, engine_params, parameters, structures, experiments, calculator + ): + return np.array([1.0, 2.0, 3.0]) + + minimizer = Minimizer() + objective = minimizer._create_objective_function( + parameters=[], + structures=None, + experiments=None, + calculator=None, + ) + + np.testing.assert_allclose(objective({}), np.array([1.0, 2.0, 3.0])) + + +def test_minimizer_base_fit_stops_tracking_when_solver_prep_fails(): + from easydiffraction.analysis.minimizers.base import MinimizerBase + + class Minimizer(MinimizerBase): + def __init__(self) -> None: + super().__init__(name='dummy', method='m', max_iterations=5) + self.started = False + self.stopped = False + + def _start_tracking(self, minimizer_name, verbosity=None): + self.started = True + + def _stop_tracking(self): + self.stopped = True + + def _prepare_solver_args(self, parameters): + message = 'prep failed' + raise ValueError(message) + + def _run_solver(self, objective_function, **kwargs): + message = 'should not run solver' + raise AssertionError(message) + + def _sync_result_to_parameters(self, parameters, raw_result): + return None + + def _check_success(self, raw_result): + return True + + minimizer = Minimizer() + + with pytest.raises(ValueError, match='prep failed'): + minimizer.fit(parameters=[DummyParam(1.0)], objective_function=lambda _: np.array([0.0])) + + assert minimizer.started is True + assert minimizer.stopped is True + + +def test_minimizer_base_applies_physical_limits_and_warns(monkeypatch): + from easydiffraction.analysis.minimizers.base import MinimizerBase + + warnings: list[str] = [] + monkeypatch.setattr( + 'easydiffraction.analysis.minimizers.base.log.warning', + lambda message: warnings.append(message), + ) + + class BoundaryParam(DummyParam): + def __init__(self) -> None: + super().__init__(5.0) + self.unique_name = 'boundary' + + def _physical_lower_bound(self) -> float: + return 0.0 + + def _physical_upper_bound(self) -> float: + return 10.0 + + class DummyResult: + success = True + + class Minimizer(MinimizerBase): + def __init__(self) -> None: + super().__init__(name='dummy', method='m', max_iterations=5) + + def _prepare_solver_args(self, parameters): + return {'engine_parameters': {}} + + def _run_solver(self, objective_function, **kwargs): + residuals = objective_function(kwargs.get('engine_parameters')) + self.tracker.track(residuals=np.array(residuals), parameters=[1]) + return DummyResult() + + def _sync_result_to_parameters(self, parameters, raw_result): + parameters[0].value = 11.0 + + def _check_success(self, raw_result): + return True + + def _compute_residuals( + self, engine_params, parameters, structures, experiments, calculator + ): + return np.array([0.0, 0.0]) + + minimizer = Minimizer() + parameter = BoundaryParam() + objective = minimizer._create_objective_function( + parameters=[parameter], + structures=None, + experiments=None, + calculator=None, + ) + + result = minimizer.fit( + parameters=[parameter], + objective_function=objective, + use_physical_limits=True, + ) + + assert result.success is True + assert parameter.fit_min == 0.0 + assert parameter.fit_max == 10.0 + assert parameter._outside_physical_limits is True + assert any('upper bound' in message for message in warnings) + assert any('physical upper limit' in message for message in warnings) + + +def test_minimizer_base_rejects_random_seed_when_not_supported(): + from easydiffraction.analysis.minimizers.base import MinimizerBase + + class Minimizer(MinimizerBase): + def _prepare_solver_args(self, parameters): + return {'engine_parameters': {}} + + def _run_solver(self, objective_function, **kwargs): + return object() + + def _sync_result_to_parameters(self, parameters, raw_result): + return None + + def _check_success(self, raw_result): + return True + + def _compute_residuals( + self, engine_params, parameters, structures, experiments, calculator + ): + return np.array([0.0]) + + minimizer = Minimizer(name='dummy') + + with pytest.raises( + ValueError, + match=r"Minimizer 'dummy' does not support random_seed\.", + ): + minimizer.fit(parameters=[], objective_function=lambda _: np.array([0.0]), random_seed=7) diff --git a/tests/integration/fitting/test_bumps_dream_support.py b/tests/integration/fitting/test_bumps_dream_support.py new file mode 100644 index 00000000..bf87549a --- /dev/null +++ b/tests/integration/fitting/test_bumps_dream_support.py @@ -0,0 +1,559 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +from types import SimpleNamespace +from unittest.mock import MagicMock +from unittest.mock import patch + +import numpy as np +import pytest + + +class FakeParam: + def __init__( + self, + uid: str, + value: float, + uncertainty: float | None = None, + *, + fit_min: float | None = 0.0, + fit_max: float | None = 1.0, + ) -> None: + self._minimizer_uid = uid + self.unique_name = uid + self.name = uid.upper() + self.value = value + self.uncertainty = uncertainty + self.fit_min = fit_min + self.fit_max = fit_max + + def _set_value_from_minimizer(self, value: float) -> None: + self.value = value + + +def test_type_info_and_default_init(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum + from easydiffraction.analysis.minimizers.enums import MinimizerTypeEnum + + minimizer = BumpsDreamMinimizer() + + assert minimizer.type_info.tag == MinimizerTypeEnum.BUMPS_DREAM + assert minimizer.init is DreamPopulationInitializationEnum.LHS + assert minimizer.steps == 3000 + + +def test_dream_progress_monitor_allocates_rows_by_phase_ratio(): + from easydiffraction.analysis.minimizers.bumps_dream import _DreamProgressMonitor + + monitor = _DreamProgressMonitor( + tracker=MagicMock(), + n_points=100, + n_parameters=3, + total_generations=100, + burn_steps=40, + ) + + assert len(monitor._burn_targets) == 10 + assert len(monitor._sampling_targets) == 15 + + +def test_dream_progress_monitor_helper_edge_cases(): + from easydiffraction.analysis.minimizers.bumps_dream import _DreamProgressMonitor + + monitor = _DreamProgressMonitor( + tracker=MagicMock(), + n_points=2, + n_parameters=3, + total_generations=10, + burn_steps=2, + ) + + assert _DreamProgressMonitor._progress_targets(start=3, stop=2, target_count=2) == [] + assert _DreamProgressMonitor._progress_targets(start=1, stop=5, target_count=0) == [] + assert _DreamProgressMonitor._phase_progress_point_counts( + total_generations=10, burn_steps=0 + ) == (0, 10) + assert _DreamProgressMonitor._phase_progress_point_counts( + total_generations=10, burn_steps=10 + ) == (10, 0) + assert _DreamProgressMonitor._population_mean_log_posterior( + SimpleNamespace(population_values=[], value=[2.5]) + ) == pytest.approx(-2.5) + assert _DreamProgressMonitor._population_mean_log_posterior( + SimpleNamespace(population_values=[np.array([np.nan, np.inf])], value=[1.5]) + ) == pytest.approx(-1.5) + assert monitor._reduced_chi_square_from_nllf(4.0) == pytest.approx(8.0) + + +def test_init_accepts_enum_or_string_and_rejects_invalid(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum + + minimizer = BumpsDreamMinimizer() + + minimizer.init = DreamPopulationInitializationEnum.LHS + assert minimizer.init is DreamPopulationInitializationEnum.LHS + + minimizer.init = 'random' + assert minimizer.init is DreamPopulationInitializationEnum.RANDOM + + with pytest.raises( + ValueError, + match=r"DREAM setting 'init' must be one of: eps, cov, lhs, random\.", + ): + minimizer.init = 'bad-init' + + +def test_resolve_random_seed_returns_provided_or_generated(monkeypatch): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + assert minimizer._resolve_random_seed(17) == 17 + assert minimizer._resolved_random_seed == 17 + + generator = SimpleNamespace(integers=lambda *args, **kwargs: 123456) + monkeypatch.setattr(np.random, 'default_rng', lambda: generator) + + assert minimizer._resolve_random_seed(None) == 123456 + assert minimizer._resolved_random_seed == 123456 + + +def test_dream_numeric_validators_reject_boolean_inputs(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + with pytest.raises( + TypeError, + match=r"DREAM setting 'steps' must be a positive integer\.", + ): + minimizer.steps = True + with pytest.raises( + TypeError, + match=r"DREAM setting 'parallel' must be a non-negative integer\.", + ): + minimizer.parallel = True + with pytest.raises(TypeError, match='DREAM random_seed must be an integer'): + minimizer._validated_random_seed_value(random_seed=True) + + +@pytest.mark.parametrize('seed', [-1, np.iinfo(np.uint32).max + 1]) +def test_resolve_random_seed_rejects_out_of_range_values(seed): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + with pytest.raises( + ValueError, + match=r'DREAM random_seed must be an integer between 0 and 4294967295\.', + ): + minimizer._resolve_random_seed(seed) + + +def test_resolved_burn_uses_auto_or_explicit_and_validates(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + assert minimizer._resolved_burn(steps=200) == 50 + + minimizer.burn = 20 + assert minimizer._resolved_burn(steps=200) == 20 + + minimizer.burn = 200 + with pytest.raises( + ValueError, + match=r"DREAM setting 'burn' must be smaller than 'steps'\.", + ): + minimizer._resolved_burn(steps=200) + + +def test_sampler_settings_include_init_and_sample_count(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.enums import DreamPopulationInitializationEnum + + minimizer = BumpsDreamMinimizer() + minimizer.thin = 1 + minimizer.pop = 4 + minimizer.init = DreamPopulationInitializationEnum.LHS + + settings = minimizer._sampler_settings( + random_seed=7, + steps=10, + burn=2, + n_parameters=3, + ) + + assert settings['random_seed'] == 7 + assert settings['parallel'] == 0 + assert settings['init'] == 'lhs' + assert settings['samples'] == 120 + + +@pytest.mark.parametrize( + ('fit_min', 'fit_max', 'value', 'message'), + [ + (None, 1.0, 0.5, r'fit_min must be finite'), + (0.0, np.inf, 0.5, r'fit_max must be finite'), + (2.0, 1.0, 1.5, r'fit_min \(2\.0\) must be smaller than fit_max \(1\.0\)'), + (0.0, 1.0, 2.0, r'starting value 2\.0 is outside \[0\.0, 1\.0\]'), + ], +) +def test_prepare_solver_args_rejects_invalid_dream_bounds(fit_min, fit_max, value, message): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + parameter = FakeParam('alpha', value, fit_min=fit_min, fit_max=fit_max) + + with pytest.raises(ValueError, match=message): + minimizer._prepare_solver_args([parameter]) + + +def test_prepare_solver_args_lists_all_offending_dream_parameters(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + parameters = [ + FakeParam('alpha', 2.0, fit_min=0.0, fit_max=1.0), + FakeParam('beta', 0.5, fit_min=None, fit_max=1.0), + ] + + with pytest.raises( + ValueError, + match=r'alpha: .*outside \[0\.0, 1\.0\][\s\S]*beta: .*fit_min', + ): + minimizer._prepare_solver_args(parameters) + + +def test_sync_result_to_parameters_restores_starting_values_on_failure(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + parameters = [FakeParam('a', 10.0, uncertainty=0.7), FakeParam('b', 20.0, uncertainty=0.8)] + raw_result = SimpleNamespace( + x=np.array([99.0, 88.0]), + success=False, + starting_values=np.array([1.5, 2.5]), + starting_uncertainties=[0.1, None], + ) + + minimizer._sync_result_to_parameters(parameters, raw_result) + + assert parameters[0].value == 1.5 + assert parameters[0].uncertainty == 0.1 + assert parameters[1].value == 2.5 + assert parameters[1].uncertainty is None + + +def test_build_mapper_falls_back_for_serial_and_unpicklable(monkeypatch): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + minimizer.parallel = 1 + assert minimizer._build_mapper('problem') is None + + warnings: list[str] = [] + minimizer.parallel = 0 + monkeypatch.setattr( + 'easydiffraction.analysis.minimizers.bumps_dream.can_pickle', lambda problem: False + ) + monkeypatch.setattr( + 'easydiffraction.analysis.minimizers.bumps_dream.log.warning', + lambda message: warnings.append(message), + ) + + assert minimizer._build_mapper('problem') is None + assert any('falling back to serial execution' in message for message in warnings) + + +def test_run_solver_preserves_parameter_order_and_forwards_init(): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + minimizer.steps = 4 + minimizer.burn = 1 + minimizer.thin = 1 + minimizer.pop = 2 + minimizer.init = 'lhs' + + draw_index = np.array([0.0, 1.0]) + parameter_samples = np.array( + [ + [[1.0, 10.0], [2.0, 20.0]], + [[3.0, 30.0], [4.0, 40.0]], + ], + dtype=float, + ) + log_posterior = np.array([[0.1, 0.2], [0.3, 0.4]], dtype=float) + + class FakeState: + labels = ['uid_a', 'uid_b'] + + def chains(self): + return draw_index, parameter_samples, log_posterior + + def best(self): + return np.array([11.0, 22.0]), 3.5 + + fake_fitter = SimpleNamespace(id='dream') + + with ( + patch('easydiffraction.analysis.minimizers.bumps_dream.FitDriver') as mock_driver_cls, + patch('easydiffraction.analysis.minimizers.bumps_dream.FitProblem'), + patch('easydiffraction.analysis.minimizers.bumps_dream.FITTERS', [fake_fitter]), + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.compute_convergence_diagnostics', + return_value={'converged': True}, + ), + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.summarize_posterior_parameters', + return_value=[ + PosteriorParameterSummary( + unique_name='beta', + display_name='Beta', + map_value=22.0, + median=21.0, + standard_deviation=0.4, + interval_68=(20.5, 21.5), + interval_95=(20.0, 22.0), + ), + PosteriorParameterSummary( + unique_name='alpha', + display_name='Alpha', + map_value=11.0, + median=10.5, + standard_deviation=0.3, + interval_68=(10.0, 11.0), + interval_95=(9.5, 11.5), + ), + ], + ) as summarize_mock, + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.standard_deviations_from_summaries', + return_value=np.array([0.4, 0.3]), + ), + ): + driver_instance = mock_driver_cls.return_value + driver_instance.clip = MagicMock() + driver_instance.fit.return_value = (np.array([22.0, 11.0]), 0.25) + driver_instance.fitter = SimpleNamespace(state=FakeState()) + + result = minimizer._run_solver( + lambda values: np.array([0.0, 0.0]), + bumps_params=[ + SimpleNamespace(name='uid_a', value=1.0), + SimpleNamespace(name='uid_b', value=2.0), + ], + parameter_names=['beta', 'alpha'], + parameter_display_names=['Beta', 'Alpha'], + parameter_uids=['uid_b', 'uid_a'], + random_seed=17, + starting_uncertainties=[0.01, 0.02], + ) + + assert mock_driver_cls.call_args.kwargs['init'] == 'lhs' + np.testing.assert_allclose(result.x, np.array([22.0, 11.0])) + np.testing.assert_allclose(result.dx, np.array([0.4, 0.3])) + assert result.posterior_samples.parameter_names == ['beta', 'alpha'] + np.testing.assert_allclose( + result.posterior_samples.parameter_samples[:, :, 0], parameter_samples[:, :, 1] + ) + np.testing.assert_allclose( + result.posterior_samples.parameter_samples[:, :, 1], parameter_samples[:, :, 0] + ) + assert result.sampler_settings['init'] == 'lhs' + assert result.sampler_settings['random_seed'] == 17 + assert summarize_mock.call_args.kwargs['parameter_names'] == ['beta', 'alpha'] + + +def test_build_driver_stops_mapper_when_driver_clip_fails(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + minimizer = BumpsDreamMinimizer() + + with ( + patch.object(minimizer, '_build_mapper', return_value='mapper'), + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.FitProblem', return_value='problem' + ), + patch('easydiffraction.analysis.minimizers.bumps_dream.FitDriver') as mock_driver_cls, + patch( + 'easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper' + ) as stop_mapper, + ): + mock_driver_cls.return_value.clip.side_effect = RuntimeError('clip failed') + + with pytest.raises(RuntimeError, match='clip failed'): + minimizer._build_driver( + fitclass=object(), + fitness=SimpleNamespace(numpoints=lambda: 10), + steps=10, + burn=2, + init=minimizer.init, + sampler_settings={'samples': 40}, + n_parameters=1, + ) + + stop_mapper.assert_called_once() + + +def test_execute_driver_stops_mapper_when_seed_is_invalid(): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + + driver = SimpleNamespace(fit=MagicMock(), fitter=SimpleNamespace(state=None)) + + with patch( + 'easydiffraction.analysis.minimizers.bumps_dream.MPMapper.stop_mapper' + ) as stop_mapper: + result = BumpsDreamMinimizer._execute_driver(driver=driver, random_seed=-1) + + assert isinstance(result.error, ValueError) + driver.fit.assert_not_called() + stop_mapper.assert_called_once() + + +def test_run_solver_failure_paths_return_failure_results(monkeypatch): + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.bumps_dream import _DreamDriverResult + from easydiffraction.analysis.minimizers.bumps_dream import _DreamRunContext + + minimizer = BumpsDreamMinimizer() + context = _DreamRunContext( + driver=object(), + parameter_names=['alpha'], + parameter_display_names=['Alpha'], + parameter_uids=['uid_alpha'], + sampler_settings={'random_seed': 7}, + starting_values=np.array([1.0]), + starting_uncertainties=[0.1], + ) + + monkeypatch.setattr( + minimizer, + '_prepare_run_context', + lambda *, objective_function, kwargs: context, + ) + monkeypatch.setattr( + minimizer, + '_execute_driver', + lambda *, driver, random_seed: _DreamDriverResult( + best_values=None, + best_nllf=None, + raw_state='state', + error=RuntimeError('boom'), + ), + ) + + failed = minimizer._run_solver(lambda _: np.array([0.0])) + + assert failed.success is False + assert failed.message == 'DREAM sampling failed: boom' + assert failed.sampler_completed is False + + monkeypatch.setattr( + minimizer, + '_execute_driver', + lambda *, driver, random_seed: _DreamDriverResult( + best_values=np.array([1.0]), + best_nllf=0.5, + raw_state=None, + error=None, + ), + ) + + unusable = minimizer._run_solver(lambda _: np.array([0.0])) + + assert unusable.success is False + assert unusable.message == 'DREAM sampling did not produce usable posterior samples.' + assert unusable.sampler_completed is False + + +def test_build_success_result_handles_invalid_samples_and_warns_when_not_converged(monkeypatch): + from easydiffraction.analysis.fit_helpers.bayesian import PosteriorParameterSummary + from easydiffraction.analysis.minimizers.bumps_dream import BumpsDreamMinimizer + from easydiffraction.analysis.minimizers.bumps_dream import _DreamRunContext + + minimizer = BumpsDreamMinimizer() + context = _DreamRunContext( + driver=object(), + parameter_names=['alpha'], + parameter_display_names=['Alpha'], + parameter_uids=['uid_alpha'], + sampler_settings={'random_seed': 7}, + starting_values=np.array([1.0]), + starting_uncertainties=[0.1], + ) + + class BadState: + labels = ['uid_alpha'] + + @staticmethod + def chains(): + return np.array([0.0]), np.array([1.0]), np.array([0.0]) + + @staticmethod + def best(): + return np.array([1.0]), 0.5 + + failed = minimizer._build_success_result(context=context, raw_state=BadState(), best_nllf=0.5) + + assert failed.success is False + assert failed.sampler_completed is True + + class GoodState: + labels = ['uid_alpha'] + + @staticmethod + def chains(): + return ( + np.array([0.0, 1.0]), + np.ones((2, 2, 1), dtype=float), + np.zeros((2, 2), dtype=float), + ) + + @staticmethod + def best(): + return np.array([1.0]), 0.5 + + warnings: list[str] = [] + monkeypatch.setattr( + 'easydiffraction.analysis.minimizers.bumps_dream.compute_convergence_diagnostics', + lambda posterior_samples: {'converged': False}, + ) + monkeypatch.setattr( + 'easydiffraction.analysis.minimizers.bumps_dream.summarize_posterior_parameters', + lambda **kwargs: [ + PosteriorParameterSummary( + unique_name='alpha', + display_name='Alpha', + map_value=1.0, + median=1.0, + standard_deviation=0.2, + interval_68=(0.9, 1.1), + interval_95=(0.8, 1.2), + ) + ], + ) + monkeypatch.setattr( + 'easydiffraction.analysis.minimizers.bumps_dream.standard_deviations_from_summaries', + lambda summaries: np.array([0.2]), + ) + monkeypatch.setattr( + 'easydiffraction.analysis.minimizers.bumps_dream.log.warning', + lambda message: warnings.append(message), + ) + + successful = minimizer._build_success_result( + context=context, + raw_state=GoodState(), + best_nllf=0.5, + ) + + assert successful.success is True + assert successful.sampler_completed is True + assert any('poorly mixed' in message for message in warnings) diff --git a/tests/integration/fitting/test_cli_entrypoints.py b/tests/integration/fitting/test_cli_entrypoints.py new file mode 100644 index 00000000..636c0ca4 --- /dev/null +++ b/tests/integration/fitting/test_cli_entrypoints.py @@ -0,0 +1,173 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +from typer.testing import CliRunner + +runner = CliRunner() + + +def test_cli_version_invokes_show_version(monkeypatch): + import easydiffraction as ed + import easydiffraction.__main__ as main_mod + + called = {'ok': False} + + def fake_show_version() -> None: + print('VERSION_OK') + called['ok'] = True + + monkeypatch.setattr(ed, 'show_version', fake_show_version) + + result = runner.invoke(main_mod.app, ['--version']) + + assert result.exit_code == 0 + assert called['ok'] is True + assert 'VERSION_OK' in result.stdout + + +def test_cli_help_shows_and_exits_zero(): + import easydiffraction.__main__ as main_mod + + result = runner.invoke(main_mod.app, ['--help']) + + assert result.exit_code == 0 + assert 'EasyDiffraction command-line interface' in result.stdout + + +def test_cli_subcommands_call_utils(monkeypatch): + import easydiffraction as ed + import easydiffraction.__main__ as main_mod + + calls: list[str] = [] + monkeypatch.setattr(ed, 'list_tutorials', lambda: calls.append('LIST')) + monkeypatch.setattr( + ed, + 'download_all_tutorials', + lambda destination='tutorials', overwrite=False: calls.append('DOWNLOAD_ALL'), + ) + monkeypatch.setattr( + ed, + 'download_tutorial', + lambda id, destination='tutorials', overwrite=False: calls.append(f'DOWNLOAD_{id}'), + ) + + list_result = runner.invoke(main_mod.app, ['list-tutorials']) + download_all_result = runner.invoke(main_mod.app, ['download-all-tutorials']) + download_one_result = runner.invoke(main_mod.app, ['download-tutorial', '1']) + + assert list_result.exit_code == 0 + assert download_all_result.exit_code == 0 + assert download_one_result.exit_code == 0 + assert calls == ['LIST', 'DOWNLOAD_ALL', 'DOWNLOAD_1'] + + +def test_cli_fit_loads_and_fits(monkeypatch, tmp_path): + import easydiffraction.__main__ as main_mod + from easydiffraction.project.project import Project + + calls: list[str] = [] + + class FakeInfo: + _path = '/some/path' + + class FakeExperiment: + name = 'exp1' + + class FakeProject: + info = FakeInfo() + experiments = [FakeExperiment()] + + class _analysis: + @staticmethod + def fit() -> None: + calls.append('FIT') + + class display: + @staticmethod + def fit_results() -> None: + calls.append('DISPLAY') + + analysis = _analysis() + + class _display: + class _plotter: + @staticmethod + def plot_param_correlations() -> None: + calls.append('PLOT_CORR') + + @staticmethod + def plot_meas_vs_calc(expt_name: str, *, show_residual: bool = False) -> None: + calls.append(f'PLOT_{expt_name}_{show_residual}') + + plotter = _plotter() + + display = _display() + + fake_project = FakeProject() + + project_dir = tmp_path / 'proj' + project_dir.mkdir() + (project_dir / 'project.cif').write_text('_project.id test\n') + + monkeypatch.setattr(Project, 'load', staticmethod(lambda path: fake_project)) + + result = runner.invoke(main_mod.app, ['fit', str(project_dir)]) + + assert result.exit_code == 0 + assert calls == ['FIT', 'DISPLAY', 'PLOT_CORR', 'PLOT_exp1_True'] + + +def test_cli_fit_dry_clears_path(monkeypatch, tmp_path): + import easydiffraction.__main__ as main_mod + from easydiffraction.project.project import Project + + class FakeInfo: + _path = '/some/path' + + class FakeExperiment: + name = 'exp1' + + class FakeProject: + info = FakeInfo() + experiments = [FakeExperiment()] + + class _analysis: + @staticmethod + def fit() -> None: + return None + + class display: + @staticmethod + def fit_results() -> None: + return None + + analysis = _analysis() + + class _display: + class _plotter: + @staticmethod + def plot_param_correlations() -> None: + return None + + @staticmethod + def plot_meas_vs_calc(expt_name: str, *, show_residual: bool = False) -> None: + return None + + plotter = _plotter() + + display = _display() + + fake_project = FakeProject() + + project_dir = tmp_path / 'proj' + project_dir.mkdir() + (project_dir / 'project.cif').write_text('_project.id test\n') + + monkeypatch.setattr(Project, 'load', staticmethod(lambda path: fake_project)) + + result = runner.invoke(main_mod.app, ['fit', '--dry', str(project_dir)]) + + assert result.exit_code == 0 + assert fake_project.info._path is None From c22525e7df427abc9c1b2c4400ef55e90cc23f12 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Wed, 13 May 2026 22:52:29 +0200 Subject: [PATCH 105/106] Remove unused benchmark dependency and track serial benchmarks --- docs/dev/issues_open.md | 24 ++++++++++++++++++++++++ pixi.lock | 36 ------------------------------------ pyproject.toml | 1 - 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/docs/dev/issues_open.md b/docs/dev/issues_open.md index 014aa467..21976afd 100644 --- a/docs/dev/issues_open.md +++ b/docs/dev/issues_open.md @@ -180,6 +180,30 @@ minimiser. --- +## 16. 🟒 Add Serial Pattern-Generation Benchmarks + +**Type:** Performance + +The dev environment previously installed `pytest-benchmark`, but the +repository does not currently define any benchmark tests. At the same +time, the integration, script, and notebook pytest tasks all run with +`pytest-xdist`, so benchmark plugins only add warning noise and do not +provide reliable performance regression coverage. + +Performance regressions are still worth tracking, especially for single +diffraction-pattern calculation where backend or profile changes can +quietly slow interactive workflows. + +**Fix:** add a dedicated serial benchmark task outside the normal +parallel pytest suite. Benchmark representative single-pattern +calculations on fixed datasets and calculators, run without `-n auto`, +and define regression thresholds only after measurements are stable on a +controlled runner. + +**Depends on:** nothing. + +--- + ## 17. 🟒 Use PDF-Specific CIF Names for Total Scattering **Type:** Naming diff --git a/pixi.lock b/pixi.lock index 04890b1c..f1532e2b 100644 --- a/pixi.lock +++ b/pixi.lock @@ -209,7 +209,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz @@ -329,7 +328,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl @@ -549,7 +547,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl @@ -673,7 +670,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -881,7 +877,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl @@ -1006,7 +1001,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl @@ -1235,7 +1229,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/75/98a7eb100dc5cfd20b019046452f08d5e67dfbacc71d8f28763d32426fd3/spglib-2.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl @@ -1357,7 +1350,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl @@ -1577,7 +1569,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/a0/37fb236da6040e337381dd656cafb97d09eacb998c5db3057547f5ffddd9/pycifrw-5.0.1-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl @@ -1702,7 +1693,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -1912,7 +1902,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl @@ -2034,7 +2023,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -2260,7 +2248,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/eb/f9f1ded8e4db9638f9530c3782eb01f5ab04945f4cb9e597a51c203fa4c5/diffpy_pdffit2-1.6.0.tar.gz @@ -2380,7 +2367,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/04/c5bb20d64417d20cba0105277235c51969444fa873000fbc26ac0a3fc5a8/gemmi-0.7.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl @@ -2600,7 +2586,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl @@ -2724,7 +2709,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -2932,7 +2916,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/2f/c8/005d1de3af80f54411703d1263a0b9d31276411ec9f273d9432c59b17299/arviz_plots-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-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/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl @@ -3057,7 +3040,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/b7/901d837999a9350a7773289f7760cb473d4ba01fdc6ebae0ff2553d269ac/ncrystal_python-4.4.2-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/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e4/bc/daa30c02069eeac5b9198985ba42f5d65ca71bed6705b18329e51d352b7c/plopp-26.4.2-py3-none-any.whl @@ -8209,7 +8191,6 @@ packages: - pre-commit ; extra == 'dev' - pydoclint ; extra == 'dev' - pytest ; extra == 'dev' - - pytest-benchmark ; extra == 'dev' - pytest-cov ; extra == 'dev' - pytest-xdist ; extra == 'dev' - pyyaml ; extra == 'dev' @@ -9280,19 +9261,6 @@ packages: - prettytable - ply - numpy -- pypi: https://files.pythonhosted.org/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-py3-none-any.whl - name: pytest-benchmark - version: 5.2.3 - sha256: bc839726ad20e99aaa0d11a127445457b4219bdb9e80a1afc4b51da7f96b0803 - requires_dist: - - pytest>=8.1 - - py-cpuinfo - - aspectlib ; extra == 'aspect' - - pygal ; extra == 'histogram' - - pygaljs ; extra == 'histogram' - - setuptools ; extra == 'histogram' - - elasticsearch ; extra == 'elasticsearch' - requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl name: distlib version: 0.4.0 @@ -12796,10 +12764,6 @@ packages: - mkdocs-section-index ; extra == 'docs' - mkdocs-literate-nav ; extra == 'docs' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl - name: py-cpuinfo - version: 9.0.0 - sha256: 859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5 - pypi: https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl name: multidict version: 6.7.1 diff --git a/pyproject.toml b/pyproject.toml index 3bab31f7..f81f2303 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,6 @@ dev = [ 'pytest', # Testing 'pytest-cov', # Test coverage 'pytest-xdist', # Enable parallel testing - 'pytest-benchmark', # Benchmarking tests 'ruff', # Linting and formatting code 'radon', # Code complexity and maintainability 'validate-pyproject[all]', # Validate pyproject.toml From d2f53fba71189ae7d228cea71b61383fa6a28054 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Wed, 13 May 2026 23:23:21 +0200 Subject: [PATCH 106/106] Normalize styled console output in Windows integration tests --- .../test_analysis_and_fit_category_support.py | 10 +++++++++- .../fitting/test_bayesian_helper_support.py | 12 ++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/tests/integration/fitting/test_analysis_and_fit_category_support.py b/tests/integration/fitting/test_analysis_and_fit_category_support.py index f476b0d4..7a52c63d 100644 --- a/tests/integration/fitting/test_analysis_and_fit_category_support.py +++ b/tests/integration/fitting/test_analysis_and_fit_category_support.py @@ -3,8 +3,16 @@ from __future__ import annotations +import re + import pytest +ANSI_ESCAPE_RE = re.compile(r'\x1b\[[0-?]*[ -/]*[@-~]') + + +def _unstyled_output(text: str) -> str: + return ANSI_ESCAPE_RE.sub('', text) + def _make_project(): class ExpCol: @@ -210,7 +218,7 @@ def test_analysis_help_and_mode_switching(capsys): assert len(analysis.joint_fit_experiments) == 0 analysis.help() - out = capsys.readouterr().out + out = _unstyled_output(capsys.readouterr().out) assert "Help for 'Analysis'" in out assert 'fit' in out assert 'display' in out diff --git a/tests/integration/fitting/test_bayesian_helper_support.py b/tests/integration/fitting/test_bayesian_helper_support.py index 8a5fed2f..a4eef900 100644 --- a/tests/integration/fitting/test_bayesian_helper_support.py +++ b/tests/integration/fitting/test_bayesian_helper_support.py @@ -3,9 +3,17 @@ from __future__ import annotations +import re + import numpy as np import pytest +ANSI_ESCAPE_RE = re.compile(r'\x1b\[[0-?]*[ -/]*[@-~]') + + +def _unstyled_output(text: str) -> str: + return ANSI_ESCAPE_RE.sub('', text) + class Identity: def __init__(self) -> None: @@ -329,7 +337,7 @@ def test_bayesian_fit_results_display_results_prints_sampler_and_convergence(cap results.display_results(y_obs=[10.0, 20.0], y_calc=[9.5, 19.5]) - out = capsys.readouterr().out + out = _unstyled_output(capsys.readouterr().out) assert 'Bayesian fit results' in out assert 'Overall status: completed with warnings' in out assert 'Sampler status: DREAM sampling completed' in out @@ -596,7 +604,7 @@ def test_fitresults_display_results_prints_and_table(capsys): f_calc=[5.1, 5.9], ) - out = capsys.readouterr().out + out = _unstyled_output(capsys.readouterr().out) assert 'Fit results' in out assert 'Success: True' in out assert 'reduced χ²' in out