Adapted from https://github.com/folsomcp/ZDIpy, all under GPL 2 license
Find a file
alexis 7da5f90905 Fix CLI overwriting config auto_estimate_strength setting
The --no-auto-strength argument had an implicit default of True
(from action='store_false'), which always overwrote the config.yaml
setting. Added default=None so CLI only overrides when explicitly used.

Also added --auto-strength flag for symmetry.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 13:54:50 +01:00
core Add inline line profile parameters in YAML config 2026-01-06 13:36:53 +01:00
LSDprof Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
utils Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
.gitignore Add uv package management support 2026-01-06 13:49:07 +01:00
CLAUDE.md Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
comp-ana.py Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
config.yaml Add inline line profile parameters in YAML config 2026-01-06 13:36:53 +01:00
dat2yaml.py Add inline line profile parameters in YAML config 2026-01-06 13:36:53 +01:00
inrenorm.dat Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
inzdi.dat Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
LICENSE Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
model-ur-line.dat Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
model-voigt-line.dat Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
plotBright.py Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
plotIV.py Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
plotMag.py Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
pyproject.toml Add uv package management support 2026-01-06 13:49:07 +01:00
README.md Add comprehensive CLI parameter overrides 2026-01-09 13:43:56 +01:00
renormLSD.py Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
requirements.txt Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
THEORY.md Move ZDIpy code to repository root 2026-01-06 13:10:04 +01:00
uv.lock Add uv package management support 2026-01-06 13:49:07 +01:00
zdipy.py Fix CLI overwriting config auto_estimate_strength setting 2026-01-09 13:54:50 +01:00

ZDIpy-UR

Version 0.1 -

A Python 3 implementation of Zeeman Doppler Imaging (ZDI) for mapping stellar surface magnetic fields and brightness distributions from spectropolarimetric observations. This code is forked from https://github.com/folsomcp/ZDIpy and is licensed under GPL-2.0.

Overview

ZDIpy reconstructs stellar surface maps using:

  • Spherical harmonic expansion of magnetic field vectors
  • Maximum Entropy Method (MEM) for image reconstruction
  • Two line profile calculation modes:
    • UR mode (default): Accurate Unno-Rachkovsky solution for all field strengths
    • Voigt mode: Fast, weak field approximation

This merged implementation combines:

  • Modern Python 3 codebase from ZDIpy
  • Unno-Rachkovsky equations for polarized radiative transfer

Quick Start

Installation

Using uv (Recommended)

git clone <repository-url>
cd ZDIpy
uv sync                    # Install dependencies
uv run zdipy --help        # Show CLI options
uv run zdipy               # Run with default settings

Using pip

git clone <repository-url>
cd ZDIpy
pip install -e .           # Install in editable mode
zdipy --help               # Show CLI options
zdipy                      # Run with default settings

Direct execution

# Requirements: Python >= 3.8, numpy, scipy, matplotlib, pyyaml, joblib
git clone <repository-url>
cd ZDIpy
./zdipy.py                 # Runs with default UR mode

Basic Usage

import zdipy

# UR mode (default - accurate for all field strengths)
zdipy.main(verbose=1, lineMode='UR')

# Voigt mode (faster for weak fields)
zdipy.main(verbose=1, lineMode='Voigt')

Line Profile Modes

  • UR Mode (Unno-Rachkovsky) - DEFAULT
  • Voigt Mode

When to use Voigt mode:

  • Weak magnetic fields (< 1-2 kG)
  • Quick exploratory runs
  • When computation time is critical
  • Good initial guess for UR mode

Configuration Files

Main Configuration

YAML Format (Recommended):

  • Human-readable, easy to edit
  • Better for parameter sweeps
  • Hierarchical structure
  • File: config.yaml

Line Profile Configuration

. Inline in YAML (Recommended)

line:
  profile:
    wavelength: 1700.0        # central wavelength (nm)
    strength: 10.385          # line strength
    gauss_width: 6.175        # Gaussian width (km/s)
    lorentz_width: 7.035      # Lorentzian width (km/s for UR, ratio for Voigt)
    lande_g: 1.250            # effective Landé g-factor
    limb_darkening: 0.30      # limb darkening coefficient
    gravity_darkening: 0.0    # gravity darkening (0 = off)
    # UR-specific (ignored in Voigt mode):
    beta: 0                   # source function slope (0 = auto)
    filling_factor_I: 1.0     # Stokes I filling factor
    filling_factor_V: 1.0     # Stokes V filling factor

