Skip to content

Local FFT pseudo-4DSTEM for HRTEM images, with phase and in-plane orientation mapping - #314

Open
cophus wants to merge 1 commit into
electronmicroscopy:devfrom
cophus:acom-fft
Open

cophus wants to merge 1 commit into
electronmicroscopy:devfrom
cophus:acom-fft

Conversation

@cophus

@cophus cophus commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

What problem this PR addresses

Lattice fringes in HRTEM images carry local phase and orientation information, but quantEM had no way to map them. This PR treats an HRTEM image as a pseudo-4DSTEM dataset: a tapered window moves across the image, and the local Fourier transform at each window position becomes a diffraction pattern. These patterns then go through the existing 4DSTEM workflow (Bragg disk detection and pixel size calibration), followed by phase and in-plane orientation mapping.

acom_fft_pipeline

Left to right: HRTEM image with four positions of the moving window, the four tapered windows, their local Fourier transforms with the detected Bragg disks on the front pattern, and the phase map (LiF yellow, Li2O cyan) and LiF in-plane orientation map.

What's here

  • imaging/local_fft.py: LocalFFT.from_image cuts a window of window_size pixels every step pixels, applies a disk mask with a sin² taper over the full radius (window_mask), and stores the cropped power spectra as a Dataset4dstem in Å and 1/Å. Each pattern is normalized by the azimuthal median of the scan-mean pattern as I / background - 1, so the background is 0 and the noise is close to 1 at every frequency, and the center disk is set to 0. The window centers are known exactly, so LocalFFT.origins goes directly to BraggVectors.correct_peak_origins and we skip origin fitting and ellipse calibration. print(lfft) reports the window diameter and FWHM, which sets the spatial resolution.
  • diffraction/systematic_row.py: SystematicRowMap. Most HRTEM windows show a single set of lattice fringes, which is a single systematic row: it determines the phase and the in-plane direction of g, but not the rotation of the crystal about g. Instead of full ACOM, we pair Friedel spots (+g and -g), assign |g| to the nearest reflection family of the candidate crystals, and map the phase and the in-plane angle of g (fiber texture). Plots: plot_rings, plot_phase, plot_orientation and plot_angle_distribution. Orientation colors use the same perceptually uniform hue as the rest of ACOM (array_to_rgba), with brightness from the row intensity, and angles follow the quantEM convention atan2(g_col, g_row).
  • Crystal.from_cif removes the ase Spacegroup object that the ase CIF reader leaves in atoms.info. Crystal finds the space group itself (Crystal.spacegroup), so it now holds only native data and saves without the dill fallback.
  • One test each for LocalFFT and SystematicRowMap.

Validation (notebook, not in the repo)

HRTEM image of LiF and Li2O recorded by Guoliang Hu, 300 kV, 4096 x 4096 pixels of 0.355 Å. We used a resolution of 20 Å (112 pixel window, 40 Å diameter) and a step of 28 pixels, giving 143 x 143 windows.

  • The pixel size calibration against LiF (200) and Li2O (111) gives a correction of +2.08% relative to the microscope calibration, with a residual of 0.47%.
  • LiF is found in 95.7% and Li2O in 4.3% of the windows with indexed fringes.
  • The in-plane g angles agree with Guoliang's independent fringe angle maps to a median of 1.0° for LiF and 0.8° for Li2O.
  • Only 37 of the 10,019 windows with fringes show two fringe directions from one crystal, so we do not attempt full 3D orientations.

What should the reviewer(s) do

Review the new LocalFFT and SystematicRowMap classes and merge.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant