Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,28 +91,37 @@ tox
### Docstring Style

- Include docstrings for all public modules, classes, and functions
- Use **Sphinx/reStructuredText style** docstrings (`:param`, `:type`,
`:return`, `:rtype`)
- Use **NumPy style** docstrings (`Parameters` / `Returns` / `Raises`
sections), the style `mkdocstrings` is configured to parse
- Use clear, concise descriptions
- Document parameters, return values, and exceptions
- Example format:

```python
"""
Brief description of the function.
"""Brief description of the function.

Parameters
----------
param_name : type
Description of the parameter.

:param param_name: description of parameter
:type param_name: type
:return: description of return value
:rtype: return_type
Returns
-------
type
Description of the return value.
"""
```

### Documentation Build

- Documentation is built using Sphinx (version 8.1.3)
- Source files are in the `docs/` directory
- Use `myst_parser` (MyST parser) for Markdown support
- Documentation is built with MkDocs (Material theme), configured in
`docs/mkdocs.yml`
- Source files are Markdown and Jupyter notebooks under `docs/docs/`;
every page must be listed in the `nav` section of `docs/mkdocs.yml`
- API reference pages are one-liners rendered by `mkdocstrings`
(`::: easyreflectometry.<module>`)
- Build locally with `pixi run docs-build` or preview with
`pixi run docs-serve`
- Include code examples in documentation where appropriate

## Dependencies
Expand Down
68 changes: 0 additions & 68 deletions .github/workflows/documentation-build.yml

This file was deleted.

31 changes: 30 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,27 @@
project files without the new keys load unchanged; files saved with
constraints keep the file format at 2 (old readers ignore the additive
keys and lose the constraints).
- New `clamp_sum_partners` / `restore_sum_partners`: a
`constrain_to_sum` remainder can be driven negative by a fit that
pushes the partners past the total (a layer of negative thickness).
`clamp_sum_partners` caps each partner's `max` at the headroom it
leaves, sharing the slack in proportion to the current values;
`restore_sum_partners` hands the original maxima back and is
idempotent. The stashed maxima are persisted by structural path, so
the round trip survives project save/load. New `is_constrained_to_sum`
reports whether a parameter carries a `constrain_to_sum` dependency,
including after a reload.
- New `easyreflectometry.UnitError`, raised by `check_units` for a unit
problem in an inequality constraint. It subclasses `ValueError`, so
existing `except ValueError` handlers keep working, but callers no
longer have to match message substrings.
- New `Model.total_thickness`: a read-only derived parameter equal to
the summed thickness of the layers between superphase and subphase,
rebuilt whenever the layer structure changes. New
`conformal_thickness` / `conformal_roughness` toggles on assemblies.
`conformal_thickness` / `conformal_roughness` toggles on assemblies,
also accepted as `Multilayer` / `RepeatingMultilayer` constructor
arguments and serialized from the current graph state, so the ties are
rebuilt on `from_dict`.
- Structural parameter paths (`Project.parameter_path` /
`Project.resolve_parameter_path`) address parameters stably across
save/load.
Expand Down Expand Up @@ -206,6 +223,18 @@ returned.
disable/re-enable cycle and are re-attached when magnetism is enabled
again. `update_layer` also accepts the magnetism keys one at a time.

## Documentation

- The documentation is now MkDocs (Material) only. The legacy Sphinx
tree (`docs/src`, `docs/Makefile`, `docs/make.bat`) and the
tag-triggered `documentation-build.yml` workflow have been removed;
the site is built and deployed by `docs.yml` from `docs/mkdocs.yml`.
- New tutorials wired into the navigation: _Constraints & Inequalities_
and _Bayesian Fitting_.
- New API reference pages for constraints, inequality constraints,
Bayesian analysis, calculators, parameter limits, `LayerMagnetism`,
ORSO, summary and plotting.

# Version 1.7.0 (1 Aug 2026)

