Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

torch-scattering

License PyPI Python Version CI codecov

Multislice electron scattering simulation in PyTorch, for cryo-EM/cryo-ET forward modelling.

Overview

torch_scattering computes the 2D exit wave produced by propagating an electron beam through a 3D electrostatic potential in volts. The potential has shape (..., Z, H, W), where Z is the beam direction. pixel_size is the isotropic voxel spacing in Angstroms, so it specifies both the Y/X pixel spacing and the Z slice thickness. Every function returns a complex exit wave of shape (..., H, W).

Real float32 and float64 potentials model non-absorbing specimens and can be passed directly; callers do not need to cast them to complex. Complex potentials remain supported for modelling absorption.

Four propagation modes are provided, trading physical accuracy for speed:

  • multislice() - full multislice propagation (Kirkland, Advanced Computing in Electron Microscopy), alternating transmission through each slice with Fresnel propagation to the next. The most accurate mode.
  • rytov() - Rytov approximation, accumulating phase in the exponent rather than the wave itself.
  • firstborn() - first Born approximation, summing single-scattering contributions from each slice.
  • projection() - projection approximation, treating the specimen as infinitely thin and skipping inter-slice propagation entirely. The fastest and least accurate mode.

All four share the same required inputs and can be swapped in for one another. multislice, rytov, and firstborn also accept an n_slices argument to coarsen the potential into fewer, thicker slabs before propagating.

Lower-level, pure-math primitives (fresnel_propagator, transmission_function, multislice_step, chunk_slices, interaction_parameter) are also exposed for building custom propagation schemes.

Installation

pip install torch-scattering

Usage

import torch
from torch_scattering import multislice

# A real electrostatic potential in volts, shape (Z, H, W).
potential = torch.zeros((50, 64, 64), dtype=torch.float32)

# propagate a plane wave through it
exit_wave = multislice(
    potential=potential,
    pixel_size=1.0,   # Angstroms
    voltage=300,      # kV
)
# exit_wave.shape is (64, 64)
# exit_wave.dtype is torch.complex64

rytov, firstborn, and projection share the same call signature:

from torch_scattering import firstborn, projection, rytov

exit_wave = rytov(potential, pixel_size=1.0, voltage=300)
exit_wave = firstborn(potential, pixel_size=1.0, voltage=300)
exit_wave = projection(potential, pixel_size=1.0, voltage=300)  # n_slices not applicable

Coarsening slices

n_slices groups the potential into fewer, thicker slabs before propagating. By default (n_slices=None), every slice of the potential is propagated individually - the most accurate but slowest setting.

# propagate as 10 chunks instead of all 50 slices individually
exit_wave = multislice(potential, pixel_size=1.0, voltage=300, n_slices=10)

Batching

All functions accept arbitrary leading batch dimensions on potential:

potential = torch.zeros((8, 50, 64, 64), dtype=torch.complex64)  # batch of 8
exit_wave = multislice(potential, pixel_size=1.0, voltage=300)
# exit_wave.shape is (8, 64, 64)

Structure-to-wave pipeline

Structure handling and potential generation are deliberately separate packages. They are not runtime dependencies of torch-scattering; their real tensor output is passed through the public tensor API:

import pandas as pd
from torch_calculate_electrostatic_potential import (
    GridConfig,
    potential_from_structure_3d,
)
from torch_scattering import multislice
from torch_structure_manipulation import (
    AtomicStructure,
    annotate_bonding_environments,
)

# mmdf-compatible coordinates are in Angstroms.
atoms = pd.DataFrame(
    [
        ("A", 1, "ALA", "C", "C", 0.0, 0.0, 0.0),
        ("A", 1, "ALA", "O", "O", 1.2, 0.0, 0.0),
        ("A", 1, "ALA", "CA", "C", -1.2, 0.0, 0.0),
        ("A", 2, "GLY", "N", "N", 2.4, 0.0, 0.0),
    ],
    columns=[
        "chain", "residue_id", "residue", "atom", "element", "x", "y", "z"
    ],
)
atoms["b_isotropic"] = 10.0  # Angstrom squared
atoms["occupancy"] = 1.0

# Annotate a complete local residue context, then build the desired structure.
annotated = annotate_bonding_environments(atoms, include_hydrogens=False)
structure = AtomicStructure.from_dataframe(annotated.iloc[[0]])

grid = GridConfig.from_grid_shape_and_voxel_size(
    grid_shape=(9, 9, 9),       # Z, Y, X
    voxel_size=(1.0, 1.0, 1.0), # Angstroms; isotropic for scattering
    center_zyx=(0.0, 0.0, 0.0),
    sublattice_radius=4.0,
)
elemental_volts = potential_from_structure_3d(structure, grid)
bonded_volts = potential_from_structure_3d(
    structure,
    grid,
    scattering_factors="peng_bonded",
    bonded_fallback="error",
)

# Both volumes are real tensors in volts and are accepted directly.
elemental_wave = multislice(elemental_volts, pixel_size=1.0, voltage=300.0)
bonded_wave = multislice(bonded_volts, pixel_size=1.0, voltage=300.0)
# Both waves are complex tensors; voltage is in kV.

projection() is a wave-propagation approximation that numerically sums this sampled 3D volume along Z. It is distinct from the electrostatic package's analytic 2D projected-potential calculation and from projection alignment in torch-fit-in-map.

Low-level primitives

For building custom propagation schemes directly on top of the multislice recurrence:

import torch
from torch_grid_utils import fftfreq_grid
from torch_scattering import (
    fresnel_propagator,
    interaction_parameter,
    multislice_step,
)

frequency_grid = fftfreq_grid(image_shape=(64, 64), rfft=False, spacing=1.0, norm=True)
propagator = fresnel_propagator(frequency_grid, wavelength=0.01969, dz=1.0)
sigma = interaction_parameter(voltage=300)

wave = torch.ones((64, 64), dtype=torch.complex64)
potential_slice = torch.zeros((64, 64), dtype=torch.complex64)
wave = multislice_step(wave, potential_slice, propagator, sigma, dz=1.0)

License

This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

torch_scattering-0.6.0rc2.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

torch_scattering-0.6.0rc2-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

Details for the file torch_scattering-0.6.0rc2.tar.gz.

File metadata

  • Download URL: torch_scattering-0.6.0rc2.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for torch_scattering-0.6.0rc2.tar.gz
Algorithm Hash digest
SHA256 5694ea038e7777d594707867b50dc9c97de88535cfe89642f8a5f02f7a4dc67e
MD5 169b131bb071414c723c4cdcc745089d
BLAKE2b-256 99a2d4ba92c1e5323db66f7d7982b69fe53854a3593403a3885f25ba7b7a02c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for torch_scattering-0.6.0rc2.tar.gz:

Publisher: deploy.yml on teamtomo/teamtomo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file torch_scattering-0.6.0rc2-py3-none-any.whl.

File metadata

File hashes

Hashes for torch_scattering-0.6.0rc2-py3-none-any.whl
Algorithm Hash digest
SHA256 48847e4075bf74a9bbe7f8773f608e3c2242802e39271602e8ae04ce94b98a46
MD5 bc7ce7ca73fa32ac4dcf6bd8dfccc688
BLAKE2b-256 ef5023660097d51429122aa6dac2c681ffedb00edcf444c82b943ede41f9744e

See more details on using hashes here.

Provenance

The following attestation bundles were made for torch_scattering-0.6.0rc2-py3-none-any.whl:

Publisher: deploy.yml on teamtomo/teamtomo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.6.0

2 files

This release

0.6.0rc2 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page