Pair Distribution Function: Si, NPD¶
This example demonstrates a pair distribution function (PDF) analysis of Si, based on data collected from a time-of-flight neutron powder diffraction experiment at NOMAD at SNS.
🛠️ Import Library¶
In [2]:
Copied!
import easydiffraction as ed
import easydiffraction as ed
📦 Define Project¶
Create Project¶
In [3]:
Copied!
project = ed.Project(name='si_nomad_pdf')
project = ed.Project(name='si_nomad_pdf')
Set Plotting Engine¶
In [4]:
Copied!
project.rendering_plot.show_supported()
project.rendering_plot.show_supported()
Rendering Plot types
| Type | Description | ||
|---|---|---|---|
| 1 | * | auto | Environment default rendering_plot engine |
| 2 | asciichartpy | Console ASCII line charts | |
| 3 | plotly | Interactive browser-based graphing library |
In [5]:
Copied!
# Set global plot range for plots
project.rendering_plot.plotter.x_max = 40
# Set global plot range for plots
project.rendering_plot.plotter.x_max = 40
Add Structure¶
In [6]:
Copied!
project.structures.create(name='si')
project.structures.create(name='si')
In [7]:
Copied!
structure = project.structures['si']
structure.space_group.name_h_m.value = 'F d -3 m'
structure.space_group.it_coordinate_system_code = '1'
structure.cell.length_a = 5.43146
structure.atom_sites.create(
label='Si',
type_symbol='Si',
fract_x=0,
fract_y=0,
fract_z=0,
adp_iso=0.5,
)
structure = project.structures['si']
structure.space_group.name_h_m.value = 'F d -3 m'
structure.space_group.it_coordinate_system_code = '1'
structure.cell.length_a = 5.43146
structure.atom_sites.create(
label='Si',
type_symbol='Si',
fract_x=0,
fract_y=0,
fract_z=0,
adp_iso=0.5,
)
Display Structure¶
In [8]:
Copied!
project.display.structure(struct_name='si')
project.display.structure(struct_name='si')
Structure 🧩 'si' (Atom view type: 'covalent')
Loading plot…
drag = rotate
wheel = zoom
right-drag = pan
wheel = zoom
right-drag = pan
Add Experiment¶
In [9]:
Copied!
data_path = ed.download_data(id=5, destination='data')
data_path = ed.download_data(id=5, destination='data')
Getting data...
Data #5: NOM_9999_Si_640g_PAC_50_ff_ftfrgr_up-to-50.gr
✅ Data #5 downloaded to '../../../data/ed-5.gr'
In [10]:
Copied!
project.experiments.add_from_data_path(
name='nomad',
data_path=data_path,
sample_form='powder',
beam_mode='time-of-flight',
radiation_probe='neutron',
scattering_type='total',
)
project.experiments.add_from_data_path(
name='nomad',
data_path=data_path,
sample_form='powder',
beam_mode='time-of-flight',
radiation_probe='neutron',
scattering_type='total',
)
⚠️ No uncertainty (sy) column provided. Defaulting to 0.03.
Data loaded successfully
Experiment 🔬 'nomad'. Number of data points: 5033.
In [11]:
Copied!
experiment = project.experiments['nomad']
experiment.linked_phases.create(id='si', scale=1.0)
experiment.peak.damp_q = 0.02
experiment.peak.broad_q = 0.03
experiment.peak.cutoff_q = 35.0
experiment.peak.sharp_delta_1 = 0.0
experiment.peak.sharp_delta_2 = 4.0
experiment.peak.damp_particle_diameter = 0
experiment = project.experiments['nomad']
experiment.linked_phases.create(id='si', scale=1.0)
experiment.peak.damp_q = 0.02
experiment.peak.broad_q = 0.03
experiment.peak.cutoff_q = 35.0
experiment.peak.sharp_delta_1 = 0.0
experiment.peak.sharp_delta_2 = 4.0
experiment.peak.damp_particle_diameter = 0
🚀 Perform Analysis¶
Set Free Parameters¶
In [12]:
Copied!
project.structures['si'].cell.length_a.free = True
project.structures['si'].atom_sites['Si'].adp_iso.free = True
experiment.linked_phases['si'].scale.free = True
project.structures['si'].cell.length_a.free = True
project.structures['si'].atom_sites['Si'].adp_iso.free = True
experiment.linked_phases['si'].scale.free = True
In [13]:
Copied!
experiment.peak.damp_q.free = True
experiment.peak.broad_q.free = True
experiment.peak.sharp_delta_1.free = True
experiment.peak.sharp_delta_2.free = True
experiment.peak.damp_q.free = True
experiment.peak.broad_q.free = True
experiment.peak.sharp_delta_1.free = True
experiment.peak.sharp_delta_2.free = True
Run Fitting¶
In [14]:
Copied!
project.analysis.fit()
project.display.fit.results()
project.display.fit.correlations()
project.analysis.fit()
project.display.fit.results()
project.display.fit.correlations()
Standard fitting
📋 Using experiment 🔬 'nomad' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit progress:
| iteration | time (s) | χ² | change / status | |
|---|---|---|---|---|
| 1 | 1 | 0.24 | 3102.63 | |
| 2 | 11 | 2.47 | 2177.55 | 29.8% ↓ |
| 3 | 19 | 4.09 | 345.28 | 84.1% ↓ |
| 4 | 27 | 5.75 | 180.23 | 47.8% ↓ |
| 5 | 35 | 7.42 | 170.60 | 5.3% ↓ |
| 6 | 59 | 12.56 | 170.54 | |
| 7 | 68 | 14.54 | 170.54 |
🏆 Best goodness-of-fit (reduced χ²) is 170.54 at iteration 67
✅ Fitting complete.
⚙️ 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.54 |
| 4 | 🔁 Iterations | 65 |
| 5 | 📏 Goodness-of-fit (reduced χ²) | 170.54 |
| 6 | 📏 R-factor (Rf, %) | 8.40 |
| 7 | 📏 R-factor squared (Rf², %) | 8.30 |
| 8 | 📏 Weighted R-factor (wR, %) | 8.30 |
📈 Refined parameters:
| datablock | category | entry | parameter | units | start | value | s.u. | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | si | cell | length_a | Å | 5.4315 | 5.4306 | 0.0000 | 0.02 % ↓ | |
| 2 | si | atom_site | Si | adp_iso | Ų | 0.5000 | 0.7170 | 0.0055 | 43.40 % ↑ |
| 3 | nomad | linked_phases | si | scale | 1.0000 | 1.2728 | 0.0014 | 27.28 % ↑ | |
| 4 | nomad | peak | damp_q | Å⁻¹ | 0.0200 | 0.0251 | 0.0001 | 25.66 % ↑ | |
| 5 | nomad | peak | broad_q | Å⁻² | 0.0300 | 0.0183 | 0.0003 | 39.10 % ↓ | |
| 6 | nomad | peak | sharp_delta_1 | Å | 0.0000 | 2.5400 | 0.0529 | N/A | |
| 7 | nomad | peak | sharp_delta_2 | Ų | 4.0000 | -1.7525 | 0.1244 | 143.81 % ↓ |
• 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
Loading plot…
Display Pattern¶
In [15]:
Copied!
project.display.pattern(expt_name='nomad')
project.display.pattern(expt_name='nomad')
Loading plot…
💾 Save Project¶
In [16]:
Copied!
project.save_as(dir_path='projects/ed_11_si_nomad_pdf')
project.save_as(dir_path='projects/ed_11_si_nomad_pdf')
Saving project 📦 'si_nomad_pdf' to '../../../projects/ed_11_si_nomad_pdf'
├── 📄 project.cif
├── 📁 structures/
│ └── 📄 si.cif
├── 📁 experiments/
│ └── 📄 nomad.cif
├── 📁 analysis/
│ └── 📄 analysis.cif
└── 📁 reports/
└── 📄 si_nomad_pdf.html