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                                                                             |
+-----------------------------+---------------------------------------------------------------------------------+
| ages (100,)                 | 4.95e+05 yr -> 9.83e+07 yr (Mean: 4.59e+07 yr)                                  |
+-----------------------------+---------------------------------------------------------------------------------+
| metallicities (100,)        | 4.30e-05 -> 9.85e-03 (Mean: 4.94e-03)                                           |
+-----------------------------+---------------------------------------------------------------------------------+
| initial_masses (100,)       | 1.00e+06 Msun -> 1.00e+06 Msun (Mean: 1.00e+06 Msun)                            |
+-----------------------------+---------------------------------------------------------------------------------+
| log10ages (100,)            | 5.69e+00 dimensionless -> 7.99e+00 dimensionless (Mean: 7.49e+00 dimensionless) |
+-----------------------------+---------------------------------------------------------------------------------+
| log10metallicities (100,)   | -4.37e+00 -> -2.01e+00 (Mean: -2.50e+00)                                        |
+-----------------------------+---------------------------------------------------------------------------------+
/home/runner/work/synthesizer/synthesizer/src/synthesizer/utils/ascii_table.py:67: FutureWarning: The `particle_photo_fluxes` attribute is deprecated. Use `particle_photo_fnu` instead. Will be removed in v1.0.0
  self.attributes[name] = getattr(obj, name)
/home/runner/work/synthesizer/synthesizer/src/synthesizer/utils/ascii_table.py:67: FutureWarning: The `photo_fluxes` attribute is deprecated. Use `photo_fnu` instead. Will be removed in v1.0.0
  self.attributes[name] = getattr(obj, name)
/home/runner/work/synthesizer/synthesizer/src/synthesizer/utils/ascii_table.py:67: FutureWarning: The `particle_photo_luminosities` attribute is deprecated. Use `particle_photo_lnu` instead. Will be removed in v1.0.0
  self.attributes[name] = getattr(obj, name)

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_dir = "../../../tests/test_grid"
grid_name = "test_grid"

grid = Grid(grid_name, grid_dir=grid_dir)

sfzh = stars.get_sfzh(grid.log10age, grid.log10metallicity)
sfzh.plot_sfzh()
../_images/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.log10age)
stars.plot_metal_dist(grid.metallicity)
../_images/components_stars_8_0.png
../_images/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                                                                             |
+-------------------------------+---------------------------------------------------------------------------------+
| coordinates (100, 3)          | 5.00e+01 Mpc -> 5.00e+01 Mpc (Mean: 5.00e+01 Mpc)                               |
+-------------------------------+---------------------------------------------------------------------------------+
| masses (100,)                 | 2.77e+03 Msun -> 9.98e+05 Msun (Mean: 4.96e+05 Msun)                            |
+-------------------------------+---------------------------------------------------------------------------------+
| centre                        | [50 50 50] Mpc                                                                  |
+-------------------------------+---------------------------------------------------------------------------------+
| tau_v (100,)                  | 5.20e-03 -> 9.86e-01 (Mean: 5.27e-01)                                           |
+-------------------------------+---------------------------------------------------------------------------------+
| ages (100,)                   | 4.95e+05 yr -> 9.83e+07 yr (Mean: 4.59e+07 yr)                                  |
+-------------------------------+---------------------------------------------------------------------------------+
| metallicities (100,)          | 4.30e-05 -> 9.85e-03 (Mean: 4.94e-03)                                           |
+-------------------------------+---------------------------------------------------------------------------------+
| initial_masses (100,)         | 1.00e+06 Msun -> 1.00e+06 Msun (Mean: 1.00e+06 Msun)                            |
+-------------------------------+---------------------------------------------------------------------------------+
| current_masses (100,)         | 2.77e+03 Msun -> 9.98e+05 Msun (Mean: 4.96e+05 Msun)                            |
+-------------------------------+---------------------------------------------------------------------------------+
| centered_coordinates (100, 3) | -1.42e-02 Mpc -> 1.62e-02 Mpc (Mean: 9.33e-05 Mpc)                              |
+-------------------------------+---------------------------------------------------------------------------------+
| log10ages (100,)              | 5.69e+00 dimensionless -> 7.99e+00 dimensionless (Mean: 7.49e+00 dimensionless) |
+-------------------------------+---------------------------------------------------------------------------------+
| log10metallicities (100,)     | -4.37e+00 -> -2.01e+00 (Mean: -2.50e+00)                                        |
+-------------------------------+---------------------------------------------------------------------------------+
| total_mass                    | 49581032.42875412 Msun                                                          |
+-------------------------------+---------------------------------------------------------------------------------+

