import numpy as np
import pandas as pd
from tardis.io.model.readers.cmfgen_deprecated import (
read_cmfgen_composition,
read_cmfgen_density,
)
from tardis.io.model.readers.generic_readers import (
ConfigurationError,
read_csv_composition,
read_simple_ascii_density,
read_simple_ascii_mass_fractions,
)
[docs]
def read_mass_fractions_file(
mass_fractions_filename,
mass_fractions_filetype,
inner_boundary_idx=None,
outer_boundary_idx=None,
density_filename=None,
):
"""
read different density file formats
Parameters
----------
mass_fractions_filename : str
filename or path of the density file
mass_fractions_filetype : str
type of the density file
inner_boundary_idx : int
index of the inner shell, default None
outer_boundary_idx : int
index of the outer shell, default None
density_filename : str or pathlib.Path
Matching density file. Required for ARTIS isotope mass fractions,
which are stored in the ARTIS density file.
"""
file_parsers = {
"simple_ascii": read_simple_ascii_mass_fractions,
"cmfgen_model": read_cmfgen_composition,
"custom_composition": read_csv_composition,
}
isotope_mass_fractions = pd.DataFrame()
if mass_fractions_filetype in ["cmfgen_model", "custom_composition"]:
index, mass_fractions, isotope_mass_fractions = file_parsers[
mass_fractions_filetype
](mass_fractions_filename)
elif mass_fractions_filetype == "artis":
from tardis.io.model.artis.readers import (
read_artis_composition,
read_artis_mass_fractions,
)
if density_filename is None:
mass_fractions = read_artis_mass_fractions(mass_fractions_filename)
index = mass_fractions.T.index
else:
index, mass_fractions, isotope_mass_fractions = (
read_artis_composition(
density_filename, mass_fractions_filename
)
)
index = mass_fractions.T.index
else:
index, mass_fractions = file_parsers[mass_fractions_filetype](
mass_fractions_filename
)
if outer_boundary_idx is not None:
outer_boundary_idx_m1 = outer_boundary_idx - 1
else:
outer_boundary_idx_m1 = None
index = index[inner_boundary_idx:outer_boundary_idx]
mass_fractions = mass_fractions.loc[
:, slice(inner_boundary_idx, outer_boundary_idx_m1)
]
mass_fractions.columns = np.arange(len(mass_fractions.columns))
if not isotope_mass_fractions.empty:
isotope_mass_fractions = isotope_mass_fractions.loc[
:, slice(inner_boundary_idx, outer_boundary_idx_m1)
]
isotope_mass_fractions.columns = np.arange(
len(isotope_mass_fractions.columns)
)
return index, mass_fractions, isotope_mass_fractions
[docs]
def read_density_file(filename, filetype):
"""
read different density file formats
Parameters
----------
filename : str
filename or path of the density file
filetype : str
type of the density file
Returns
-------
time_of_model : astropy.units.Quantity
time at which the model is valid
velocity : np.ndarray
the array containing the N + 1 shell-boundary velocities
unscaled_mean_densities : np.ndarray
the array containing the N shell densities
electron_densities : np.ndarray
The array containing the N shell electron densities
temperature : np.ndarray
The array containing the N shell temperatures
Notes
-----
Every supported file type stores one row per velocity edge. The first
row's velocity is the inner edge of the innermost shell, and the cell
values in that row are discarded by the file parsers. See
:ref:`model-leading-row`.
"""
# Lazy import to avoid circular dependency
from tardis.io.model.artis.readers import (
read_artis_density,
)
file_parsers = {
"artis": read_artis_density,
"simple_ascii": read_simple_ascii_density,
"cmfgen_model": read_cmfgen_density,
}
electron_densities = None
temperature = None
if filetype == "cmfgen_model":
(
time_of_model,
velocity,
unscaled_mean_densities,
electron_densities,
temperature,
) = read_cmfgen_density(filename)
else:
(time_of_model, velocity, unscaled_mean_densities) = file_parsers[
filetype
](filename)
v_inner = velocity[:-1]
v_outer = velocity[1:]
invalid_volume_mask = (v_outer - v_inner) <= 0
if invalid_volume_mask.sum() > 0:
message = "\n".join(
[
f"cell {i:d}: v_inner {v_inner_i:s}, v_outer {v_outer_i:s}"
for i, v_inner_i, v_outer_i in zip(
np.arange(len(v_outer))[invalid_volume_mask],
v_inner[invalid_volume_mask],
v_outer[invalid_volume_mask],
)
]
)
raise ConfigurationError(
f"Invalid volume of following cell(s):\n{message:s}"
)
return (
time_of_model,
velocity,
unscaled_mean_densities,
electron_densities,
temperature,
)