Source code for snewpy.models.ccsn

# -*- coding: utf-8 -*-
"""
The submodule ``snewpy.models.ccsn`` contains models of core-collapse supernovae
derived from the :class:`SupernovaModel` base class.

Since SNEWPY v1.3, the prefered method is to initialise a model based on its physics parameters.
Initialisation from a file name is deprecated.

Use the ``param`` class property to view all physics parameters and their possible values:

>>> from snewpy.models.ccsn import Nakazato_2013
>>> Nakazato_2013.param
{'progenitor_mass': <Quantity [13., 20., 30., 50.] solMass>,
 'revival_time': <Quantity [  0., 100., 200., 300.] ms>,
 'metallicity': [0.02, 0.004],
 'eos': ['LS220', 'shen', 'togashi']}

For some models, not all combinations of parameters are valid. Use the ``get_param_combinations()``
class method to get a list of all valid combinations and filter it:

>>> list(params for params in Nakazato_2013.get_param_combinations() if params['eos'] != 'shen')
[{'progenitor_mass': <Quantity 30. solMass>, 'revival_time': <Quantity 0. ms>,
  'metallicity': 0.004, 'eos': 'LS220'},
 {'progenitor_mass': <Quantity 30. solMass>, 'revival_time': <Quantity 0. ms>,
  'metallicity': 0.004, 'eos': 'togashi'}]

.. _Garching Supernova Archive: https://wwwmpa.mpa-garching.mpg.de/ccsnarchive/

"""
import logging
import os
import re
import tarfile

import numpy as np
from astropy import units as u
from astropy.table import Table

from snewpy.models import ccsn_loaders as loaders
from .base import PinchedModel

from snewpy.models.registry_model import RegistryModel, Parameter
from snewpy.models.registry_model import deprecated, legacy_filename_initialization
from snewpy.models.registry_model import all_models
from textwrap import dedent


