ShowDiffraction#

Open in Colab

Hide synthetic data generation code

import numpy as np

from quantem.widget import ShowDiffraction

rng = np.random.default_rng(0)
size = 256
center = (size - 1) / 2
rows, cols = np.mgrid[0:size, 0:size]
radius = np.hypot(rows - center, cols - center)


def bragg_lattice(rotation_deg=0.0, spacing_px=28.0):
    angle = np.deg2rad(rotation_deg)
    cos_a, sin_a = np.cos(angle), np.sin(angle)
    pattern = np.zeros((size, size), np.float32)
    for h in range(-4, 5):
        for k in range(-4, 5):
            spot_row = center + (h * cos_a - k * sin_a) * spacing_px
            spot_col = center + (h * sin_a + k * cos_a) * spacing_px
            amplitude = 6.0 if h == 0 and k == 0 else 1.0 / (1 + 0.4 * (h * h + k * k))
            pattern += amplitude * np.exp(-((rows - spot_row) ** 2 + (cols - spot_col) ** 2) / 8.0)
    return pattern


single_crystal = bragg_lattice()
tilt_series = np.stack([bragg_lattice(angle) for angle in (0, 4, 8, 12)]).astype(np.float32)

ring_radii_px = (34.0, 55.0, 78.0, 96.0)
polycrystalline = 3.0 * np.exp(-(radius ** 2) / 32.0)
for ring_radius in ring_radii_px:
    polycrystalline += 2.0 * np.exp(-((radius - ring_radius) ** 2) / 9.68)
polycrystalline = (polycrystalline + 0.01 * rng.random((size, size))).astype(np.float32)

Single-crystal SAED#

saed = ShowDiffraction(
    single_crystal,
    center=(center, center),
    bf_radius=14,
    k_pixel_size=0.018,
    title="Single-crystal SAED",
    
    verbose=False,
    panel_width_px=530,
)
saed.detect_spots(max_spots=12)
saed

Polycrystalline rings#

powder = ShowDiffraction(polycrystalline, title="Polycrystalline", verbose=False, panel_width_px=530)
powder.detect_rings(max_rings=4)
powder.calibrate_from_ring(powder.rings[0]["radius_px"], d_known=2.355)
powder

Tilt series#

tilt = ShowDiffraction(
    tilt_series,
    center=(center, center),
    bf_radius=14,
    k_pixel_size=0.018,
    title="Tilt series",
    
    verbose=False,
    panel_width_px=530,
)
tilt

Magnetite-like rings#

Generate a magnetite-style ring pattern in the notebook so the tutorial stays self-contained.

Hide synthetic data generation code

# Synthetic magnetite-like SAED pattern: central beam + Debye-Scherrer rings.
size_m = 512
center_m = (size_m - 1) / 2
m_rows, m_cols = np.mgrid[0:size_m, 0:size_m]
m_radius = np.hypot(m_rows - center_m, m_cols - center_m)
magnetite_pattern = 4.0 * np.exp(-(m_radius ** 2) / 80.0)
for ring_radius, strength, width in [
    (70.0, 1.7, 6.0),
    (113.0, 1.3, 7.0),
    (140.0, 1.0, 8.0),
    (184.0, 0.8, 9.0),
    (226.0, 0.55, 10.0),
]:
    magnetite_pattern += strength * np.exp(-((m_radius - ring_radius) ** 2) / (2 * width ** 2))
magnetite_pattern += 0.035 * rng.random((size_m, size_m))
magnetite_pattern = magnetite_pattern.astype(np.float32)
magnetite = ShowDiffraction(magnetite_pattern, title="Magnetite-like rings", verbose=False, panel_width_px=530)
magnetite.auto_detect_center()
magnetite.detect_rings(max_rings=5, exclude_radius=40)
inner_ring = min(magnetite.rings, key=lambda ring: ring["radius_px"])
magnetite.calibrate_from_ring(inner_ring["radius_px"], d_known=2.532)
magnetite.dp_colormap = "viridis"
magnetite

Save the analysis#

magnetite.summary()
magnetite.save("magnetite_state.json")

ShowDiffraction.measurements_from_state("magnetite_state.json")[:2]
Magnetite-like rings
════════════════════════════════
Frames:   1 (showing #0)
Detector: 512×512 (0.0057 1/Å/px)
Calib:    from_ring (d=2.532 Å @ r=69.6 px)
Center:   (255.5, 255.6)  BF r=11.9 px
Spots:    0
Rings:    5
Display:  viridis | log
[{'id': 1,
  'kind': 'ring',
  'raw_row': None,
  'raw_col': None,
  'row': None,
  'col': None,
  'row_err': None,
  'col_err': None,
  'r_pixels': 69.61941528320312,
  'r_pixels_err': None,
  'g_inv_angstrom': 0.3949447077409163,
  'g_inv_angstrom_err': None,
  'd_angstrom': 2.532,
  'd_angstrom_err': None,
  'angle_deg': None,
  'angle_deg_err': None,
  'intensity': 1.7121703624725342,
  'fit_quality': None,
  'hkl': '',
  'note': ''},
 {'id': 2,
  'kind': 'ring',
  'raw_row': None,
  'raw_col': None,
  'row': None,
  'col': None,
  'row_err': None,
  'col_err': None,
  'r_pixels': 112.69329833984375,
  'r_pixels_err': None,
  'g_inv_angstrom': 0.6392989885958967,
  'g_inv_angstrom_err': None,
  'd_angstrom': 1.5642133302859074,
  'd_angstrom_err': None,
  'angle_deg': None,
  'angle_deg_err': None,
  'intensity': 1.317672848701477,
  'fit_quality': None,
  'hkl': '',
  'note': ''}]
# Optional
export_path = saed.export_html("showdiffraction_saed.html", title="Single-crystal SAED")
export_path.name
'showdiffraction_saed.html'