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> |
||
|---|---|---|
| core | ||
| LSDprof | ||
| utils | ||
| .gitignore | ||
| CLAUDE.md | ||
| comp-ana.py | ||
| config.yaml | ||
| dat2yaml.py | ||
| inrenorm.dat | ||
| inzdi.dat | ||
| LICENSE | ||
| model-ur-line.dat | ||
| model-voigt-line.dat | ||
| plotBright.py | ||
| plotIV.py | ||
| plotMag.py | ||
| pyproject.toml | ||
| README.md | ||
| renormLSD.py | ||
| requirements.txt | ||
| THEORY.md | ||
| uv.lock | ||
| zdipy.py | ||
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 coefficientsoutBrightMap.dat- Brightness mapoutBrightMapGDark.dat- Gravity-darkened brightness mapoutLineModels.dat- Synthetic line profilesoutObserved.dat- Observed data points usedoutFitSummary.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:
- Folsom et al. 2018, MNRAS, 474, 4956
- For oblate geometry: Cang et al. 2020, A&A, 643, A39
Version History
-
0.5.0 (2026): Merged implementation with UR equations
- Added
core.lineprofileUnnoRmodule - Dynamic Voigt/UR mode selection
- Comprehensive documentation
- Added
-
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.