homodyne.optimization

The homodyne.optimization package provides two independent optimization backends for XPCS parameter estimation:

Backend

Module

Best For

NLSQ

homodyne.optimization.nlsq — Adapter / homodyne.optimization.nlsq — Wrapper

Fast point estimates; primary method

CMC

homodyne.optimization.cmc

Bayesian uncertainty quantification


Choosing Between NLSQ and CMC

Use NLSQ when you need:

  • Fast parameter estimates (seconds to minutes per dataset)

  • Initial values for a subsequent CMC run (warm-start)

  • Exploratory analysis or parameter sensitivity studies

  • Datasets up to ~1 billion points (streaming mode)

Use CMC when you need:

  • Posterior distributions for uncertainty quantification

  • Publication-quality error bars on physical parameters

  • Evidence of multi-modality in the posterior

  • Convergence diagnostics (R-hat, ESS, divergence rate)

Tip

The recommended production workflow is always NLSQ first, then CMC with the NLSQ result as warm-start. This reduces CMC divergences from ~28 % to under 5 % and cuts warmup time significantly.


Common Workflow Patterns

Pattern 1: NLSQ only (fast, no uncertainties)

from homodyne.optimization.nlsq import fit_nlsq_jax
from homodyne.config.manager import ConfigManager
from homodyne.data.xpcs_loader import XPCSDataLoader

config_manager = ConfigManager("my_config.yaml")
loader = XPCSDataLoader(config_dict=config_manager.config)
data = loader.load_experimental_data()

result = fit_nlsq_jax(data, config_manager.config)
print(result.parameters)    # best-fit physical parameters (ndarray)
print(result.chi_squared)   # goodness-of-fit

Pattern 3: CLI workflow (two-step)

# Step 1: NLSQ
homodyne --method nlsq --config config.yaml --output-dir results/

# Step 2: CMC using pre-computed NLSQ warm-start
homodyne --method cmc --config config.yaml \
         --nlsq-result results/ \
         --output-dir results/

Package Structure

homodyne/optimization/
├── nlsq/
   ├── core.py              # fit_nlsq_jax() — primary entry point
   ├── adapter.py           # NLSQAdapter (recommended, JIT caching)
   ├── wrapper.py           # NLSQWrapper orchestrator (delegates below)
   ├── fallback_chain.py    # OptimizationStrategy enum, fallback logic
   ├── recovery.py          # 3-attempt error recovery, error diagnosis
   ├── config.py            # NLSQConfig dataclass
   ├── cmaes_wrapper.py     # CMA-ES global optimizer
   ├── anti_degeneracy_controller.py  # Per-angle scaling defense
   ├── strategies/
      ├── stratified_ls.py     # Primary: stratified least-squares
      ├── hybrid_streaming.py  # Hybrid streaming for large datasets
      ├── out_of_core.py       # Out-of-core JTJ accumulation
      ├── executors.py         # Strategy selection and dispatch
      ├── residual.py          # Residual function (NumPy path)
      ├── residual_jit.py      # Residual function (JIT path)
      ├── sequential.py        # Sequential per-angle optimization
      └── chunking.py          # Out-of-core data chunking
   └── validation/          # Input and result validation
└── cmc/
    ├── core.py              # fit_mcmc_jax() — primary entry point
    ├── config.py            # CMCConfig dataclass
    ├── model.py             # XPCS model variants (5 models)
    ├── sampler.py           # SamplingPlan, NUTS execution
    ├── reparameterization.py  # Log-space priors, t_ref
    ├── priors.py            # Prior distribution builders
    └── backends/
        └── multiprocessing.py  # Multi-process execution