Computing characteristics radii

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

[6]:
r = stars.get_half_mass_radius()
print(r)
0.008526097800247113 Mpc

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

[7]:
r = stars.get_attr_radius("tau_v")
print(r)
0.0082284378618158 Mpc

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

[8]:
r20 = stars.get_attr_radius("masses", frac=0.2)
r80 = stars.get_attr_radius("masses", frac=0.8)
print(r20, r80)
0.005909722961673986 Mpc 0.011653849729033798 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.

[9]:
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.004939952181144108
0.00513123597552142
-2.448332309728657

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

[10]:
print(stars.get_mass_weighted_age())
print(stars.get_mass_weighted_metallicity())
print(stars.get_mass_weighted_optical_depth())
45918096.01152092 yr
0.004939952181144108
0.5274379707924111

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.

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.

[11]:
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).

[12]:
# Create the SFZH axis arrays
log10ages = np.arange(6.0, 10.5, 0.1)  # log10(age/yr)
log10metallicities = np.arange(-5.0, -1.5, 0.25)
metallicities = 10**log10metallicities

# 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.

[13]:
print(inst_stars)
+---------------------------------------------------------------------------+
|                                   STARS                                   |
+--------------------------+------------------------------------------------+
| Attribute                | Value                                          |
+--------------------------+------------------------------------------------+
| component_type           | 'Stars'                                        |
+--------------------------+------------------------------------------------+
| fesc                     | 0.00e+00                                       |
+--------------------------+------------------------------------------------+
| fesc_ly_alpha            | 1.00                                           |
+--------------------------+------------------------------------------------+
| metallicity_grid_type    | 'log10Z'                                       |
+--------------------------+------------------------------------------------+
| log10ages_lims           | [6.0, 10.399999999999984]                      |
+--------------------------+------------------------------------------------+
| metallicities_lims       | [1e-05, 0.01778279410038923]                   |
+--------------------------+------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.75]                                  |
+--------------------------+------------------------------------------------+
| ages (45,)               | 1.00e+06 yr -> 2.51e+10 yr (Mean: 2.71e+09 yr) |
+--------------------------+------------------------------------------------+
| metallicities (14,)      | 1.00e-05 -> 1.78e-02 (Mean: 2.90e-03)          |
+--------------------------+------------------------------------------------+
| sf_hist (45,)            | 0.00e+00 -> 7.88e+08 (Mean: 2.22e+07)          |
+--------------------------+------------------------------------------------+
| metal_dist (14,)         | 0.00e+00 -> 1.00e+09 (Mean: 7.14e+07)          |
+--------------------------+------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                              |
+--------------------------+------------------------------------------------+
| sfzh (45, 14)            | 0.00e+00 -> 7.88e+08 (Mean: 1.59e+06)          |
+--------------------------+------------------------------------------------+
| log10ages (45,)          | 6.00e+00 -> 1.04e+01 (Mean: 8.20e+00)          |
+--------------------------+------------------------------------------------+
| log10metallicities (14,) | -5.00e+00 -> -1.75e+00 (Mean: -3.38e+00)       |
+--------------------------+------------------------------------------------+
/home/runner/work/synthesizer/synthesizer/src/synthesizer/utils/ascii_table.py:67: FutureWarning: The `photo_luminosities` attribute is deprecated. Use `photo_lnu` instead. Will be removed in v1.0.0
  self.attributes[name] = getattr(obj, name)

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

[14]:
fig, ax = inst_stars.plot_sfzh(show=True)
../_images/components_stars_28_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.

