Source code for tardis.io.model.readers.base

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, )