| name | reflectometry-common |
| description | Baseline domain knowledge for neutron reflectometry modeling and fitting with refl1d. Provides common material SLD values, chi-squared interpretation guidelines, model complexity rules (BIC), roughness constraints, refl1d API conventions, and general constraints that apply to ALL reflectometry analyses.
|
| version | 2 |
| review | {"status":"pending","reviewer":null,"reviewed_on":null,"basis":[],"notes":"v2: restructured to required skill anatomy (Overview / When to Use / Process / Rationalizations / Red Flags / Verification). Existing reflectometry guidance retained and reorganized.\n","approved_commit":null} |
| metadata | {"author":"Mat Doucet","version":"1.0"} |
Reflectometry Common
Overview
This skill provides baseline constraints and interpretation rules for neutron
reflectometry model construction and fitting in refl1d. It is intended to
stabilize fits, avoid unphysical parameter drift, and prevent unnecessary model
complexity.
When to Use
Use this skill when:
- Building or reviewing a refl1d model and parameter bounds.
- Interpreting χ² and deciding whether model complexity changes are justified.
- Troubleshooting multi-segment co-refinement behavior.
Do not use this skill when:
- You need instrument-control or data-acquisition scripting.
- You need a full model-file template; use
refl1d-model-script.
Process
Data Structure
The Liquids Reflectometer (REF_L) and Magnetism Reflectometer (REF_M) at the Spallation Neutron Source (SNS) produces data files with a specific structure. Each file contains multiple segments corresponding to different measurement configurations, such as varying the angle of incidence or the neutron wavelength band. The segments are typically labeled with metadata that indicates the measurement conditions.
There are two common approaches to fitting data:
-
Combined Data File Fitting: This is the usual approach where all the segments are combined in a single data file. Since all Q points are in one file, we may not have the information about which angle was used for which Q points. When loading the data in refl1d, we can use the load4 function, making sure to set the FWHM parameter according to how the Q resolution is defined in the data file.
-
Multi-Segment Co-refinement Fitting: Fit each segment separately, allowing for a different normalization factor, angle offset, or "sample broadening" for each segment. Sample broadening is an added component to the Q resolution that accounts for experimental factors with the sample or the instrument. When creating the probe for each segment, we have to use the incident angle (theta) corresponding to that segment, which can be extracted from the data file header. In this case we use the following code:
def create_probe(data_file, theta):
q, data, errors, dq = np.loadtxt(data_file).T
wl = 4 * np.pi * np.sin(np.pi / 180 * theta) / q
dT = dq / q * np.tan(np.pi / 180 * theta) * 180 / np.pi
dL = 0 * q
probe = make_probe(
T=theta,
dT=dT,
L=wl,
dL=dL,
data=(data, errors),
radiation="neutron",
resolution="uniform",
)
return probe
Common SLD Values (×10⁻⁶ Å⁻²)
| Material | SLD |
|---|
| Silicon | 2.07 |
| SiO₂ | 3.47 |
| Air | 0.0 |
| Gold | 4.5 |
| Copper | 6.55 |
| Titanium | -1.95 |
SLD Range Guidelines
- Set
sld_min and sld_max to at least ±2.0 around the nominal SLD value for each layer.
For example, for copper (SLD 6.55): sld_min = 4.5, sld_max = 8.5.
For titanium (SLD -1.95): sld_min = -4.0, sld_max = 0.1.
- This allows the fitter enough freedom to find the correct values even when the
material is not perfectly stoichiometric, has intermixing, or partial isotopic substitution.
- Never use ranges narrower than ±1.0.
- For adhesion layers like titanium that can intermix with adjacent layers, use ranges
of ±3.0 or wider (e.g., -5.0 to 1.0 for Ti).
Chi-Squared (χ²) Interpretation
- χ² ≈ 1: Ideal fit (model matches data within error bars)
- χ² < 0.5: Possible overfitting or overestimated errors
- χ² 1–2: Excellent fit
- χ² 2–5: Good fit, minor discrepancies
- χ² 5–10: Marginal fit, model may be missing features
- χ² > 10: Poor fit, significant model problems
Model Complexity (BIC)
- BIC = n·ln(χ²) + k·ln(n), where n = number of data points, k = free parameters.
- Lower BIC is better.
- Each layer adds 3 free parameters (thickness, SLD, roughness).
- Adding a layer must produce a substantial χ² improvement to lower BIC.
- Do NOT suggest adding layers unless the BIC would clearly improve.
- Do NOT split existing layers into sublayers (e.g., CuO + Cu₂O) unless χ² > 10
with clear evidence in residuals of unmodeled contrast steps.
- If a previous attempt to add a layer was reverted due to BIC regression,
do NOT re-add the same layer — try a different approach.
Roughness Constraints
- Roughness should be ≥ 5 Å (values below are often physically unrealistic) unless specified.
- Roughness should be less than half the thickness of either adjacent layer
(otherwise artifacts occur). User may specify larger roughness if they have reason to believe the interface is very diffuse.
In this case the "layer" interpretation becomes more of a gradient and the physical meaning of "thickness" and "roughness" parameters breaks down, but it may still be useful to capture the overall SLD profile shape.
- Typical roughness range: 5–30 Å.
Refl1d API Rules
CRITICAL: SLD(...) objects do NOT have .material, .thickness, or .interface
attributes. Those attributes only exist on Slab objects inside the sample stack.
You MUST set parameter bounds using sample[i] indexing:
sample[0].material.rho.range(5.5, 7.0) # ambient SLD
sample[1].thickness.range(10.0, 30.0) # first layer thickness
sample[1].material.rho.range(2.0, 4.0) # first layer SLD
sample[1].interface.range(0.0, 5.0) # first layer roughness
NEVER write copper.material.rho.range(...) — this crashes with
"'SLD' object has no attribute 'material'".
General Constraints
- NEVER suggest changing the fitting engine/method. The fitting method is chosen
by the workflow and is not a model issue.
- NEVER suggest reversing the layer order or changing the back-reflection geometry.
The measurement geometry is set by the user and must not be changed.
- NEVER suggest changing error bars, resolution, or Q-range — these are experimental
parameters that cannot be modified.
- Unless specifically requested by the user, never allow the substrate SLD to vary.
Native SiO₂ on Silicon
By default, avoid adding an SiO₂ layer on the silicon substrate. Native SiO₂ is
typically only 10–30 Å and in reflectometry it adds 3 parameters that can absorb
signal from more important layers. If an SiO₂ layer is already in the model,
consider removing it or fixing its thickness to < 30 Å to free up fitting capacity
for unknown layers. However, if the user explicitly requests an SiO₂ layer,
you MUST add it.
Refinement Strategy — General
When χ² is above the acceptance threshold, follow this priority order:
- Constrain unphysical parameters first. If a fitted value is far from its
nominal/expected value (e.g., Ti thickness 5× nominal), tighten that parameter's
bounds to a physically realistic range before trying other changes.
- Widen bounds on parameters hitting limits. If a parameter is pinned at its
bound, widen that bound — but only in the physically plausible direction.
- Adjust starting values. Set starting values to the best-fit values from the
previous iteration where they are physically reasonable.
- Check the ambient SLD. If the fitted ambient SLD deviates significantly from
the expected value for the stated solvent, flag this and constrain it. This is a
common source of high χ² that does not require structural model changes.
- Enable sample_broadening for multi-segment data when indicated (see below).
- Structural changes are a last resort. Only add or remove layers when:
- χ² remains > 10 after parameter adjustments, AND
- residual fringes clearly indicate an unmodeled layer, AND
- BIC analysis supports the added complexity.
- Never make multiple structural changes at once. Add or remove one layer at
a time so the effect can be evaluated.
Refinement Strategy — Multi-Segment Co-refinement
When fitting multiple segments/files together (multi-segment co-refinement with
angle-based probes), two additional probe-level parameters become available:
sample_broadening
sample_broadening adds an extra angular divergence component (in degrees) to the
Q resolution for each probe segment. It accounts for sample curvature, waviness,
or alignment issues that broaden reflectivity features beyond the instrumental
resolution.
When to enable sample_broadening — enable it when:
- Per-segment χ² values are uneven, particularly when the low-Q segment is
significantly worse (e.g., χ² > 2× the best segment).
- The critical edge region appears rounder or more smeared in the data than in
the model prediction.
- Structural parameter adjustments (thickness, SLD, roughness) and intensity
normalization changes have not resolved the per-segment χ² imbalance after
1–2 iterations.
- Structural parameters are drifting to unphysical values (e.g., adhesion layer
thickness inflating 5×, SLD far from nominal) — this often indicates the fitter
is using structural params as proxies for missing resolution broadening.
Do NOT enable when:
- Single-file fitting (no angle info available; probes are Q-based).
- All segments fit equally well (uniform χ² across segments).
- χ² is already below the acceptance threshold.
Typical ranges: "min": 0.0, "max": 0.05 (degrees). Start with the default
range; widen only if the fitted value hits the upper bound.
theta_offset
theta_offset allows for a small correction to the incident angle of each probe
segment (in degrees). It accounts for sample misalignment or goniometer
calibration errors.
When to enable theta_offset — enable it when:
- The fit is poor specifically in the overlap region between adjacent segments
(discontinuity in the stitched data).
- There is a systematic shift between segments that intensity normalization alone
cannot explain.
Do NOT enable unless there is clear evidence of angular misalignment.
Typical ranges: "min": -0.02, "max": 0.02 (degrees). This is a small
correction; values larger than ±0.1° suggest a more serious calibration issue.
Priority order for multi-segment issues
When per-segment χ² values are uneven (one segment much worse than others):
- First: Check intensity normalization — widen intensity bounds if a segment
is hitting its limit.
- Second: Enable
sample_broadening — this is the most common cause of
uneven segment fits, especially when the low-Q segment is worst.
- Third: Enable
theta_offset — only if overlap regions show misalignment.
- Last: Consider structural changes — only if broadening and offset do not
resolve the issue and residual fringes indicate a missing layer.
Rationalizations
| Excuse | Rebuttal |
|---|
| "I can add layers until χ² looks small." | Extra layers increase free parameters and can worsen model validity; BIC and residual structure should justify complexity changes. |
| "I will fit substrate SLD to absorb the mismatch." | Substrate SLD is typically known and floating it often masks real model deficiencies in film layers. |
| "Segment imbalance means I should change layer chemistry first." | In multi-segment data, probe-level effects like sample_broadening or theta_offset often explain imbalance before structural changes do. |
Red Flags
- Parameter values remain pinned at bounds without a physically justified range update.
- Roughness exceeds physically interpretable limits relative to adjacent layer thickness.
- Layer additions are proposed without BIC improvement or clear residual evidence.
- Substrate SLD is floated without explicit user request.
- Multi-segment fits show strong segment-to-segment χ² imbalance but probe-level controls are not evaluated.
Verification