Fitting pd-neut-tof Si-SEPD¶
This example shows how to refine the crystal structure parameters of Si from neutron diffraction data in a time-of-flight experiment performed on SEPD diffractometer at Argonne.
Import EasyDiffraction¶
import easydiffraction as ed
Create a job¶
Create a job — the main object to store all the information
job = ed.Job(type='tof')
print(job.type)
Job type: pd-tof-unp-1d-neut
Define a model¶
Create a phase object
phase = ed.Phase(name='si')
Set space group
phase.space_group.name_hm_alt = 'F d -3 m'
Set cell parameters
phase.cell.length_a = 5.43146
Add atoms
phase.atom_sites.append(label='Si',
type_symbol='Si',
fract_x=0,
fract_y=0,
fract_z=0,
occupancy=1,
b_iso_or_equiv=0.529)
Add phase to the job object
job.add_phase(phase=phase)
print(job.phases)
Several values of it_coordinate_system_code have been defined: 2, 1 The default value has been choosen:'2'. Several values of it_coordinate_system_code have been defined: 2, 1 The default value has been choosen:'2'. Collection of 1 phases: ['si']
Show phase info in CIF format
phase = job.phases['si']
print(phase.cif)
data_si _cell_length_a 5.43146 _cell_length_b 5.43146 _cell_length_c 5.43146 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _space_group_name_H-M_ref 'F d -3 m' _space_group_IT_coordinate_system_code 1 loop_ _atom_site_label _atom_site_type_symbol _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy _atom_site_adp_type _atom_site_B_iso_or_equiv Si Si 0.00000000 0.00000000 0.00000000 1.00000000 Biso 0.529
Display the crystal structure of a given model
job.show_crystal_structure(id='si')
3Dmol.js failed to load for some reason. Please check your browser console for error messages.
Define an experiment¶
Download the data file from the EasyDiffraction repository on GitHub
ed.download_from_repository('sepd.xye', destination='data')
Show content of the downloaded file (first 5 lines)
with open('data/sepd.xye') as f:
print(''.join(f.readlines()[:5]))
2000.0 213.8 3.3 2005.0 213.8 3.3 2010.0 210.1 3.3 2015.0 213.3 3.3 2020.0 211.9 3.3
Load experimentally measured data from a file in XYE format
job.add_experiment_from_file('data/sepd.xye')
Display the experimentally measured data
job.show_experiment_chart(show_legend=False)
Define a point background
background_points = [(x, 200) for x in range(0, 35000, 5000)]
print(background_points)
[(0, 200), (5000, 200), (10000, 200), (15000, 200), (20000, 200), (25000, 200), (30000, 200)]
job.set_background(background_points)
Display the experiment chart after setting the background
job.show_experiment_chart()
Perform an analysis¶
Display the analysis chart before setting initial parameter values
job.show_analysis_chart()
Create aliases for the two types of experimental parameters
pattern_params = job.pattern
experiment_params = job.parameters
Change the default value of some instrumental parameters and display the analysis chart again
experiment_params.dtt1 = 7476.91
experiment_params.dtt2 = -1.54
experiment_params.ttheta_bank = 144.845
job.show_analysis_chart()
Change the scale and display the analysis chart again
phase.scale = 10
job.show_analysis_chart()
Change the default values of the peak profile related parameters and display the analysis chart again
experiment_params.alpha0 = 0.024
experiment_params.alpha1 = 0.204
experiment_params.beta0 = 0.038
experiment_params.beta1 = 0.011
experiment_params.sigma0 = 0.0
experiment_params.sigma1 = 0.0
experiment_params.sigma2 = 0.0
job.show_analysis_chart()
Select parameters to be refined in the first round
phase.scale.free = True
pattern_params.zero_shift.free = True
Print parameters to be refined (free parameters) before fitting
job.show_free_parameters()
name | value | error | ||
---|---|---|---|---|
1 | .phases['si'].scale | 10.0 | 0.0 |
Start Least-Squares minimization to refine the selected parameters
job.fit()
Fitting result Status: 🥳 Success Duration: ⌛ 7.87 s Reduced χ²: 👍 36.80
Print the refined parameters after fitting
job.show_free_parameters()
name | value | error | ||
---|---|---|---|---|
1 | .phases['si'].scale | 12.810954 | 0.112699 | |
2 | .pattern.zero_shift | -4.166396 | µs | 0.052262 |
Display the analysis chart after the first fitting
job.show_analysis_chart()
Allow background parameters to be refined
for background_point in pattern_params.backgrounds[0]:
background_point.y.free = True
Print free parameters before the second fitting
job.show_free_parameters()
name | value | error | ||
---|---|---|---|---|
1 | .phases['si'].scale | 12.810954 | 0.112699 | |
2 | .pattern.zero_shift | -4.166396 | µs | 0.052262 |
3 | .pattern.backgrounds[0]['0,0_deg'].intensity | 200.000000 | 0.000000 | |
4 | .pattern.backgrounds[0]['5000,0_deg'].intensity | 200.000000 | 0.000000 | |
5 | .pattern.backgrounds[0]['10000,0_deg'].intensity | 200.000000 | 0.000000 | |
6 | .pattern.backgrounds[0]['15000,0_deg'].intensity | 200.000000 | 0.000000 | |
7 | .pattern.backgrounds[0]['20000,0_deg'].intensity | 200.000000 | 0.000000 | |
8 | .pattern.backgrounds[0]['25000,0_deg'].intensity | 200.000000 | 0.000000 | |
9 | .pattern.backgrounds[0]['30000,0_deg'].intensity | 200.000000 | 0.000000 |
Start second round of minimization
job.fit()
Fitting result Status: 🥳 Success Duration: ⌛ 5.49 s Reduced χ²: 👍 16.18
Print free parameters after the second fitting
job.show_free_parameters()
name | value | error | ||
---|---|---|---|---|
1 | .phases['si'].scale | 13.169738 | 0.075010 | |
2 | .pattern.zero_shift | -4.165397 | µs | 0.033715 |
3 | .pattern.backgrounds[0]['0,0_deg'].intensity | 269.666225 | 7.992930 | |
4 | .pattern.backgrounds[0]['5000,0_deg'].intensity | 150.600340 | 2.523188 | |
5 | .pattern.backgrounds[0]['10000,0_deg'].intensity | 121.156660 | 1.990883 | |
6 | .pattern.backgrounds[0]['15000,0_deg'].intensity | 136.251201 | 1.988307 | |
7 | .pattern.backgrounds[0]['20000,0_deg'].intensity | 133.911792 | 1.974323 | |
8 | .pattern.backgrounds[0]['25000,0_deg'].intensity | 175.057849 | 2.293309 | |
9 | .pattern.backgrounds[0]['30000,0_deg'].intensity | 183.334800 | 3.224987 |
Display the analysis chart after the second fitting
job.show_analysis_chart()
Select more parameters to be refined in the third round
experiment_params.sigma0.free = True
experiment_params.sigma1.free = True
experiment_params.sigma2.free = True
Disable refinement of background parameters
for background_point in pattern_params.backgrounds[0]:
background_point.y.free = False
Print free parameters before the third fitting
job.show_free_parameters()
name | value | error | ||
---|---|---|---|---|
1 | .phases['si'].scale | 13.169738 | 0.075010 | |
2 | .instrument.sigma0 | 0.000000 | µs² | 0.000000 |
3 | .instrument.sigma1 | 0.000000 | µs²/Ų | 0.000000 |
4 | .instrument.sigma2 | 0.000000 | µs²/Å⁴ | 0.000000 |
5 | .pattern.zero_shift | -4.165397 | µs | 0.033715 |
Start third round of minimization
job.fit()
Fitting result Status: 🥳 Success Duration: ⌛ 13.52 s Reduced χ²: 👍 5.57
Print free parameters after the third fitting
job.show_free_parameters()
name | value | error | ||
---|---|---|---|---|
1 | .phases['si'].scale | 14.846289 | 0.046806 | |
2 | .instrument.sigma0 | -4.968327 | µs² | 0.923895 |
3 | .instrument.sigma1 | 66.704832 | µs²/Ų | 1.503366 |
4 | .instrument.sigma2 | -10.512966 | µs²/Å⁴ | 0.172826 |
5 | .pattern.zero_shift | -3.357013 | µs | 0.034452 |
Display the analysis chart after the third fitting
job.show_analysis_chart()