Skip to main content

SPECtroscopic Inference of stEllar parameterS

Project description

SPECIES v4

SPECtroscopic Inference of stEllar parameterS

A modern stellar spectroscopy pipeline for determining atmospheric parameters, chemical abundances, and broadening from high-resolution echelle spectra.

Originally created by Maritza Soto & James Jenkins (Soto & Jenkins 2018). Modernized and maintained by Jose Vines.

What it does

Given a high-resolution stellar spectrum, SPECIES determines:

  • Atmospheric parameters: Teff, log g, [Fe/H], microturbulence
  • Chemical abundances: Na, Mg, Al, Si, Ca, Ti, Cr, Mn, Fe, Ni, Cu, Zn (14 ions)
  • Broadening: vsini (rotational velocity) and vmac (macroturbulence)

It works by measuring equivalent widths of iron lines, then iteratively solving for the atmospheric parameters that produce excitation balance, ionization balance, and abundance consistency using MOOG (Sneden 1973) under the assumption of local thermodynamic equilibrium (LTE). Atmosphere models are interpolated from ATLAS9 grids (Castelli & Kurucz 2004).

Installation

pip install astro-species
species install-moog
species check

install-moog downloads and compiles MOOG from source. You need gfortran installed:

Platform Command
Ubuntu/Debian sudo apt install gfortran
Fedora/RHEL sudo dnf install gcc-gfortran
macOS brew install gcc
Conda conda install -c conda-forge gfortran

You also need ATLAS9 atmosphere model grids (~3.3 GB). These are not bundled with the package. Set SPECIES_ATLAS9_DIR to point to your local copy, or they will be downloaded on first use (TBD).

Docker

For zero-setup usage:

docker build -t species .
docker run -v ./spectra:/data species analyze /data/my_star.fits

Quick start

Python API

from species import Spectrum, Analyzer

# Load a spectrum (auto-detects instrument from FITS header)
spectrum = Spectrum.from_fits("my_star_feros.fits")

# Or from arrays (e.g. from your own reduction pipeline)
spectrum = Spectrum.from_arrays(wavelength, flux, snr=120, instrument="FEROS")

# Run the full analysis
result = Analyzer(spectrum).run()

# Results are structured Python objects
print(result.params.teff)           # 5822.0
print(result.params.logg)           # 4.52
print(result.params.feh)            # -0.003
print(result.abundances["SiI"])     # ElementAbundance(abundance=+0.068, n_lines=20)
print(result.broadening.vsini)      # 2.1 km/s

# Serialize
result.to_fits("results.fits")
result.to_dict()  # for databases, JSON, etc.

Batch processing

from pathlib import Path
from species import Spectrum, Analyzer

# Load multiple spectra
spectra = [Spectrum.from_fits(f) for f in Path("spectra/").glob("*.fits")]

# Analyze in parallel (4 cores)
results = Analyzer.batch(spectra, output_dir="./results", n_cores=4)

for result in results:
    print(f"{result.star_name}: T={result.params.teff:.0f}  [Fe/H]={result.params.feh:.3f}")

Command line

# Single star
species analyze my_star.fits --output ./results

# Multiple stars
species analyze star1.fits star2.fits star3.fits --output ./results

