Skip to content

Commit 920edef

Browse files
maxbrielHeloiseSfindesghMartin Glatzle
authored
Complex Stellar Populations (#64)
This submodule introduces the possibility to create Complex Stellar Populations with BPASS data. The two main modules are `csp.eventrate` and `csp.spectra` `csp.eventrate` contains the `CSPEventRate` class, which can be used to calculate event rates from a given Stellar Formation History and Metallicity evolution. The following methods are available in this class: `at_time`: calculates the event rates at a given lookback time. `over_time`: calculates the event rates over a lookback time (binned). `grid_at_time`: alternative input. Takes a grid of points instead of a function. Does the same as at_time. `grid_over_time`: alternative input. Takes a grid of points instead of a function. Does the same as over_time. `csp.spectra` contains the `CSPSpectra` class, which can be used to calculate synthetic spectra for the given population. The same methods are available in this class as `CSPEventRate`, but provide spectra rather than even rates. `csp.sfh` contains a class with which a Stellar Formation History (SFH) can be made. A collection of common parametric SFH are available (see documentation), but a custom one can also be given. As support for these high level functions, a collection of utility and helper functions has been added. These can be found in `csp.utils`. Some these are optimised for performance (`numba` JIT compiled) and are not user friendly. * Created CSP archistecture and basic sfh class * Added variables to constants * implements utility functions & new test files * Implements event rate calculation over time * BPASS data_files for testing file_loading * Adds `at_time` function to the event rate class * Adds docstrings and extra tests * Implements calculate spectrum at_time and over_time functions * Add normalisation function for the BPASS spectrum * fixed hrd plot * adding csp folder * minor changes * Moved tests to CSP folder + fix in function name _type_check * added a hokitype error * Added some code review for Max and minor stylistic changes * Added some code review for Max and minor stylistic changes * Updated the tests * bla * Adjust tests and docstrings * Adjust eventrate functions to take lists of functions * Disabled spectra test * Added parametric star formation histories to SFH and refactored some variable names * fixing CI * Auto stash before merge of "csp" and "official_hoki/csp" * upload files for remote work * Improve testing and functions * Add SpectraCompiler test * Adds extensive tests for the CSP package * Update SpectraCompiler * Documentation update + SFH input * Removed CSP from utils due to cyclical import * Updated setup.cfg to include csp_test_data subfolder * Removes leftover print statement + prints loading precompiled failed * Correct metallicity mid-points * Added the parametric star formation histories as public functions * at_time new default sample rate + load functions moved to hoki.load * Fixed typo * Removes cyclical import * Adjusted tests that use SpectraCompiler * Getting tox to work * private optimised mass_per_time_bin calculation * Refactored Event Rate calculation from array data * Removed dependency and added more doc information * BUG: pass on kwarg to spectra compiler. * Fix SpectraCompiler * BUG: use np instead of pd in SpectraCompiler. * BUG: fix index and make test pass. * BUG: fix another regression bug. * Fix further regression bug. * Clean up loading module * Updates mass per bin calculation for vectorized funciton input * Renames CSPEventRate functions and adds grid functions * np.zeros to np.empty where possible * Fixed incorrect test of at_time and over_time * Set default sample rate for at_time * Adds `cache` parameter to over_time_spectrum * Adds grid functions for the spectra calculation * Adds return_time_edges to grid_over_time & bug fix sfh vectorisation * Bug fix in nr_time_bins (grid_over_time functions) * Docs string cleanup * Solve cyclical import error * Fix tox and remove corner plot * File check, combined data_compiler tests, renames func+variables Co-authored-by: Max Briel <max.briel@auckland.ac.nz> Co-authored-by: heloises <heloisefw@gmail.com> Co-authored-by: Heloise <HeloiseS@users.noreply.github.com> Co-authored-by: findesgh <findessp@yandex.ru> Co-authored-by: Martin Glatzle <mglatzle@mpa-garching.mpg.de>
1 parent cfbacab commit 920edef

34 files changed

+3875
-36
lines changed

.github/workflows/testing.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ on:
99

1010
pull_request:
1111

12-
1312
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
1413
jobs:
1514
# This workflow contains a single job called "build"

README.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ This way it'll show you each test as they pass or FAIL. In the pip and github ve
5858

5959
.. code-block:: none
6060
61-
62-
`astropy`, `numpy`, `pandas`, `matplotlib`, `pyyaml`, `wheel`, `emcee`, `corner`
61+
`astropy`, `numpy`, `pandas`, `matplotlib`, `pyyaml`, `wheel`, `emcee`, `corner`, `numba`
6362
6463
**Note:** Python 2 is not supported
6564

hoki/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,3 @@ class UnsupportedPythonError(Exception):
3333
#__all__ += ['module_input', 'module_output']
3434
# or you can keep everything from the subpackage with the following instead
3535
# __all__ += example_mod.__all__
36-

hoki/age_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ def calculate_distributions_dt_divided(obs_df, model):
480480
# We add the time bins in there because it can make plotting extra convenient.
481481
# distributions_df['time_bins'] = hoki.constants.BPASS_TIME_BINS
482482

483+
483484
return likelihoods_df
484485

485486

@@ -490,7 +491,7 @@ def calculate_distributions_dt_divided(obs_df, model):
490491

491492
def calculate_sample_pdf(distributions_df, not_you=None):
492493
"""
493-
Multiplies together all the columns in given in DataFrame apart from the "time_bins" column
494+
Multiplies together all the columns in given in DataFrame apart from the "time_axis" column
494495
495496
Parameters
496497
----------

hoki/constants.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,23 @@
2323
OUTPUTS_PATH = settings['outputs_path'] # This constant for dev purposes.
2424
BPASS_TIME_BINS = np.arange(6.0, 11.1, 0.1)
2525
BPASS_TIME_INTERVALS = np.array([10**(t+0.05) - 10**(t-0.05) for t in BPASS_TIME_BINS])
26-
BPASS_TIME_WEIGHT_GRID = np.array([np.zeros((100,100)) + dt for dt in BPASS_TIME_INTERVALS])
26+
BPASS_TIME_WEIGHT_GRID = np.array([np.zeros((100, 100)) + dt for dt in BPASS_TIME_INTERVALS])
27+
28+
BPASS_LINEAR_TIME_EDGES = np.append([0.0], 10**np.arange(6.05, 11.15, 0.1))
29+
BPASS_LINEAR_TIME_INTERVALS = np.diff(BPASS_LINEAR_TIME_EDGES)
30+
31+
BPASS_METALLICITIES = ["zem5", "zem4", "z001","z002", "z003", "z004", "z006", "z008", "z010", "z014", "z020", "z030", "z040"]
32+
BPASS_NUM_METALLICITIES = np.array([0.00001, 0.0001, 0.001, 0.002, 0.003, 0.004, 0.006, 0.008, 0.010,
33+
0.014, 0.020, 0.030, 0.040])
34+
BPASS_METALLICITY_MID_POINTS = (BPASS_NUM_METALLICITIES[1:] + BPASS_NUM_METALLICITIES[:-1])/2
35+
36+
BPASS_EVENT_TYPES = ["Ia", "IIP", "II", "Ib", "Ic", "LGRB", "PISNe", "low_mass"]
37+
HOKI_NOW = 13.799e9
38+
39+
BPASS_IMFS = ["imf_chab100", "imf_chab300", "imf100_100", "imf100_300",
40+
"imf135_100", "imf135_300", "imf135all_100", "imf170_100",
41+
"imf170_300"]
42+
2743

2844
# Create a deprecation warning when using dummy_dict
2945
dummy_dict = {'timestep': 0, 'age': 1, 'log(R1)': 2, 'log(T1)': 3, 'log(L1)': 4, 'M1': 5, 'He_core1': 6, 'CO_core1': 7,
@@ -202,4 +218,3 @@ def set_default_bpass_version(version):
202218

203219
print('Looks like everything went well! You can check the path was correctly updated by looking at this file:'
204220
'\n'+path_to_settings)
205-

hoki/csp/__init__.py

Whitespace-only changes.

hoki/csp/csp.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
"""
2+
Author: Max Briel
3+
4+
Parent class of a complex stellar population
5+
"""
6+
7+
from hoki.csp.sfh import SFH
8+
from hoki.utils.exceptions import HokiTypeError, HokiFormatError
9+
from hoki.constants import HOKI_NOW
10+
11+
12+
############################################
13+
# Complex Stellar Populations Parent Class #
14+
############################################
15+
16+
17+
class CSP(object):
18+
"""
19+
Complex Stellar Population class
20+
21+
Notes
22+
-----
23+
Parent class for `CSPEventRate` and `CSPSpectra`
24+
25+
Attributes
26+
----------
27+
now : `float`
28+
The age of the universe.
29+
"""
30+
now = HOKI_NOW
31+
32+
def __init__(self):
33+
pass
34+
35+
def _type_check_histories(self, sfh, zeh):
36+
"""
37+
Function to check sfh and zeh are the correct type and transform them
38+
into a consistent format.
39+
40+
Notes
41+
-----
42+
sfh and zeh can either be a callable python function or a list of
43+
callables.
44+
45+
Input
46+
-----
47+
sfh
48+
Stellar formation history
49+
zeh
50+
Z evolution history
51+
52+
Returns
53+
-------
54+
`tuple` ([sfh callables,], [zeh callables,])
55+
A tuple containing the sfh callables and zeh callables as arrays.
56+
"""
57+
# Check sfh list
58+
if isinstance(sfh, list):
59+
60+
# check if zeh is also a list
61+
if isinstance(zeh, list):
62+
# have to be equal lengths
63+
if len(sfh) == len(zeh):
64+
# have to be all callables
65+
if (all(callable(val) for val in sfh) and all(callable(val) for val in zeh)):
66+
return (sfh, zeh)
67+
# A non-callable is present
68+
else:
69+
raise HokiTypeError(
70+
"SFH or ZEH contains an object that's not a SFH object or function.")
71+
# sfh and zeh are not equal length
72+
else:
73+
raise HokiFormatError(
74+
"sfh_functions and Z_functions must have the same length.")
75+
# zeh is not a list
76+
else:
77+
# sfh has to be 1 length and a callable, zeh has to be a callable
78+
if len(sfh) == 1:
79+
if (callable(sfh[0]) and callable(zeh)):
80+
81+
return (sfh, [zeh])
82+
else:
83+
raise HokiTypeError(
84+
"SFH or ZEH contains an object that's not a SFH object or python callable.")
85+
else:
86+
raise HokiFormatError(
87+
"SFH must have length 1, be a python callable, or a SFH object.")
88+
# sfh is a callable
89+
elif callable(sfh):
90+
# zeh is a list
91+
if isinstance(zeh, list):
92+
# list has to be 1 long, because sfh is callable
93+
if len(zeh) == 1:
94+
return ([sfh], zeh)
95+
# list it too long
96+
else:
97+
raise HokiFormatError(
98+
"ZEH must be either length 1 or a python callable")
99+
100+
# zeh is also a callable return
101+
elif callable(zeh):
102+
return ([sfh], [zeh])
103+
else:
104+
raise HokiTypeError(
105+
"ZEH is not a python callable or a list of callables.")
106+
# sfh cannot be identified
107+
else:
108+
raise HokiTypeError(
109+
"SFH type is not a python callable or a SFH object."
110+
)

0 commit comments

Comments
 (0)