[docs] @RegistryModel() class Fischer_2020(loaders.Fischer_2020): """Model based on simulations from `Fischer et al. (2020) <https://arxiv.org/abs/1804.10890>` """ def __init__(self): self.metadata["EOS"] = "HS(DD2)" self.metadata["Progenitor mass"] = 18 * u.Msun filename='Fischer_2020.tar.gz' return super().__init__(filename, metadata=self.metadata)
[docs] @legacy_filename_initialization @RegistryModel( progenitor_mass = [13, 20, 30, 50] * u.Msun, revival_time = [0, 100, 200, 300] * u.ms, metallicity = [0.02, 0.004], eos = ['LS220', 'shen', 'togashi'], _param_validator = lambda p: (p['revival_time'] == 0 * u.ms and p['progenitor_mass'] == 30 * u.Msun and p['metallicity'] == 0.004) or \ (p['revival_time'] != 0 * u.ms and p['eos'] == 'shen' and not (p['progenitor_mass'] == 30 * u.Msun and p['metallicity'] == 0.004)) ) class Nakazato_2013(loaders.Nakazato_2013): """Model based on simulations from Nakazato et al., ApJ S 205:2 (2013), ApJ 804:75 (2015), PASJ 73:639 (2021). See also http://asphwww.ph.noda.tus.ac.jp/snn/. """ def _metadata_from_filename(self, filename:str)->dict: metadata = {'Progenitor mass': float(filename.split('-')[-1].strip('s%.fits')) * u.Msun} if 't_rev' in filename: metadata.update({ 'EOS': filename.split('-')[-4].upper(), 'Metallicity': float(filename.split('-')[-3].strip('z%')), 'Revival time': float(filename.split('-')[-2].strip('t_rev%ms')) * u.ms }) # No revival time because the explosion "failed" (BH formation). else: metadata.update({ 'EOS': filename.split('-')[-4].upper(), 'Metallicity': float(filename.split('-')[-2].strip('z%')), 'Revival time': 0 * u.ms }) return metadata def __init__(self, progenitor_mass:u.Quantity, revival_time:u.Quantity, metallicity:float, eos:str): # Strip units for filename construction progenitor_mass = progenitor_mass.to(u.Msun).value revival_time = revival_time.to(u.ms).value if revival_time != 0: filename = f"nakazato-{eos}-z{metallicity}-t_rev{int(revival_time)}ms-s{progenitor_mass:3.1f}.fits" else: filename = f"nakazato-{eos}-BH-z{metallicity}-s{progenitor_mass:3.1f}.fits" #modify metadata if needed... #self.metadata['name']=value return super().__init__(filename, self.metadata)
[docs] @legacy_filename_initialization @RegistryModel( progenitor_mass = [27., 9.6] * u.Msun, eos = ['LS220', 'SFHo'] ) class Sukhbold_2015(loaders.Sukhbold_2015): """Model based on simulations from Sukhbold et al., ApJ 821:38,2016. Models were shared privately by email. """ def _metadata_from_filename(self, filename:str): metadata = { 'Progenitor mass': float(filename.split('-')[-1].strip('z%.fits')) * u.Msun, 'EOS': filename.split('-')[-2] } return metadata def __init__(self, progenitor_mass:u.Quantity, eos:str): if progenitor_mass.value == 9.6: filename = f'sukhbold-{eos}-z{progenitor_mass.value:3.1f}.fits' else: filename = f'sukhbold-{eos}-s{progenitor_mass.value:3.1f}.fits' return super().__init__(filename, self.metadata)
[docs] @deprecated('eos') @legacy_filename_initialization @RegistryModel( progenitor_mass = [11.2, 20., 27.] * u.Msun, direction = [1,2,3], eos=['LS220'], _param_validator = lambda p: (p['progenitor_mass'] == 11.2 * u.Msun and p['direction'] in (1,)) or \ (p['progenitor_mass'] == 20. * u.Msun and p['direction'] in (1,)) or \ (p['progenitor_mass'] == 27. * u.Msun and p['direction'] in (1,2,3)) ) class Tamborra_2014(loaders.Tamborra_2014): """Model based on 3D simulations from `Tamborra et al., PRD 90:045032, 2014 <https://arxiv.org/abs/1406.0006>`_. Data files are from the `Garching Supernova Archive`_. """ def __init__(self, *, progenitor_mass:u.Quantity, direction:int): filename = f's{progenitor_mass.value:3.1f}c_3D_dir{direction}' # Metadata is handled by __init__ in _GarchingArchiveModel return super().__init__(filename=filename, metadata=self.metadata)
[docs] @deprecated('eos') @legacy_filename_initialization @RegistryModel( progenitor_mass= [11.2, 27.] * u.Msun, eos = ['LS220'] ) class Bollig_2016(loaders.Bollig_2016): """Model based on simulations from `Bollig et al. (2016) <https://arxiv.org/abs/1508.00785>`_. Models were taken, with permission, from the `Garching Supernova Archive`_. """ def __init__(self, progenitor_mass:u.Quantity, eos:str='LS220'): filename = f's{progenitor_mass.value:3.1f}c' return super().__init__(filename=filename, metadata=self.metadata)
[docs] @deprecated('eos') @legacy_filename_initialization @RegistryModel( progenitor_mass = [15.] * u.Msun, rotation = ['fast','slow','non'], direction = [1,2,3], eos=['LS220'] ) class Walk_2018(loaders.Walk_2018): """Model based on SASI-dominated simulations from `Walk et al., PRD 98:123001, 2018 <https://arxiv.org/abs/1807.02366>`_. Data files are from the `Garching Supernova Archive`_. """ def __init__(self, *, progenitor_mass:u.Quantity, rotation:str, direction:int): filename = f's{progenitor_mass.value:3.1f}c_3D_{rotation}rot_dir{direction}' return super().__init__(filename=filename, metadata=self.metadata)
[docs] @deprecated('eos') @legacy_filename_initialization @RegistryModel( progenitor_mass = [40., 75.] * u.Msun, direction = [1,2,3], eos=['LS220'], _param_validator = lambda p: (p['progenitor_mass'] == 75. * u.Msun and p['direction'] in (1,2)) or \ (p['progenitor_mass'] == 40. * u.Msun and p['direction'] in (1,2,3)) ) class Walk_2019(loaders.Walk_2019): """Model based on SASI-dominated simulations from `Walk et al., PRD 101:123013, 2019 <https://arxiv.org/abs/1910.12971>`_. Data files are from the `Garching Supernova Archive`_. """ def __init__(self, * ,progenitor_mass:u.Quantity, direction:int): filename = f's{progenitor_mass.value:3.1f}c_3DBH_dir{direction}' return super().__init__(filename=filename, metadata=self.metadata)
@RegistryModel( progenitor_mass = Parameter(values=(list(range(12, 34)) + list(range(35, 61, 5)) + [70, 80, 100, 120]) * u.Msun, desc_values='[12..33, 35..5..60, 70, 80, 100, 120] solMass' ), eos = ['HShen', 'LS220'] ) class _OConnor_2013_new(loaders.OConnor_2013): """Model based on the black hole formation simulation in `O'Connor & Ott (2013) <https://arxiv.org/abs/1207.1100>`_. """ def __init__(self, eos:str, progenitor_mass:u.Quantity): # Load from Parameters filename = f'{eos}_timeseries.tar.gz' return super().__init__(filename=filename, metadata=self.metadata)
[docs] class OConnor_2013(legacy_filename_initialization(_OConnor_2013_new)): _config_path='ccsn.OConnor_2013' @deprecated('base', 'mass') def __init__(self, base=None, mass=None, eos='LS220', *, progenitor_mass=None): """ Parameters ---------- base : str Absolute or relative path folder with model data. This argument is deprecated. mass: int Mass of model progenitor in units Msun. This argument is deprecated. """ if mass: progenitor_mass = mass*u.Msun if base: self.metadata = {'Progenitor mass': progenitor_mass, 'EOS': eos} filename = f'{base}/{eos}_timeseries.tar.gz' return super().__init__(filename=filename, eos=eos, progenitor_mass=progenitor_mass) else: return super().__init__(eos=eos, progenitor_mass=progenitor_mass)
OConnor_2013.__init__.__doc__=dedent(OConnor_2013.__init__.__doc__)+_OConnor_2013_new.__init__.__doc__ #make sure that only the latest class is present in the models table all_models.remove(OConnor_2013.__mro__[1]) all_models.add(OConnor_2013)
[docs] @deprecated('eos') @legacy_filename_initialization @RegistryModel( progenitor_mass = [40 * u.Msun], eos=['LS220'] ) class OConnor_2015(loaders.OConnor_2015): """Model based on the black hole formation simulation in `O'Connor (2015) <https://arxiv.org/abs/1411.7058>`_. """ def __init__(self, progenitor_mass:u.Quantity): # Filename is currently the same regardless of parameters filename = 'M1_neutrinos.dat' return super().__init__(filename, self.metadata)
[docs] @deprecated('eos') @legacy_filename_initialization @RegistryModel( progenitor_mass = Parameter(values=(list(range(16, 27)) + [19.89, 22.39, 30, 33]) * u.Msun, desc_values = '[16..26, 19.89, 22.39, 30, 33] solMass' ), eos = ['STOS_B145'] ) class Zha_2021(loaders.Zha_2021): """Model based on the hadron-quark phse transition models from `Zha et al. 2021 <https://arxiv.org/abs/2103.02268>`_. """ def _metadata_from_filename(self, filename:str)->dict: metadata = {'Progenitor mass': float(os.path.splitext(os.path.basename(filename))[0][1:]) * u.Msun} return metadata def __init__(self, *, progenitor_mass:u.Quantity): filename = f's{progenitor_mass.value:g}.dat' return super().__init__(filename, self.metadata)
[docs] @deprecated('eos') @legacy_filename_initialization @RegistryModel( progenitor_mass=Parameter(np.concatenate((np.linspace(9.0, 12.75, 16), np.linspace(13, 30., 171), np.linspace(31., 33., 3), np.linspace(35, 55, 5), np.linspace(60, 80, 3), np.linspace(100, 120, 2))) << u.Msun, desc_values='[9..0.25..13, 13..0.1..30, 31..33, 35..5..60, 70, 80, 100, 120] solMass'), turbmixing_param= Parameter([1.23, 1.25, 1.27], name='turbmixing_param', label='Turb. mixing param.', description='Turbulent mixing parameter alpha_lambda', ), eos=['SFHo'] ) class Warren_2020(loaders.Warren_2020): """Model based on simulations from Warren et al., ApJ 898:139, 2020. Neutrino fluxes available at https://doi.org/10.5281/zenodo.3667908.""" # TODO: (For v2.0) Resolve Zenodo issues (Missing files) # np.arange with decimal increments can produce floating point errors # Though it may be more intuitive to use np.arange, these fp-errors quickly become troublesome def _metadata_from_filename(self, filename:str)->dict: _, _, turbmixing_param, progenitor_mass = os.path.splitext(os.path.basename(filename))[0].split('_') metadata = {'Progenitor mass': float(progenitor_mass[1:]) * u.Msun, 'Turb. mixing param.': float(turbmixing_param[1:]), 'EOS': 'SFHo'} return metadata def __init__(self, *, progenitor_mass, turbmixing_param): if progenitor_mass.value.is_integer() and progenitor_mass.value <= 30.: fname = f'stir_a{turbmixing_param:3.2f}/stir_multimessenger_a{turbmixing_param:3.2f}_m{progenitor_mass.value:.1f}.h5' else: fname = f'stir_a{turbmixing_param:3.2f}/stir_multimessenger_a{turbmixing_param:3.2f}_m{progenitor_mass.value:g}.h5' return super().__init__(fname, self.metadata)
[docs] @deprecated('eos','mass') @legacy_filename_initialization @RegistryModel( rotational_velocity= [0, 1] * u.rad / u.s, magnetic_field_exponent= Parameter([0, 12, 13], label='B_0 Exponent', description='Exponent of magnetic field (See Eq. 46)'), eos=['LS220'], progenitor_mass=[20*u.Msun], _param_validator = lambda p: (p['rotational_velocity'].value == 1 and p['magnetic_field_exponent'] in (12, 13)) or \ (p['rotational_velocity'].value == 0 and p['magnetic_field_exponent'] == 0) ) class Kuroda_2020(loaders.Kuroda_2020): """Model based on simulations from `Kuroda et al. (2020) <https://arxiv.org/abs/2009.07733>`_.""" def _metadata_from_filename(self, filename:str)->dict: _, rotational_velocity, magnetic_field_exponent = re.split('R|B', os.path.splitext(os.path.basename(filename))[0]) metadata = { 'Progenitor mass': 20 * u.Msun, 'Rotational Velocity': int(rotational_velocity[0]), 'B_0 Exponent': int(magnetic_field_exponent), 'EOS': 'LS220' } return metadata def __init__(self, mass=None, *, rotational_velocity, magnetic_field_exponent): filename = f'LnuR{int(rotational_velocity.value):1d}0B{int(magnetic_field_exponent):02d}.dat' return super().__init__(filename, self.metadata)
[docs] @legacy_filename_initialization @RegistryModel( progenitor_mass=[9, 10, 12, 13, 14, 15, 16, 19, 25, 60] * u.Msun, ) class Fornax_2019(loaders.Fornax_2019): """Model based on 3D simulations from D. Vartanyan, A. Burrows, D. Radice, M. A. Skinner and J. Dolence, MNRAS 482(1):351, 2019. Data available at https://www.astro.princeton.edu/~burrows/nu-emissions.3d/ """ def _metadata_from_filename(self, filename:str)->dict: progenitor_mass = os.path.splitext(os.path.basename(filename))[0].split('_')[2] metadata = {'Progenitor mass': int(progenitor_mass[:-1]) * u.Msun} return metadata def __init__(self, cache_flux=False, *, progenitor_mass): """ Parameters ---------- cache_flux : bool If true, pre-compute the flux on a fixed angular grid and store the values in a FITS file. """ if progenitor_mass.value == 16: filename = f'lum_spec_{int(progenitor_mass.value):d}M_r250.h5' else: filename = f'lum_spec_{int(progenitor_mass.value):d}M.h5' return super().__init__(filename, self.metadata, cache_flux=cache_flux)
[docs] @legacy_filename_initialization @RegistryModel( progenitor_mass = Parameter((list(range(12, 24)) + [25, 26, 26.99]) * u.Msun, desc_values='[12..23, 25, 26, 26.99] solMass') ) class Fornax_2021(loaders.Fornax_2021): """Model based on 3D simulations from D. Vartanyan, A. Burrows, D. Radice, M. A. Skinner and J. Dolence, MNRAS 482(1):351, 2019. Data available at https://www.astro.princeton.edu/~burrows/nu-emissions.3d/ """ def _metadata_from_filename(self, filename:str)->dict: progenitor_mass = os.path.splitext(os.path.basename(filename))[0].split('_')[2] metadata = {'Progenitor mass': float(progenitor_mass[:-1]) * u.Msun} return metadata def __init__(self, progenitor_mass:u.Quantity): # Load from Parameters if progenitor_mass.value.is_integer(): filename = f'lum_spec_{int(progenitor_mass.value):2d}M_r10000_dat.h5' else: filename = f'lum_spec_{progenitor_mass.value:.2f}M_r10000_dat.h5' return super().__init__(filename, self.metadata)
_fornax_2022_progenitors = [ '9.0', '9.25', '9.5', '9.75', '10.0', '10.25', '10.5', '10.75', '11.0', '11.25', '11.5', '11.75', '12.00.bh', '12.03.bh', '12.07.bh', '12.1.bh', '12.13', '12.15', '12.18.bh', '12.20.bh', '12.25', '12.33.bh', '12.40.bh', '12.45.bh', '12.50.bh', '12.54.bh', '12.60.bh', '12.63', '12.70', '12.72.bh', '12.75', '12.80.bh', '12.85.bh', '12.90.bh', '12.93', '12.97.bh', '13.00.bh', '13.05.bh', '13.11', '13.25.bh', '13.27.bh', '13.32.bh', '13.40.bh', '13.45', '13.50.bh', '13.60.bh', '13.75', '13.82.bh', '13.90.bh', '13.96', '14.01', '14.13.bh', '14.25.bh', '14.40.bh', '14.41.bh', '14.43', '14.44.bh', '14.70.bh', '14.87.bh', '15.00.bh', '15.01', '15.04.bh', '15.05', '15.38.bh', '16.43', '16.65', '16.99', '17.00', '17.07', '17.10', '17.40', '17.48', '17.50', '17.51', '17.83', '18.04', '18.05', '18.09', '18.10', '18.50', '19.02', '19.56', '19.83', '19.99', '20.08', '20.09', '20.18', '20.37', '21.00', '21.68', '22.00', '22.30', '22.82', '23.00', '23.04', '23.43', '24.00', '25.00', '26.00', '26.99'] _fornax_2022_masses = [float(p.strip('.bh')) for p in _fornax_2022_progenitors] << u.Msun
[docs] @RegistryModel(progenitor_mass = _fornax_2022_masses ) class Fornax_2022(loaders.Fornax_2022): """Model based on 2D simulations of 100 progenitors from Tianshu Wang, David Vartanyan, Adam Burrows, and Matthew S.B. Coleman, MNRAS 517:543, 2022. Data available at https://www.astro.princeton.edu/~burrows/nu-emissions.2d.large/ """ #a mapping of mass to the progenitor _mass_to_progenitor = dict(zip(_fornax_2022_masses,_fornax_2022_progenitors)) def __init__(self, progenitor_mass:u.Quantity): progenitor = self._mass_to_progenitor[progenitor_mass] self.metadata['Black hole'] = progenitor.endswith('.bh') filename = f'lum_spec_{progenitor}_dat.h5' return super().__init__(filename, self.metadata)
[docs] @RegistryModel( _param_validator = lambda p: \ (p['axion_mass'] == 0 and p['axion_coupling'] == 0) or \ (p['axion_mass'].to_value('MeV') == 100 and p['axion_coupling'].to_value('1e-10/GeV') in (2,4,10,12,14,16,20)) or \ (p['axion_mass'].to_value('MeV') == 200 and p['axion_coupling'].to_value('1e-10/GeV') in (2,4,6,8,10,20)), axion_mass = Parameter(values=[0, 100, 200]<<u.MeV, description='Axion mass in units of MeV'), axion_coupling = Parameter(values=[0, 2, 4, 6, 8, 10, 12, 14, 16, 20]<<(1e-10/u.GeV), description='Axion-photon coupling, in units of 1e-10/GeV', precision=2 #round to 1e-12/u.GeV ), progenitor_mass=[20]*u.Msun ) class Mori_2023(loaders.Mori_2023): """Model based on 2D simulations with axionlike particles, K. Mori, T. Takiwaki, K. Kotake and S. Horiuchi, Phys. Rev. D 108:063027, 2023. All models are based on the non-rotating 20 M_sun solar metallicity progenitor model from S.E. Woolsey and A. Heger, Phys. Rep. 442:269, 2007. Data from private communication. """ def __init__(self, axion_mass:u.Quantity, axion_coupling:u.Quantity): # Make sure axion coupling is converted to units 1e-10/GeV: #axion_coupling = np.round(axion_coupling.to('1e-10/GeV')) if axion_mass == 0: filename = 't-prof_std.dat' else: filename = f't-prof_{axion_mass.to_value("MeV"):g}_{axion_coupling.to_value("1e-10/GeV"):g}.dat' # PNS mass table, from Mori+ 2023. mpns = { (0, 0): 1.78, (100, 2): 1.77, (100, 4): 1.76, (100, 10): 1.77, (100, 12): 1.77, (100, 14): 1.77, (100, 16): 1.77, (100, 20): 1.74, (200, 2): 1.77, (200, 4): 1.76, (200, 6): 1.75, (200, 8): 1.74, (200, 10): 1.73, (200, 20): 1.62 } am = int(axion_mass.to_value('MeV')) if isinstance(axion_mass, u.quantity.Quantity) else int(axion_mass) ac = int(axion_coupling.to_value('1e-10/GeV')) if isinstance(axion_coupling, u.quantity.Quantity) else int(axion_coupling) pns_mass = mpns[(am,ac)] # Set the metadata. self.metadata['PNS mass'] = pns_mass*u.Msun return super().__init__(filename, self.metadata)
[docs] @RegistryModel( Bfield = ['hydro','L1','L2'], direction = ['average','equator','north','south'], grav=['A','B',None], rotation=[0,90,None], _param_validator = lambda p: (p['Bfield'] == 'hydro' and p['grav'] == None and p['rotation'] == None ) or (p['Bfield'] == 'L1' and p['grav'] == None and p['rotation'] in [0,90]) or (p['Bfield'] == 'L2' and p['rotation'] == None and p['grav'] in ['A','B']) ) class Bugli_2021(loaders.Bugli_2021): """Model based on `Buggli (2021) <https://arxiv.org/abs/2105.00665>`_. """ def __init__(self, *, Bfield:str, direction:str, rotation:int=None, grav:str=None): filename = f'{Bfield}_3d_snewpy_{direction}.dat' self.metadata['Progenitor mass'] = 35*u.Msun self.metadata['EOS'] = 'LS220' if Bfield=='L2': filename = f'{Bfield}_b12_dipdecay_3d_grav{grav}_snewpy_{direction}.dat' if Bfield=='L1': filename = f'{Bfield}_b12_3d_{rotation}deg_snewpy_{direction}.dat' return super().__init__(filename=filename, metadata=self.metadata)
[docs] class SNOwGLoBES: """A model that does not inherit from SupernovaModel (yet) and imports a group of SNOwGLoBES files.""" def __init__(self, tarfilename): """ Parameters ---------- tarfilename: str Absolute or relative path to tar archive with SNOwGLoBES files. """ self.tfname = tarfilename tf = tarfile.open(self.tfname) # For now just pull out the "NoOsc" files. datafiles = sorted([f.name for f in tf if '.dat' in f.name]) noosc = [df for df in datafiles if 'NoOsc' in df] noosc.sort(key=len) # Loop through the noosc files and pull out the number fluxes. self.time = [] self.energy = None self.flux = {} self.fmin = 1e99 self.fmax = -1e99 for nooscfile in noosc: with tf.extractfile(nooscfile) as f: logging.debug('Reading {}'.format(nooscfile)) meta = f.readline() metatext = meta.decode('utf-8') t = float(metatext.split('TBinMid=')[-1].split('sec')[0]) dt = float(metatext.split('tBinWidth=')[-1].split('s')[0]) dE = float(metatext.split('eBinWidth=')[-1].split('MeV')[0]) data = Table.read(f, format='ascii.commented_header', header_start=-1) data.meta['t'] = t data.meta['dt'] = dt data.meta['dE'] = dE self.time.append(t) if self.energy is None: self.energy = (data['E(GeV)'].data*1000).tolist() for flavor in ['NuE', 'NuMu', 'NuTau', 'aNuE', 'aNuMu', 'aNuTau']: if flavor in self.flux: self.flux[flavor].append(data[flavor].data.tolist()) else: self.flux[flavor] = [data[flavor].data.tolist()] # We now have a table with rows=times and columns=energies. Transpose # so that rows=energy and cols=time. for k, v in self.flux.items(): self.flux[k] = np.transpose(self.flux[k]) self.fmin = np.minimum(self.fmin, np.min(self.flux[k])) self.fmax = np.maximum(self.fmax, np.max(self.flux[k]))
[docs] def get_fluence(self, t): """Return the fluence at a given time t. Parameters ---------- t : float Time in seconds. Returns ------- fluence : dict A dictionary giving fluence at time t, keyed by flavor. """ # Get index of closest element in the array idx = np.abs(np.asarray(self.time) - t).argmin() fluence = {} for k, fl in self.flux.items(): fluence[k] = fl[:,idx] return fluence
[docs] class Analytic3Species(PinchedModel): """An analytical model calculating spectra given total luminosity, average energy, and rms or pinch, for each species. """ param = "There are no input files available for this class. Use `doc/scripts/Analytic.py` in the SNEWPY GitHub repo to create a custom input file." def get_param_combinations(cls): print(cls.param) return [] def __init__(self, filename): """ Parameters ---------- filename : str Absolute or relative path to file with model data. """ simtab = Table.read(filename,format='ascii') self.filename = filename super().__init__(simtab, metadata={})