Stellar Models and Photometry#

This page explains the stellar evolution models used in brutus and how they connect intrinsic stellar properties to observable photometry.

Tip

For quick definitions of key terms (EEP, isochrone, etc.), see the Glossary.

MIST Stellar Evolution Models#

brutus uses MIST (MESA Isochrones and Stellar Tracks) v1.2 as its foundation (MIST homepage). MIST models are computed using the MESA stellar evolution code and provide:

  • Evolutionary tracks: How individual stars evolve over time

  • Isochrones: Snapshots of coeval stellar populations at fixed age

  • Stellar parameters: Mass, radius, temperature, luminosity, surface gravity

  • Bolometric corrections: Synthetic photometry in many filter systems

Parameter Coverage#

MIST models span:

Initial mass

0.1 to 300 M☉

Metallicity [Fe/H]

-4.0 to +0.5 dex

Ages

~1 Myr to 14 Gyr (mass-dependent)

The models include all evolutionary phases: pre-main-sequence, main sequence, subgiant, red giant branch, horizontal branch, and asymptotic giant branch (for low/intermediate mass stars).

EEP: Equivalent Evolutionary Point#

A key feature of MIST is the EEP (Equivalent Evolutionary Point) parameterization. EEP is an integer index that tracks evolutionary phase in a mass-independent way.

Why Not Use Age Directly?#

Age is problematic as a stellar evolution coordinate:

  1. Non-monotonic evolution: Stars loop back and forth in the H-R diagram during complex phases

  2. Mass-dependent timescales: A 0.8 M☉ star lives ~15 Gyr on the main sequence; a 5 M☉ star exhausts hydrogen in ~100 Myr

  3. Degeneracies: Multiple evolutionary phases produce similar temperatures and luminosities

EEP solves these problems by defining phase relative to physical transitions in stellar structure.

Key EEP Values#

EEP

Phase

Description

202

Pre-main-sequence

Contracting toward main sequence

353

ZAMS

Zero-age main sequence (hydrogen fusion begins)

454

TAMS

Terminal-age main sequence (core hydrogen exhausted)

605

Base RGB

Beginning of red giant branch ascent

631

Tip RGB

Maximum RGB luminosity before helium flash

707

ZAHB

Zero-age horizontal branch (helium core burning)

808

TP-AGB

Thermal pulses on asymptotic giant branch

EEP varies smoothly between these primary points, providing a well-defined coordinate for interpolation.

Using EEP in brutus#

brutus parameterizes stellar models as:

\[(M_{\rm init}, {\rm EEP}, [{\rm Fe/H}]) \rightarrow (T_{\rm eff}, L, R, \log g, {\rm age}, \ldots)\]

This allows prediction of stellar parameters for any combination of mass, evolutionary phase, and metallicity:

from brutus.core import EEPTracks

tracks = EEPTracks()

# Get predictions for a 1.0 solar mass star at TAMS with solar metallicity
# Labels are [mini, eep, feh, afe]
params = tracks.get_predictions([1.0, 454, 0.0, 0.0])
# Returns: [log_age, log_L, log_Teff, log_g, ...]

print(f"Age: {10**params[0] / 1e9:.2f} Gyr")
print(f"Teff: {10**params[2]:.0f} K")
print(f"log(g): {params[3]:.2f}")

Note

Users rarely need to work with EEP directly. The BruteForce fitter handles EEP internally when fitting photometric data. EEP becomes important when generating custom models or interpreting detailed results.

Evolutionary Tracks vs Isochrones#

brutus provides two complementary representations:

Evolutionary Tracks

Isochrones

Fixed

Mass, composition

Age, composition

Variable

EEP (evolutionary phase)

Mass

Question answered

How does a star of given mass evolve?

What masses exist at a given age?

Use case

Individual field stars

Stellar clusters

Evolutionary Tracks (EEPTracks, StarEvolTrack)#

Use tracks when modeling individual stars with unknown masses:

from brutus.core import EEPTracks, StarEvolTrack

tracks = EEPTracks()
star = StarEvolTrack(tracks=tracks, filters=['Gaia_G_MAW', 'Gaia_BP_MAWf', 'Gaia_RP_MAW'])

# Generate photometry for a specific stellar model
result = star.get_seds(
    mini=1.2,       # Initial mass (solar masses)
    eep=400,        # Main sequence
    feh=0.0,        # Solar metallicity
    av=0.1,         # V-band extinction
    dist=1000.0     # Distance in parsecs
)

seds, params1, params2 = result
# seds: magnitudes in each filter
# params1: primary component stellar parameters (Teff, logg, age, etc.)
# params2: secondary component parameters (for binaries)

Isochrones (Isochrone, StellarPop)#

Use isochrones when modeling coeval populations (clusters):

from brutus.core import Isochrone, StellarPop

iso = Isochrone()
pop = StellarPop(isochrone=iso, filters=['Gaia_G_MAW', 'PS_g', 'PS_r', '2MASS_J'])

# Generate photometry for a 1 Gyr, solar metallicity population
result = pop.get_seds(
    feh=0.0,        # Metallicity
    loga=9.0,       # log10(age/yr) = 9.0 → 1 Gyr
    av=0.1,         # V-band extinction
    dist=2000.0     # Distance in parsecs
)

seds, params1, params2 = result
# seds: (N_stars, N_filters) array of magnitudes along the isochrone
# params1: primary component stellar parameters for each point
# params2: secondary component parameters (for binaries)

From Parameters to Photometry#

Converting stellar parameters to observable magnitudes requires two steps:

Bolometric Corrections#