Restored the measured per-point resolution on data load (issue #368).
Expand Down
20 changes: 0 additions & 20 deletions docs/Makefile

This file was deleted.

1 change: 1 addition & 0 deletions docs/docs/api-reference/bayesian.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: easyreflectometry.analysis.bayesian
85 changes: 85 additions & 0 deletions docs/docs/api-reference/constraints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Constraints

EasyReflectometry offers three kinds of constraints between model
parameters: equality constraints, derived read-only parameters and
[inequality constraints](inequality_constraints.md). The
[Constraints tutorial](../tutorials/advancedfitting/constraints.ipynb)
walks through all three on a worked example.

## Equality constraints (dependencies)

A parameter can be tied to an arbitrary expression of other parameters.
It then leaves the set of free fit parameters and follows the
expression.

```python
from easyreflectometry import constrain
from easyreflectometry import constrain_equal
from easyreflectometry import unconstrain

constrain_equal(layer_b.roughness, to=layer_a.roughness)
constrain(layer_b.thickness, '2 * t', t=layer_a.thickness)
unconstrain(layer_b.thickness)
```

Constraints survive `Project` save/load: the expression and the
structural paths of the parameters it refers to are stored with the
project, and the graph is rebuilt when it is loaded. This covers the
helpers above; a dependency created by calling `make_dependent_on`
directly is not recorded.

## Derived (read-only) parameters

A _derived parameter_ is a dependent parameter that belongs to no layer:
a live calculation that can be shown or referenced from an equality
constraint.

```python
from easyreflectometry import constrain_to_sum
from easyreflectometry import derived_parameter

total = derived_parameter('total', 'a + b', a=layer_a.thickness, b=layer_b.thickness)
# keep the film thickness fixed at 120 Å while the split is fitted
constrain_to_sum(layer_b.thickness, [layer_a.thickness, layer_b.thickness], total=120.0)
```

!!! warning

A standalone derived parameter is **session-only**: it has no
structural path, so it cannot be named in an inequality constraint,
and a project whose equality constraints depend on one cannot be
saved (`Project.as_dict` raises). Numeric totals (as above) are
fine — they are embedded by value.

For a derived value that persists and can be used in inequalities, use
one owned by the model: every [`Model`](model.md) exposes
`total_thickness`, the summed thickness of the layers between the
superphase and the subphase, re-derived whenever the layer structure
changes.

## Guarding a sum remainder

The parameter tied by `constrain_to_sum` absorbs whatever the others
leave over, so on its own the constraint lets a fit push the partners
past the total and drive the remainder negative — a layer of negative
thickness. `clamp_sum_partners` narrows each partner's `max` to the
headroom it actually leaves, sharing the slack in proportion to the
current values, and `restore_sum_partners` hands the original maxima
back when the constraint is released.

```python
from easyreflectometry import clamp_sum_partners
from easyreflectometry import is_constrained_to_sum
from easyreflectometry import restore_sum_partners

clamp_sum_partners([layer_a.thickness], remainder=layer_b.thickness.value)
is_constrained_to_sum(layer_b.thickness) # True, also after a project reload

unconstrain(layer_b.thickness)
restore_sum_partners([layer_a.thickness])
```

The narrowed maxima are persisted by structural path, so removing the
constraint after a save/load still gives the original bounds back.

::: easyreflectometry.constraints
1 change: 1 addition & 0 deletions docs/docs/api-reference/elements/layer_magnetism.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: easyreflectometry.sample.elements.layers.layer_magnetism
38 changes: 38 additions & 0 deletions docs/docs/api-reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,35 @@ Fitting helpers and objective functions.

- [Fitting](fitting.md)

## Constraints

Equality constraints and derived parameters tie parameters together and
remove the dependent one from the fit. Inequality constraints keep every
parameter free and are enforced as penalties on the BUMPS fit problem.

- [Constraints](constraints.md)
- [Inequality Constraints](inequality_constraints.md)

## Bayesian Analysis

Posterior analysis of a DREAM sampling run: convergence diagnostics,
credible intervals and correlation plots.

- [Bayesian Analysis](bayesian.md)

## Calculators

The backend engines (refl1d, refnx) that turn a model into a
reflectivity curve, including the polarized interface.

- [Calculators](calculators.md)

## Parameter Limits

Default `min` / `max` windows applied to parameters that have none.

- [Parameter Limits](limits.md)

## Assemblies

Assemblies are collections of layers that are used to represent a
Expand All @@ -54,6 +83,7 @@ material with a thickness and a roughness.

- [Layer](elements/layer.md)
- [Layer Area Per Molecule](elements/layer_area_per_molecule.md)
- [Layer Magnetism](elements/layer_magnetism.md)

### Materials

Expand All @@ -70,3 +100,11 @@ material with given physical properties.
Collection of helper functions.

- [Data](data.md)
- [ORSO](orso.md)

## Reporting

Summaries of a project and its fit results, and the plotting helpers.

- [Summary](summary.md)
- [Plotting](plot.md)
36 changes: 36 additions & 0 deletions docs/docs/api-reference/inequality_constraints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Inequality Constraints

Cross-parameter inequalities such as `t_head < t_tail` or
`t1 + t2 <= total` are not dependencies: no parameter is removed from
the fit. They are declared as `InequalitySpec` objects on the project
and enforced by the **BUMPS** engines (the `Bumps*` minimizers and the
DREAM sampler) as penalties on the fit problem. LMFit and DFO-LS cannot
enforce them, and `fit` raises `ValueError` in that case rather than
silently dropping the physics.

```python
from easyscience.fitting import AvailableMinimizers

from easyreflectometry import InequalitySpec

project.minimizer = AvailableMinimizers.Bumps
t_a = project.parameter_path(layer_a.thickness) # 'models/0/sample/1/layers/0/thickness'
t_b = project.parameter_path(layer_b.thickness)
project.add_inequality_constraint(InequalitySpec('a', '<', 'b', {'a': t_a}, {'b': t_b}, name='order'))
project.add_inequality_constraint(InequalitySpec('a + b', '<', '90', {'a': t_a, 'b': t_b}, {}))

project.violated_inequality_constraints() # check the start point first
project.fitter.fit_single_data_set_1d(dataset) # penalties applied automatically
```

Parameters are referenced by _structural path_ (see
`Project.parameter_path`) so the constraints are saved with the project.
While a constraint is violated BUMPS skips the model evaluation and adds
a penalty growing with the violation, steering the optimizer back into
the feasible region; the `Bumps_lm` method spreads the penalty over the
residuals instead and enforces inequalities more weakly.

Both sides of a spec are unit-checked when it is registered; a mismatch
raises `UnitError`, a subclass of `ValueError`.

::: easyreflectometry.inequality_constraints
1 change: 1 addition & 0 deletions docs/docs/api-reference/limits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: easyreflectometry.limits
1 change: 1 addition & 0 deletions docs/docs/api-reference/orso.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: easyreflectometry.orso_utils
1 change: 1 addition & 0 deletions docs/docs/api-reference/plot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: easyreflectometry.plot
1 change: 1 addition & 0 deletions docs/docs/api-reference/summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: easyreflectometry.summary.summary
Loading
Loading