Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proof of concept: Initialise all models as ThreeFlavor #335

Merged
merged 6 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions python/snewpy/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,16 @@ def __init__(self, simtab, metadata):
metadata: dict
Model parameters dict
"""
if not 'L_NU_X_BAR' in simtab.colnames:
# table only contains NU_E, NU_E_BAR, and NU_X, so double up
# the use of NU_X for NU_X_BAR.
if not 'L_NU_MU' in simtab.colnames:
# table only contains NU_E, NU_E_BAR, and NU_X, so re-use NU_X for MU/TAU (anti)neutrinos.
for val in ['L','E','ALPHA']:
simtab[f'{val}_NU_X_BAR'] = simtab[f'{val}_NU_X']
simtab[f'{val}_NU_MU'] = simtab[f'{val}_NU_X']
simtab[f'{val}_NU_MU_BAR'] = simtab.columns.get(f'{val}_NU_X_BAR', simtab[f'{val}_NU_X'])
simtab[f'{val}_NU_TAU'] = simtab[f'{val}_NU_X']
simtab[f'{val}_NU_TAU_BAR'] = simtab.columns.get(f'{val}_NU_X_BAR', simtab[f'{val}_NU_X'])
del simtab[f'{val}_NU_X']
if f'{val}_NU_X_BAR' in simtab.colnames:
del simtab[f'{val}_NU_X_BAR']
# Get grid of model times.
time = simtab['TIME'] << u.s
# Set up dictionary of luminosity, mean energy and shape parameter
Expand Down
63 changes: 27 additions & 36 deletions python/snewpy/models/ccsn_loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ def __init__(self, filename, eos='LS220', metadata={}):
# merge the data into one giant table.
mergtab = None
for flavor in Flavor:
_flav = Flavor.NU_X if flavor == Flavor.NU_X_BAR else flavor
_sfx = _flav.name.replace('_', '').lower()
_sfx = flavor.name.replace('_', '').lower() if flavor.is_electron else "nux"
_filename = '{}_{}_{}'.format(filename, eos, _sfx)
_lname = 'L_{}'.format(flavor.name)
_ename = 'E_{}'.format(flavor.name)
Expand Down Expand Up @@ -273,12 +272,12 @@ def __init__(self, filename, metadata={}):

# Get grid of model times.
simtab['TIME'] = simtab['Tpb[ms]'] << u.ms
for f in [Flavor.NU_E, Flavor.NU_E_BAR, Flavor.NU_X]:
fkey = re.sub('(E|X)_BAR', r'A\g<1>', f.name).lower()
simtab[f'L_{f.name}'] = simtab[f'<L{fkey}>'] * 1e51 << u.erg / u.s
simtab[f'E_{f.name}'] = simtab[f'<E{fkey}>'] << u.MeV
for f in ["NU_E", "NU_E_BAR", "NU_X"]:
fkey = re.sub('(E|X)_BAR', r'A\g<1>', f).lower()
simtab[f'L_{f}'] = simtab[f'<L{fkey}>'] * 1e51 << u.erg / u.s
simtab[f'E_{f}'] = simtab[f'<E{fkey}>'] << u.MeV
# There is no pinch parameter so use alpha=2.0.
simtab[f'ALPHA_{f.name}'] = np.full_like(simtab[f'E_{f.name}'].value, 2.)
simtab[f'ALPHA_{f}'] = np.full_like(simtab[f'E_{f}'].value, 2.)

self.filename = os.path.basename(filename)

Expand All @@ -302,6 +301,14 @@ def __init__(self, filename, metadata={}, cache_flux=False):
self.fluxunit = 1e50 * u.erg/(u.s*u.MeV)
self.time = None

# Conversion of flavor to key name in the model HDF5 file.
self._flavorkeys = {Flavor.NU_E: 'nu0',
Flavor.NU_E_BAR: 'nu1',
Flavor.NU_MU: 'nu2',
Flavor.NU_MU_BAR: 'nu2',
Flavor.NU_TAU: 'nu2',
Flavor.NU_TAU_BAR: 'nu2'}

# Read a cached flux file in FITS format or generate one.
self.is_cached = cache_flux and 'healpy' in sys.modules
if cache_flux and not 'healpy' in sys.modules:
Expand All @@ -328,12 +335,6 @@ def __init__(self, filename, metadata={}, cache_flux=False):
self.nside = hp.npix2nside(npix)
else:
with h5py.File(filename, 'r') as _h5file:
# Conversion of flavor to key name in the model HDF5 file.
self._flavorkeys = {Flavor.NU_E: 'nu0',
Flavor.NU_E_BAR: 'nu1',
Flavor.NU_X: 'nu2',
Flavor.NU_X_BAR: 'nu2'}

if self.time is None:
self.time = _h5file['nu0']['g0'].attrs['time'] * u.s

Expand Down Expand Up @@ -391,12 +392,6 @@ def __init__(self, filename, metadata={}, cache_flux=False):
# Write output to FITS.
self._write_fits(fitsfile, overwrite=True)
else:
# Conversion of flavor to key name in the model HDF5 file.
self._flavorkeys = {Flavor.NU_E: 'nu0',
Flavor.NU_E_BAR: 'nu1',
Flavor.NU_X: 'nu2',
Flavor.NU_X_BAR: 'nu2'}

# Open the requested filename using the model downloader.
datafile = self.request_file(filename)
# Open HDF5 data file.
Expand Down Expand Up @@ -551,13 +546,6 @@ def _get_binnedspectra(self, t, theta, phi):

# Read the HDF5 input file directly and extract the spectra.
else:
# File only contains NU_E, NU_E_BAR, and NU_X.
if flavor == Flavor.NU_X_BAR:
E[flavor] = E[Flavor.NU_X]
dE[flavor] = dE[Flavor.NU_X]
binspec[flavor] = binspec[Flavor.NU_X]
continue

key = self._flavorkeys[flavor]

# Energy binning of the model for this flavor, in units of MeV.
Expand Down Expand Up @@ -678,8 +666,10 @@ def __init__(self, filename, metadata={}):
# Convert flavor to key name in the model HDF5 file
key = {Flavor.NU_E: 'nu0',
Flavor.NU_E_BAR: 'nu1',
Flavor.NU_X: 'nu2',
Flavor.NU_X_BAR: 'nu2'}[flavor]
Flavor.NU_MU: 'nu2',
Flavor.NU_MU_BAR: 'nu2',
Flavor.NU_TAU: 'nu2',
Flavor.NU_TAU_BAR: 'nu2'}[flavor]

self._E[flavor] = np.asarray(_h5file[key]['egroup'])
self._dLdE[flavor] = {f"g{i}": np.asarray(_h5file[key][f'g{i}']) for i in range(12)}
Expand Down Expand Up @@ -798,8 +788,10 @@ def __init__(self, filename, metadata={}):
# Convert flavor to key name in the model HDF5 file
key = {Flavor.NU_E: 'nu0',
Flavor.NU_E_BAR: 'nu1',
Flavor.NU_X: 'nu2',
Flavor.NU_X_BAR: 'nu2'}[flavor]
Flavor.NU_MU: 'nu2',
Flavor.NU_MU_BAR: 'nu2',
Flavor.NU_TAU: 'nu2',
Flavor.NU_TAU_BAR: 'nu2'}[flavor]

self._E[flavor] = np.asarray(_h5file[key]['egroup'])
self._dLdE[flavor] = {f"g{i}": np.asarray(_h5file[key][f'g{i}']) for i in range(12)}
Expand Down Expand Up @@ -837,8 +829,8 @@ def __init__(self, filename, metadata={}):

# Get grid of model times.
simtab['TIME'] = simtab['2:t_pb[s]'] << u.s
for j, (f, fkey) in enumerate(zip([Flavor.NU_E, Flavor.NU_E_BAR, Flavor.NU_X], 'ebx')):
simtab[f'L_{f.name}'] = simtab[f'{6+j}:Le{fkey}[e/s]'] << u.erg / u.s
for j, (f, fkey) in enumerate(zip(["NU_E", "NU_E_BAR", "NU_X"], 'ebx')):
simtab[f'L_{f}'] = simtab[f'{6+j}:Le{fkey}[e/s]'] << u.erg / u.s
# Compute the pinch parameter from E_rms and E_avg
# <E^2> / <E>^2 = (2+a)/(1+a), where
# E_rms^2 = <E^2> - <E>^2.
Expand All @@ -848,9 +840,9 @@ def __init__(self, filename, metadata={}):
x = E2 / Eavg**2
alpha = (2-x) / (x-1)

simtab[f'E_{f.name}'] = Eavg << u.MeV
simtab[f'E2_{f.name}'] = E2 << u.MeV**2
simtab[f'ALPHA_{f.name}'] = alpha
simtab[f'E_{f}'] = Eavg << u.MeV
simtab[f'E2_{f}'] = E2 << u.MeV**2
simtab[f'ALPHA_{f}'] = alpha

# simtab[f'E_{f.name}'] = simtab[f'{9+j}:Em{fkey}[MeV]'] << u.MeV
# Erms = simtab[f'{12+j}:Er{fkey}[MeV]'] * u.MeV
Expand All @@ -863,4 +855,3 @@ def __init__(self, filename, metadata={}):
self.filename = os.path.basename(filename)

super().__init__(simtab, metadata)

15 changes: 10 additions & 5 deletions python/snewpy/models/presn_loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,13 @@ def __init__(self, filename:str):
self.request_file(filename),
comment="#",
sep='\s+',
names=["time","Enu",Flavor.NU_E,Flavor.NU_E_BAR,Flavor.NU_X,Flavor.NU_X_BAR],
names=["time","Enu",Flavor.NU_E,Flavor.NU_E_BAR,Flavor.NU_MU,Flavor.NU_MU_BAR],
usecols=range(6),
)

df[Flavor.NU_TAU] = df[Flavor.NU_MU]
df[Flavor.NU_TAU_BAR] = df[Flavor.NU_MU_BAR]

df = df.set_index(["time", "Enu"])
times = df.index.levels[0].to_numpy()
energies = df.index.levels[1].to_numpy()
Expand Down Expand Up @@ -115,10 +118,12 @@ def __init__(self, path):
times, step = np.loadtxt(self.request_file(f"{path}/total_nue/lightcurve_nue_all.dat"), usecols=[0, 3]).T

file_base = {Flavor.NU_E: 'total_nue/spe_all',
Flavor.NU_E_BAR:'total_nueb/spe_all',
Flavor.NU_X: 'total_nux/spe_sum_mu_nu',
Flavor.NU_X_BAR:'total_nux/spe_sum_mu'
}
Flavor.NU_E_BAR: 'total_nueb/spe_all',
Flavor.NU_MU: 'total_nux/spe_sum_mu_nu',
Flavor.NU_MU_BAR: 'total_nux/spe_sum_mu',
Flavor.NU_TAU: 'total_nux/spe_sum_mu_nu',
Flavor.NU_TAU_BAR: 'total_nux/spe_sum_mu'
}
for flv,file_base in file_base.items():
d2NdEdT = []
for s in step:
Expand Down
2 changes: 1 addition & 1 deletion python/snewpy/neutrino.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import Optional
import numpy as np
from collections.abc import Mapping
from .flavor import TwoFlavor as Flavor
from .flavor import ThreeFlavor as Flavor

class MassHierarchy(IntEnum):
"""Neutrino mass ordering: ``NORMAL`` or ``INVERTED``."""
Expand Down
18 changes: 9 additions & 9 deletions python/snewpy/test/test_03_neutrino.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@ def test_flavor(self):
"""
Neutrino flavor types
"""
nue = Flavor.NU_E
nue = Flavor.NU_E
self.assertTrue(nue.is_electron)
self.assertTrue(nue.is_neutrino)
self.assertFalse(nue.is_antineutrino)

nux = Flavor.NU_X
self.assertFalse(nux.is_electron)
self.assertTrue(nux.is_neutrino)
self.assertFalse(nux.is_antineutrino)
numu = Flavor.NU_MU
self.assertFalse(numu.is_electron)
self.assertTrue(numu.is_neutrino)
self.assertFalse(numu.is_antineutrino)

nueb = Flavor.NU_E_BAR
self.assertTrue(nueb.is_electron)
self.assertFalse(nueb.is_neutrino)
self.assertTrue(nueb.is_antineutrino)

nuxb = Flavor.NU_X_BAR
self.assertFalse(nuxb.is_electron)
self.assertFalse(nuxb.is_neutrino)
self.assertTrue(nuxb.is_antineutrino)
numub = Flavor.NU_MU_BAR
self.assertFalse(numub.is_electron)
self.assertFalse(numub.is_neutrino)
self.assertTrue(numub.is_antineutrino)


def test_mixing_nmo(self):
Expand Down
1 change: 1 addition & 0 deletions python/snewpy/test/test_05_snowglobes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def rates_calculation(fluence_file):
result[det] = table['weighted']['smeared'].values.sum()
return result

@pytest.mark.xfail(reason="Rate calculation uses `get_transformed_flux`, which is currently hard coded to a TwoFlavor scheme.", raises=AttributeError)
@pytest.mark.parametrize('model_parameters',param_values)
def test_total_rate_equals_table_value(model_parameters):
fluence_file = fluence_calculation(*model_parameters)
Expand Down
1 change: 1 addition & 0 deletions python/snewpy/test/test_presn_rates.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
T = np.geomspace(-1*u.hour, -1*u.min,1000)
E = np.linspace(0,20,100)*u.MeV

@pytest.mark.xfail(reason="`model.get_flux` uses `get_transformed_flux`, which is currently hard coded to a TwoFlavor scheme.", raises=AttributeError)
@pytest.mark.parametrize('model_class',[presn.Odrzywolek_2010, presn.Kato_2017, presn.Patton_2017])
@pytest.mark.parametrize('transformation',[AdiabaticMSW(mh=mh) for mh in MassHierarchy])
@pytest.mark.parametrize('detector', ["wc100kt30prct"])
Expand Down
2 changes: 2 additions & 0 deletions python/snewpy/test/test_rate_calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def fluence(snmodel):
flux = snmodel.get_flux(t=times, E=energies, distance=10<<u.kpc, flavor_xform=ft.AdiabaticMSW())
return flux.integrate('time')

@pytest.mark.xfail(reason="Fluence calculation uses `get_transformed_flux`, which is currently hard coded to a TwoFlavor scheme.", raises=AttributeError)
@pytest.mark.parametrize('detector, expected_total',crosscheck_table_unsmeared)
def test_rate_unsmeared(rc, fluence, detector, expected_total):
#calculate the event rates
Expand All @@ -52,6 +53,7 @@ def test_rate_unsmeared(rc, fluence, detector, expected_total):
#check the final value
assert N_total == pytest.approx(expected_total, 0.01)

@pytest.mark.xfail(reason="Fluence calculation uses `get_transformed_flux`, which is currently hard coded to a TwoFlavor scheme.", raises=AttributeError)
@pytest.mark.parametrize('detector, expected_total',crosscheck_table)
def test_rate_smeared(rc, fluence, detector, expected_total):
#calculate the event rates
Expand Down