Stellar atmosphere models (ATLAS12/SYNTHE) predict spectral flux distributions \(F_\lambda(T_{\rm eff}, \log g, [{\rm Fe/H}])\). These are integrated through filter transmission curves to yield synthetic magnitudes:

\[M_{\rm band} = M_{\rm bol} - {\rm BC}_{\rm band}(T_{\rm eff}, \log g, [{\rm Fe/H}])\]

where BC is the bolometric correction for each filter.

Neural Network Acceleration#

Computing full spectral synthesis at every model evaluation would be prohibitively slow. brutus uses trained neural networks (FastNN) to predict bolometric corrections:

\[(T_{\rm eff}, \log g, [{\rm Fe/H}]) \xrightarrow{\text{neural net}} \{{\rm BC}_{\rm band}\}\]

This provides:

  • Speed: Orders of magnitude faster than full spectral synthesis

  • Accuracy: Sufficient for photometric precision of typical surveys

  • Flexibility: Any combination of supported filters

Extinction Modeling#

Interstellar dust modifies photometry through wavelength-dependent extinction. brutus models this with reddening vectors:

\[m_{\rm band} = M_{\rm band} + \mu + A_V \times \left( R_{\rm band} + R_V \times R'_{\rm band} \right)\]

where \(R_{\rm band}\) and \(R'_{\rm band}\) encode how extinction affects each filter for a given stellar spectrum.

The reddening vectors are pre-computed using the Fitzpatrick & Massa (2009) extinction curve. This extinction law is parameterized by R_V and is baked into the neural network predictions, allowing efficient evaluation of reddened magnitudes for any \((A_V, R_V)\) combination.

See also

See Prior Distributions for the default R_V prior distribution, which is based on Schlafly et al. (2016).

Available Photometric Filters#

brutus supports these photometric systems through its neural network models:

Space-Based

  • Gaia DR3: Gaia_G_MAW, Gaia_BP_MAWf, Gaia_RP_MAW

  • WISE: WISE_W1, WISE_W2, WISE_W3, WISE_W4

  • Hipparcos: Hipparcos_Hp

  • Kepler: Kepler_D51, Kepler_Kp

  • TESS: TESS

Ground-Based Optical

  • Pan-STARRS: PS_g, PS_r, PS_i, PS_z, PS_y, PS_w, PS_open

  • SDSS: SDSS_u, SDSS_g, SDSS_r, SDSS_i, SDSS_z

  • DECam: DECam_u, DECam_g, DECam_r, DECam_i, DECam_z, DECam_Y

  • Bessell (Johnson-Cousins): Bessell_U, Bessell_B, Bessell_V, Bessell_R, Bessell_I

  • Tycho: Tycho_B, Tycho_V

Ground-Based Near-IR

  • 2MASS: 2MASS_J, 2MASS_H, 2MASS_Ks

  • VISTA: VISTA_Z, VISTA_Y, VISTA_J, VISTA_H, VISTA_Ks

  • UKIDSS: UKIDSS_Z, UKIDSS_Y, UKIDSS_J, UKIDSS_H, UKIDSS_K

Pre-computed Grids vs On-the-Fly Models#

brutus offers two strategies:

Pre-computed Grids

On-the-Fly Models

Class

StarGrid

StarEvolTrack, StellarPop

Speed

Very fast (~ms per star)

Slower (~100 ms per evaluation)

Flexibility

Fixed filter set

Any filter combination

Memory

Large (several GB)

Minimal

Best for

Large surveys, production fitting

Exploration, custom filters, clusters

Pre-computed grids (for large-scale fitting):

from brutus.core import StarGrid
from brutus.data import load_models

models, labels, label_mask = load_models('grid_mist_v9.h5', filters=filters)
grid = StarGrid(models, labels)

On-the-fly models (for flexibility):

from brutus.core import EEPTracks, StarEvolTrack

tracks = EEPTracks()
star = StarEvolTrack(tracks=tracks, filters=['Gaia_G_MAW', '2MASS_J', '2MASS_Ks'])

See also

See Grid-Based Fitting for creating custom pre-computed grids.

Model Limitations#

MIST models have known limitations:

  • Non-rotating: Rotation affects stellar structure and lifetimes, especially for massive stars

  • Single stars: Binary evolution (mass transfer, mergers) not included. However, unresolved binary companions can be partially modeled via the binary_fraction parameter in StellarPop.get_seds(), which adds flux from a secondary star drawn from a mass ratio distribution.

  • Solar-scaled abundances: No alpha-enhancement or individual element variations

  • M dwarf temperatures: Models predict slightly incorrect temperatures for low-mass stars

  • Radius inflation: Magnetic activity inflates radii of active low-mass stars by 5–15%

For empirical corrections to some of these issues, see Empirical Calibrations.

References#

MIST Stellar Models:

  • Choi et al. (2016), “Mesa Isochrones and Stellar Tracks (MIST). I. Solar-scaled Models”, ApJ, 823, 102

  • Dotter (2016), “MESA Isochrones and Stellar Tracks (MIST) 0: Methods for the Construction of Stellar Isochrones”, ApJS, 222, 8

MESA Stellar Evolution Code:

  • Paxton et al. (2011, 2013, 2015, 2018, 2019), “Modules for Experiments in Stellar Astrophysics (MESA)”, ApJS series

Extinction Law:

  • Fitzpatrick & Massa (2009), “An Analysis of the Shapes of Interstellar Extinction Curves. VI. The Near-IR Extinction Law”, ApJ, 699, 1209

brutus Implementation:

  • Speagle et al. (2025), “Deriving Stellar Properties, Distances, and Reddenings using Photometry and Astrometry with BRUTUS”, arXiv:2503.02227