# Glob pattern + parallel
species analyze spectra/*.fits --ncores 4

# Skip broadening (faster)
species analyze my_star.fits --no-broadening

# Giant star
species analyze my_star.fits --giant

# EW measurement only
species ew-only my_star.fits

# Check installation
species check

Configuration

All settings can be overridden via environment variables or constructor arguments:

from species import Analyzer, Spectrum, Settings

config = Settings(
    atlas9_dir="/path/to/grids",
    moog_binary="/usr/local/bin/MOOGSILENT",
    is_giant=True,
)

result = Analyzer(spectrum, config=config).run()

Environment variables use the SPECIES_ prefix: SPECIES_ATLAS9_DIR, SPECIES_MOOG_BINARY, etc.

Supported instruments

SPECIES reads spectra from:

  • HARPS (ESO 3.6m)
  • FEROS (ESO/MPG 2.2m)
  • UVES (ESO VLT)
  • HIRES (Keck)
  • CORALIE (Euler 1.2m)
  • PFS (Magellan)
  • AAT
  • LCO NRES
  • Generic FITS (auto-detected from WCS keywords or 2D data layout)

Instrument is auto-detected from the FITS header INSTRUME keyword or the filename convention (starname_instrument.fits). You can also pass instrument="FEROS" explicitly.

Changes from the original SPECIES

Algorithmic improvements

Broyden's method replaces per-parameter bisection. The original adjusted one parameter at a time (metallicity, then temperature, then gravity, then microturbulence) via bisection, cycling until all four diagnostics converged. This required 600-900 MOOG calls per star and had convergence issues when porting from Python 2 to 3 due to float comparison semantics. The new default uses Broyden's quasi-Newton method, which solves the 4-equation system simultaneously in 10-16 MOOG calls. The residual norm is typically 250x smaller. The old bisection method is still available via method="per_parameter".

Broadening uses MOOG 5x instead of 75x. The original ran a separate MOOG synthesis for each vsini grid point (15 values x 5 lines = 75 calls). But the unbroadened spectrum is identical regardless of vsini — rotational broadening is applied afterward. The new code synthesizes once per diagnostic line and applies pyasl.rotBroad() in numpy.

Error propagation unified. The original had two nearly identical files (CalcErrors_new.py for dwarfs, CalcErrorsGiant_new.py for giants) differing only in polynomial coefficients. Now a single parameterized module.

Architecture

Aspect Original (v3) v4
Python version 2.7/3.x compatible 3.12+
Packaging None (clone and run) pip install astro-species
API CLI only (python SPECIES.py -starlist ...) Python library + CLI
Configuration 80+ global variables, 40+ CLI flags Pydantic Settings + env vars
MOOG interface os.system("MOOGSILENT") subprocess.run() with timeout, error handling
Type hints None Full coverage
Tests None 17 integration tests
Output Text files at hardcoded paths Structured dataclasses, FITS, ASCII
Parallelism Per-star (multiprocessing.Pool) Per-star + MOOGSession for per-call efficiency
Lines of code ~9,800 ~5,800

What was removed

  • Isochrone fitting (FindIsochrones.py): Mass, age, and radius determination is now handled by downstream tools (Lachesis). SPECIES focuses on spectroscopy.
  • Python 2 compatibility: from __future__ imports, past.utils.old_div, builtins shims.
  • MultiNest/emcee dependencies: These were only used by the isochrone module.
  • mwdust dependency: Extinction correction is handled elsewhere.
  • Full PhotometricRelations_class.py: Replaced with a lightweight Vizier lookup for initial parameter guesses. With Broyden's method, initial guesses matter less.

Performance

Metric Original v4
MOOG calls per star 600-900 15-25
Wall-clock time 10-20 min ~1 min
Convergence residual ~0.05 ~0.0002

Package structure

src/species/
    __init__.py          # Public API: Spectrum, Analyzer, Settings
    config.py            # Pydantic Settings (replaces global variables)
    cli.py               # Command-line interface
    analyzer.py          # Main orchestrator
    spectrum.py          # Spectrum loading + instrument readers
    ccf.py               # Cross-correlation for RV / rest-frame correction
    ew.py                # Equivalent width measurement
    atmosphere.py        # Atmospheric parameter fitting (Broyden + bisection)
    errors.py            # Error propagation (unified dwarf/giant)
    abundances.py        # Chemical abundance determination
    broadening.py        # vsini / vmac measurement
    photometry.py        # Vizier initial parameter estimation
    moog/
        wrapper.py       # MOOG subprocess interface + MOOGSession
        parser.py        # MOOG output parsing
        par_file.py      # Parameter file generation
        atmosphere_grid.py  # ATLAS9 grid interpolation
    io/
        results.py       # Result dataclasses + serialization
        plots.py         # Diagnostic plots
    data/
        linelists/       # Bundled iron + abundance line lists
        masks/           # Binary masks for CCF
        solar.py         # Asplund 2009 solar abundances

Citation

If you use SPECIES in your work, please cite:

  • Soto & Jenkins 2018, A&A 615, A76 (ADS)
  • Soto et al. 2021, MNRAS 508, 1

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

astro_species-4.0.0.tar.gz (9.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

astro_species-4.0.0-py3-none-any.whl (9.6 MB view details)

Uploaded Python 3

File details

Details for the file astro_species-4.0.0.tar.gz.

File metadata

  • Download URL: astro_species-4.0.0.tar.gz
  • Upload date:
  • Size: 9.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for astro_species-4.0.0.tar.gz
Algorithm Hash digest
SHA256 979c79f5466a4382ab81288c800a7c7d4baa52c59c3ff977b5744e64f9289fd1
MD5 175ad55b65d1951ade541fe5aeb54743
BLAKE2b-256 884fdde5ad2c5d8d9f76f3064e9a9628834d5c8f3606863231eda5aeaa93b09f

See more details on using hashes here.

File details

Details for the file astro_species-4.0.0-py3-none-any.whl.

File metadata

  • Download URL: astro_species-4.0.0-py3-none-any.whl
  • Upload date:
  • Size: 9.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for astro_species-4.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f88e434464a8c3055e5a5af3ca8839269674ed174b76979ce8e35282cef5e146
MD5 9b5ea7c4b2cbda646ef1296dd612278a
BLAKE2b-256 6216ba97f6d129119217452f6d04596f9f1c9f59cb98838fc62f54610a4a0edc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page