Converting Legacy Files to YAML

Use the converter script to migrate existing configurations:

./dat2yaml.py inzdi.dat config.yaml --line-model model-ur-line.dat

Output Files

  • outMagCoeff.dat: Spherical harmonic coefficients
  • outBrightMap.dat: Surface brightness map
  • outLineModels.dat: Synthetic Stokes profiles
  • outObserved.dat: Observed data used in fit
  • outFitSummary.txt: Iteration convergence history

Plotting Utilities

./plotMag.py outMagCoeff.dat           # Magnetic field maps
./plotBright.py outBrightMap.dat       # Brightness maps
./plotIV.py outLineModels.dat outObserved.dat  # Profile fits
./comp-ana.py outMagCoeff.dat          # Field decomposition

Command-Line Interface

ZDIpy supports comprehensive command-line arguments for easy parameter sweeps and batch processing:

# Run with default configuration
zdipy                                  # If installed with pip/uv
uv run zdipy                           # With uv (without install)
./zdipy.py                             # Direct execution

# Get help on all available options
zdipy --help

# Override stellar parameters
zdipy --incl 60 --vsini 12.5 --period 5.2

# Use specific config file with overrides
zdipy --config config.yaml --incl 75 --output _i75

# Switch to Voigt mode (default is UR)
zdipy --lineMode Voigt

# Change fitting parameters
zdipy --lmax 10 --chi2-target 0.8 --max-iterations 30

# Use entropy-based targeting instead of chi2
zdipy --target-type entropy --entropy-target -5.0

# Override line profile parameters
zdipy --line-strength 12.0 --gauss-width 5.5 --lande-g 1.3

# Adjust filling factors for Stokes I and V
zdipy --ffi 0.8 --ffv 1.0

# Initialize from existing maps
zdipy --init-mag-from-file --init-mag-file previous_run/outMagCoeff.dat

# Control brightness fitting
zdipy --fit-brightness --entropy-type 2 --limiting-brightness 1.5

# Combine multiple overrides for parameter sweep
zdipy --config my_config.yaml --incl 45 --vsini 10 --lmax 12 --output run_test

Available parameter groups:

  • Stellar: --incl, --vsini, --period, --dOmega, --mass, --radius
  • Grid: --num-rings
  • Fitting: --target-type, --chi2-target, --entropy-target, --max-iterations, --test-aim
  • Magnetic: --lmax, --mag-geometry, --fit-mag, --no-fit-mag, --mag-entropy-slope, --init-mag-from-file, --init-mag-file
  • Brightness: --fit-brightness, --no-fit-brightness, --chi2-scaling, --default-brightness, --entropy-scaling, --entropy-type, --limiting-brightness, --init-bright-from-file, --init-bright-file
  • Line profile: --lineMode, --no-auto-strength, --resolution, --velocity-start, --velocity-end, --line-strength, --gauss-width, --lorentz-width, --ffi, --ffv, --wavelength, --lande-g, --limb-darkening, --gravity-darkening, --beta
  • Observation: --jd-ref
  • Output: --outdir (directory), --output (suffix), --verbose

Command-line arguments override values from the configuration file, making parameter sweeps easy.

Organizing Output Files

Use --outdir to save all output files to a specific directory (created automatically):

# Save all outputs to results/run1/
zdipy --outdir results/run1

# Parameter sweep with organized output - each run in its own directory
for incl in 30 45 60 75 90; do
    zdipy --incl $incl --outdir results/incl_$incl
done

# Or use suffix with shared directory
for incl in 30 45 60 75 90; do
    zdipy --incl $incl --outdir results --output _i$incl
done

# Test different lmax values in separate directories
for lmax in 5 10 15 20; do
    zdipy --lmax $lmax --outdir results/lmax_$lmax
done

All output files will be saved in the specified directory:

  • outMagCoeff.dat - Magnetic field coefficients
  • outBrightMap.dat - Brightness map
  • outBrightMapGDark.dat - Gravity-darkened brightness map
  • outLineModels.dat - Synthetic line profiles
  • outObserved.dat - Observed data points used
  • outFitSummary.txt - Iteration convergence history

