Stars

Particle Stars

A particle.Starsobject is the core object in synthesizer for modelling stellar distributions described by discrete particles (e.g. in hydrodynamical simulations).

To initialise one you need equal length arrays describing the ages, metallicities and initial masses of your star particles. These can then be provided directly to the Stars object on initialisation. In the example below, we make some mock data (with units) and load these into a particle Stars object:

[1]:
import numpy as np
from unyt import Mpc, Msun, Myr

from synthesizer.particle import Stars

N = 100
ages = np.random.rand(N) * 100 * Myr
metallicities = np.random.rand(N) / 100
initial_masses = np.ones(N) * 1e6 * Msun

stars = Stars(
    initial_masses=initial_masses,
    ages=ages,
    metallicities=metallicities,
)

The provided ages, metallicities and initial masses of the star particles describe the star formation and metal enrichment (SFZH) history. Some basic statistics of this object can be viewed by:

[2]:
print(stars)
+------------------------------------------------------------------------------------+
|                                       STARS                                        |
+-----------------------------+------------------------------------------------------+
| Attribute                   | Value                                                |
+-----------------------------+------------------------------------------------------+
| nparticles                  | 100                                                  |
+-----------------------------+------------------------------------------------------+
| metallicity_floor           | 1.00e-05                                             |
+-----------------------------+------------------------------------------------------+
| name                        | 'Stars'                                              |
+-----------------------------+------------------------------------------------------+
| component_type              | 'Stars'                                              |
+-----------------------------+------------------------------------------------------+
| fesc                        | 0.00e+00                                             |
+-----------------------------+------------------------------------------------------+
| fesc_ly_alpha               | 1.00                                                 |
+-----------------------------+------------------------------------------------------+
| resampled                   | False                                                |
+-----------------------------+------------------------------------------------------+
| young_stars_parametrisation | False                                                |
+-----------------------------+------------------------------------------------------+
| nstars                      | 100                                                  |
+-----------------------------+------------------------------------------------------+
| is_parametric               | False                                                |
+-----------------------------+------------------------------------------------------+
| is_particle                 | True                                                 |
+-----------------------------+------------------------------------------------------+
| ages (100,)                 | 2.57e+05 yr -> 9.97e+07 yr (Mean: 4.97e+07 yr)       |
+-----------------------------+------------------------------------------------------+
| metallicities (100,)        | 5.51e-04 -> 9.95e-03 (Mean: 5.29e-03)                |
+-----------------------------+------------------------------------------------------+
| log10metallicities (100,)   | -3.26e+00 -> -2.00e+00 (Mean: -2.37e+00)             |
+-----------------------------+------------------------------------------------------+
| log10ages (100,)            | 5.41e+00 -> 8.00e+00 (Mean: 7.56e+00)                |
+-----------------------------+------------------------------------------------------+
| initial_masses (100,)       | 1.00e+06 Msun -> 1.00e+06 Msun (Mean: 1.00e+06 Msun) |
+-----------------------------+------------------------------------------------------+

But more informatively this can be visualised in Synthesizer by calling the get_sfzh method, which will assign the star particles to a SFZH grid. This can be an arbitrary grid, but here we will use the Grid object’s axes.

[3]:
from synthesizer.grid import Grid

grid_name = "test_grid"

grid = Grid(grid_name)

sfzh = stars.get_sfzh(grid.log10ages, grid.metallicities)
sfzh.plot_sfzh()
../_images/galaxy_components_stars_6_0.png
[3]:
(<Figure size 350x350 with 3 Axes>,
 <Axes: xlabel='$\\log_{10}(\\mathrm{age}/\\mathrm{yr})$', ylabel='$\\log_{10}(Z)$'>)

You can also calculate (with get_* methods) or plot (with plot_* methods) the star formation history (SFH) and metallicity distribution (ZD) in isolation.

[4]:
stars.plot_sfh(grid.log10ages)
stars.plot_metal_dist(grid.metallicities)
../_images/galaxy_components_stars_8_0.png
../_images/galaxy_components_stars_8_1.png
[4]:
(<Figure size 640x480 with 1 Axes>,
 <Axes: xlabel='$Z$', ylabel='Z_D / M$_\\odot$'>)

By providing a Grid to the Stars object one can generate the stellar emission. This can include the integrated SED (see Sed docs), line emission (see line docs), as well as the per–particle SED and line luminosity / equivalent widths.

Optional arguments

Any component can take arbitrary extra arguments. Some of these are pre-defined kwargs (e.g. coordinates, redshift, current_masses etc.), but any additional **kwargs will be unpacked and attached to the component instances (here a Stars instance). This is particularly useful when working with emission models that require component level attributes (e.g. particle specific optical depths).

[5]:
tau_v = np.random.rand(N)
coordinates = np.random.normal(50, 0.005, (N, 3)) * Mpc
centre = np.array([50, 50, 50]) * Mpc
redshift = 5

