Skip to main content
Pre-release

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

cryoJAX

Continuous Integration codecov

Summary

CryoJAX is a library that simulates cryo-electron microscopy (cryo-EM) images in JAX. Its purpose is to provide the tools for building downstream data analysis in external workflows and libraries that leverage the statistical inference and machine learning resources of the JAX scientific computing ecosystem. To achieve this, image simulation in cryoJAX is built for reliability and flexibility; it implements a variety of established models and algorithms as well as a framework for implementing new models and algorithms downstream. If your application uses cryo-EM image simulation and it cannot be built downstream, open a pull request.

Documentation

See the documentation at https://michael-0brien.github.io/cryojax/. It is a work-in-progress, so thank you for your patience!

Installation

Installing cryojax is simple. To start, I recommend creating a new virtual environment. For example, you could do this with uv.

uv venv --python=3.11 ~/path/to/venv/
source ~/path/to/venv/bin/activate

Note that python>=3.10 is required. After creating and activating the new environment, install JAX with either CPU or GPU support. Then, install cryojax. For the latest stable release, install using pip.

uv pip install cryojax

To install the latest commit in development mode, run

git clone https://github.com/michael-0brien/cryojax
cd cryojax
git checkout dev
uv pip install -e `.[dev,tests]`
uv run pre-commit install

Quick example

Image simulation in cryoJAX revolves around the image_model class. The following is a basic example for instantiating an image_model and simulating an image:

import jax
import jax.numpy as jnp
import cryojax.simulator as cxs

# Instantiate a cryoJAX `image_model`
image_model = cxs.make_image_model(
    # ... load atoms as gaussians mixture from tabulated electron scattering factors
    volume=cxs.load_tabulated_volume(
        "example.pdb", output_type=cxs.GaussianMixtureVolume
    ),
    # ... configure the image
    image_config=cxs.BasicImageConfig(shape=(320, 320), pixel_size=1., voltage_in_kilovolts=300),
    # ... the pose
    pose=cxs.EulerAnglePose(phi_angle=20., theta_angle=80., psi_angle=-10.),
    # ... the CTF
    transfer_theory=cxs.ContrastTransferTheory(
        ctf=cxs.AstigmaticCTF(defocus_in_angstroms=9800., astigmatism_in_angstroms=200., astigmatism_angle=10.),
        amplitude_contrast_ratio=0.1,
    ),
)
# Simulate an image
image = image_model.simulate(outputs_real_space=True)

For more advanced image simulation examples and to understand the many features in this library, see the documentation.

JAX transformations

CryoJAX is built on JAX to make use of JIT-compilation, automatic differentiation, and vectorization for cryo-EM data analysis. JAX implements these operations as function transformations. If you aren't familiar with this concept, see the JAX documentation.

Below are examples of implementing these transformations using equinox, a popular JAX library for PyTorch-like classes that smoothly integrate with JAX functional programming. To learn more about how equinox assists with JAX transformations, see here.

Your first JIT compiled function

import equinox as eqx

# Define image simulation function using `equinox.filter_jit`
@eqx.filter_jit
def simulate_fn(image_model):
    """Simulate an image with JIT compilation"""
    return image_model.simulate()

# Simulate an image
image = simulate_fn(image_model)

Computing gradients of a loss function

import equinox as eqx
import jax
import jax.numpy as jnp

# Load observed data
observed_image = ...

# Split the `image_model` by differentiated and non-differentiated
# arguments. Here, differentiate with respect to the pose.
is_pose = lambda x: isinstance(x, cxs.AbstractPose)
filter_spec = jax.tree.map(is_pose, image_model, is_leaf=is_pose)
model_grad, model_nograd = eqx.partition(image_model, filter_spec)

@eqx.filter_value_and_grad
def loss_fn(model_grad, model_nograd, observed_image):
    """Compute gradients with respect to the pose."""
    image_model = eqx.combine(model_grad, model_nograd)
    return jnp.sum((image_model.simulate() - observed_image)**2)

# Compute the loss and gradients
loss, gradients = loss_fn(model_grad, model_nograd, observed_image)