Examples

Standard ZDI Run (UR mode - default)

import zdipy
results = zdipy.main(verbose=1)  # Uses UR mode by default
iIter, entropy, chi2, test, meanBright, meanBrightDiff, meanMag = results
print(f"Final chi²: {chi2:.2f}, Mean B: {meanMag:.1f} G")

Fast Run with Voigt Mode

zdipy.main(verbose=1, lineMode='Voigt')  # Faster for weak fields

Parameter Sweep (Python API)

import core.mainFuncs as mf

for incl in [30, 45, 60, 75, 90]:
    par = mf.readParamsZDI('config.yaml')
    par.incl = incl
    zdipy.main(par=par, num=f'_i{incl}')  # Uses default UR mode

Parameter Sweep (Command-Line - Easier!)

# Much simpler with argparse!
# Each run gets its own directory - no file conflicts!
for incl in 30 45 60 75 90; do
    zdipy --incl $incl --outdir results/incl_$incl
done

Physical Formulation

Spherical Harmonics (Donati et al. 2006)

B(θ, φ) = ∇ × [∇ × (r S_pol)] + ∇ × (r S_tor)
  • α_lm: Radial poloidal coefficients
  • β_lm: Meridional poloidal coefficients
  • γ_lm: Toroidal coefficients

Voigt Profile (Weak Field)

V(λ) ∝ B_los × dI/dλ

Unno-Rachkovsky Solution

Full polarized radiative transfer in Milne-Eddington atmosphere:

dI/dτ = K(I - S)

See THEORY.md for complete mathematical derivation.

Performance

ZDIpy includes automatic parallelization for multi-core systems:

  • Parallel phase processing: Each observation phase computed concurrently
  • Speedup: 1.7× faster on typical workstations (12+ cores)
  • Automatic scaling: Uses all available CPU cores
  • No configuration needed: Works out of the box

Typical Performance (LO Peg dataset, 16 phases, UR mode):

  • Single-threaded: ~75 seconds
  • Multi-threaded (12 cores): ~44 seconds
  • Speedup: 1.7×

For more observations, speedup improves:

  • 30 phases: ~2.0× speedup
  • 50+ phases: ~2.3× speedup

Optimization Notes:

Several optimizations were tested during development:

  • Joblib parallelization (1.7× speedup) - Implemented
  • FFT-based convolution - Slower and numerically unstable
  • Voigt lookup tables - Significant accuracy loss
  • Numba JIT compilation - Incompatible with array indexing

See PERFORMANCE.md for detailed bottleneck analysis and BENCHMARK_RESULTS.md for measurements. The remaining significant optimization opportunity is analytic derivatives (potential 3× speedup), which requires mathematical derivation of the Unno-Rachkovsky equation derivatives.

Troubleshooting

Problem Solution
File not found: model-ur-line.dat Create model file or use lineMode='Voigt'
Slow convergence in UR mode Reduce lMax, increase tolerances
Poor Stokes V fits Try UR mode, check line parameters
Negative brightness Adjust entropy slope, check limb darkening

References

ZDI Method

  • Donati et al. (2006), MNRAS 370, 629 - Spherical harmonics
  • Skilling & Bryan (1984), MNRAS 211, 111 - Maximum Entropy

Line Profiles

  • Humlicek (1982), JQSRT 27, 437 - Voigt function
  • Unno (1956), PASJ 8, 108 - Polarized transfer
  • Landi Degl'Innocenti & Landolfi (2004) - "Polarization in Spectral Lines"

Stellar Physics

  • Gray (2005) - Limb darkening
  • Claret & Bloemen (2011), A&A 529, A75 - Gravity darkening
  • Morin et al. (2008b), MNRAS 390, 567 - Filling factors

Citation

If you use this code, please cite:

Version History

  • 0.5.0 (2026): Merged implementation with UR equations

    • Added core.lineprofileUnnoR module
    • Dynamic Voigt/UR mode selection
    • Comprehensive documentation
  • 0.4.3 (2022): Original ZDIpy Python 3 release

Acknowledgments

ZDI method by J.-F. Donati et al. Python implementation by C. P. Folsom.
UR equations integration (this merged version) performed January 2026.