stars = Stars(
    initial_masses=initial_masses,
    ages=ages,
    metallicities=metallicities,
    # Pre defined Quantitys
    coordinates=coordinates,
    centre=centre,
    # Optional argument
    redshift=redshift,
    current_masses=initial_masses - (np.random.rand(N) * 1e6 * Msun),
    # Arbitrary kwarg for modelling
    tau_v=tau_v,
)
print(stars)
+--------------------------------------------------------------------------------------+
|                                        STARS                                         |
+-------------------------------+------------------------------------------------------+
| Attribute                     | Value                                                |
+-------------------------------+------------------------------------------------------+
| redshift                      | 5                                                    |
+-------------------------------+------------------------------------------------------+
| nparticles                    | 100                                                  |
+-------------------------------+------------------------------------------------------+
| metallicity_floor             | 1.00e-05                                             |
+-------------------------------+------------------------------------------------------+
| name                          | 'Stars'                                              |
+-------------------------------+------------------------------------------------------+
| component_type                | 'Stars'                                              |
+-------------------------------+------------------------------------------------------+
| fesc                          | 0.00e+00                                             |
+-------------------------------+------------------------------------------------------+
| fesc_ly_alpha                 | 1.00                                                 |
+-------------------------------+------------------------------------------------------+
| resampled                     | False                                                |
+-------------------------------+------------------------------------------------------+
| young_stars_parametrisation   | False                                                |
+-------------------------------+------------------------------------------------------+
| nstars                        | 100                                                  |
+-------------------------------+------------------------------------------------------+
| is_parametric                 | False                                                |
+-------------------------------+------------------------------------------------------+
| is_particle                   | True                                                 |
+-------------------------------+------------------------------------------------------+
| coordinates (100, 3)          | 5.00e+01 Mpc -> 5.00e+01 Mpc (Mean: 5.00e+01 Mpc)    |
+-------------------------------+------------------------------------------------------+
| masses (100,)                 | 1.26e+03 Msun -> 9.95e+05 Msun (Mean: 5.16e+05 Msun) |
+-------------------------------+------------------------------------------------------+
| centre                        | [50. 50. 50.] Mpc                                    |
+-------------------------------+------------------------------------------------------+
| tau_v (100,)                  | 3.87e-03 -> 9.97e-01 (Mean: 5.16e-01)                |
+-------------------------------+------------------------------------------------------+
| ages (100,)                   | 2.57e+05 yr -> 9.97e+07 yr (Mean: 4.97e+07 yr)       |
+-------------------------------+------------------------------------------------------+
| metallicities (100,)          | 5.51e-04 -> 9.95e-03 (Mean: 5.29e-03)                |
+-------------------------------+------------------------------------------------------+
| log10metallicities (100,)     | -3.26e+00 -> -2.00e+00 (Mean: -2.37e+00)             |
+-------------------------------+------------------------------------------------------+
| log10ages (100,)              | 5.41e+00 -> 8.00e+00 (Mean: 7.56e+00)                |
+-------------------------------+------------------------------------------------------+
| initial_masses (100,)         | 1.00e+06 Msun -> 1.00e+06 Msun (Mean: 1.00e+06 Msun) |
+-------------------------------+------------------------------------------------------+
| current_masses (100,)         | 1.26e+03 Msun -> 9.95e+05 Msun (Mean: 5.16e+05 Msun) |
+-------------------------------+------------------------------------------------------+
| centered_coordinates (100, 3) | -1.38e-02 Mpc -> 1.47e-02 Mpc (Mean: -1.32e-04 Mpc)  |
+-------------------------------+------------------------------------------------------+
| total_mass                    | 51563280.31511461 Msun                               |
+-------------------------------+------------------------------------------------------+

Smoothing lengths

Smoothed particle imaging and line-of-sight calculations require smoothing_lengths for each particle. If these are not already present in your input data, you can derive them from the particle coordinates with calculate_smoothing_lengths. By default this performs a self-query, using the stellar coordinates as both the input and source set.

You can also derive stellar smoothing lengths from a different particle distribution by passing source_coords. This is useful when the stars should inherit their smoothing scale from the gas distribution, for example when preparing stellar line-of-sight calculations based on gas particles. The same interface is available on the particle object itself via stars.calculate_smoothing_lengths(source_coords=...).

[6]:
from synthesizer.particle.utils import calculate_smoothing_lengths

star_coords = np.random.normal(50, 0.005, (N, 3)) * Mpc
gas_coords = np.random.normal(50, 0.01, (4 * N, 3)) * Mpc

stellar_smls = calculate_smoothing_lengths(star_coords)
stellar_smls_from_gas = calculate_smoothing_lengths(
    star_coords,
    source_coords=gas_coords,
    num_neighbours=32,
)