Vectorizing image simulation

import equinox as eqx

# Vectorize model instantiation over poses
@eqx.filter_vmap(in_axes=(0, None, None, None), out_axes=(eqx.if_array(0), None))
def make_model_vmap(wxyz, volume, image_config, transfer_theory):
    pose = cxs.QuaternionPose(wxyz=wxyz)
    image_model = cxs.make_image_model(
        volume, image_config, pose, transfer_theory, normalizes_signal=True
    )
    is_pose = lambda x: isinstance(x, cxs.AbstractPose)
    filter_spec = jax.tree.map(is_pose, image_model, is_leaf=is_pose)
    model_vmap, model_novmap = eqx.partition(image_model, filter_spec)

    return model_vmap, model_novmap


# Define image simulation function with respect to vectorized arguments
@eqx.filter_vmap(in_axes=(eqx.if_array(0), None))
def simulate_fn_vmap(model_vmap, model_novmap):
    image_model = eqx.combine(model_vmap, model_novmap)
    return image_model.simulate()

# Batch image simulation over poses
wxyz = ...  # ... load quaternions
model_vmap, model_novmap = make_model_vmap(wxyz, volume, image_config, transfer_theory)
images = simulate_fn_vmap(model_vmap, model_novmap)

Projects using cryoJAX

CryoJAX is meant to support an ecosystem of libraries for the development of emerging data analysis techniques in cryo-EM. If your package uses cryoJAX, open a PR to get it added to this list!

  • cryospax: A small library to support cryo-EM single particle analysis applications using cryoJAX

Citation

If you use cryoJAX in your work, we would appreciate it if you cite:

@article{obrien2026cryojax,
    author = "O'Brien, Michael J. and Silva-S{\'{a}}nchez, David and Woollard, Geoffrey and Je, Kwanghwi and Hanson, Sonya M. and Needleman, Daniel J. and Cossio, Pilar and Thiede, Erik Henning and Astore, Miro A.",
    title = "{CryoJAX: a cryo-electron microscopy image-simulation library in JAX}",
    journal = "Acta Crystallographica Section D",
    year = "2026",
    volume = "82",
    number = "3",
    pages = "",
    month = "Mar",
    doi = {10.1107/S2059798326000550},
    url = {https://doi.org/10.1107/S2059798326000550},
}

Acknowledgements

  • Implementations of several models and algorithms, such as the CTF, fourier slice extraction, and electrostatic potential computations has been informed by the open-source cryo-EM software cisTEM.
  • cryojax is built using equinox, a popular JAX library for PyTorch-like classes that smoothly integrate with JAX functional programming. We highly recommend learning about equinox to fully make use of the power of jax.

Metadata

Release files for cryojax 0.6.0rc2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cryojax 0.6.0rc2
File Size Uploaded
cryojax-0.6.0rc2.tar.gz 3.6 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for cryojax 0.6.0rc2
File Interpreter ABI Platform
cryojax-0.6.0rc2-py3-none-any.whl Python 3 none any Details

Total release size: 3.8 MB

Release files / cryojax-0.6.0rc2.tar.gz

Download URL cryojax-0.6.0rc2.tar.gz
Size 3.6 MB
Tags Source
SHA-256 checksum
How to use checksums
8758b706231a140bda444cf50f6512ccf6bd364216e06fde0394d7e9ed9a2f38
BLAKE2b-256 checksum
How to use checksums
bca0a0251cca0df236ed537b8773add31636bc03dc4eb921c0f2189f7644034b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / cryojax-0.6.0rc2-py3-none-any.whl

Download URL cryojax-0.6.0rc2-py3-none-any.whl
Size 184.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7b9db14d41c636f2d9409868ceadcad7dc5a5d94f2fd3cd0bdd6a289ef0d342d
BLAKE2b-256 checksum
How to use checksums
43a409ab1093e502ac81e2a11ab6b87bebfcd2bdf28aabda6a3bd2c7459c895e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.0

2 release files

This release

0.6.0rc2 This release

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release 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