Structure Refinement: LBCO, HRPT¶
This basic example is designed to show how Rietveld refinement can be performed when both the crystal structure and experiment parameters are defined using CIF files.
For this example, constant-wavelength neutron powder diffraction data for La0.5Ba0.5CoO3 from HRPT at PSI is used.
The example is intended for users who are already familiar with the EasyDiffraction library and want to quickly get started with a basic refinement.
It is also useful for those who want to see how constraints can be applied to highly correlated parameters. For a more detailed explanation of the code, please refer to the other tutorials.
🛠️ Import Library¶
In [2]:
Copied!
import easydiffraction as ed
import easydiffraction as ed
📦 Define Project¶
In [3]:
Copied!
# Create a minimal project with a short name
project = ed.Project(name='lbco_hrpt')
# Create a minimal project with a short name
project = ed.Project(name='lbco_hrpt')
🧩 Define Structure¶
In [4]:
Copied!
# Download CIF file from repository
structure_path = ed.download_data(id=1, destination='data')
# Download CIF file from repository
structure_path = ed.download_data(id=1, destination='data')
Getting data...
Data #1: La0.5Ba0.5CoO3 (crystal structure)
✅ Data #1 downloaded to '../../../data/ed-1.cif'
In [5]:
Copied!
# Add structure from downloaded CIF
project.structures.add_from_cif_path(structure_path)
# Add structure from downloaded CIF
project.structures.add_from_cif_path(structure_path)
In [6]:
Copied!
# Plot the crystal structure
project.display.structure(struct_name='lbco')
# Plot the crystal structure
project.display.structure(struct_name='lbco')
Structure 🧩 'lbco' (Atom view type: 'covalent')
Loading plot…
drag = rotate
wheel = zoom
right-drag = pan
wheel = zoom
right-drag = pan
🔬 Define Experiment¶
In [7]:
Copied!
# Download CIF file from repository
expt_path = ed.download_data(id=2, destination='data')
# Download CIF file from repository
expt_path = ed.download_data(id=2, destination='data')
Getting data...
Data #2: La0.5Ba0.5CoO3, HRPT (PSI), 300 K
✅ Data #2 downloaded to '../../../data/ed-2.cif'
In [8]:
Copied!
# Add experiment from downloaded CIF
project.experiments.add_from_cif_path(expt_path)
# Add experiment from downloaded CIF
project.experiments.add_from_cif_path(expt_path)
🚀 Perform Analysis¶
Without Constraints¶
In [9]:
Copied!
# Start refinement. All parameters, which have standard uncertainties
# in the input CIF files, are refined by default.
project.analysis.fit()
# Start refinement. All parameters, which have standard uncertainties
# in the input CIF files, are refined by default.
project.analysis.fit()
Standard fitting
📋 Using experiment 🔬 'hrpt' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit progress:
| iteration | time (s) | χ² | change / status | |
|---|---|---|---|---|
| 1 | 1 | 0.35 | 165.50 | |
| 2 | 28 | 1.80 | 33.67 | 79.7% ↓ |
| 3 | 45 | 2.71 | 10.85 | 67.8% ↓ |
| 4 | 63 | 3.68 | 6.43 | 40.7% ↓ |
| 5 | 81 | 4.66 | 3.33 | 48.2% ↓ |
| 6 | 98 | 5.58 | 2.23 | 33.2% ↓ |
| 7 | 116 | 6.84 | 1.91 | 14.5% ↓ |
| 8 | 133 | 7.75 | 1.50 | 21.1% ↓ |
| 9 | 150 | 8.66 | 1.45 | 3.6% ↓ |
| 10 | 167 | 9.59 | 1.34 | 7.7% ↓ |
| 11 | 185 | 10.56 | 1.29 | 3.4% ↓ |
| 12 | 276 | 14.95 | 1.29 |
🏆 Best goodness-of-fit (reduced χ²) is 1.29 at iteration 261
✅ Fitting complete.
In [10]:
Copied!
# Show fit results summary
project.display.fit.results()
# Show fit results summary
project.display.fit.results()
⚙️ Settings used:
| Name | Value | Description | |
|---|---|---|---|
| 1 | max_iterations | 1000 | Maximum solver iterations. |
📋 Least-squares fit results:
| Metric | Value | |
|---|---|---|
| 1 | 🧪 Minimizer | lmfit (leastsq) |
| 2 | ✅ Overall status | success |
| 3 | ⏱️ Fitting time (seconds) | 14.95 |
| 4 | 🔁 Iterations | 273 |
| 5 | 📏 Goodness-of-fit (reduced χ²) | 1.29 |
| 6 | 📏 R-factor (Rf, %) | 5.62 |
| 7 | 📏 R-factor squared (Rf², %) | 5.25 |
| 8 | 📏 Weighted R-factor (wR, %) | 4.40 |
📈 Refined parameters:
| datablock | category | entry | parameter | units | start | value | s.u. | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | lbco | cell | length_a | Å | 3.8800 | 3.8909 | 0.0000 | 0.28 % ↑ | |
| 2 | lbco | atom_site | La | adp_iso | Ų | 0.5000 | 0.5051 | 6011.8674 | 1.02 % ↑ |
| 3 | lbco | atom_site | Ba | adp_iso | Ų | 0.5000 | 0.5052 | 9770.9689 | 1.04 % ↑ |
| 4 | lbco | atom_site | Co | adp_iso | Ų | 0.5000 | 0.2371 | 0.0611 | 52.59 % ↓ |
| 5 | lbco | atom_site | O | adp_iso | Ų | 0.5000 | 1.3935 | 0.0168 | 178.70 % ↑ |
| 6 | hrpt | linked_phases | lbco | scale | 10.0000 | 9.1349 | 0.0643 | 8.65 % ↓ | |
| 7 | hrpt | peak | broad_gauss_u | deg² | 0.1000 | 0.0816 | 0.0031 | 18.44 % ↓ | |
| 8 | hrpt | peak | broad_gauss_v | deg² | -0.1000 | -0.1159 | 0.0067 | 15.90 % ↑ | |
| 9 | hrpt | peak | broad_gauss_w | deg² | 0.1000 | 0.1204 | 0.0033 | 20.45 % ↑ | |
| 10 | hrpt | peak | broad_lorentz_y | deg | 0.1000 | 0.0844 | 0.0021 | 15.57 % ↓ | |
| 11 | hrpt | instrument | twotheta_offset | deg | 0.6000 | 0.6226 | 0.0010 | 3.76 % ↑ | |
| 12 | hrpt | background | 1 | y | 170.0000 | 168.4242 | 1.3977 | 0.93 % ↓ | |
| 13 | hrpt | background | 2 | y | 170.0000 | 164.3715 | 1.0025 | 3.31 % ↓ | |
| 14 | hrpt | background | 3 | y | 170.0000 | 166.8870 | 0.7391 | 1.83 % ↓ | |
| 15 | hrpt | background | 4 | y | 170.0000 | 175.3977 | 0.6586 | 3.18 % ↑ | |
| 16 | hrpt | background | 5 | y | 170.0000 | 174.3027 | 0.9113 | 2.53 % ↑ |
• start = parameter value before refinement
• value = refined value from least-squares minimization
• s.u. = standard uncertainty (one sigma), from the covariance matrix
• change = relative change from start, in %; ↑ = increase, ↓ = decrease
• value = refined value from least-squares minimization
• s.u. = standard uncertainty (one sigma), from the covariance matrix
• change = relative change from start, in %; ↑ = increase, ↓ = decrease
⚠️ Red s.u.: exceeds the refined value (consider adding constraints)
In [11]:
Copied!
# Show parameter correlations
project.display.fit.correlations()
# Show parameter correlations
project.display.fit.correlations()
Loading plot…
With Constraints¶
In [12]:
Copied!
# As can be seen from the parameter-correlation plot, the isotropic
# displacement parameters of La and Ba are highly correlated. Because
# La and Ba share the same mixed-occupancy site, their contributions to
# the neutron diffraction pattern are difficult to separate, especially
# since their coherent scattering lengths are not very different.
# Therefore, it is necessary to constrain them to be equal. First we
# define aliases and then use them to create a constraint.
project.analysis.aliases.create(
label='biso_La',
param=project.structures['lbco'].atom_sites['La'].adp_iso,
)
project.analysis.aliases.create(
label='biso_Ba',
param=project.structures['lbco'].atom_sites['Ba'].adp_iso,
)
project.analysis.constraints.create(expression='biso_Ba = biso_La')
# As can be seen from the parameter-correlation plot, the isotropic
# displacement parameters of La and Ba are highly correlated. Because
# La and Ba share the same mixed-occupancy site, their contributions to
# the neutron diffraction pattern are difficult to separate, especially
# since their coherent scattering lengths are not very different.
# Therefore, it is necessary to constrain them to be equal. First we
# define aliases and then use them to create a constraint.
project.analysis.aliases.create(
label='biso_La',
param=project.structures['lbco'].atom_sites['La'].adp_iso,
)
project.analysis.aliases.create(
label='biso_Ba',
param=project.structures['lbco'].atom_sites['Ba'].adp_iso,
)
project.analysis.constraints.create(expression='biso_Ba = biso_La')
In [13]:
Copied!
# Start refinement. All parameters, which have standard uncertainties
# in the input CIF files, are refined by default.
project.analysis.fit()
# Start refinement. All parameters, which have standard uncertainties
# in the input CIF files, are refined by default.
project.analysis.fit()
Standard fitting
📋 Using experiment 🔬 'hrpt' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit progress:
| iteration | time (s) | χ² | change / status | |
|---|---|---|---|---|
| 1 | 1 | 0.05 | 1.29 | |
| 2 | 20 | 1.28 | 1.29 |
🏆 Best goodness-of-fit (reduced χ²) is 1.29 at iteration 19
✅ Fitting complete.
In [14]:
Copied!
# Show fit results summary
project.display.fit.results()
# Show fit results summary
project.display.fit.results()
⚙️ Settings used:
| Name | Value | Description | |
|---|---|---|---|
| 1 | max_iterations | 1000 | Maximum solver iterations. |
📋 Least-squares fit results:
| Metric | Value | |
|---|---|---|
| 1 | 🧪 Minimizer | lmfit (leastsq) |
| 2 | ✅ Overall status | success |
| 3 | ⏱️ Fitting time (seconds) | 1.28 |
| 4 | 🔁 Iterations | 17 |
| 5 | 📏 Goodness-of-fit (reduced χ²) | 1.29 |
| 6 | 📏 R-factor (Rf, %) | 5.62 |
| 7 | 📏 R-factor squared (Rf², %) | 5.25 |
| 8 | 📏 Weighted R-factor (wR, %) | 4.40 |
📈 Refined parameters:
| datablock | category | entry | parameter | units | start | value | s.u. | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | lbco | cell | length_a | Å | 3.8909 | 3.8909 | 0.0000 | 0.00 % ↑ | |
| 2 | lbco | atom_site | La | adp_iso | Ų | 0.5051 | 0.5051 | 0.0278 | 0.00 % ↑ |
| 3 | lbco | atom_site | Co | adp_iso | Ų | 0.2371 | 0.2371 | 0.0564 | 0.00 % ↓ |
| 4 | lbco | atom_site | O | adp_iso | Ų | 1.3935 | 1.3935 | 0.0160 | 0.00 % ↑ |
| 5 | hrpt | linked_phases | lbco | scale | 9.1349 | 9.1349 | 0.0538 | 0.00 % ↓ | |
| 6 | hrpt | peak | broad_gauss_u | deg² | 0.0816 | 0.0816 | 0.0031 | 0.00 % ↑ | |
| 7 | hrpt | peak | broad_gauss_v | deg² | -0.1159 | -0.1159 | 0.0066 | 0.01 % ↑ | |
| 8 | hrpt | peak | broad_gauss_w | deg² | 0.1204 | 0.1204 | 0.0032 | 0.00 % ↑ | |
| 9 | hrpt | peak | broad_lorentz_y | deg | 0.0844 | 0.0844 | 0.0021 | 0.00 % ↓ | |
| 10 | hrpt | instrument | twotheta_offset | deg | 0.6226 | 0.6226 | 0.0010 | 0.00 % ↑ | |
| 11 | hrpt | background | 1 | y | 168.4242 | 168.4242 | 1.3974 | 0.00 % ↑ | |
| 12 | hrpt | background | 2 | y | 164.3715 | 164.3715 | 1.0023 | 0.00 % ↑ | |
| 13 | hrpt | background | 3 | y | 166.8870 | 166.8871 | 0.7388 | 0.00 % ↑ | |
| 14 | hrpt | background | 4 | y | 175.3977 | 175.3978 | 0.6490 | 0.00 % ↑ | |
| 15 | hrpt | background | 5 | y | 174.3027 | 174.3026 | 0.8956 | 0.00 % ↓ |
• start = parameter value before refinement
• value = refined value from least-squares minimization
• s.u. = standard uncertainty (one sigma), from the covariance matrix
• change = relative change from start, in %; ↑ = increase, ↓ = decrease
• value = refined value from least-squares minimization
• s.u. = standard uncertainty (one sigma), from the covariance matrix
• change = relative change from start, in %; ↑ = increase, ↓ = decrease
In [15]:
Copied!
# Show parameter correlations
project.display.fit.correlations()
# Show parameter correlations
project.display.fit.correlations()
Loading plot…
In [16]:
Copied!
# Show defined experiment names
project.experiments.show_names()
# Show defined experiment names
project.experiments.show_names()
Defined experiments 🔬
['hrpt']
In [17]:
Copied!
# Plot measured vs. calculated diffraction patterns
project.display.pattern(expt_name='hrpt')
# Plot measured vs. calculated diffraction patterns
project.display.pattern(expt_name='hrpt')
Loading plot…
💾 Save Project¶
In [18]:
Copied!
project.save_as(dir_path='projects/ed_1_lbco_hrpt')
project.save_as(dir_path='projects/ed_1_lbco_hrpt')
Saving project 📦 'lbco_hrpt' to '../../../projects/ed_1_lbco_hrpt'
├── 📄 project.cif
├── 📁 structures/
│ └── 📄 lbco.cif
├── 📁 experiments/
│ └── 📄 hrpt.cif
├── 📁 analysis/
│ └── 📄 analysis.cif
└── 📁 reports/
└── 📄 lbco_hrpt.html