[15]:
# 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                                           |
+--------------------------+------------------------------------------------+
| metallicity_grid_type    | 'log10Z'                                       |
+--------------------------+------------------------------------------------+
| log10ages_lims           | [6.0, 10.399999999999984]                      |
+--------------------------+------------------------------------------------+
| metallicities_lims       | [1e-05, 0.01778279410038923]                   |
+--------------------------+------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.75]                                  |
+--------------------------+------------------------------------------------+
| ages (45,)               | 1.00e+06 yr -> 2.51e+10 yr (Mean: 2.71e+09 yr) |
+--------------------------+------------------------------------------------+
| metallicities (14,)      | 1.00e-05 -> 1.78e-02 (Mean: 2.90e-03)          |
+--------------------------+------------------------------------------------+
| sf_hist (45,)            | 0.00e+00 -> 1.00e+00 (Mean: 1.67e-01)          |
+--------------------------+------------------------------------------------+
| metal_dist (14,)         | 0.00e+00 -> 1.00e+00 (Mean: 1.43e-01)          |
+--------------------------+------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                              |
+--------------------------+------------------------------------------------+
| sfzh (45, 14)            | 0.00e+00 -> 6.67e+07 (Mean: 1.59e+06)          |
+--------------------------+------------------------------------------------+
| log10ages (45,)          | 6.00e+00 -> 1.04e+01 (Mean: 8.20e+00)          |
+--------------------------+------------------------------------------------+
| log10metallicities (14,) | -5.00e+00 -> -1.75e+00 (Mean: -3.38e+00)       |
+--------------------------+------------------------------------------------+
../_images/components_stars_30_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`.

[16]:
print(SFH.parametrisations)
print(ZDist.parametrisations)
('Constant', 'Gaussian', 'Exponential', 'TruncatedExponential', 'DecliningExponential', 'DelayedExponentialLogNormal', 'DoublePowerLaw', 'DenseBasis')
('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.

[17]:
# 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 0x7f8ff23ef100>         |
+--------------------------+----------------------------------------------------------------------------+
| metal_dist_func          | <synthesizer.parametric.metal_dist.DeltaConstant object at 0x7f8ff23ef4c0> |
+--------------------------+----------------------------------------------------------------------------+
| metallicity_grid_type    | 'log10Z'                                                                   |
+--------------------------+----------------------------------------------------------------------------+
| log10ages_lims           | [6.0, 10.399999999999984]                                                  |
+--------------------------+----------------------------------------------------------------------------+
| metallicities_lims       | [1e-05, 0.01778279410038923]                                               |
+--------------------------+----------------------------------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.75]                                                              |
+--------------------------+----------------------------------------------------------------------------+
| ages (45,)               | 1.00e+06 yr -> 2.51e+10 yr (Mean: 2.71e+09 yr)                             |
+--------------------------+----------------------------------------------------------------------------+
| metallicities (14,)      | 1.00e-05 -> 1.78e-02 (Mean: 2.90e-03)                                      |
+--------------------------+----------------------------------------------------------------------------+
| sf_hist (45,)            | 0.00e+00 -> 1.85e+08 (Mean: 2.22e+07)                                      |
+--------------------------+----------------------------------------------------------------------------+
| metal_dist (14,)         | 0.00e+00 -> 1.00e+09 (Mean: 7.14e+07)                                      |
+--------------------------+----------------------------------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                                                          |
+--------------------------+----------------------------------------------------------------------------+
| sfzh (45, 14)            | 0.00e+00 -> 1.85e+08 (Mean: 1.59e+06)                                      |
+--------------------------+----------------------------------------------------------------------------+
| log10ages (45,)          | 6.00e+00 -> 1.04e+01 (Mean: 8.20e+00)                                      |
+--------------------------+----------------------------------------------------------------------------+
| log10metallicities (14,) | -5.00e+00 -> -1.75e+00 (Mean: -3.38e+00)                                   |
+--------------------------+----------------------------------------------------------------------------+
/opt/hostedtoolcache/Python/3.10.16/x64/lib/python3.10/site-packages/unyt/array.py:1832: RuntimeWarning: divide by zero encountered in log10
  out_arr = func(np.asarray(inp), out=out_func, **kwargs)
../_images/components_stars_34_2.png

Combining Stars

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

[18]:
# 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                                           |
+--------------------------+------------------------------------------------+
| metallicity_grid_type    | 'log10Z'                                       |
+--------------------------+------------------------------------------------+
| log10ages_lims           | [6.0, 10.399999999999984]                      |
+--------------------------+------------------------------------------------+
| metallicities_lims       | [1e-05, 0.01778279410038923]                   |
+--------------------------+------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.75]                                  |
+--------------------------+------------------------------------------------+
| ages (45,)               | 1.00e+06 yr -> 2.51e+10 yr (Mean: 2.71e+09 yr) |
+--------------------------+------------------------------------------------+
| metallicities (14,)      | 1.00e-05 -> 1.78e-02 (Mean: 2.90e-03)          |
+--------------------------+------------------------------------------------+
| sf_hist (45,)            | 0.00e+00 -> 1.12e+09 (Mean: 6.67e+07)          |
+--------------------------+------------------------------------------------+
| metal_dist (14,)         | 0.00e+00 -> 2.25e+09 (Mean: 2.14e+08)          |
+--------------------------+------------------------------------------------+
| initial_mass             | 3000000000.0 Msun                              |
+--------------------------+------------------------------------------------+
| sfzh (45, 14)            | 0.00e+00 -> 1.03e+09 (Mean: 4.76e+06)          |
+--------------------------+------------------------------------------------+
| log10ages (45,)          | 6.00e+00 -> 1.04e+01 (Mean: 8.20e+00)          |
+--------------------------+------------------------------------------------+
| log10metallicities (14,) | -5.00e+00 -> -1.75e+00 (Mean: -3.38e+00)       |
+--------------------------+------------------------------------------------+
../_images/components_stars_36_1.png
../_images/components_stars_36_2.png
../_images/components_stars_36_3.png
[18]:
(<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.

[19]:
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<=duration
        sfr = 0; t>duration

    Attributes:
        duration (float)
            The duration of the period of constant star formation.
    """

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

        Args:
            duration (unyt_quantity)
                The duration of the period of constant star formation.
        """

        # Initialise the parent
        SFH.Common.__init__(self, name="Constant", duration=duration)

        # Set the model parameters
        self.duration = duration.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 duration.
        if age <= self.duration:
            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(duration=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'>
duration: 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 0x7f8ff23cb2e0>   |
+--------------------------+------------------------------------------------+
| metal_dist_func          | <__main__.Normal object at 0x7f9002779b10>     |
+--------------------------+------------------------------------------------+
| metallicity_grid_type    | 'log10Z'                                       |
+--------------------------+------------------------------------------------+
| log10ages_lims           | [6.0, 10.399999999999984]                      |
+--------------------------+------------------------------------------------+
| metallicities_lims       | [1e-05, 0.01778279410038923]                   |
+--------------------------+------------------------------------------------+
| log10metallicities_lims  | [-5.0, -1.75]                                  |
+--------------------------+------------------------------------------------+
| ages (45,)               | 1.00e+06 yr -> 2.51e+10 yr (Mean: 2.71e+09 yr) |
+--------------------------+------------------------------------------------+
| metallicities (14,)      | 1.00e-05 -> 1.78e-02 (Mean: 2.90e-03)          |
+--------------------------+------------------------------------------------+
| sf_hist (45,)            | 0.00e+00 -> 1.85e+08 (Mean: 2.22e+07)          |
+--------------------------+------------------------------------------------+
| metal_dist (14,)         | 0.00e+00 -> 1.00e+09 (Mean: 7.14e+07)          |
+--------------------------+------------------------------------------------+
| initial_mass             | 1000000000.0 Msun                              |
+--------------------------+------------------------------------------------+
| sfzh (45, 14)            | 0.00e+00 -> 1.85e+08 (Mean: 1.59e+06)          |
+--------------------------+------------------------------------------------+
| log10ages (45,)          | 6.00e+00 -> 1.04e+01 (Mean: 8.20e+00)          |
+--------------------------+------------------------------------------------+
| log10metallicities (14,) | -5.00e+00 -> -1.75e+00 (Mean: -3.38e+00)       |
+--------------------------+------------------------------------------------+
../_images/components_stars_38_1.png