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
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
"id": "72470023",
"metadata": {},
"source": [
"# Multi-Dataset Reflectometry Fitting\n",
"# Multi-Dataset Reflectometry Fitting - Teaching Notebook\n",
"\n",
"This notebook demonstrates **simultaneous fitting** of multiple reflectivity datasets using a single Ni-on-Si model with [EasyReflectometry](https://github.com/easyscience/EasyReflectometryLib).\n",
"This notebook is structured as guided teaching material for **simultaneous fitting** of multiple reflectivity datasets using [EasyReflectometry](https://github.com/easyscience/EasyReflectometryLib).\n",
"\n",
"The input file `reflectivity_geomgrid.ort` contains **4 datasets** (data_set: 0–3) from an ESS Estia instrument simulation. All datasets share the same structural model but each covers its own Q-range. The `MultiFitter` fits them simultaneously — just like the ERA GUI does."
"The input file `reflectivity_geomgrid.ort` contains **4 datasets** (data_set: 0-3) from an ESS Estia instrument simulation. All datasets share one structural model but each covers its own Q-range.\n",
"\n",
"Learning goals:\n",
"- Build and fit a baseline layer model from physical reasoning.\n",
"- Critically evaluate fit quality and propose improvements.\n",
"- Compare a simple model against a more realistic interlayer model."
]
},
{
Expand All @@ -34,8 +39,12 @@
"from easyreflectometry.calculators import CalculatorFactory\n",
"from easyreflectometry.data import load\n",
"from easyreflectometry.fitting import MultiFitter\n",
"from easyreflectometry.model import Model, PercentageFwhm\n",
"from easyreflectometry.sample import Layer, Material, Multilayer, Sample\n",
"from easyreflectometry.model import Model\n",
"from easyreflectometry.model import PercentageFwhm\n",
"from easyreflectometry.sample import Layer\n",
"from easyreflectometry.sample import Material\n",
"from easyreflectometry.sample import Multilayer\n",
"from easyreflectometry.sample import Sample\n",
"\n",
"%matplotlib inline"
]
Expand Down Expand Up @@ -76,9 +85,21 @@
"id": "ae052acf",
"metadata": {},
"source": [
"## 3. Define Materials\n",
"## 3. Materials and Layer-Order Hypothesis\n",
"\n",
"Before looking at any model-building code, answer this:\n",
"\n",
"- Given materials **Air**, **Ni**, **Si**, what is the physical stack order?\n",
"- Which one is the **superphase**?\n",
"- Which one is the **thin film**?\n",
"- Which one is the **substrate**?\n",
"\n",
"Expected baseline interpretation:\n",
"- Air = superphase\n",
"- Ni = thin film\n",
"- Si = substrate\n",
"\n",
"We define three materials for our Ni-on-Si model:\n",
"We define these three materials for the baseline model:\n",
"\n",
"| Material | SLD (10⁻⁶ Å⁻²) | Description |\n",
"|----------|-----------------|-------------|\n",
Expand All @@ -104,9 +125,12 @@
"id": "eedaf83b",
"metadata": {},
"source": [
"## 4. Define Layers\n",
"## 4. Define Layers (Try First, Then Expand)\n",
"\n",
"Each material is wrapped in a `Layer` with initial guesses for **thickness** and **roughness**. The air and Si layers are semi-infinite (thickness = 0)."
"Task:\n",
"- Create layer objects for Air, Ni, and Si.\n",
"- Choose initial guesses for thickness and roughness.\n",
"- Keep Air and Si semi-infinite (`thickness = 0`).\n"
]
},
{
Expand All @@ -126,14 +150,19 @@
"id": "4ad2248a",
"metadata": {},
"source": [
"## 5. Build the Model\n",
"## 5. Build the Model (Try First, Then Expand)\n",
"\n",
"Assemble layers into a `Sample` and wrap it in a `Model` with:\n",
"Task:\n",
"- Assemble a `Sample` using the stack Air | Ni | Si.\n",
"- Wrap it in a `Model` with scale, background, and resolution.\n",
"- Connect the calculator interface.\n",
"\n",
"Hints for physical meaning:\n",
"- **Scale factor** — overall intensity scaling \n",
"- **Background** — incoherent/instrumental background \n",
"- **Resolution** — Gaussian smearing (3% FWHM) \n",
"\n",
"A single model instance is shared across all datasets."
"A single model instance is shared across all datasets.\n"
]
},
{
Expand Down Expand Up @@ -161,9 +190,13 @@
"id": "21f2a006",
"metadata": {},
"source": [
"## 6. Set Free Parameters\n",
"## 6. Set Free Parameters (Try First, Then Expand)\n",
"\n",
"Task:\n",
"- Decide which parameters should vary in the baseline model.\n",
"- Propose physically sensible bounds.\n",
"\n",
"Select which parameters to refine and set physically reasonable bounds."
"Start with: Ni thickness, Ni roughness, Si roughness, scale, and background.\n"
]
},
{
Expand Down Expand Up @@ -248,7 +281,12 @@
"source": [
"## 8. Fit Results\n",
"\n",
"Print the goodness-of-fit metric and the refined parameter values."
"Print the goodness-of-fit metric and the refined parameter values.\n",
"\n",
"Discussion prompts:\n",
"- Does the fit capture all features across the full Q-range?\n",
"- Which parts of the curve show the largest mismatch?\n",
"- What missing physics might explain residual structure?"
]
},
{
Expand Down Expand Up @@ -345,14 +383,19 @@
"source": [
"---\n",
"\n",
"# Part 2: Interlayer Model — Si | NiSi | Ni | NiO | Air\n",
"# Part 2: Guided Improvement Challenge\n",
"\n",
"The simple **Si | Ni | air** model above assumes atomically sharp interfaces. In reality, interdiffusion and oxidation can form thin interlayers at:\n",
"The simple **Si | Ni | Air** model assumes ideal, sharp interfaces.\n",
"\n",
"- The **Ni–air** interface → a **NiO** oxide layer \n",
"- The **Si–Ni** interface → a **NiSi** silicide intermixing layer\n",
"Before revealing a refined model, propose improvements:\n",
"- What could form between **Ni and Air** after exposure/processing?\n",
"- What could form between **Si and Ni** due to intermixing or reaction?\n",
"\n",
"We now extend the model with these two additional layers and check whether the fit improves (lower reduced χ²)."
"Possible hypothesis:\n",
"- A nickel oxide-like layer (**NiOx**) near the top interface\n",
"- A nickel silicide-like intermixed layer (**NiSi**) near the substrate interface\n",
"\n",
"We now extend the model and check whether reduced chi-squared improves."
]
},
{
Expand All @@ -362,6 +405,10 @@
"source": [
"## 10. Define Interlayer Materials\n",
"\n",
"One concrete implementation uses:\n",
"- **NiOx** represented here with a NiO-like SLD\n",
"- **NiSi** as an intermixed silicide layer\n",
"\n",
"| Material | SLD (10⁻⁶ Å⁻²) | Description |\n",
"|----------|-----------------|-------------|\n",
"| NiO | 6.7 | Nickel oxide at the Ni–air interface |\n",
Expand All @@ -384,11 +431,15 @@
"id": "b4cab8e9",
"metadata": {},
"source": [
"## 11. Define Interlayer Layers & Rebuild the Sample\n",
"## 11. Define Interlayer Layers and Rebuild the Sample (Try First, Then Expand)\n",
"\n",
"We create NiO and NiSi layers with initial thickness and roughness guesses, along with fresh copies of the Ni, Si, and air layers. The full layer stack from substrate to superphase is:\n",
"Task:\n",
"- Add interlayers at the two interfaces motivated above.\n",
"- Rebuild the sample with a physically consistent order.\n",
"\n",
"**Si → NiSi → Ni → NiO → Air**"
"The full stack from substrate to superphase is:\n",
"\n",
"**Si -> NiSi -> Ni -> NiO -> Air**\n"
]
},
{
Expand Down Expand Up @@ -432,14 +483,18 @@
"id": "9b7baae1",
"metadata": {},
"source": [
"## 12. Set Free Parameters for Interlayer Model\n",
"## 12. Set Free Parameters for Interlayer Model (Try First, Then Expand)\n",
"\n",
"Task:\n",
"- Decide which new interlayer parameters should be free.\n",
"- Set realistic bounds to avoid unphysical solutions.\n",
"\n",
"We vary more parameters than in Part 1. In addition to Ni thickness/roughness, Si roughness, scale, and background, we now also refine:\n",
"Compared with Part 1, we now also refine:\n",
"\n",
"- **NiO**: SLD, thickness, roughness \n",
"- **NiSi**: SLD, thickness, roughness\n",
"\n",
"This adds 6 extra degrees of freedom (11 total vs. 5 before)."
"This adds 6 extra degrees of freedom (11 total vs. 5 before).\n"
]
},
{
Expand Down Expand Up @@ -500,7 +555,8 @@
"\n",
"model2.background.max = 1e-4\n",
"\n",
"# Scale & backgroundmodel2.background.min = 1e-10\n",
"# Scale and background\n",
"model2.background.min = 1e-10\n",
"\n",
"model2.scale.fixed = False\n",
"model2.background.fixed = False\n",
Expand Down Expand Up @@ -540,7 +596,12 @@
"source": [
"## 14. Interlayer Fit Results & χ² Comparison\n",
"\n",
"Print the refined parameters and compare the reduced χ² of the two models to see whether the interlayers improve the fit."
"Print the refined parameters and compare reduced chi-squared for the two models.\n",
"\n",
"Discussion prompts:\n",
"- Did the interlayer model improve the fit significantly?\n",
"- Is the improvement large enough to justify the added complexity?\n",
"- Which parameters are physically interpretable, and which may be compensating each other?"
]
},
{
Expand Down Expand Up @@ -584,7 +645,14 @@
"id": "ccdb8df5",
"metadata": {},
"source": [
"## 15. Visualisation — Interlayer Model"
"## 15. Final Comparison and Reflection\n",
"\n",
"Use the plots and metrics to evaluate model quality.\n",
"\n",
"Final teaching questions:\n",
"- What specific improvements do you observe in reflectivity and SLD behaviour?\n",
"- What additional complexity could be added next (e.g., graded interfaces, multiple oxides, hydration, lateral inhomogeneity)?\n",
"- What data or constraints would be needed to justify more complex structures?"
]
},
{
Expand Down Expand Up @@ -637,7 +705,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "era",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
Expand All @@ -651,7 +719,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.12"
"version": "3.12.11"
}
},
"nbformat": 4,
Expand Down
Loading