smoothed_stars = Stars(
    initial_masses=initial_masses,
    ages=ages,
    metallicities=metallicities,
    coordinates=star_coords,
    current_masses=initial_masses,
    smoothing_lengths=stellar_smls_from_gas,
)

print(stellar_smls[:3])
print(stellar_smls_from_gas[:3])
print(smoothed_stars.smoothing_lengths[:3])
[0.00840338 0.00712569 0.00619827] Mpc
[0.00542085 0.00558486 0.00591542] Mpc
[0.00542085 0.00558486 0.00591542] Mpc

Computing characteristics radii

Characteristic radii can be computed for the stellar particle distribution. We can either calculate the half-mass radius.

[7]:
r = stars.get_half_mass_radius()
print(r)
0.007024703549092593 Mpc

Or use an aribtrary attribute for the radius weight. Here we’ll use the optical depth for a “half tau_V radius”.

[8]:
r = stars.get_attr_radius("tau_v")
print(r)
0.007562061408858964 Mpc

We can also compute radii for different fractions by passing the fraction we want to calculate a radius for.

[9]:
r20 = stars.get_attr_radius("masses", frac=0.2)
r80 = stars.get_attr_radius("masses", frac=0.8)
print(r20, r80)
0.004149232599532768 Mpc 0.009664055463453215 Mpc

We can also calculate characteristic light radii from photometry. See the photometry documentation for more details.

Getting weighted attributes

We can get weighted attributes from any particle object using the get_weighted_attr method. This takes the name of an attribute to weight and either the name of an attribute to use for a weight or an array of weights.

[10]:
print(stars.get_weighted_attr("metallicities", "initial_masses"))
print(stars.get_weighted_attr("metallicities", stars.masses))
print(stars.get_weighted_attr("log10metallicities", stars.masses))
0.00529396230127877
0.005043112877680557
-2.395911542501602

In addition to this generic method we also provide some pre-defined methods for common attributes, shown below.

[11]:
print(stars.get_mass_weighted_age())
print(stars.get_mass_weighted_metallicity())
print(stars.get_mass_weighted_optical_depth())
49745773.693967745 yr
0.00529396230127877
0.5160015710163116

Parametric Stars

The core element of the parametric modelling in synthesizer is the parametric.Stars object. This contains everything necessary to describe a stellar population including:

  • A 2D SFZH grid containing the stellar mass formed in stellar age and metallicity bins.

  • A Morphology object describing it’s distribution (optional but required for imaging).

  • The axes of the SFZH grid.

  • The total initial stellar mass or the surviving mass.

And if calculated by the user:

There are a number of different methods to define a parametric stellar population (from here on a Stars object). In what follows we will focus on user defined values/arrays but note that each different method could instead use simulated data (e.g. from Semi Analytic Models) rather than user defined values.

The possible ways of defining a Stars object are (the age and metallicity axis of the SFZH must always be supplied):

  • Explictly providing the SFZH grid itself. Note that this will mean all other definitions below are ignored.

  • Providing singular age and metallicity values to define an “instantaneous” SFZH, i.e. one where all the stellar mass is in a single age and metallicity bin.

  • Providing arrays which contain the SFH and metallicity distribution in terms of stellar mass formed.

  • Providing SFH and metallcity distribution functions (from parametric.sf_hist and parametric.metal_dist). These will be used internally to compute the arrays from the previous point.

  • Any combination of the above.

Below we simply import some packages and objects we’ll need.

[12]:
import numpy as np
from unyt import Myr

from synthesizer.parametric import SFH, Stars, ZDist

Defining an instantaneous SFZH

To define an instantaneous SFZH we need only provide the age and metallicity of the SFZH bin, alongside the SFZH axis arrays and the total initial mass of the Stars object. Note that the log10ages and log10metallicites/metallicities will likely come from a Grid object in most workflows (see the Grid docs).

[13]:
# load test_grid
grid = Grid("test_grid")
log10ages = grid.log10ages
metallicities = grid.metallicities


# Get the instantaneous Stars
inst_stars = Stars(
    log10ages,
    metallicities,
    sf_hist=105 * Myr,
    metal_dist=10**-3,
    initial_mass=10**9 * Msun,
)

To see the created SFZH you can print some basic statistics by running print directly on the Stars object.

