Structure Refinement: Si, SEPD¶
This example demonstrates a Rietveld refinement of Si crystal structure using time-of-flight neutron powder diffraction data from SEPD at Argonne.
Import Library¶
In [2]:
Copied!
from easydiffraction import ExperimentFactory
from easydiffraction import Project
from easydiffraction import StructureFactory
from easydiffraction import download_data
from easydiffraction import ExperimentFactory
from easydiffraction import Project
from easydiffraction import StructureFactory
from easydiffraction import download_data
In [3]:
Copied!
structure = StructureFactory.from_scratch(name='si')
structure = StructureFactory.from_scratch(name='si')
Set Space Group¶
In [4]:
Copied!
structure.space_group.name_h_m = 'F d -3 m'
structure.space_group.it_coordinate_system_code = '2'
structure.space_group.name_h_m = 'F d -3 m'
structure.space_group.it_coordinate_system_code = '2'
Set Unit Cell¶
In [5]:
Copied!
structure.cell.length_a = 5.431
structure.cell.length_a = 5.431
Set Atom Sites¶
In [6]:
Copied!
structure.atom_sites.create(
label='Si',
type_symbol='Si',
fract_x=0.125,
fract_y=0.125,
fract_z=0.125,
adp_iso=0.5,
)
structure.atom_sites.create(
label='Si',
type_symbol='Si',
fract_x=0.125,
fract_y=0.125,
fract_z=0.125,
adp_iso=0.5,
)
In [7]:
Copied!
data_path = download_data(id=7, destination='data')
data_path = download_data(id=7, destination='data')
Getting data...
Data #7: Si, SEPD (Argonne)
✅ Data #7 already present at 'data/ed-7.xye'. Keeping existing file.
Create Experiment¶
In [8]:
Copied!
expt = ExperimentFactory.from_data_path(
name='sepd', data_path=data_path, beam_mode='time-of-flight'
)
expt = ExperimentFactory.from_data_path(
name='sepd', data_path=data_path, beam_mode='time-of-flight'
)
Set Instrument¶
In [9]:
Copied!
expt.instrument.setup_twotheta_bank = 144.845
expt.instrument.calib_d_to_tof_offset = 0.0
expt.instrument.calib_d_to_tof_linear = 7476.91
expt.instrument.calib_d_to_tof_quad = -1.54
expt.instrument.setup_twotheta_bank = 144.845
expt.instrument.calib_d_to_tof_offset = 0.0
expt.instrument.calib_d_to_tof_linear = 7476.91
expt.instrument.calib_d_to_tof_quad = -1.54
Set Peak Profile¶
In [10]:
Copied!
expt.show_supported_peak_profile_types()
expt.show_current_peak_profile_type()
expt.peak.broad_gauss_sigma_0 = 3.0
expt.peak.broad_gauss_sigma_1 = 40.0
expt.peak.broad_gauss_sigma_2 = 2.0
expt.peak.exp_decay_beta_0 = 0.04221
expt.peak.exp_decay_beta_1 = 0.00946
expt.peak.exp_rise_alpha_0 = 0.0
expt.peak.exp_rise_alpha_1 = 0.5971
expt.show_supported_peak_profile_types()
expt.show_current_peak_profile_type()
expt.peak.broad_gauss_sigma_0 = 3.0
expt.peak.broad_gauss_sigma_1 = 40.0
expt.peak.broad_gauss_sigma_2 = 2.0
expt.peak.exp_decay_beta_0 = 0.04221
expt.peak.exp_decay_beta_1 = 0.00946
expt.peak.exp_rise_alpha_0 = 0.0
expt.peak.exp_rise_alpha_1 = 0.5971
Supported types
| Type | Description | |
|---|---|---|
| 1 | jorgensen | Jorgensen BBE ⊗ Gaussian profile |
| 2 | jorgensen-von-dreele | Jorgensen-Von Dreele BBE ⊗ pseudo-Voigt profile |
| 3 | double-jorgensen-von-dreele | Double-exp ⊗ pseudo-Voigt profile (Z-Rietveld type0m) |
Current peak profile type
jorgensen
Set Background¶
In [11]:
Copied!
expt.background_type = 'line-segment'
for x in range(0, 35000, 5000):
expt.background.create(id=str(x), x=x, y=200)
expt.background_type = 'line-segment'
for x in range(0, 35000, 5000):
expt.background.create(id=str(x), x=x, y=200)
Background type for experiment 'sepd' already set to
line-segment
Set Linked Phases¶
In [12]:
Copied!
expt.linked_phases.create(id='si', scale=10.0)
expt.linked_phases.create(id='si', scale=10.0)
In [13]:
Copied!
project = Project()
project = Project()
Add Structure¶
In [14]:
Copied!
project.structures.add(structure)
project.structures.add(structure)
Add Experiment¶
In [15]:
Copied!
project.experiments.add(expt)
project.experiments.add(expt)
In [16]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
Perform Fit 1/5¶
Set parameters to be refined.
In [17]:
Copied!
structure.cell.length_a.free = True
expt.linked_phases['si'].scale.free = True
expt.instrument.calib_d_to_tof_offset.free = True
structure.cell.length_a.free = True
expt.linked_phases['si'].scale.free = True
expt.instrument.calib_d_to_tof_offset.free = True
Show free parameters after selection.
In [18]:
Copied!
project.analysis.display.free_params()
project.analysis.display.free_params()
Free parameters for both structures (🧩 data blocks) and experiments (🔬 data blocks)
| datablock | category | entry | parameter | value | uncertainty | min | max | units | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.43100 | -inf | inf | Å | ||
| 2 | sepd | linked_phases | si | scale | 10.00000 | -inf | inf | ||
| 3 | sepd | instrument | d_to_tof_offset | 0.00000 | -inf | inf | μs |
Run Fitting¶
In [19]:
Copied!
project.analysis.fit()
project.analysis.display.fit_results()
project.analysis.fit()
project.analysis.display.fit_results()
Standard fitting
📋 Using experiment 🔬 'sepd' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit (reduced χ²) change:
| iteration | χ² | improvement [%] | |
|---|---|---|---|
| 1 | 1 | 113.06 | |
| 2 | 7 | 72.20 | 36.1% ↓ |
| 3 | 11 | 66.76 | 7.5% ↓ |
| 4 | 30 | 66.72 |
🏆 Best goodness-of-fit (reduced χ²) is 66.72 at iteration 26
✅ Fitting complete.
Fit results
✅ Success: True
⏱️ Fitting time: 10.35 seconds
📏 Goodness-of-fit (reduced χ²): 66.72
📏 R-factor (Rf): 23.08%
📏 R-factor squared (Rf²): 12.55%
📏 Weighted R-factor (wR): 12.51%
📈 Fitted parameters:
| datablock | category | entry | parameter | start | fitted | uncertainty | units | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.4310 | 5.4314 | 0.0002 | Å | 0.01 % ↑ | |
| 2 | sepd | linked_phases | si | scale | 10.0000 | 13.3619 | 0.1153 | 33.62 % ↑ | |
| 3 | sepd | instrument | d_to_tof_offset | 0.0000 | -9.2543 | 0.2503 | μs | N/A |
Plot Measured vs Calculated¶
In [20]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
In [21]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
Perform Fit 2/5¶
Set more parameters to be refined.
In [22]:
Copied!
for point in expt.background:
point.y.free = True
for point in expt.background:
point.y.free = True
Show free parameters after selection.
In [23]:
Copied!
project.analysis.display.free_params()
project.analysis.display.free_params()
Free parameters for both structures (🧩 data blocks) and experiments (🔬 data blocks)
| datablock | category | entry | parameter | value | uncertainty | min | max | units | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.43135 | 0.00018 | -inf | inf | Å | |
| 2 | sepd | linked_phases | si | scale | 13.36187 | 0.11531 | -inf | inf | |
| 3 | sepd | instrument | d_to_tof_offset | -9.25432 | 0.25033 | -inf | inf | μs | |
| 4 | sepd | background | 0 | y | 200.00000 | -inf | inf | ||
| 5 | sepd | background | 5000 | y | 200.00000 | -inf | inf | ||
| 6 | sepd | background | 10000 | y | 200.00000 | -inf | inf | ||
| 7 | sepd | background | 15000 | y | 200.00000 | -inf | inf | ||
| 8 | sepd | background | 20000 | y | 200.00000 | -inf | inf | ||
| 9 | sepd | background | 25000 | y | 200.00000 | -inf | inf | ||
| 10 | sepd | background | 30000 | y | 200.00000 | -inf | inf |
Run Fitting¶
In [24]:
Copied!
project.analysis.fit()
project.analysis.display.fit_results()
project.analysis.fit()
project.analysis.display.fit_results()
Standard fitting
📋 Using experiment 🔬 'sepd' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit (reduced χ²) change:
| iteration | χ² | improvement [%] | |
|---|---|---|---|
| 1 | 1 | 66.80 | |
| 2 | 14 | 3.38 | 94.9% ↓ |
| 3 | 48 | 3.38 |
🏆 Best goodness-of-fit (reduced χ²) is 3.38 at iteration 47
✅ Fitting complete.
Fit results
✅ Success: True
⏱️ Fitting time: 15.76 seconds
📏 Goodness-of-fit (reduced χ²): 3.38
📏 R-factor (Rf): 9.29%
📏 R-factor squared (Rf²): 6.33%
📏 Weighted R-factor (wR): 5.95%
📈 Fitted parameters:
| datablock | category | entry | parameter | start | fitted | uncertainty | units | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.4314 | 5.4314 | 0.0000 | Å | 0.00 % ↑ | |
| 2 | sepd | linked_phases | si | scale | 13.3619 | 14.6317 | 0.0265 | 9.50 % ↑ | |
| 3 | sepd | instrument | d_to_tof_offset | -9.2543 | -9.2534 | 0.0515 | μs | 0.01 % ↓ | |
| 4 | sepd | background | 0 | y | 200.0000 | 268.6002 | 0.9745 | 34.30 % ↑ | |
| 5 | sepd | background | 5000 | y | 200.0000 | 144.7589 | 0.4071 | 27.62 % ↓ | |
| 6 | sepd | background | 10000 | y | 200.0000 | 120.0247 | 0.4282 | 39.99 % ↓ | |
| 7 | sepd | background | 15000 | y | 200.0000 | 135.8494 | 0.8169 | 32.08 % ↓ | |
| 8 | sepd | background | 20000 | y | 200.0000 | 132.6887 | 1.4317 | 33.66 % ↓ | |
| 9 | sepd | background | 25000 | y | 200.0000 | 175.1775 | 2.8755 | 12.41 % ↓ | |
| 10 | sepd | background | 30000 | y | 200.0000 | 180.4556 | 5.8525 | 9.77 % ↓ |
Plot Measured vs Calculated¶
In [25]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
In [26]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
Perform Fit 3/5¶
Fix background points.
In [27]:
Copied!
for point in expt.background:
point.y.free = False
for point in expt.background:
point.y.free = False
Set more parameters to be refined.
In [28]:
Copied!
expt.peak.broad_gauss_sigma_0.free = True
expt.peak.broad_gauss_sigma_1.free = True
expt.peak.broad_gauss_sigma_2.free = True
expt.peak.broad_gauss_sigma_0.free = True
expt.peak.broad_gauss_sigma_1.free = True
expt.peak.broad_gauss_sigma_2.free = True
Show free parameters after selection.
In [29]:
Copied!
project.analysis.display.free_params()
project.analysis.display.free_params()
Free parameters for both structures (🧩 data blocks) and experiments (🔬 data blocks)
| datablock | category | entry | parameter | value | uncertainty | min | max | units | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.43137 | 0.00004 | -inf | inf | Å | |
| 2 | sepd | linked_phases | si | scale | 14.63167 | 0.02651 | -inf | inf | |
| 3 | sepd | peak | gauss_sigma_0 | 3.00000 | -inf | inf | μs² | ||
| 4 | sepd | peak | gauss_sigma_1 | 40.00000 | -inf | inf | μs/Å | ||
| 5 | sepd | peak | gauss_sigma_2 | 2.00000 | -inf | inf | μs²/Ų | ||
| 6 | sepd | instrument | d_to_tof_offset | -9.25336 | 0.05153 | -inf | inf | μs |
Run Fitting¶
In [30]:
Copied!
project.analysis.fit()
project.analysis.display.fit_results()
project.analysis.fit()
project.analysis.display.fit_results()
Standard fitting
📋 Using experiment 🔬 'sepd' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit (reduced χ²) change:
| iteration | χ² | improvement [%] | |
|---|---|---|---|
| 1 | 1 | 3.38 | |
| 2 | 10 | 3.21 | 5.0% ↓ |
| 3 | 39 | 3.21 |
🏆 Best goodness-of-fit (reduced χ²) is 3.21 at iteration 38
✅ Fitting complete.
Fit results
✅ Success: True
⏱️ Fitting time: 12.93 seconds
📏 Goodness-of-fit (reduced χ²): 3.21
📏 R-factor (Rf): 8.99%
📏 R-factor squared (Rf²): 5.52%
📏 Weighted R-factor (wR): 4.88%
📈 Fitted parameters:
| datablock | category | entry | parameter | start | fitted | uncertainty | units | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.4314 | 5.4314 | 0.0000 | Å | 0.00 % ↑ | |
| 2 | sepd | linked_phases | si | scale | 14.6317 | 14.7057 | 0.0257 | 0.51 % ↑ | |
| 3 | sepd | peak | gauss_sigma_0 | 3.0000 | 5.7727 | 0.4206 | μs² | 92.42 % ↑ | |
| 4 | sepd | peak | gauss_sigma_1 | 40.0000 | 44.2827 | 0.7966 | μs/Å | 10.71 % ↑ | |
| 5 | sepd | peak | gauss_sigma_2 | 2.0000 | 1.2962 | 0.1680 | μs²/Ų | 35.19 % ↓ | |
| 6 | sepd | instrument | d_to_tof_offset | -9.2534 | -9.2506 | 0.0546 | μs | 0.03 % ↓ |
Plot Measured vs Calculated¶
In [31]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
In [32]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
Perform Fit 4/5¶
Set more parameters to be refined.
In [33]:
Copied!
structure.atom_sites['Si'].adp_iso.free = True
expt.peak.exp_decay_beta_0.free = True
expt.peak.exp_decay_beta_1.free = True
expt.peak.exp_rise_alpha_1.free = True
structure.atom_sites['Si'].adp_iso.free = True
expt.peak.exp_decay_beta_0.free = True
expt.peak.exp_decay_beta_1.free = True
expt.peak.exp_rise_alpha_1.free = True
Show free parameters after selection.
In [34]:
Copied!
project.analysis.display.free_params()
project.analysis.display.free_params()
Free parameters for both structures (🧩 data blocks) and experiments (🔬 data blocks)
| datablock | category | entry | parameter | value | uncertainty | min | max | units | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.43143 | 0.00004 | -inf | inf | Å | |
| 2 | si | atom_site | Si | adp_iso | 0.50000 | -inf | inf | Ų | |
| 3 | sepd | linked_phases | si | scale | 14.70568 | 0.02567 | -inf | inf | |
| 4 | sepd | peak | rise_alpha_1 | 0.59710 | -inf | inf | μs/Å | ||
| 5 | sepd | peak | decay_beta_0 | 0.04221 | -inf | inf | μs | ||
| 6 | sepd | peak | decay_beta_1 | 0.00946 | -inf | inf | μs/Å | ||
| 7 | sepd | peak | gauss_sigma_0 | 5.77274 | 0.42055 | -inf | inf | μs² | |
| 8 | sepd | peak | gauss_sigma_1 | 44.28265 | 0.79664 | -inf | inf | μs/Å | |
| 9 | sepd | peak | gauss_sigma_2 | 1.29621 | 0.16795 | -inf | inf | μs²/Ų | |
| 10 | sepd | instrument | d_to_tof_offset | -9.25065 | 0.05458 | -inf | inf | μs |
Run Fitting¶
In [35]:
Copied!
project.analysis.fit()
project.analysis.display.fit_results()
project.analysis.fit()
project.analysis.display.fit_results()
Standard fitting
📋 Using experiment 🔬 'sepd' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit (reduced χ²) change:
| iteration | χ² | improvement [%] | |
|---|---|---|---|
| 1 | 1 | 3.21 | |
| 2 | 15 | 3.17 | 1.2% ↓ |
| 3 | 16 | 3.13 | 1.5% ↓ |
| 4 | 26 | 3.01 | 3.7% ↓ |
| 5 | 38 | 2.96 | 1.7% ↓ |
| 6 | 60 | 2.93 | 1.1% ↓ |
| 7 | 105 | 2.93 |
🏆 Best goodness-of-fit (reduced χ²) is 2.93 at iteration 104
✅ Fitting complete.
Fit results
✅ Success: True
⏱️ Fitting time: 35.20 seconds
📏 Goodness-of-fit (reduced χ²): 2.93
📏 R-factor (Rf): 8.39%
📏 R-factor squared (Rf²): 4.16%
📏 Weighted R-factor (wR): 2.48%
📈 Fitted parameters:
| datablock | category | entry | parameter | start | fitted | uncertainty | units | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | 5.4314 | 5.4325 | 0.0001 | Å | 0.02 % ↑ | |
| 2 | si | atom_site | Si | adp_iso | 0.5000 | 0.5240 | 0.0033 | Ų | 4.80 % ↑ |
| 3 | sepd | linked_phases | si | scale | 14.7057 | 14.9693 | 0.0355 | 1.79 % ↑ | |
| 4 | sepd | peak | rise_alpha_1 | 0.5971 | 0.2370 | 0.0043 | μs/Å | 60.31 % ↓ | |
| 5 | sepd | peak | decay_beta_0 | 0.0422 | 0.0386 | 0.0002 | μs | 8.65 % ↓ | |
| 6 | sepd | peak | decay_beta_1 | 0.0095 | 0.0106 | 0.0002 | μs/Å | 11.67 % ↑ | |
| 7 | sepd | peak | gauss_sigma_0 | 5.7727 | 6.9657 | 0.4577 | μs² | 20.67 % ↑ | |
| 8 | sepd | peak | gauss_sigma_1 | 44.2827 | 25.6509 | 1.0250 | μs/Å | 42.07 % ↓ | |
| 9 | sepd | peak | gauss_sigma_2 | 1.2962 | 1.1001 | 0.1584 | μs²/Ų | 15.13 % ↓ | |
| 10 | sepd | instrument | d_to_tof_offset | -9.2506 | -8.7248 | 0.0740 | μs | 5.68 % ↓ |
Show parameter correlations¶
In [36]:
Copied!
project.plotter.plot_param_correlations()
project.plotter.plot_param_correlations()
⚠️ No parameter pairs with |correlation| >= 0.70 were found.
Plot Measured vs Calculated¶
In [37]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', show_residual=True)
In [38]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', x_min=23200, x_max=23700, show_residual=True)
In [39]:
Copied!
project.plotter.plot_meas_vs_calc(expt_name='sepd', x='d_spacing', show_residual=True)
project.plotter.plot_meas_vs_calc(expt_name='sepd', x='d_spacing', show_residual=True)