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).
flowchart LR
A["Standard recipe<br/>instrument refined"] -->|run| B["output_recipe.json"]
B -->|"copy payload.instrument<br/>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/.
examples/example_LaB6/input.json
examples/example_LaB6/topas/input.json
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, TOPAS or easydiffraction.
Then run it:
pixi run -e gsasii powderline my_lab6/input.json
pixi run powderline my_lab6/input.json --topas-version 6 --topas-dir C:/TOPAS6
TOPAS runs on Windows only. See Run TOPAS recipes.
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 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:
"U": [49.11908, true] becomes "U": [49.11908, false]
Do this for every flag in payload.instrument:
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].
Every parameter in radiation, corrections and broadening.parameters.
Values are [value, flag, min, max]; leave the bounds as they are.
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 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.
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.
EB-93 shows what that means when the same data go to
easydiffraction. TOPAS
(EB-69) and easydiffraction (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#
pixi run powderline my_sample/input.json --validate-only
Then run it with your engine:
pixi run -e gsasii powderline my_sample/input.json
pixi run powderline my_sample/input.json --topas-version 6 --topas-dir C:/TOPAS6
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.
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, or Run a series to refine one sample’s model against many patterns.