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_from_repository
from easydiffraction import ExperimentFactory
from easydiffraction import Project
from easydiffraction import SampleModelFactory
from easydiffraction import download_from_repository
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_from_args(
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_from_args(
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_from_args(
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_from_args(
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_from_args(
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_from_args(
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_from_args(
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_from_args(
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_from_args(
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_from_args(
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!
download_from_repository('mcstas_lbco-si.xye', destination='data')
download_from_repository('mcstas_lbco-si.xye', destination='data')
Downloading...
File 'mcstas_lbco-si.xye' from 'easyscience/diffraction-lib'
Create Experiment¶
In [12]:
Copied!
experiment = ExperimentFactory.create(
name='mcstas',
data_path='data/mcstas_lbco-si.xye',
sample_form='powder',
beam_mode='time-of-flight',
radiation_probe='neutron',
scattering_type='bragg',
)
experiment = ExperimentFactory.create(
name='mcstas',
data_path='data/mcstas_lbco-si.xye',
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_from_args(x=45000, y=0.2)
experiment.background.add_from_args(x=50000, y=0.2)
experiment.background.add_from_args(x=55000, y=0.2)
experiment.background.add_from_args(x=65000, y=0.2)
experiment.background.add_from_args(x=70000, y=0.2)
experiment.background.add_from_args(x=75000, y=0.2)
experiment.background.add_from_args(x=80000, y=0.2)
experiment.background.add_from_args(x=85000, y=0.2)
experiment.background.add_from_args(x=90000, y=0.2)
experiment.background.add_from_args(x=95000, y=0.2)
experiment.background.add_from_args(x=100000, y=0.2)
experiment.background.add_from_args(x=105000, y=0.2)
experiment.background.add_from_args(x=110000, y=0.2)
experiment.background.add_from_args(x=45000, y=0.2)
experiment.background.add_from_args(x=50000, y=0.2)
experiment.background.add_from_args(x=55000, y=0.2)
experiment.background.add_from_args(x=65000, y=0.2)
experiment.background.add_from_args(x=70000, y=0.2)
experiment.background.add_from_args(x=75000, y=0.2)
experiment.background.add_from_args(x=80000, y=0.2)
experiment.background.add_from_args(x=85000, y=0.2)
experiment.background.add_from_args(x=90000, y=0.2)
experiment.background.add_from_args(x=95000, y=0.2)
experiment.background.add_from_args(x=100000, y=0.2)
experiment.background.add_from_args(x=105000, y=0.2)
experiment.background.add_from_args(x=110000, y=0.2)
Set Linked Phases¶
In [17]:
Copied!
experiment.linked_phases.add_from_args(id='lbco', scale=4.0)
experiment.linked_phases.add_from_args(id='si', scale=0.2)
experiment.linked_phases.add_from_args(id='lbco', scale=4.0)
experiment.linked_phases.add_from_args(id='si', scale=0.2)
In [18]:
Copied!
project = Project()
project = Project()
Set Plotting Engine¶
In [19]:
Copied!
project.plotter.engine = 'plotly'
project.plotter.engine = 'plotly'
Add Sample Models¶
In [20]:
Copied!
project.sample_models.add(model_1)
project.sample_models.add(model_2)
project.sample_models.add(model_1)
project.sample_models.add(model_2)
Show Sample Models¶
In [21]:
Copied!
project.sample_models.show_names()
project.sample_models.show_names()
Defined sample models 🧩
['lbco', 'si']
Add Experiments¶
In [22]:
Copied!
project.experiments.add(experiment)
project.experiments.add(experiment)
Set Excluded Regions¶
Show measured data as loaded from the file.
In [23]:
Copied!
project.plot_meas(expt_name='mcstas')
project.plot_meas(expt_name='mcstas')
Add excluded regions.
In [24]:
Copied!
experiment.excluded_regions.add_from_args(start=0, end=40000)
experiment.excluded_regions.add_from_args(start=108000, end=200000)
experiment.excluded_regions.add_from_args(start=0, end=40000)
experiment.excluded_regions.add_from_args(start=108000, end=200000)
Show excluded regions.
In [25]:
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 [26]:
Copied!
project.plot_meas(expt_name='mcstas')
project.plot_meas(expt_name='mcstas')
Show experiment as CIF.
In [27]:
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 |
| 9 | _peak.gauss_sigma_1 -52394 |
| 10 | _peak.gauss_sigma_2 22998 |
| 11 | _peak.lorentz_gamma_0 0.0 |
| 12 | _peak.lorentz_gamma_1 0.0 |
| 13 | _peak.lorentz_gamma_2 0.0 |
| 14 | _peak.mix_beta_0 0.0055 |
| 15 | _peak.mix_beta_1 0.0041 |
| 16 | _peak.asym_alpha_0 0 |
| 17 | _peak.asym_alpha_1 0.0097 |
| 18 | |
| 19 | _instr.2theta_bank 94.90931761529106 |
| 20 | _instr.d_to_tof_offset 0.0 |
| 21 | _instr.d_to_tof_linear 58724.76869981215 |
| 22 | _instr.d_to_tof_quad -1e-05 |
| 23 | _instr.d_to_tof_recip 0.0 |
| 24 | |
| 25 | loop_ |
| 26 | _pd_phase_block.id |
| 27 | _pd_phase_block.scale |
| 28 | lbco 4.0 |
| 29 | si 0.2 |
| 30 | |
| 31 | loop_ |
| 32 | _excluded_region.start |
| 33 | _excluded_region.end |
| 34 | 0 40000 |
| 35 | 108000 200000 |
| 36 | |
| 37 | loop_ |
| 38 | _pd_background.line_segment_X |
| 39 | _pd_background.line_segment_intensity |
| 40 | 45000 0.2 |
| 41 | 50000 0.2 |
| 42 | 55000 0.2 |
| 43 | 65000 0.2 |
| 44 | 70000 0.2 |
| 45 | 75000 0.2 |
| 46 | 80000 0.2 |
| 47 | 85000 0.2 |
| 48 | 90000 0.2 |
| 49 | 95000 0.2 |
| 50 | 100000 0.2 |
| 51 | 105000 0.2 |
| 52 | 110000 0.2 |
| 53 | |
| 54 | loop_ |
| 55 | _pd_meas.time_of_flight |
| 56 | _pd_meas.intensity_total |
| 57 | _pd_meas.intensity_total_su |
| 58 | 41168.1286 0.21537107469310052 0.024851140698641586 |
| 59 | 41273.8536 0.2608731253560513 0.03329888041963864 |
| 60 | 41379.5785 0.3043368615904641 0.0354708759178845 |
| 61 | 41485.3035 0.473667080481105 0.04206283617542718 |
| 62 | 41591.0285 0.6002651986502522 0.04196647994561225 |
| 63 | ... |
| 64 | 107563.4097 0.2230171962356684 0.007062820875646159 |
| 65 | 107669.1347 0.2196314236755727 0.007156715455880738 |
| 66 | 107774.8597 0.22676234246085125 0.00713080922521723 |
| 67 | 107880.5847 0.21245260466359916 0.006812625277766074 |
| 68 | 107986.3096 0.21452950815000962 0.006898412477966333 |
In [28]:
Copied!
project.analysis.current_calculator = 'cryspy'
project.analysis.current_calculator = 'cryspy'
Current calculator changed to
cryspy
Set Minimizer¶
In [29]:
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 [30]:
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 [31]:
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 [32]:
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.41 | |
| 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.04 seconds
📏 Goodness-of-fit (reduced χ²): 3.24
📏 R-factor (Rf): 4.76%
📏 R-factor squared (Rf²): 5.16%
📏 Weighted R-factor (wR): 5.22%
📈 Fitted parameters:
| datablock | category | entry | parameter | start | fitted | uncertainty | units | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | lbco | cell | None | 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 | None | length_a | 5.4315 | 5.4327 | 0.0006 | Å | 0.02 % ↑ |
| 5 | mcstas | peak | None | gauss_sigma_0 | 45137.0000 | 45210.8969 | 2868.4651 | µs² | 0.16 % ↑ |
| 6 | mcstas | peak | None | gauss_sigma_1 | -52394.0000 | -52476.8991 | 3797.9256 | µs/Å | 0.16 % ↑ |
| 7 | mcstas | peak | None | gauss_sigma_2 | 22998.0000 | 23014.3392 | 1193.4306 | µs²/Ų | 0.07 % ↑ |
| 8 | mcstas | peak | None | mix_beta_0 | 0.0055 | 0.0055 | 0.0001 | deg | 0.64 % ↑ |
| 9 | mcstas | peak | None | mix_beta_1 | 0.0041 | 0.0041 | 0.0003 | deg | 0.32 % ↓ |
| 10 | mcstas | peak | None | asym_alpha_1 | 0.0097 | 0.0097 | 0.0002 | 0.40 % ↓ | |
| 11 | mcstas | linked_phases | lbco | scale | 4.0000 | 4.5577 | 0.0318 | 13.94 % ↑ | |
| 12 | mcstas | linked_phases | si | scale | 0.2000 | 0.0314 | 0.0008 | 84.28 % ↓ | |
| 13 | mcstas | background | 45000 | y | 0.2000 | 0.2502 | 0.0082 | 25.09 % ↑ | |
| 14 | mcstas | background | 50000 | y | 0.2000 | 0.2498 | 0.0080 | 24.91 % ↑ | |
| 15 | mcstas | background | 55000 | y | 0.2000 | 0.2674 | 0.0047 | 33.68 % ↑ | |
| 16 | mcstas | background | 65000 | y | 0.2000 | 0.2551 | 0.0036 | 27.53 % ↑ | |
| 17 | mcstas | background | 70000 | y | 0.2000 | 0.2463 | 0.0035 | 23.17 % ↑ | |
| 18 | mcstas | background | 75000 | y | 0.2000 | 0.2417 | 0.0027 | 20.86 % ↑ | |
| 19 | mcstas | background | 80000 | y | 0.2000 | 0.2421 | 0.0033 | 21.07 % ↑ | |
| 20 | mcstas | background | 85000 | y | 0.2000 | 0.2374 | 0.0021 | 18.71 % ↑ | |
| 21 | mcstas | background | 90000 | y | 0.2000 | 0.2381 | 0.0020 | 19.07 % ↑ | |
| 22 | mcstas | background | 95000 | y | 0.2000 | 0.2423 | 0.0025 | 21.14 % ↑ | |
| 23 | mcstas | background | 100000 | y | 0.2000 | 0.2258 | 0.0022 | 12.88 % ↑ | |
| 24 | mcstas | background | 105000 | y | 0.2000 | 0.2228 | 0.0026 | 11.40 % ↑ | |
| 25 | mcstas | background | 110000 | y | 0.2000 | 0.2225 | 0.0078 | 11.23 % ↑ |
Plot Measured vs Calculated¶
In [33]:
Copied!
project.plot_meas_vs_calc(expt_name='mcstas')
project.plot_meas_vs_calc(expt_name='mcstas')