Structure Refinement: LBCO+Si, McStas¶
This example demonstrates a Rietveld refinement of La0.5Ba0.5CoO3 crystal structure with a small amount of Si phase using time-of-flight neutron powder diffraction data simulated with McStas.
Import Library¶
In [2]:
Copied!
from easydiffraction import ExperimentFactory
from easydiffraction import Project
from easydiffraction import SampleModelFactory
from easydiffraction import download_data
from easydiffraction import ExperimentFactory
from easydiffraction import Project
from easydiffraction import SampleModelFactory
from easydiffraction import download_data
In [3]:
Copied!
model_1 = SampleModelFactory.create(name='lbco')
model_1 = SampleModelFactory.create(name='lbco')
Set Space Group¶
In [4]:
Copied!
model_1.space_group.name_h_m = 'P m -3 m'
model_1.space_group.it_coordinate_system_code = '1'
model_1.space_group.name_h_m = 'P m -3 m'
model_1.space_group.it_coordinate_system_code = '1'
Set Unit Cell¶
In [5]:
Copied!
model_1.cell.length_a = 3.8909
model_1.cell.length_a = 3.8909
Set Atom Sites¶
In [6]:
Copied!
model_1.atom_sites.add(
label='La',
type_symbol='La',
fract_x=0,
fract_y=0,
fract_z=0,
wyckoff_letter='a',
b_iso=0.2,
occupancy=0.5,
)
model_1.atom_sites.add(
label='Ba',
type_symbol='Ba',
fract_x=0,
fract_y=0,
fract_z=0,
wyckoff_letter='a',
b_iso=0.2,
occupancy=0.5,
)
model_1.atom_sites.add(
label='Co',
type_symbol='Co',
fract_x=0.5,
fract_y=0.5,
fract_z=0.5,
wyckoff_letter='b',
b_iso=0.2567,
)
model_1.atom_sites.add(
label='O',
type_symbol='O',
fract_x=0,
fract_y=0.5,
fract_z=0.5,
wyckoff_letter='c',
b_iso=1.4041,
)
model_1.atom_sites.add(
label='La',
type_symbol='La',
fract_x=0,
fract_y=0,
fract_z=0,
wyckoff_letter='a',
b_iso=0.2,
occupancy=0.5,
)
model_1.atom_sites.add(
label='Ba',
type_symbol='Ba',
fract_x=0,
fract_y=0,
fract_z=0,
wyckoff_letter='a',
b_iso=0.2,
occupancy=0.5,
)
model_1.atom_sites.add(
label='Co',
type_symbol='Co',
fract_x=0.5,
fract_y=0.5,
fract_z=0.5,
wyckoff_letter='b',
b_iso=0.2567,
)
model_1.atom_sites.add(
label='O',
type_symbol='O',
fract_x=0,
fract_y=0.5,
fract_z=0.5,
wyckoff_letter='c',
b_iso=1.4041,
)
Create Sample Model 2: Si¶
In [7]:
Copied!
model_2 = SampleModelFactory.create(name='si')
model_2 = SampleModelFactory.create(name='si')
Set Space Group¶
In [8]:
Copied!
model_2.space_group.name_h_m = 'F d -3 m'
model_2.space_group.it_coordinate_system_code = '2'
model_2.space_group.name_h_m = 'F d -3 m'
model_2.space_group.it_coordinate_system_code = '2'
Set Unit Cell¶
In [9]:
Copied!
model_2.cell.length_a = 5.43146
model_2.cell.length_a = 5.43146
Set Atom Sites¶
In [10]:
Copied!
model_2.atom_sites.add(
label='Si',
type_symbol='Si',
fract_x=0.0,
fract_y=0.0,
fract_z=0.0,
wyckoff_letter='a',
b_iso=0.0,
)
model_2.atom_sites.add(
label='Si',
type_symbol='Si',
fract_x=0.0,
fract_y=0.0,
fract_z=0.0,
wyckoff_letter='a',
b_iso=0.0,
)
In [11]:
Copied!
data_path = download_data(id=8, destination='data')
data_path = download_data(id=8, destination='data')
Getting data...
Data #8: La0.5Ba0.5CoO3 + Si, McStas simulation
✅ Data #8 downloaded to 'data/ed-8.xye'
Create Experiment¶
In [12]:
Copied!
experiment = ExperimentFactory.create(
name='mcstas',
data_path=data_path,
sample_form='powder',
beam_mode='time-of-flight',
radiation_probe='neutron',
scattering_type='bragg',
)
experiment = ExperimentFactory.create(
name='mcstas',
data_path=data_path,
sample_form='powder',
beam_mode='time-of-flight',
radiation_probe='neutron',
scattering_type='bragg',
)
Data loaded successfully
Experiment 🔬 'mcstas'. Number of data points: 1000
Set Instrument¶
In [13]:
Copied!
experiment.instrument.setup_twotheta_bank = 94.90931761529106
experiment.instrument.calib_d_to_tof_offset = 0.0
experiment.instrument.calib_d_to_tof_linear = 58724.76869981215
experiment.instrument.calib_d_to_tof_quad = -0.00001
experiment.instrument.setup_twotheta_bank = 94.90931761529106
experiment.instrument.calib_d_to_tof_offset = 0.0
experiment.instrument.calib_d_to_tof_linear = 58724.76869981215
experiment.instrument.calib_d_to_tof_quad = -0.00001
Set Peak Profile¶
In [14]:
Copied!
# experiment.peak_profile_type = 'pseudo-voigt * ikeda-carpenter'
experiment.peak.broad_gauss_sigma_0 = 45137
experiment.peak.broad_gauss_sigma_1 = -52394
experiment.peak.broad_gauss_sigma_2 = 22998
experiment.peak.broad_mix_beta_0 = 0.0055
experiment.peak.broad_mix_beta_1 = 0.0041
experiment.peak.asym_alpha_0 = 0
experiment.peak.asym_alpha_1 = 0.0097
# experiment.peak_profile_type = 'pseudo-voigt * ikeda-carpenter'
experiment.peak.broad_gauss_sigma_0 = 45137
experiment.peak.broad_gauss_sigma_1 = -52394
experiment.peak.broad_gauss_sigma_2 = 22998
experiment.peak.broad_mix_beta_0 = 0.0055
experiment.peak.broad_mix_beta_1 = 0.0041
experiment.peak.asym_alpha_0 = 0
experiment.peak.asym_alpha_1 = 0.0097
Set Background¶
Select the background type.
In [15]:
Copied!
experiment.background_type = 'line-segment'
experiment.background_type = 'line-segment'
Background type for experiment 'mcstas' changed to
line-segment
Add background points.
In [16]:
Copied!
experiment.background.add(id='1', x=45000, y=0.2)
experiment.background.add(id='2', x=50000, y=0.2)
experiment.background.add(id='3', x=55000, y=0.2)
experiment.background.add(id='4', x=65000, y=0.2)
experiment.background.add(id='5', x=70000, y=0.2)
experiment.background.add(id='6', x=75000, y=0.2)
experiment.background.add(id='7', x=80000, y=0.2)
experiment.background.add(id='8', x=85000, y=0.2)
experiment.background.add(id='9', x=90000, y=0.2)
experiment.background.add(id='10', x=95000, y=0.2)
experiment.background.add(id='11', x=100000, y=0.2)
experiment.background.add(id='12', x=105000, y=0.2)
experiment.background.add(id='13', x=110000, y=0.2)
experiment.background.add(id='1', x=45000, y=0.2)
experiment.background.add(id='2', x=50000, y=0.2)
experiment.background.add(id='3', x=55000, y=0.2)
experiment.background.add(id='4', x=65000, y=0.2)
experiment.background.add(id='5', x=70000, y=0.2)
experiment.background.add(id='6', x=75000, y=0.2)
experiment.background.add(id='7', x=80000, y=0.2)
experiment.background.add(id='8', x=85000, y=0.2)
experiment.background.add(id='9', x=90000, y=0.2)
experiment.background.add(id='10', x=95000, y=0.2)
experiment.background.add(id='11', x=100000, y=0.2)
experiment.background.add(id='12', x=105000, y=0.2)
experiment.background.add(id='13', x=110000, y=0.2)
Set Linked Phases¶
In [17]:
Copied!
experiment.linked_phases.add(id='lbco', scale=4.0)
experiment.linked_phases.add(id='si', scale=0.2)
experiment.linked_phases.add(id='lbco', scale=4.0)
experiment.linked_phases.add(id='si', scale=0.2)
In [18]:
Copied!
project = Project()
project = Project()
Add Sample Models¶
In [19]:
Copied!
project.sample_models.add(sample_model=model_1)
project.sample_models.add(sample_model=model_2)
project.sample_models.add(sample_model=model_1)
project.sample_models.add(sample_model=model_2)
Show Sample Models¶
In [20]:
Copied!
project.sample_models.show_names()
project.sample_models.show_names()
Defined sample models 🧩
['lbco', 'si']
Add Experiments¶
In [21]:
Copied!
project.experiments.add(experiment=experiment)
project.experiments.add(experiment=experiment)
Set Excluded Regions¶
Show measured data as loaded from the file.
In [22]:
Copied!
project.plot_meas(expt_name='mcstas')
project.plot_meas(expt_name='mcstas')
Add excluded regions.
In [23]:
Copied!
experiment.excluded_regions.add(id='1', start=0, end=40000)
experiment.excluded_regions.add(id='2', start=108000, end=200000)
experiment.excluded_regions.add(id='1', start=0, end=40000)
experiment.excluded_regions.add(id='2', start=108000, end=200000)
Show excluded regions.
In [24]:
Copied!
experiment.excluded_regions.show()
experiment.excluded_regions.show()
Excluded regions
| start | end | |
|---|---|---|
| 1 | 0 | 40000 |
| 2 | 108000 | 200000 |
Show measured data after adding excluded regions.
In [25]:
Copied!
project.plot_meas(expt_name='mcstas')
project.plot_meas(expt_name='mcstas')
Show experiment as CIF.
In [26]:
Copied!
project.experiments['mcstas'].show_as_cif()
project.experiments['mcstas'].show_as_cif()
Experiment 🔬 'mcstas' as cif
| CIF | |
|---|---|
| 1 | data_mcstas |
| 2 | |
| 3 | _expt_type.sample_form powder |
| 4 | _expt_type.beam_mode time-of-flight |
| 5 | _expt_type.radiation_probe neutron |
| 6 | _expt_type.scattering_type bragg |
| 7 | |
| 8 | _peak.gauss_sigma_0 45137.0000 |
| 9 | _peak.gauss_sigma_1 -52394.0000 |
| 10 | _peak.gauss_sigma_2 22998.0000 |
| 11 | _peak.lorentz_gamma_0 0.0000 |
| 12 | _peak.lorentz_gamma_1 0.0000 |
| 13 | _peak.lorentz_gamma_2 0.0000 |
| 14 | _peak.mix_beta_0 0.0055 |
| 15 | _peak.mix_beta_1 0.0041 |
| 16 | _peak.asym_alpha_0 0.0000 |
| 17 | _peak.asym_alpha_1 0.0097 |
| 18 | |
| 19 | _instr.2theta_bank 94.9093 |
| 20 | _instr.d_to_tof_offset 0.0000 |
| 21 | _instr.d_to_tof_linear 58724.7687 |
| 22 | _instr.d_to_tof_quad -0.0000 |
| 23 | _instr.d_to_tof_recip 0.0000 |
| 24 | |
| 25 | loop_ |
| 26 | _pd_phase_block.id |
| 27 | _pd_phase_block.scale |
| 28 | lbco 4.0000 |
| 29 | si 0.2000 |
| 30 | |
| 31 | loop_ |
| 32 | _excluded_region.id |
| 33 | _excluded_region.start |
| 34 | _excluded_region.end |
| 35 | 1 0.0000 40000.0000 |
| 36 | 2 108000.0000 200000.0000 |
| 37 | |
| 38 | loop_ |
| 39 | _pd_meas.time_of_flight |
| 40 | _pd_data.point_id |
| 41 | _pd_proc.d_spacing |
| 42 | _pd_meas.intensity_total |
| 43 | _pd_meas.intensity_total_su |
| 44 | _pd_calc.intensity_total |
| 45 | _pd_calc.intensity_bkg |
| 46 | _pd_data.refinement_status |
| 47 | 41168.1286 1 0.7010 0.2154 0.0249 0.2544 0.2000 incl |
| 48 | 41273.8536 2 0.7028 0.2609 0.0333 0.3380 0.2000 incl |
| 49 | 41379.5785 3 0.7046 0.3043 0.0355 0.4664 0.2000 incl |
| 50 | 41485.3035 4 0.7064 0.4737 0.0421 0.5860 0.2000 incl |
| 51 | 41591.0285 5 0.7082 0.6003 0.0420 0.6236 0.2000 incl |
| 52 | 41696.7534 6 0.7100 0.6017 0.0397 0.5577 0.2000 incl |
| 53 | 41802.4784 7 0.7118 0.5012 0.0381 0.4329 0.2000 incl |
| 54 | 41908.2034 8 0.7136 0.3770 0.0346 0.3153 0.2000 incl |
| 55 | 42013.9284 9 0.7154 0.2753 0.0319 0.2457 0.2000 incl |
| 56 | 42119.6533 10 0.7172 0.2618 0.0283 0.2273 0.2000 incl |
| 57 | ... |
| 58 | 145835.8489 991 2.4834 0.2241 0.0113 0.2000 0.2000 excl |
| 59 | 145941.5739 992 2.4852 0.2138 0.0107 0.2000 0.2000 excl |
| 60 | 146047.2988 993 2.4870 0.2093 0.0109 0.2000 0.2000 excl |
| 61 | 146153.0238 994 2.4888 0.2184 0.0109 0.2000 0.2000 excl |
| 62 | 146258.7488 995 2.4906 0.2161 0.0110 0.2000 0.2000 excl |
| 63 | 146364.4737 996 2.4924 0.2057 0.0111 0.2000 0.2000 excl |
| 64 | 146470.1987 997 2.4942 0.2262 0.0114 0.2000 0.2000 excl |
| 65 | 146575.9237 998 2.4960 0.2211 0.0115 0.2000 0.2000 excl |
| 66 | 146681.6486 999 2.4978 0.2086 0.0110 0.2000 0.2000 excl |
| 67 | 146787.3736 1000 2.4996 0.2088 0.0109 0.2000 0.2000 excl |
| 68 | |
| 69 | loop_ |
| 70 | _pd_background.id |
| 71 | _pd_background.line_segment_X |
| 72 | _pd_background.line_segment_intensity |
| 73 | 1 45000.0000 0.2000 |
| 74 | 2 50000.0000 0.2000 |
| 75 | 3 55000.0000 0.2000 |
| 76 | 4 65000.0000 0.2000 |
| 77 | 5 70000.0000 0.2000 |
| 78 | 6 75000.0000 0.2000 |
| 79 | 7 80000.0000 0.2000 |
| 80 | 8 85000.0000 0.2000 |
| 81 | 9 90000.0000 0.2000 |
| 82 | 10 95000.0000 0.2000 |
| 83 | 11 100000.0000 0.2000 |
| 84 | 12 105000.0000 0.2000 |
| 85 | 13 110000.0000 0.2000 |
In [27]:
Copied!
project.analysis.current_calculator = 'cryspy'
project.analysis.current_calculator = 'cryspy'
Current calculator changed to
cryspy
Set Minimizer¶
In [28]:
Copied!
project.analysis.current_minimizer = 'lmfit (leastsq)'
project.analysis.current_minimizer = 'lmfit (leastsq)'
Current minimizer changed to
lmfit (leastsq)
Set Fitting Parameters¶
Set sample model parameters to be optimized.
In [29]:
Copied!
model_1.cell.length_a.free = True
model_1.atom_sites['Co'].b_iso.free = True
model_1.atom_sites['O'].b_iso.free = True
model_2.cell.length_a.free = True
model_1.cell.length_a.free = True
model_1.atom_sites['Co'].b_iso.free = True
model_1.atom_sites['O'].b_iso.free = True
model_2.cell.length_a.free = True
Set experiment parameters to be optimized.
In [30]:
Copied!
experiment.linked_phases['lbco'].scale.free = True
experiment.linked_phases['si'].scale.free = True
experiment.peak.broad_gauss_sigma_0.free = True
experiment.peak.broad_gauss_sigma_1.free = True
experiment.peak.broad_gauss_sigma_2.free = True
experiment.peak.asym_alpha_1.free = True
experiment.peak.broad_mix_beta_0.free = True
experiment.peak.broad_mix_beta_1.free = True
for point in experiment.background:
point.y.free = True
experiment.linked_phases['lbco'].scale.free = True
experiment.linked_phases['si'].scale.free = True
experiment.peak.broad_gauss_sigma_0.free = True
experiment.peak.broad_gauss_sigma_1.free = True
experiment.peak.broad_gauss_sigma_2.free = True
experiment.peak.asym_alpha_1.free = True
experiment.peak.broad_mix_beta_0.free = True
experiment.peak.broad_mix_beta_1.free = True
for point in experiment.background:
point.y.free = True
Perform Fit¶
In [31]:
Copied!
project.analysis.fit()
project.analysis.fit()
Using experiment 🔬 'mcstas' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit (reduced χ²) change:
| iteration | χ² | improvement [%] | |
|---|---|---|---|
| 1 | 1 | 301.38 | |
| 2 | 29 | 3.36 | 98.9% ↓ |
| 3 | 55 | 3.24 | 3.7% ↓ |
| 4 | 134 | 3.24 |
🏆 Best goodness-of-fit (reduced χ²) is 3.24 at iteration 133
✅ Fitting complete.
Fit results
✅ Success: True
⏱️ Fitting time: 5.34 seconds
📏 Goodness-of-fit (reduced χ²): 3.24
📏 R-factor (Rf): 4.74%
📏 R-factor squared (Rf²): 5.12%
📏 Weighted R-factor (wR): 5.18%
📈 Fitted parameters:
| datablock | category | entry | parameter | start | fitted | uncertainty | units | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | lbco | cell | length_a | 3.8909 | 3.8904 | 0.0001 | Å | 0.01 % ↓ | |
| 2 | lbco | atom_site | Co | b_iso | 0.2567 | 0.3233 | 0.0853 | Ų | 25.94 % ↑ |
| 3 | lbco | atom_site | O | b_iso | 1.4041 | 2.1686 | 0.0282 | Ų | 54.45 % ↑ |
| 4 | si | cell | length_a | 5.4315 | 5.4327 | 0.0006 | Å | 0.02 % ↑ | |
| 5 | mcstas | linked_phases | lbco | scale | 4.0000 | 4.5577 | 0.0318 | 13.94 % ↑ | |
| 6 | mcstas | linked_phases | si | scale | 0.2000 | 0.0314 | 0.0008 | 84.28 % ↓ | |
| 7 | mcstas | peak | gauss_sigma_0 | 45137.0000 | 45210.8969 | 2868.4651 | µs² | 0.16 % ↑ | |
| 8 | mcstas | peak | gauss_sigma_1 | -52394.0000 | -52476.8991 | 3797.9256 | µs/Å | 0.16 % ↑ | |
| 9 | mcstas | peak | gauss_sigma_2 | 22998.0000 | 23014.3392 | 1193.4306 | µs²/Ų | 0.07 % ↑ | |
| 10 | mcstas | peak | mix_beta_0 | 0.0055 | 0.0055 | 0.0001 | deg | 0.64 % ↑ | |
| 11 | mcstas | peak | mix_beta_1 | 0.0041 | 0.0041 | 0.0003 | deg | 0.32 % ↓ | |
| 12 | mcstas | peak | asym_alpha_1 | 0.0097 | 0.0097 | 0.0002 | 0.40 % ↓ | ||
| 13 | mcstas | background | 1 | y | 0.2000 | 0.2502 | 0.0082 | 25.09 % ↑ | |
| 14 | mcstas | background | 2 | y | 0.2000 | 0.2498 | 0.0080 | 24.91 % ↑ | |
| 15 | mcstas | background | 3 | y | 0.2000 | 0.2674 | 0.0047 | 33.68 % ↑ | |
| 16 | mcstas | background | 4 | y | 0.2000 | 0.2551 | 0.0036 | 27.53 % ↑ | |
| 17 | mcstas | background | 5 | y | 0.2000 | 0.2463 | 0.0035 | 23.17 % ↑ | |
| 18 | mcstas | background | 6 | y | 0.2000 | 0.2417 | 0.0027 | 20.86 % ↑ | |
| 19 | mcstas | background | 7 | y | 0.2000 | 0.2421 | 0.0033 | 21.07 % ↑ | |
| 20 | mcstas | background | 8 | y | 0.2000 | 0.2374 | 0.0021 | 18.71 % ↑ | |
| 21 | mcstas | background | 9 | y | 0.2000 | 0.2381 | 0.0020 | 19.07 % ↑ | |
| 22 | mcstas | background | 10 | y | 0.2000 | 0.2423 | 0.0025 | 21.14 % ↑ | |
| 23 | mcstas | background | 11 | y | 0.2000 | 0.2258 | 0.0022 | 12.88 % ↑ | |
| 24 | mcstas | background | 12 | y | 0.2000 | 0.2228 | 0.0026 | 11.40 % ↑ | |
| 25 | mcstas | background | 13 | y | 0.2000 | 0.2225 | 0.0078 | 11.23 % ↑ |
Plot Measured vs Calculated¶
In [32]:
Copied!
project.plot_meas_vs_calc(expt_name='mcstas')
project.plot_meas_vs_calc(expt_name='mcstas')
In [ ]:
Copied!