Skip to main content

XPCSJAX - JAX-native NLSQ fitting for XPCS.

xpcsjax logo

PyPI version License: MIT Python Documentation

Disclaimer: XPCSJAX is pre-release software under active development and testing. APIs, model implementations, and numerical results may change without notice. Outputs have not been independently validated for all use cases. Use at your own risk and verify critical results against established reference data before relying on them in research or industrial applications.

XPCSJAX implements the transport-coefficient framework of He et al. PNAS 2024 and He et al. PNAS 2025 for characterizing nonequilibrium dynamics in flowing soft-matter systems.


Install

To get every feature and avoid missing-dependency issues, install with the all extra (pulls every optional dependency — GUI, fast-viz, plus the dev/docs/packaging tooling).

With uv (recommended):

uv pip install "xpcsjax[all]"

In a mamba/conda environment, install directly from the imewei Anaconda.org channel:

mamba install imewei::xpcsjax
# or: conda install imewei::xpcsjax

Or use pip inside the same environment — or any other virtualenv (venv, virtualenv, pyenv):

pip install "xpcsjax[all]"

For a minimal core install (NLSQ fitting only, no GUI), drop the extra: uv pip install xpcsjax or pip install xpcsjax — this already includes datashader-accelerated plotting. The xpcsjax[gui] extra adds the desktop workbench.

Python 3.12+ required, CPU-only in v0.1 (GPU support is v0.2+). Runtime dependencies are managed via pyproject.toml and mirror what the source homodyne package pins (versions of jax, nlsq, evosax, h5py, jaxopt, psutil, tqdm, etc.).

From source (development): clone the repo and use an editable install — uv sync && uv pip install -e ".[dev]". See docs/source/development/contributing.rst.

Sanity-check the install (environment, dependencies, JAX config) with:

xpcsjax-validate

Quickstart

No config yet? Generate one from a mode template:

xpcsjax-config --mode laminar_flow --output config.yaml

Then fit:

from xpcsjax import load_xpcs_data, fit_nlsq

data   = load_xpcs_data("config.yaml")
result = fit_nlsq(data, "config.yaml")
print(result.parameters)

The YAML config's analysis_mode field selects the physics model and parameter set:

analysis_mode Lineage Model Physics params
static_isotropic homodyne Equilibrium diffusion, angle-collapsed 3
static_anisotropic homodyne Same physics; angle-resolved data prep 3
laminar_flow homodyne Diffusion + sinc-shear 7
two_component (or heterodyne) heterodyne Two-component: reference + sample + velocity + mixing 14

fit_nlsq returns a single OptimizationResult for every mode (result.parameters is a NumPy array). Heterodyne (two_component) fits all phi angles jointly and packs the multi-angle result into that same object. Two per-angle scaling parameters (contrast, offset) are appended automatically for every azimuthal angle in all modes.

Data flow

YAML config --> XPCSDataLoader(HDF5) --> HomodyneModel / HeterodyneModel --> NLSQ engine --> Results (JSON + NPZ)

save_results (xpcsjax/service/persist.py) writes nlsq_result.json (fitted parameters, uncertainties, χ², diagnostics) and nlsq_result.npz (correlation and residual arrays) to the configured output directory.


Running XPCSJAX

Three front-ends drive the same YAML config and NLSQ engine — pick whichever fits your workflow.

Command line. The xpcsjax console script (alias xj) runs a flag-driven fit:

xpcsjax --config analysis.yaml                          # run an NLSQ fit
xpcsjax --config analysis.yaml --output ./results       # override the output dir
xpcsjax --config analysis.yaml --multistart --multistart-n 16
xpcsjax --config analysis.yaml --plot-experimental-data # plot only, skip the fit

Exit codes: 0 converged · 2 ran but did not converge (outputs still written) · 1 error · 130 interrupted. xjexp / xjsim are experimental-/simulated-data plotting shortcuts. See the CLI guide for the full command reference.

Interactive workbench (GUI). Needs the gui extra (pip install "xpcsjax[gui]"). Launch the PySide6 analysis workbench with:

xpcsjax-gui      # or: xj-gui

Load a config, run fits, and browse per-angle results and residual maps. The fit runs in a JAX-free worker process so the UI stays responsive; xpcsjax-gui -platform offscreen does a headless smoke run.

Shell completion. After install, wire up tab-completion (bash/zsh; fish is a non-fatal no-op) and optional XLA flags into your environment:

xpcsjax-post-install   # interactive: completion + XLA_FLAGS into the venv activate script
xpcsjax-cleanup        # remove what post-install added

Physics models

XPCSJAX fits two-time intensity correlation functions $c_2(\vec{q}, t_1, t_2)$. All time integrals are evaluated numerically via cumulative trapezoid on the discrete time grid — no analytical antiderivatives — so the general power-law forms stay correct.

Homodyne (static_*, laminar_flow)

Single-component scattering where correlation decay encodes diffusion and shear. The laminar-flow two-time kernel (xpcsjax core/physics_nlsq.py; derived in docs/source/theory/homodyne_model.rst) is

$$c_2(\vec{q}, t_1, t_2) = c_{\text{offset}}(\phi) + \beta(\phi) \exp\left(-q^2\int_{t_1}^{t_2} J(t') dt'\right) \mathrm{sinc}^2\left(\frac{q h \cos(\phi - \phi_0) \Gamma(t_1, t_2)}{2\pi}\right)$$

with $\mathrm{sinc}(x) = \sin(\pi x)/(\pi x)$, accumulated strain $\Gamma(t_1, t_2) = \int_{t_1}^{t_2}\dot{\gamma}(t) dt$, rheometer gap $h$ (instrument geometry, not fitted), flow angle $\phi_0$, and per-angle scaling $\beta(\phi)$ / $c_{\text{offset}}(\phi)$ (the contrast / offset parameters). The static modes drop the shear term ($\mathrm{sinc}^2 \to 1$). Transport and shear follow power-law forms:

$$J(t) = D_0 t^{\alpha} + D_{\text{offset}} \qquad \dot{\gamma}(t) = \dot{\gamma}0 t^{\beta} + \dot{\gamma}{\text{offset}}$$

Registry parameter names (xpcsjax/config/parameter_registry.py) and their defaults:

Group Parameter Description Default Units
Diffusion D0 Diffusion prefactor 1e3 Ų/s
alpha Transport exponent (0 = Wiener, 1 = ballistic) 0.5 —
D_offset Transport rate offset 10 Ų/s
Shear (laminar_flow only) gamma_dot_t0 Shear-rate prefactor 0.01 s⁻¹
beta Shear-rate exponent (0 = constant shear) 0.5 —
gamma_dot_t_offset Shear-rate offset 0.0 s⁻¹
Flow angle phi0 Flow angle offset relative to q-vector 0.0 degrees
Per-angle scaling contrast Optical (speckle) contrast 0.5 —
offset Baseline offset 1.0 —

The static modes use the 3 diffusion parameters; laminar_flow adds the 3 shear parameters and the flow angle (7 physics parameters total).

Heterodyne (two_component)

Two-component scattering (He et al. PNAS 2024 SI Appendix section 2.F / main-text Eq. 14; restated for N=2 in He et al. PNAS 2025 main-text Eqs. 1–3): light from a moving sample interferes with a static reference, and the cross-term oscillates at a frequency set by the sample velocity. The two-time correlation is

$$c_2(\vec{q}, t_1, t_2) = 1 + \frac{\beta}{f^2}\left[C_{\text{ref}} + C_{\text{sample}} + C_{\text{cross}}\right]$$

$$C_{\text{ref}} = [x_r(t_1)x_r(t_2)]^2 \exp\left(-q^2\int_{t_1}^{t_2} J_r dt'\right) \qquad C_{\text{sample}} = [x_s(t_1)x_s(t_2)]^2 \exp\left(-q^2\int_{t_1}^{t_2} J_s dt'\right)$$

$$C_{\text{cross}} = 2 x_r(t_1)x_r(t_2)x_s(t_1)x_s(t_2) \exp\left(-\tfrac{1}{2}q^2\int_{t_1}^{t_2}[J_s + J_r] dt'\right)\cos\left[q\cos(\varphi)\int_{t_1}^{t_2}\mathbb{E}[v] dt'\right]$$

where $x_s(t)$ is the sample fraction, $x_r = 1 - x_s$ the reference fraction, $\varphi$ the angle between velocity and $\vec{q}$, and $f^2 = [x_s(t_1)^2 + x_r(t_1)^2][x_s(t_2)^2 + x_r(t_2)^2]$ normalizes so that $c_2(t, t) = 1 + \beta$ on the diagonal. The fit wraps the correlation with per-angle scaling, $c_2^{\text{model}} = \text{offset} + \text{contrast}\times(C_{\text{ref}} + C_{\text{sample}} + C_{\text{cross}})/f^2$.

Each transport coefficient and the velocity follow power laws, and the sample fraction is time-dependent — 14 physics parameters in five groups:

Registry parameter names (xpcsjax/config/parameter_registry.py, canonical order) and their defaults:

Group Parameters Rate function Defaults Units
Reference transport (3) D0_ref, alpha_ref, D_offset_ref $J_r(t) = D_{0,r} t^{\alpha_r} + D_{\text{offset},r}$ 1e4, 0, 0 Ų/s, —, Ų/s
Sample transport (3) D0_sample, alpha_sample, D_offset_sample $J_s(t) = D_{0,s} t^{\alpha_s} + D_{\text{offset},s}$ 1e4, 0, 0 Ų/s, —, Ų/s
Velocity (3) v0, v_beta, v_offset $v(t) = v_0 t^{\beta} + v_{\text{offset}}$ 1e3, 1, 0 Å/s, —, Å/s
Sample fraction (4) f0, f1, f2, f3 $f_s(t) = f_0 \exp\big(f_1(t - f_2)\big) + f_3$ 0.5, 0, 0, 0 —, —, —, —
Flow angle (1) phi0_het — 0 degrees

The velocity exponent is v_beta and the flow angle phi0_het in the registry — deliberately distinct from homodyne's beta / phi0 to avoid name collisions. As with homodyne, 2 per-angle scaling parameters (contrast, offset) are tracked per azimuthal angle but live outside the 14-element physics vector. Per-angle scaling modes constant / averaged / individual (resolved from auto) reach full parity with the source heterodyne package's fit_nlsq_multi_phi.


Citation

XPCSJAX implements the transport-coefficient framework introduced in:

@article{He2024,
  author  = {He, Hongrui and Liang, Heyi and Chu, Miaoqi and Jiang, Zhang and
             de Pablo, Juan J and Tirrell, Matthew V and Narayanan, Suresh
             and Chen, Wei},
  title   = {Transport coefficient approach for characterizing nonequilibrium
             dynamics in soft matter},
  journal = {Proceedings of the National Academy of Sciences},
  volume  = {121},
  number  = {31},
  year    = {2024},
  doi     = {10.1073/pnas.2401162121}
}

@article{He2025,
  author  = {He, Hongrui and Liang, Heyi and Chu, Miaoqi and Jiang, Zhang and
             de Pablo, Juan J and Tirrell, Matthew V and Narayanan, Suresh
             and Chen, Wei},
  title   = {Bridging microscopic dynamics and rheology in the yielding
             of charged colloidal suspensions},
  journal = {Proceedings of the National Academy of Sciences},
  volume  = {122},
  number  = {42},
  year    = {2025},
  doi     = {10.1073/pnas.2514216122}
}

To cite the software itself:

@software{XPCSJAX,
  author      = {Chen, Wei},
  title       = {XPCSJAX: JAX-native NLSQ fitting for X-ray Photon Correlation Spectroscopy},
  year        = {2026},
  version     = {0.1.6},
  institution = {Argonne National Laboratory},
  url         = {https://gitlab.osti.gov/wchen/xpcsjax}
}

License

MIT. See LICENSE.

Authors

Metadata

Release files for xpcsjax 0.1.6

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

Source distribution (sdist)

Source distribution for xpcsjax 0.1.6
File Size Uploaded
xpcsjax-0.1.6.tar.gz 3.5 MB Details

Built distribution (wheel)

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

Total release size: 4.7 MB

Release files / xpcsjax-0.1.6.tar.gz

Download URL xpcsjax-0.1.6.tar.gz
Size 3.5 MB
Tags Source
SHA-256 checksum
How to use checksums
b5732f1ebaaed4f4528f11c1fe8721864431d898dede957411fd4b0117b76741
BLAKE2b-256 checksum
How to use checksums
661286591ccd59d80be49da3c27cc2f3c8e383fed3253cf6f41132045f191863
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 Aug 31, 2026.

Transparency log

Release files / xpcsjax-0.1.6-py3-none-any.whl

Download URL xpcsjax-0.1.6-py3-none-any.whl
Size 1.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
95f75abe80c24def7396f586ffdd4dce2a41448c9272b0ee78bc1ad337d825ff
BLAKE2b-256 checksum
How to use checksums
6d10ccb74c304b6cdecd577ebd03986f3e1c574cc908d443eb33beb5fb69f23a
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 Aug 31, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.8

2 release files

0.1.7

2 release files

This release

0.1.6 This release

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

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