[14]:
print(inst_stars)
+------------------------------------------------------------------------------------------------------------+
|                                                   STARS                                                    |
+--------------------------+---------------------------------------------------------------------------------+
| Attribute                | Value                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| component_type           | 'Stars'                                                                         |
+--------------------------+---------------------------------------------------------------------------------+
| fesc                     | 0.00e+00                                                                        |
+--------------------------+---------------------------------------------------------------------------------+
| fesc_ly_alpha            | 1.00                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh_normalisation       | 1.00e+09                                                                        |
+--------------------------+---------------------------------------------------------------------------------+
| is_parametric            | True                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| is_particle              | False                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages_lims           | [6.0, 11.0]                                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities_lims       | [unyt_quantity, unyt_quantity]                                                  |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.3979400086720375]                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| ages (51,)               | 1.00e+06 yr -> 1.00e+11 yr (Mean: 9.53e+09 yr)                                  |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities (13,)      | 1.00e-05 dimensionless -> 4.00e-02 dimensionless (Mean: 1.06e-02 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities (13,) | -5.00e+00 -> -1.40e+00 (Mean: -2.49e+00)                                        |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages (51,)          | 6.00e+00 -> 1.10e+01 (Mean: 8.50e+00)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sf_hist (51,)            | 0.00e+00 -> 7.88e+08 (Mean: 1.96e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| metal_dist (13,)         | 0.00e+00 -> 1.00e+09 (Mean: 7.69e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                                                               |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh (51, 13)            | 0.00e+00 -> 7.88e+08 (Mean: 1.51e+06)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sfh (51,)                | 0.00e+00 -> 7.88e+08 (Mean: 1.96e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+

Or to probe the SFZH you can plot it using the provided helper function.

[15]:
fig, ax = inst_stars.plot_sfzh(show=True)
../_images/galaxy_components_stars_30_0.png

Defining a SFZH from arrays

Of course, most of the time you won’t want an instantaneous SFZH but instead a distribution. One way to achieve this is to pass arrays describing the SFH and metallicity distribution. This is particularly useful if you have data explictly describing the ages and metallicities of a stellar population. However, here we’ll demonstrate this with entirely unphysical arrays.

[16]:
# Create arrays for SFH and ZDist
sf_hist = np.zeros_like(log10ages)
metal_dist = np.zeros_like(metallicities)
sf_hist[10:15] = 1
sf_hist[15:20] = 0.5
metal_dist[5:6] = 1
metal_dist[6:8] = 0.5

# Get the Stars
arr_stars = Stars(
    log10ages,
    metallicities,
    sf_hist=sf_hist,
    metal_dist=metal_dist,
    initial_mass=10**9 * Msun,
)
print(arr_stars)
fig, ax = arr_stars.plot_sfzh(show=True)
+------------------------------------------------------------------------------------------------------------+
|                                                   STARS                                                    |
+--------------------------+---------------------------------------------------------------------------------+
| Attribute                | Value                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| component_type           | 'Stars'                                                                         |
+--------------------------+---------------------------------------------------------------------------------+
| fesc                     | 0.00e+00                                                                        |
+--------------------------+---------------------------------------------------------------------------------+
| fesc_ly_alpha            | 1.00                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| is_parametric            | True                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| is_particle              | False                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages_lims           | [6.0, 11.0]                                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities_lims       | [unyt_quantity, unyt_quantity]                                                  |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.3979400086720375]                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| ages (51,)               | 1.00e+06 yr -> 1.00e+11 yr (Mean: 9.53e+09 yr)                                  |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities (13,)      | 1.00e-05 dimensionless -> 4.00e-02 dimensionless (Mean: 1.06e-02 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities (13,) | -5.00e+00 -> -1.40e+00 (Mean: -2.49e+00)                                        |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages (51,)          | 6.00e+00 -> 1.10e+01 (Mean: 8.50e+00)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sf_hist (51,)            | 0.00e+00 dimensionless -> 1.33e+08 dimensionless (Mean: 1.96e+07 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| metal_dist (13,)         | 0.00e+00 dimensionless -> 5.00e+08 dimensionless (Mean: 7.69e+07 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                                                               |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh (51, 13)            | 0.00e+00 dimensionless -> 6.67e+07 dimensionless (Mean: 1.51e+06 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh_normalisation       | 66666666.666666664 1/dimensionless                                              |
+--------------------------+---------------------------------------------------------------------------------+
| sfh (51,)                | 0.00e+00 dimensionless -> 1.33e+08 dimensionless (Mean: 1.96e+07 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
../_images/galaxy_components_stars_32_1.png

Defining a SFZH using functions

Synthesizer provides a suite of parametric functions to describe the SFH and metallicity distributions.

SFH parametrisations can be found in the SFH module, while metallicity distribution parametrisations can be found in the ZDist module. To see a full list of available parametrisations just print the parametrisations list from these modules`.

[17]:
print(SFH.parametrisations)
print(ZDist.parametrisations)
('Constant', 'Gaussian', 'Exponential', 'TruncatedExponential', 'DecliningExponential', 'DelayedExponential', 'LogNormal', 'DoublePowerLaw', 'DenseBasis', 'Continuity', 'ContinuityFlex', 'Dirichlet', 'ContinuityPSB', 'CombinedSFH', 'Stochastic')
('DeltaConstant', 'Normal')

To use these parametrisations you have to first define an instance of a parametrisation, and then pass it to the Stars object at instantiation. Below we demonstrate an example using a delta function for the metallicity distribution, and a constant SFH. Note that you can combine any type of SFH and metallicity distribution inputs.

[18]:
# Define a delta function for metallicity
metal_dist = ZDist.DeltaConstant(log10metallicity=-2.5)
print(metal_dist)

# Define a constant SFH
sfh = SFH.Constant(100 * Myr)
print(sfh)

# Create the Stars object
const_stars = Stars(
    log10ages,
    metallicities,
    sf_hist=sfh,
    metal_dist=metal_dist,
    initial_mass=10**9 * Msun,
)
print(const_stars)
fig, ax = const_stars.plot_sfzh(show=True)
----------
SUMMARY OF PARAMETERISED METAL ENRICHMENT HISTORY
<class 'synthesizer.parametric.metal_dist.DeltaConstant'>
metallicity: None
log10metallicity: -2.5
----------

----------
SUMMARY OF PARAMETERISED STAR FORMATION HISTORY
<class 'synthesizer.parametric.sf_hist.Constant'>
min_age: 0 yr
max_age: 100 Myr
median age: 50.00 Myr
mean age: 50.00 Myr
----------

+------------------------------------------------------------------------------------------------------------+
|                                                   STARS                                                    |
+--------------------------+---------------------------------------------------------------------------------+
| Attribute                | Value                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| component_type           | 'Stars'                                                                         |
+--------------------------+---------------------------------------------------------------------------------+
| fesc                     | 0.00e+00                                                                        |
+--------------------------+---------------------------------------------------------------------------------+
| fesc_ly_alpha            | 1.00                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| sf_hist_func             | <synthesizer.parametric.sf_hist.Constant object at 0x7fc36c61d6f0>              |
+--------------------------+---------------------------------------------------------------------------------+
| metal_dist_func          | <synthesizer.parametric.metal_dist.DeltaConstant object at 0x7fc36c61d5a0>      |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh_normalisation       | 10.00                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| is_parametric            | True                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| is_particle              | False                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages_lims           | [6.0, 11.0]                                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities_lims       | [unyt_quantity, unyt_quantity]                                                  |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.3979400086720375]                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| ages (51,)               | 1.00e+06 yr -> 1.00e+11 yr (Mean: 9.53e+09 yr)                                  |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities (13,)      | 1.00e-05 dimensionless -> 4.00e-02 dimensionless (Mean: 1.06e-02 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities (13,) | -5.00e+00 -> -1.40e+00 (Mean: -2.49e+00)                                        |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages (51,)          | 6.00e+00 -> 1.10e+01 (Mean: 8.50e+00)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sf_hist (51,)            | 0.00e+00 -> 1.85e+08 (Mean: 1.96e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| metal_dist (13,)         | 0.00e+00 -> 8.38e+08 (Mean: 7.69e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                                                               |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh (51, 13)            | 0.00e+00 -> 1.55e+08 (Mean: 1.51e+06)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sfh (51,)                | 0.00e+00 -> 1.85e+08 (Mean: 1.96e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
../_images/galaxy_components_stars_36_1.png

Instead of defining a galaxy by its initial mass—the total mass ever formed into stars — we can instead define it by its surviving stellar mass, which accounts for mass loss through stellar evolution. To enable this, you must provide a grid with the stellar_fraction attribute. At present, only certain grids include this attribute.

[19]:
# Define a delta function for metallicity
metal_dist = ZDist.DeltaConstant(log10metallicity=-2.5)
print(metal_dist)

# Define a constant SFH
sfh = SFH.Constant(100 * Myr)
print(sfh)

# Create the Stars object
const_stars2 = Stars(
    log10ages,
    metallicities,
    sf_hist=sfh,
    metal_dist=metal_dist,
    surviving_mass=10**9 * Msun,
    grid=grid,
)
print(const_stars2)
fig, ax = const_stars2.plot_sfzh(show=True)
----------
SUMMARY OF PARAMETERISED METAL ENRICHMENT HISTORY
<class 'synthesizer.parametric.metal_dist.DeltaConstant'>
metallicity: None
log10metallicity: -2.5
----------

----------
SUMMARY OF PARAMETERISED STAR FORMATION HISTORY
<class 'synthesizer.parametric.sf_hist.Constant'>
min_age: 0 yr
max_age: 100 Myr
median age: 50.00 Myr
mean age: 50.00 Myr
----------

+---------------------------------------------------------------------------------------------------------------+
|                                                     STARS                                                     |
+-----------------------------+---------------------------------------------------------------------------------+
| Attribute                   | Value                                                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| component_type              | 'Stars'                                                                         |
+-----------------------------+---------------------------------------------------------------------------------+
| fesc                        | 0.00e+00                                                                        |
+-----------------------------+---------------------------------------------------------------------------------+
| fesc_ly_alpha               | 1.00                                                                            |
+-----------------------------+---------------------------------------------------------------------------------+
| sf_hist_func                | <synthesizer.parametric.sf_hist.Constant object at 0x7fc36c61d390>              |
+-----------------------------+---------------------------------------------------------------------------------+
| metal_dist_func             | <synthesizer.parametric.metal_dist.DeltaConstant object at 0x7fc36c61c850>      |
+-----------------------------+---------------------------------------------------------------------------------+
| is_parametric               | True                                                                            |
+-----------------------------+---------------------------------------------------------------------------------+
| is_particle                 | False                                                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| log10ages_lims              | [6.0, 11.0]                                                                     |
+-----------------------------+---------------------------------------------------------------------------------+
| metallicities_lims          | [unyt_quantity, unyt_quantity]                                                  |
+-----------------------------+---------------------------------------------------------------------------------+
| log10metallicities_lims     | [-5.0, -1.3979400086720375]                                                     |
+-----------------------------+---------------------------------------------------------------------------------+
| ages (51,)                  | 1.00e+06 yr -> 1.00e+11 yr (Mean: 9.53e+09 yr)                                  |
+-----------------------------+---------------------------------------------------------------------------------+
| metallicities (13,)         | 1.00e-05 dimensionless -> 4.00e-02 dimensionless (Mean: 1.06e-02 dimensionless) |
+-----------------------------+---------------------------------------------------------------------------------+
| log10metallicities (13,)    | -5.00e+00 -> -1.40e+00 (Mean: -2.49e+00)                                        |
+-----------------------------+---------------------------------------------------------------------------------+
| log10ages (51,)             | 6.00e+00 -> 1.10e+01 (Mean: 8.50e+00)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| sf_hist (51,)               | 0.00e+00 -> 2.53e+08 (Mean: 2.54e+07)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| metal_dist (13,)            | 0.00e+00 -> 1.09e+09 (Mean: 9.97e+07)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| initial_mass                | 1296598981.5897715 Msun                                                         |
+-----------------------------+---------------------------------------------------------------------------------+
| surviving_mass              | 1000000000.0 Msun                                                               |
+-----------------------------+---------------------------------------------------------------------------------+
| stellar_fraction (51, 13)   | 3.24e-01 -> 1.00e+00 (Mean: 6.56e-01)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| sfzh (51, 13)               | 0.00e+00 -> 2.12e+08 (Mean: 1.96e+06)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| sfzh_normalisation (51, 13) | 1.00e+01 -> 3.09e+01 (Mean: 1.69e+01)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| sfh (51,)                   | 0.00e+00 -> 2.53e+08 (Mean: 2.54e+07)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
../_images/galaxy_components_stars_38_1.png

Useful Stars methods.

The Stars class includes a variety of useful methods beyond those already introduced.

Calculate the initial mass of the stars. This is the total mass of the stars that formed, before accounting for mass loss due to stellar evolution.

[20]:
initial_mass = const_stars.initial_mass
print(f"initial_mass: {initial_mass.to('Msun'):.3g}")
initial_mass: 1e+09 Msun

Calculate the surviving mass of the stars. This is the total mass of the stars that is still present at the current age, after accounting for mass loss due to stellar evolution.

[21]:
surviving_mass = const_stars.calculate_surviving_mass(grid)
print(f"surviving_mass: {surviving_mass.to('Msun'):.3g}")
print(f"remaining_fraction: {surviving_mass / initial_mass:.3g}")
surviving_mass: 7.76e+08 Msun
remaining_fraction: 0.776 dimensionless

Calculate the total mass of stars formed at some point in the past

[22]:
age = 50 * Myr

initial_mass_at_age = const_stars.calculate_initial_mass_at_age(age)
print(f"initial_mass_at_age: {initial_mass_at_age.to('Msun'):.3g}")
initial_mass_at_age: 4.97e+08 Msun

Calculate the surviving mass of stars formed at some point in the past

[23]:
age = 50 * Myr

surviving_mass_at_age = const_stars.calculate_surviving_mass_at_age(age, grid)
print(f"surviving_mass_at_age: {surviving_mass_at_age.to('Msun'):.3g}")
surviving_mass_at_age: 3.64e+08 Msun

Creating Stars Objects at Earlier Times

Parametric Stars objects provide a convenient method - get_at_earlier_time - for reconstructing the stellar population at earlier points in its evolution. This allows users to “rewind” a galaxy’s star formation and chemical enrichment history and generate a new Stars object representing the population at a specified lookback time.

[24]:
# Define a constant SFH
sfh = SFH.Constant(200 * Myr)

# Create the Stars object
const_stars3 = Stars(
    log10ages,
    metallicities,
    sf_hist=sfh,
    metal_dist=metal_dist,
    surviving_mass=10**9 * Msun,
    grid=grid,
)

# Create an earlier version of the Stars object
consts_stars3_earlier = const_stars3.get_at_earlier_time(100 * Myr)

# Compare the star formation histories
const_stars3.plot_sfh(show=True)
consts_stars3_earlier.plot_sfh(show=True)
../_images/galaxy_components_stars_49_0.png
../_images/galaxy_components_stars_49_1.png
[24]:
(<Figure size 640x480 with 1 Axes>,
 <Axes: xlabel='$\\log_{10}(\\mathrm{age}/\\mathrm{yr})$', ylabel='SFH / M$_\\odot$'>)

Combining Stars

We can also combine individual Stars objects together to produce more complicated star formation and metal enrichment histories by simply adding them.

[25]:
# Create an exponential Stars object
sfh_exp = SFH.Exponential(20 * Myr, 1000 * Myr)

exp_stars = Stars(
    log10ages,
    metallicities,
    sf_hist=sfh_exp,
    metal_dist=metal_dist,
    initial_mass=10**9 * Msun,
)

# Create a log-normal Stars object
sfh_logn = SFH.LogNormal(0.5, 100 * Myr, 3000 * Myr)

logn_stars = Stars(
    log10ages,
    metallicities,
    sf_hist=sfh_logn,
    metal_dist=0.005,
    initial_mass=10**9 * Msun,
)

combined = const_stars + exp_stars + logn_stars
print(combined)

fig, ax = combined.plot_sfzh()
combined.plot_sfh(show=True)
combined.plot_metal_dist(show=True)
+------------------------------------------------------------------------------------------------------------+
|                                                   STARS                                                    |
+--------------------------+---------------------------------------------------------------------------------+
| Attribute                | Value                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| component_type           | 'Stars'                                                                         |
+--------------------------+---------------------------------------------------------------------------------+
| fesc                     | 0.00e+00                                                                        |
+--------------------------+---------------------------------------------------------------------------------+
| fesc_ly_alpha            | 1.00                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| is_parametric            | True                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| is_particle              | False                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages_lims           | [6.0, 11.0]                                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities_lims       | [unyt_quantity, unyt_quantity]                                                  |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.3979400086720375]                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| ages (51,)               | 1.00e+06 yr -> 1.00e+11 yr (Mean: 9.53e+09 yr)                                  |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities (13,)      | 1.00e-05 dimensionless -> 4.00e-02 dimensionless (Mean: 1.06e-02 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities (13,) | -5.00e+00 -> -1.40e+00 (Mean: -2.49e+00)                                        |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages (51,)          | 6.00e+00 -> 1.10e+01 (Mean: 8.50e+00)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sf_hist (51,)            | 0.00e+00 -> 1.12e+09 (Mean: 5.88e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| metal_dist (13,)         | 0.00e+00 -> 1.68e+09 (Mean: 2.31e+08)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| initial_mass             | 3000000000.0 Msun                                                               |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh (51, 13)            | 0.00e+00 -> 8.33e+08 (Mean: 4.52e+06)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sfh (51,)                | 0.00e+00 -> 1.12e+09 (Mean: 5.88e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
../_images/galaxy_components_stars_51_1.png
../_images/galaxy_components_stars_51_2.png
../_images/galaxy_components_stars_51_3.png
[25]:
(<Figure size 640x480 with 1 Axes>,
 <Axes: xlabel='$Z$', ylabel='Z_D / M$_\\odot$'>)

Defining your own parametrisations

If synthesizer doesn’t already include a parametrisation you need, you can add a custom parametrisation by defining a new class.

The important requirements of a custom function are:

  • They inherit the Common parent class.

  • They instantiate the parent class (SFH/ZDist.Common) with the model parameters and a meaningful name.

  • They implement a private _sfr method which takes a single age and returns a single SFR weight in the SFH case, or they implement a _weight method which takes a single metallicity and returns a single metallicity weight in the ZDist case.

  • The SFH methods should perform their calculations in years.

Below we demonstrate how to define a custom function using existing SFH and metallicity distribution functions for demonstration purposes.

[26]:
class Normal(ZDist.Common):
    """A normally distributed metallicity distribution.

    Attributes:
        mean (float):
            The mean of the normal distribution.
        sigma (float):
            The standard deviation of the normal distribution.
    """

    def __init__(self, mean, sigma):
        """Initialise the metallicity distribution and parent.

        Either metallicity or log10metallicity must be provided.

        Args:
            mean (float):
                The mean of the normal distribution.
            sigma (float):
                The standard deviation of the normal distribution.
        """
        # Instantiate the parent
        ZDist.Common.__init__(
            self,
            name="Normal",
            mean=mean,
            sigma=sigma,
        )

        # Define this models parameters
        self.mean = mean
        self.sigma = sigma

    def _weight(self, metal):
        """Return the distribution at a metallicity.

        Args:
            metal (float):
                The (linear) metallicity at which to evaluate the distribution.

        Returns:
            float
                The weight of the metallicity distribution at metal.
        """
        norm = 1 / (self.sigma * np.sqrt(2 * np.pi))
        exponent = ((metal - self.mean) / self.sigma) ** 2
        return norm * np.exp(-0.5 * exponent)


class Constant(SFH.Common):
    """A constant star formation history.

    The SFR is defined such that:
        sfr = 1; t<=max_age
        sfr = 0; t>max_age

    Attributes:
        max_age (float):
            The upper age limit of constant star formation.
    """

    def __init__(self, max_age):
        """Initialise the parent and this parametrisation of the SFH.

        Args:
            max_age (unyt_quantity):
                The upper age limit of constant star formation.
        """
        # Initialise the parent
        SFH.Common.__init__(self, name="Constant", max_age=max_age)

        # Set the model parameters
        self.max_age = max_age.to("yr").value

    def _sfr(self, age):
        """Get the amount SFR weight in a single age bin.

        Args:
            age (float):
                The age (in years) at which to evaluate the SFR.
        """
        # Set the SFR based on the maximum age.
        if age <= self.max_age:
            return 1.0
        return 0.0


# Define a scaled delta function for metallicity
metal_dist = Normal(mean=0.05, sigma=0.001)
print(metal_dist)

# Define an exponential SFH
sfh = Constant(max_age=500 * Myr)
print(sfh)

# Create the Stars object
custom_stars = Stars(
    log10ages,
    metallicities,
    sf_hist=sfh,
    metal_dist=metal_dist,
    initial_mass=10**9 * Msun,
)
print(custom_stars)
fig, ax = custom_stars.plot_sfzh(show=True)
----------
SUMMARY OF PARAMETERISED METAL ENRICHMENT HISTORY
<class '__main__.Normal'>
mean: 0.05
sigma: 0.001
----------

----------
SUMMARY OF PARAMETERISED STAR FORMATION HISTORY
<class '__main__.Constant'>
max_age: 500 Myr
median age: 250.00 Myr
mean age: 250.00 Myr
----------

+------------------------------------------------------------------------------------------------------------+
|                                                   STARS                                                    |
+--------------------------+---------------------------------------------------------------------------------+
| Attribute                | Value                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| component_type           | 'Stars'                                                                         |
+--------------------------+---------------------------------------------------------------------------------+
| fesc                     | 0.00e+00                                                                        |
+--------------------------+---------------------------------------------------------------------------------+
| fesc_ly_alpha            | 1.00                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| sf_hist_func             | <__main__.Constant object at 0x7fc37ac79d80>                                    |
+--------------------------+---------------------------------------------------------------------------------+
| metal_dist_func          | <__main__.Normal object at 0x7fc37ac7a440>                                      |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh_normalisation       | 5.45e+50                                                                        |
+--------------------------+---------------------------------------------------------------------------------+
| is_parametric            | True                                                                            |
+--------------------------+---------------------------------------------------------------------------------+
| is_particle              | False                                                                           |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages_lims           | [6.0, 11.0]                                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities_lims       | [unyt_quantity, unyt_quantity]                                                  |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.3979400086720375]                                                     |
+--------------------------+---------------------------------------------------------------------------------+
| ages (51,)               | 1.00e+06 yr -> 1.00e+11 yr (Mean: 9.53e+09 yr)                                  |
+--------------------------+---------------------------------------------------------------------------------+
| metallicities (13,)      | 1.00e-05 dimensionless -> 4.00e-02 dimensionless (Mean: 1.06e-02 dimensionless) |
+--------------------------+---------------------------------------------------------------------------------+
| log10metallicities (13,) | -5.00e+00 -> -1.40e+00 (Mean: -2.49e+00)                                        |
+--------------------------+---------------------------------------------------------------------------------+
| log10ages (51,)          | 6.00e+00 -> 1.10e+01 (Mean: 8.50e+00)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sf_hist (51,)            | 0.00e+00 -> 1.85e+08 (Mean: 1.96e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| metal_dist (13,)         | 0.00e+00 -> 1.00e+09 (Mean: 7.69e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                                                               |
+--------------------------+---------------------------------------------------------------------------------+
| sfzh (51, 13)            | 0.00e+00 -> 1.85e+08 (Mean: 1.51e+06)                                           |
+--------------------------+---------------------------------------------------------------------------------+
| sfh (51,)                | 0.00e+00 -> 1.85e+08 (Mean: 1.96e+07)                                           |
+--------------------------+---------------------------------------------------------------------------------+
../_images/galaxy_components_stars_53_1.png