# Calibrate the instrument with a standard
**Goal:** measure your instrument's contribution to the pattern once, on a
standard, and reuse it for every sample measured the same way. That
contribution is its peak shape and whichever corrections apply to your
geometry. Holding the instrument fixed means the sample refinement refines only
the sample's parameters: its peak broadening, cell and structure.
**You need:**
- A pattern of a standard (LaB6, Si, CeO2) measured at the **same wavelength
and geometry** as your samples.
- A recipe for your sample, written for the **same engine** you will use for
the standard. With easydiffraction, it must also use the same calculator.
- The engine's environment ([Install](../getting-started/install.md)).
```mermaid
flowchart LR
A["Standard recipe
instrument refined"] -->|run| B["output_recipe.json"]
B -->|"copy payload.instrument
set flags to false"| C["Sample recipe"]
C -->|run| D[Sample results]
```
## 1. Refine the standard
Start from the LaB6 example for your engine. Copy it into a folder of your
own, for example `my_lab6/`.
::::{tab-set}
:sync-group: engine
:::{tab-item} GSAS-II
:sync: gsasii
`examples/example_LaB6/input.json`
:::
:::{tab-item} TOPAS
:sync: topas
`examples/example_LaB6/topas/input.json`
:::
:::{tab-item} easydiffraction
:sync: easydiffraction
`examples/example_LaB6/easydiffraction/input.json`
This example refines the cell. For a calibration, set the flags of `a`, `b`
and `c` to `false`.
:::
::::
Put your pattern into the recipe's `xrd_data` block. Set the cell to your
standard's certified value, held (`false`).
Refine the scale, the background, the peak-shape parameters and the
corrections that matter for your instrument. Which corrections those are
depends on the geometry and the engine. See the instrument section of your
engine's page: [GSAS-II](../engines/gsasii.md),
[TOPAS](../engines/topas.md) or
[easydiffraction](../engines/easydiffraction.md).
Then run it:
::::{tab-set}
:sync-group: engine
:::{tab-item} GSAS-II
:sync: gsasii
```bash
pixi run -e gsasii powderline my_lab6/input.json
```
:::
:::{tab-item} TOPAS
:sync: topas
```bash
pixi run powderline my_lab6/input.json --topas-version 6 --topas-dir C:/TOPAS6
```
TOPAS runs on Windows only. See [Run TOPAS recipes](run-topas.md).
:::
:::{tab-item} easydiffraction
:sync: easydiffraction
```bash
pixi run -e easydiffraction powderline my_lab6/input.json
```
:::
::::
Check the fit before going on. Plot `y_obs`, `y_calc` and `y_diff` from
`my_lab6/output/fit_profile.txt` and look at the difference curve, not just
Rwp. A poor calibrant fit gives a wrong instrument for every sample.
[Good refinement practice](../concepts/refinement-practice.md) has more on
judging a fit.
## 2. Copy the refined instrument
Open `my_lab6/output/output_recipe.json`. It is your recipe with the refined
values written back. Copy its whole `payload.instrument` block into your
sample recipe, replacing the one there.
:::{note}
If the run reported `output_recipe_valid: false`, the engine returned a value
the recipe format refuses. Read the `output_recipe_not_valid` warning and fix
the standard's refinement before you copy anything.
:::
## 3. Hold the instrument
Set every refine flag in the copied block to `false`. The sample refinement
should refine only the sample's parameters, not the instrument's.
Change only the flags. For each parameter, the value stays and the flag
becomes `false`:
```text
"U": [49.11908, true] becomes "U": [49.11908, false]
```
Do this for every flag in `payload.instrument`:
::::{tab-set}
:sync-group: engine
:::{tab-item} GSAS-II
:sync: gsasii
`radiation.wavelength`, the three `corrections` (`zero_shift`,
`polarization`, `axial_divergence`) and the six `broadening` terms `U`, `V`,
`W`, `X`, `Y`, `Z`. Values are `[value, flag]`.
:::
:::{tab-item} TOPAS
:sync: topas
Every parameter in `radiation`, `corrections` and `broadening.parameters`.
Values are `[value, flag, min, max]`; leave the bounds as they are.
:::
:::{tab-item} easydiffraction
:sync: easydiffraction
Every parameter in `radiation`, `corrections` and `broadening.parameters`.
Values are `[value, flag, min, max]`; leave the bounds as they are. The peak
types depend on the calculator, so the block validates only in a sample
recipe with the same `refinement_controls.calculator` as the standard's.
:::
::::
The `hold()` function under [In Python](#in-python) does this for you.
:::{caution}
Check that the refined values make sense before you hold them. A held value
carries its problem into every sample refinement. See
[Good refinement practice](../concepts/refinement-practice.md).
:::
:::{note}
A negative profile term is common and is not an error in itself; what
matters is the total peak width over your fit window. Each engine handles a
width that would go below zero in its own way. The GSAS-II LaB6 example shows
it: its refined `Y` is about −10, so its Lorentzian width would fall below
zero above about 10.7° 2θ. GSAS-II floors the width at 0.001 centidegree
there, without a message, so those peaks are computed as Gaussian.
{ref}`EB-93 ` shows what that means when the same data go to
easydiffraction. TOPAS
({ref}`EB-69 `) and easydiffraction ({ref}`EB-87 `) behave
differently, which is one more reason to refine the standard again in the
engine you use.
:::
## 4. Validate and run the sample
```bash
pixi run powderline my_sample/input.json --validate-only
```
Then run it with your engine:
::::{tab-set}
:sync-group: engine
:::{tab-item} GSAS-II
:sync: gsasii
```bash
pixi run -e gsasii powderline my_sample/input.json
```
:::
:::{tab-item} TOPAS
:sync: topas
```bash
pixi run powderline my_sample/input.json --topas-version 6 --topas-dir C:/TOPAS6
```
:::
:::{tab-item} easydiffraction
:sync: easydiffraction
```bash
pixi run -e easydiffraction powderline my_sample/input.json
```
:::
::::
**Check:** open `my_sample/output/parameter_dispositions.csv`. Every row whose
`path` starts with `payload.instrument` reads `held_by_user`.
:::{warning}
An instrument block belongs to one engine. GSAS-II's `U, V, W` give the
Gaussian variance σ² in centidegrees²; TOPAS's and easydiffraction's give
the Gaussian FWHM² in degrees² (FWHM² = 8 ln 2 · σ² / 10⁴). `X` and `Y`
swap roles. To use a GSAS-II calibration with TOPAS, refine the standard
again with TOPAS.
:::
## In Python
The same steps as a script. `hold()` sets every refine flag in a block to
`false` and leaves everything else as it is.
```python
from pathlib import Path
import powderline
cal = powderline.run(powderline.load_recipe_asset(Path("my_lab6/input.json")),
Path("my_lab6/output"))
if not cal["output_recipe_valid"]:
raise SystemExit("the standard's output recipe is not valid: check its warnings")
def hold(block):
"""Return a copy of the block with every refine flag set to False."""
if isinstance(block, dict):
return {k: hold(v) for k, v in block.items()}
if isinstance(block, list) and len(block) >= 2 and isinstance(block[1], bool):
return [block[0], False, *block[2:]]
return block
sample = powderline.load_recipe_asset(Path("my_sample/input.json"))
sample["payload"]["instrument"] = hold(cal["output_recipe"]["payload"]["instrument"])
result = powderline.run(sample, Path("my_sample/output"))
print(result["rwp"])
```
Run it in the engine's environment, for example
`pixi run -e gsasii python calibrate.py`.
**Next:** [Refine a structure](refine-structure.md), or
[Run a series](sequential-refinement.md) to refine one sample's model against
many patterns.