def parse_abundance_dict_to_dataframe(abundance_dict): atomic_number_dict = dict([(element_symbol2atomic_number(symbol), abundance_dict[symbol]) for symbol in abundance_dict]) atomic_numbers = sorted(atomic_number_dict.keys()) abundances = pd.Series([atomic_number_dict[z] for z in atomic_numbers], index=atomic_numbers) abundance_norm = abundances.sum() if abs(abundance_norm - 1) > 1e-12: logger.warn('Given abundances don\'t add up to 1 (value = %g) - normalizing', abundance_norm) abundances /= abundance_norm return abundances
def from_config_dict(cls, config_dict, atom_data=None, test_parser=False, validate=True, config_dirname=''): """ Validating and subsequently parsing a config file. Parameters ---------- config_dict : ~dict dictionary of a raw unvalidated config file atom_data: ~tardis.atomic.AtomData atom data object. if `None` will be tried to be read from atom data file path in the config_dict [default=None] test_parser: ~bool switch on to ignore a working atom_data, mainly useful for testing this reader validate: ~bool Turn validation on or off. Returns ------- `tardis.config_reader.Configuration` """ if validate: validated_config_dict = config_validator.validate_dict(config_dict) else: validated_config_dict = config_dict #First let's see if we can find an atom_db anywhere: if test_parser: atom_data = None elif 'atom_data' in validated_config_dict.keys(): if os.path.isabs(validated_config_dict['atom_data']): atom_data_fname = validated_config_dict['atom_data'] else: atom_data_fname = os.path.join( config_dirname, validated_config_dict['atom_data']) validated_config_dict['atom_data_fname'] = atom_data_fname else: raise ConfigurationError( 'No atom_data key found in config or command line') if atom_data is None and not test_parser: logger.info('Reading Atomic Data from %s', atom_data_fname) atom_data = atomic.AtomData.from_hdf5(atom_data_fname) else: atom_data = atom_data #Parsing supernova dictionary validated_config_dict['supernova']['luminosity_nu_start'] = \ validated_config_dict['supernova']['luminosity_wavelength_end'].to( u.Hz, u.spectral()) try: validated_config_dict['supernova']['luminosity_nu_end'] = \ (validated_config_dict['supernova'] ['luminosity_wavelength_start'].to(u.Hz, u.spectral())) except ZeroDivisionError: validated_config_dict['supernova']['luminosity_nu_end'] = (np.inf * u.Hz) validated_config_dict['supernova']['time_explosion'] = ( validated_config_dict['supernova']['time_explosion'].cgs) validated_config_dict['supernova']['luminosity_requested'] = ( validated_config_dict['supernova']['luminosity_requested'].cgs) #Parsing the model section model_section = validated_config_dict['model'] v_inner = None v_outer = None mean_densities = None abundances = None structure_section = model_section['structure'] if structure_section['type'] == 'specific': velocity = model_section['structure']['velocity'] start, stop, num = velocity['start'], velocity['stop'], \ velocity['num'] num += 1 velocities = quantity_linspace(start, stop, num) v_inner, v_outer = velocities[:-1], velocities[1:] mean_densities = parse_density_section( model_section['structure']['density'], v_inner, v_outer, validated_config_dict['supernova']['time_explosion']).cgs elif structure_section['type'] == 'file': if os.path.isabs(structure_section['filename']): structure_fname = structure_section['filename'] else: structure_fname = os.path.join(config_dirname, structure_section['filename']) v_inner, v_outer, mean_densities, inner_boundary_index, \ outer_boundary_index = read_density_file( structure_fname, structure_section['filetype'], validated_config_dict['supernova']['time_explosion'], structure_section['v_inner_boundary'], structure_section['v_outer_boundary']) r_inner = validated_config_dict['supernova']['time_explosion'] * v_inner r_outer = validated_config_dict['supernova']['time_explosion'] * v_outer r_middle = 0.5 * (r_inner + r_outer) structure_section['v_inner'] = v_inner.cgs structure_section['v_outer'] = v_outer.cgs structure_section['mean_densities'] = mean_densities.cgs no_of_shells = len(v_inner) structure_section['no_of_shells'] = no_of_shells structure_section['r_inner'] = r_inner.cgs structure_section['r_outer'] = r_outer.cgs structure_section['r_middle'] = r_middle.cgs structure_section['volumes'] = ((4. / 3) * np.pi * \ (r_outer ** 3 - r_inner ** 3)).cgs #### TODO the following is legacy code and should be removed validated_config_dict['structure'] = \ validated_config_dict['model']['structure'] # ^^^^^^^^^^^^^^^^ abundances_section = model_section['abundances'] if abundances_section['type'] == 'uniform': abundances = pd.DataFrame(columns=np.arange(no_of_shells), index=pd.Index(np.arange(1, 120), name='atomic_number'), dtype=np.float64) for element_symbol_string in abundances_section: if element_symbol_string == 'type': continue z = element_symbol2atomic_number(element_symbol_string) abundances.ix[z] = float( abundances_section[element_symbol_string]) elif abundances_section['type'] == 'file': if os.path.isabs(abundances_section['filename']): abundances_fname = abundances_section['filename'] else: abundances_fname = os.path.join(config_dirname, abundances_section['filename']) index, abundances = read_abundances_file( abundances_fname, abundances_section['filetype'], inner_boundary_index, outer_boundary_index) if len(index) != no_of_shells: raise ConfigurationError( 'The abundance file specified has not the same number of cells' 'as the specified density profile') abundances = abundances.replace(np.nan, 0.0) abundances = abundances[abundances.sum(axis=1) > 0] norm_factor = abundances.sum(axis=0) if np.any(np.abs(norm_factor - 1) > 1e-12): logger.warning( "Abundances have not been normalized to 1. - normalizing") abundances /= norm_factor validated_config_dict['abundances'] = abundances ########### DOING PLASMA SECTION ############### plasma_section = validated_config_dict['plasma'] if plasma_section['initial_t_inner'] < 0.0 * u.K: luminosity_requested = validated_config_dict['supernova'][ 'luminosity_requested'] plasma_section['t_inner'] = (( luminosity_requested / (4 * np.pi * r_inner[0]**2 * constants.sigma_sb))**.25).to('K') logger.info( '"initial_t_inner" is not specified in the plasma ' 'section - initializing to %s with given luminosity', plasma_section['t_inner']) else: plasma_section['t_inner'] = plasma_section['initial_t_inner'] if plasma_section['initial_t_rad'] > 0 * u.K: plasma_section['t_rads'] = np.ones(no_of_shells) * \ plasma_section['initial_t_rad'] else: plasma_section['t_rads'] = None if plasma_section['disable_electron_scattering'] is False: logger.debug("Electron scattering switched on") validated_config_dict['montecarlo'][ 'sigma_thomson'] = 6.652486e-25 / (u.cm**2) else: logger.warn('Disabling electron scattering - this is not physical') validated_config_dict['montecarlo']['sigma_thomson'] = 1e-200 / ( u.cm**2) if plasma_section['helium_treatment'] == 'recomb-nlte': validated_config_dict['plasma'][ 'helium_treatment'] == 'recomb-nlte' else: validated_config_dict['plasma']['helium_treatment'] == 'dilute-lte' ##### NLTE subsection of Plasma start nlte_validated_config_dict = {} nlte_species = [] nlte_section = plasma_section['nlte'] nlte_species_list = nlte_section.pop('species') for species_string in nlte_species_list: nlte_species.append(species_string_to_tuple(species_string)) nlte_validated_config_dict['species'] = nlte_species nlte_validated_config_dict['species_string'] = nlte_species_list nlte_validated_config_dict.update(nlte_section) if 'coronal_approximation' not in nlte_section: logger.debug( 'NLTE "coronal_approximation" not specified in NLTE section - defaulting to False' ) nlte_validated_config_dict['coronal_approximation'] = False if 'classical_nebular' not in nlte_section: logger.debug( 'NLTE "classical_nebular" not specified in NLTE section - defaulting to False' ) nlte_validated_config_dict['classical_nebular'] = False elif nlte_section: #checks that the dictionary is not empty logger.warn( 'No "species" given - ignoring other NLTE options given:\n%s', pp.pformat(nlte_section)) if not nlte_validated_config_dict: nlte_validated_config_dict['species'] = [] plasma_section['nlte'] = nlte_validated_config_dict #^^^^^^^^^^^^^^ End of Plasma Section ##### Monte Carlo Section montecarlo_section = validated_config_dict['montecarlo'] montecarlo_section['no_of_packets'] = \ int(montecarlo_section['no_of_packets']) montecarlo_section['last_no_of_packets'] = \ int(montecarlo_section['last_no_of_packets']) if montecarlo_section['last_no_of_packets'] < 0: montecarlo_section['last_no_of_packets'] = \ montecarlo_section['no_of_packets'] montecarlo_section['convergence_strategy'] = ( parse_convergence_section( montecarlo_section['convergence_strategy'])) black_body_section = montecarlo_section['black_body_sampling'] montecarlo_section['black_body_sampling'] = {} montecarlo_section['black_body_sampling']['start'] = \ black_body_section['start'] montecarlo_section['black_body_sampling']['end'] = \ black_body_section['stop'] montecarlo_section['black_body_sampling']['samples'] = \ black_body_section['num'] virtual_spectrum_section = montecarlo_section['virtual_spectrum_range'] montecarlo_section['virtual_spectrum_range'] = {} montecarlo_section['virtual_spectrum_range']['start'] = \ virtual_spectrum_section['start'] montecarlo_section['virtual_spectrum_range']['end'] = \ virtual_spectrum_section['stop'] montecarlo_section['virtual_spectrum_range']['samples'] = \ virtual_spectrum_section['num'] ###### END of convergence section reading validated_config_dict['spectrum'] = parse_spectrum_list2dict( validated_config_dict['spectrum']) return cls(validated_config_dict, atom_data)
def test_element_symbol2atomic_number(): assert util.element_symbol2atomic_number('Si') == 14
def test_element_symbol2atomic_number(element_symbol, atomic_number): assert element_symbol2atomic_number(element_symbol) == atomic_number
def from_config_dict(cls, config_dict, atom_data=None, test_parser=False, config_definition_file=None, validate=True): """ Validating and subsequently parsing a config file. Parameters ---------- config_dict : ~dict dictionary of a raw unvalidated config file atom_data: ~tardis.atomic.AtomData atom data object. if `None` will be tried to be read from atom data file path in the config_dict [default=None] test_parser: ~bool switch on to ignore a working atom_data, mainly useful for testing this reader config_definition_file: ~str path to config definition file, if `None` will be set to the default in the `data` directory that ships with TARDIS validate: ~bool Turn validation on or off. Returns ------- `tardis.config_reader.Configuration` """ if config_definition_file is None: config_definition_file = default_config_definition_file config_definition = yaml.load(open(config_definition_file)) if validate: validated_config_dict = ConfigurationValidator(config_definition, config_dict).get_config() else: validated_config_dict = config_dict #First let's see if we can find an atom_db anywhere: if test_parser: atom_data = None elif 'atom_data' in validated_config_dict.keys(): atom_data_fname = validated_config_dict['atom_data'] validated_config_dict['atom_data_fname'] = atom_data_fname else: raise ConfigurationError('No atom_data key found in config or command line') if atom_data is None and not test_parser: logger.info('Reading Atomic Data from %s', atom_data_fname) atom_data = atomic.AtomData.from_hdf5(atom_data_fname) else: atom_data = atom_data #Parsing supernova dictionary validated_config_dict['supernova']['luminosity_nu_start'] = \ validated_config_dict['supernova']['luminosity_wavelength_end'].to( u.Hz, u.spectral()) try: validated_config_dict['supernova']['luminosity_nu_end'] = \ (validated_config_dict['supernova'] ['luminosity_wavelength_start'].to(u.Hz, u.spectral())) except ZeroDivisionError: validated_config_dict['supernova']['luminosity_nu_end'] = ( np.inf * u.Hz) validated_config_dict['supernova']['time_explosion'] = ( validated_config_dict['supernova']['time_explosion'].cgs) validated_config_dict['supernova']['luminosity_requested'] = ( validated_config_dict['supernova']['luminosity_requested'].cgs) #Parsing the model section model_section = validated_config_dict['model'] v_inner = None v_outer = None mean_densities = None abundances = None structure_section = model_section['structure'] if structure_section['type'] == 'specific': start, stop, num = model_section['structure']['velocity'] num += 1 velocities = np.linspace(start, stop, num) v_inner, v_outer = velocities[:-1], velocities[1:] mean_densities = parse_density_section( model_section['structure']['density'], v_inner, v_outer, validated_config_dict['supernova']['time_explosion']).cgs elif structure_section['type'] == 'file': v_inner, v_outer, mean_densities, inner_boundary_index, \ outer_boundary_index = read_density_file( structure_section['filename'], structure_section['filetype'], validated_config_dict['supernova']['time_explosion'], structure_section['v_inner_boundary'], structure_section['v_outer_boundary']) r_inner = validated_config_dict['supernova']['time_explosion'] * v_inner r_outer = validated_config_dict['supernova']['time_explosion'] * v_outer r_middle = 0.5 * (r_inner + r_outer) structure_validated_config_dict = {} structure_section['v_inner'] = v_inner.cgs structure_section['v_outer'] = v_outer.cgs structure_section['mean_densities'] = mean_densities.cgs no_of_shells = len(v_inner) structure_section['no_of_shells'] = no_of_shells structure_section['r_inner'] = r_inner.cgs structure_section['r_outer'] = r_outer.cgs structure_section['r_middle'] = r_middle.cgs structure_section['volumes'] = ((4. / 3) * np.pi * \ (r_outer ** 3 - r_inner ** 3)).cgs #### TODO the following is legacy code and should be removed validated_config_dict['structure'] = \ validated_config_dict['model']['structure'] # ^^^^^^^^^^^^^^^^ abundances_section = model_section['abundances'] if abundances_section['type'] == 'uniform': abundances = pd.DataFrame(columns=np.arange(no_of_shells), index=pd.Index(np.arange(1, 120), name='atomic_number'), dtype=np.float64) for element_symbol_string in abundances_section: if element_symbol_string == 'type': continue z = element_symbol2atomic_number(element_symbol_string) abundances.ix[z] = float(abundances_section[element_symbol_string]) elif abundances_section['type'] == 'file': index, abundances = read_abundances_file(abundances_section['filename'], abundances_section['filetype'], inner_boundary_index, outer_boundary_index) if len(index) != no_of_shells: raise ConfigurationError('The abundance file specified has not the same number of cells' 'as the specified density profile') abundances = abundances.replace(np.nan, 0.0) abundances = abundances[abundances.sum(axis=1) > 0] norm_factor = abundances.sum(axis=0) if np.any(np.abs(norm_factor - 1) > 1e-12): logger.warning("Abundances have not been normalized to 1. - normalizing") abundances /= norm_factor validated_config_dict['abundances'] = abundances ########### DOING PLASMA SECTION ############### plasma_section = validated_config_dict['plasma'] if plasma_section['initial_t_inner'] < 0.0 * u.K: luminosity_requested = validated_config_dict['supernova']['luminosity_requested'] plasma_section['t_inner'] = ((luminosity_requested / (4 * np.pi * r_inner[0] ** 2 * constants.sigma_sb)) ** .25).to('K') logger.info('"initial_t_inner" is not specified in the plasma ' 'section - initializing to %s with given luminosity', plasma_section['t_inner']) else: plasma_section['t_inner'] = plasma_section['initial_t_inner'] plasma_section['t_rads'] = np.ones(no_of_shells) * \ plasma_section['initial_t_rad'] if plasma_section['disable_electron_scattering'] is False: logger.debug("Electron scattering switched on") validated_config_dict['montecarlo']['sigma_thomson'] = 6.652486e-25 / (u.cm ** 2) else: logger.warn('Disabling electron scattering - this is not physical') validated_config_dict['montecarlo']['sigma_thomson'] = 1e-200 / (u.cm ** 2) ##### NLTE subsection of Plasma start nlte_validated_config_dict = {} nlte_species = [] nlte_section = plasma_section['nlte'] nlte_species_list = nlte_section.pop('species') for species_string in nlte_species_list: nlte_species.append(species_string_to_tuple(species_string)) nlte_validated_config_dict['species'] = nlte_species nlte_validated_config_dict['species_string'] = nlte_species_list nlte_validated_config_dict.update(nlte_section) if 'coronal_approximation' not in nlte_section: logger.debug('NLTE "coronal_approximation" not specified in NLTE section - defaulting to False') nlte_validated_config_dict['coronal_approximation'] = False if 'classical_nebular' not in nlte_section: logger.debug('NLTE "classical_nebular" not specified in NLTE section - defaulting to False') nlte_validated_config_dict['classical_nebular'] = False elif nlte_section: #checks that the dictionary is not empty logger.warn('No "species" given - ignoring other NLTE options given:\n%s', pp.pformat(nlte_section)) if not nlte_validated_config_dict: nlte_validated_config_dict['species'] = [] plasma_section['nlte'] = nlte_validated_config_dict #^^^^^^^^^^^^^^ End of Plasma Section ##### Monte Carlo Section montecarlo_section = validated_config_dict['montecarlo'] if montecarlo_section['last_no_of_packets'] < 0: montecarlo_section['last_no_of_packets'] = \ montecarlo_section['no_of_packets'] default_convergence_section = {'type': 'damped', 'lock_t_inner_cycles': 1, 't_inner_update_exponent': -0.5, 'damping_constant': 0.5} if montecarlo_section['convergence_strategy'] is None: logger.warning('No convergence criteria selected - ' 'just damping by 0.5 for w, t_rad and t_inner') montecarlo_section['convergence_strategy'] = ( parse_convergence_section(default_convergence_section)) else: montecarlo_section['convergence_strategy'] = ( parse_convergence_section( montecarlo_section['convergence_strategy'])) black_body_section = montecarlo_section['black_body_sampling'] montecarlo_section['black_body_sampling'] = {} montecarlo_section['black_body_sampling']['start'] = \ black_body_section[0] montecarlo_section['black_body_sampling']['end'] = \ black_body_section[1] montecarlo_section['black_body_sampling']['samples'] = \ black_body_section[2] virtual_spectrum_section = montecarlo_section['virtual_spectrum_range'] montecarlo_section['virtual_spectrum_range'] = {} montecarlo_section['virtual_spectrum_range']['start'] = \ virtual_spectrum_section[0] montecarlo_section['virtual_spectrum_range']['end'] = \ virtual_spectrum_section[1] montecarlo_section['virtual_spectrum_range']['samples'] = \ virtual_spectrum_section[2] ###### END of convergence section reading validated_config_dict['spectrum'] = parse_spectrum_list2dict( validated_config_dict['spectrum']) return cls(validated_config_dict, atom_data)
def from_config_dict(cls, raw_dict, atom_data=None, test_parser=False): """ Reading in from a YAML file and commandline args. Preferring commandline args when given Parameters ---------- fname : filename for the yaml file args : namespace object Not implemented Yet Returns ------- `tardis.config_reader.TARDISConfiguration` """ config_dict = {} raw_dict = copy.deepcopy(raw_dict) #First let's see if we can find an atom_db anywhere: if test_parser: atom_data = None elif 'atom_data' in raw_dict.keys(): atom_data_fname = raw_dict['atom_data'] config_dict['atom_data_fname'] = atom_data_fname else: raise ConfigurationError('No atom_data key found in config or command line') if atom_data is None and not test_parser: logger.info('Reading Atomic Data from %s', atom_data_fname) atom_data = atomic.AtomData.from_hdf5(atom_data_fname) else: atom_data = atom_data #Parsing supernova dictionary config_dict['supernova'] = parse_supernova_section(raw_dict['supernova']) #Parsing the model section model_section = raw_dict.pop('model') v_inner = None v_outer = None mean_densities = None abundances = None if 'file' in model_section: v_inner, v_outer, mean_densities, abundances = parse_model_file_section(model_section.pop('file'), config_dict['supernova']['time_explosion']) no_of_shells = len(v_inner) structure_config_dict = {} if 'structure' in model_section: #Trying to figure out the structure (number of shells) structure_section = model_section.pop('structure') inner_boundary_index, outer_boundary_index = None, None try: structure_section_type = structure_section['type'] except KeyError: raise ConfigurationError('Structure section requires "type" keyword') if structure_section_type == 'specific': velocities = parse_quantity_linspace(structure_section['velocity']).to('cm/s') v_inner, v_outer = velocities[:-1], velocities[1:] mean_densities = parse_density_section(structure_section['density'], v_inner, v_outer, config_dict['supernova']['time_explosion']) elif structure_section_type == 'file': v_inner_boundary, v_outer_boundary = structure_section.get('v_inner_boundary', 0 * u.km/u.s), \ structure_section.get('v_outer_boundary', np.inf * u.km/u.s) if not hasattr(v_inner_boundary, 'unit'): v_inner_boundary = parse_quantity(v_inner_boundary) if not hasattr(v_outer_boundary, 'unit'): v_outer_boundary = parse_quantity(v_outer_boundary) v_inner, v_outer, mean_densities, inner_boundary_index, outer_boundary_index =\ read_density_file(structure_section['filename'], structure_section['filetype'], config_dict['supernova']['time_explosion'], v_inner_boundary, v_outer_boundary) else: raise ConfigurationError('structure section required in configuration file') r_inner = config_dict['supernova']['time_explosion'] * v_inner r_outer = config_dict['supernova']['time_explosion'] * v_outer r_middle = 0.5 * (r_inner + r_outer) structure_config_dict['v_inner'] = v_inner structure_config_dict['v_outer'] = v_outer structure_config_dict['mean_densities'] = mean_densities no_of_shells = len(v_inner) structure_config_dict['no_of_shells'] = no_of_shells structure_config_dict['r_inner'] = r_inner structure_config_dict['r_outer'] = r_outer structure_config_dict['r_middle'] = r_middle structure_config_dict['volumes'] = (4. / 3) * np.pi * (r_outer ** 3 - r_inner ** 3) config_dict['structure'] = structure_config_dict #Now that the structure section is parsed we move on to the abundances abundances_section = model_section.pop('abundances') abundances_type = abundances_section.pop('type') if abundances_type == 'uniform': abundances = pd.DataFrame(columns=np.arange(no_of_shells), index=pd.Index(np.arange(1, 120), name='atomic_number'), dtype=np.float64) for element_symbol_string in abundances_section: z = element_symbol2atomic_number(element_symbol_string) abundances.ix[z] = float(abundances_section[element_symbol_string]) elif abundances_type == 'file': index, abundances = read_abundances_file(abundances_section['filename'], abundances_section['filetype'], inner_boundary_index, outer_boundary_index) if len(index) != no_of_shells: raise ConfigurationError('The abundance file specified has not the same number of cells' 'as the specified density profile') abundances = abundances.replace(np.nan, 0.0) abundances = abundances[abundances.sum(axis=1) > 0] norm_factor = abundances.sum(axis=0) if np.any(np.abs(norm_factor - 1) > 1e-12): logger.warning("Abundances have not been normalized to 1. - normalizing") abundances /= norm_factor config_dict['abundances'] = abundances ########### DOING PLASMA SECTION ############### plasma_section = raw_dict.pop('plasma') plasma_config_dict = {} if plasma_section['ionization'] not in ('nebular', 'lte'): raise ConfigurationError('plasma_type only allowed to be "nebular" or "lte"') plasma_config_dict['ionization'] = plasma_section['ionization'] if plasma_section['excitation'] not in ('dilute-lte', 'lte'): raise ConfigurationError('plasma_type only allowed to be "nebular" or "lte"') plasma_config_dict['excitation'] = plasma_section['excitation'] if plasma_section['radiative_rates_type'] not in ('dilute-blackbody', 'detailed'): raise ConfigurationError('radiative_rates_types must be either "dilute-blackbody" or "detailed"') plasma_config_dict['radiative_rates_type'] = plasma_section['radiative_rates_type'] if plasma_section['line_interaction_type'] not in ('scatter', 'downbranch', 'macroatom'): raise ConfigurationError('radiative_rates_types must be either "scatter", "downbranch", or "macroatom"') plasma_config_dict['line_interaction_type'] = plasma_section['line_interaction_type'] if 'w_epsilon' in plasma_section: plasma_config_dict['w_epsilon'] = plasma_section['w_epsilon'] else: logger.warn('"w_epsilon" not specified in plasma section - setting it to 1e-10') plasma_config_dict['w_epsilon'] = 1e-10 if 'delta_treatment' in plasma_section: plasma_config_dict['delta_treatment'] = plasma_section['delta_treatment'] else: logger.warn('"delta_treatment" not specified in plasma section - defaulting to None') plasma_config_dict['delta_treatment'] = None if 'initial_t_inner' in plasma_section: plasma_config_dict['t_inner'] = parse_quantity(plasma_section['initial_t_inner']).to('K') else: plasma_config_dict['t_inner'] = (((config_dict['supernova']['luminosity_requested'] / \ (4 * np.pi * r_inner[0]**2 * constants.sigma_sb))**.5)**.5).to('K') logger.info('"initial_t_inner" is not specified in the plasma section - ' 'initializing to %s with given luminosity', plasma_config_dict['t_inner']) if 'initial_t_rads' in plasma_section: if isinstance('initial_t_rads', basestring): uniform_t_rads = parse_quantity(plasma_section['initial_t_rads']) plasma_config_dict['t_rads'] = u.Quantity(np.ones(no_of_shells) * uniform_t_rads.value, u.K) elif astropy.utils.isiterable(plasma_section['initial_t_rads']): assert len(plasma_section['initial_t_rads']) == no_of_shells plasma_config_dict['t_rads'] = u.Quantity(plasma_section['initial_t_rads'], u.K) else: logger.info('No "initial_t_rads" specified - initializing with 10000 K') plasma_config_dict['t_rads'] = u.Quantity(np.ones(no_of_shells) * 10000., u.K) ##### NLTE subsection of Plasma start nlte_config_dict = {} nlte_species = [] if 'nlte' in plasma_section: nlte_section = plasma_section['nlte'] if 'species' in nlte_section: nlte_species_list = nlte_section.pop('species') for species_string in nlte_species_list: nlte_species.append(species_string_to_tuple(species_string)) nlte_config_dict['species'] = nlte_species nlte_config_dict['species_string'] = nlte_species_list nlte_config_dict.update(nlte_section) if 'coronal_approximation' not in nlte_section: logger.debug('NLTE "coronal_approximation" not specified in NLTE section - defaulting to False') nlte_config_dict['coronal_approximation'] = False if 'classical_nebular' not in nlte_section: logger.debug('NLTE "classical_nebular" not specified in NLTE section - defaulting to False') nlte_config_dict['classical_nebular'] = False elif nlte_section: #checks that the dictionary is not empty logger.warn('No "species" given - ignoring other NLTE options given:\n%s', pp.pformat(nlte_section)) if not nlte_config_dict: nlte_config_dict['species'] = [] plasma_config_dict['nlte'] = nlte_config_dict #^^^^^^^ NLTE subsection of Plasma end config_dict['plasma'] = plasma_config_dict #^^^^^^^^^^^^^^ End of Plasma Section ##### Monte Carlo Section montecarlo_section = raw_dict.pop('montecarlo') montecarlo_config_dict = {} #PARSING convergence section convergence_variables = ['t_inner', 't_rad', 'w'] convergence_config_dict = {} if 'convergence_strategy' in montecarlo_section: convergence_section = montecarlo_section.pop('convergence_strategy') if 'lock_t_inner_cycles' in convergence_section: lock_t_inner_cycles = convergence_section['lock_t_inner_cycles'] logger.info('lock_t_inner_cycles set to %d cycles', lock_t_inner_cycles) else: lock_t_inner_cycles = None if 't_inner_update_exponent' in convergence_section: t_inner_update_exponent = convergence_section['t_inner_update_exponent'] logger.info('t_inner update exponent set to %g', t_inner_update_exponent) else: t_inner_update_exponent = None if convergence_section['type'] == 'damped': convergence_config_dict['type'] == 'damped' global_damping_constant = convergence_section['damping_constant'] for convergence_variable in convergence_variables: convergence_parameter_name = convergence_variable current_convergence_parameters = {} convergence_config_dict[convergence_parameter_name] = current_convergence_parameters if convergence_variable in convergence_section: current_convergence_parameters['damping_constant'] \ = convergence_section[convergence_variable]['damping_constant'] else: current_convergence_parameters['damping_constant'] = global_damping_constant elif convergence_section['type'] == 'specific': convergence_config_dict['type'] = 'specific' global_convergence_parameters = {} global_convergence_parameters['damping_constant'] = convergence_section['damping_constant'] global_convergence_parameters['threshold'] = convergence_section['threshold'] global_convergence_parameters['fraction'] = convergence_section['fraction'] for convergence_variable in convergence_variables: convergence_parameter_name = convergence_variable current_convergence_parameters = {} convergence_config_dict[convergence_parameter_name] = current_convergence_parameters if convergence_variable in convergence_section: for param in global_convergence_parameters.keys(): if param == 'fraction' and convergence_variable == 't_inner': continue if param in convergence_section[convergence_variable]: current_convergence_parameters[param] = convergence_section[convergence_variable][param] else: current_convergence_parameters[param] = global_convergence_parameters[param] else: convergence_config_dict[convergence_parameter_name] = global_convergence_parameters.copy() global_convergence_parameters['hold'] = convergence_section['hold'] convergence_config_dict['global_convergence_parameters'] = global_convergence_parameters else: raise ValueError("convergence criteria unclear %s", convergence_section['type']) else: lock_t_inner_cycles = None t_inner_update_exponent = None logger.warning('No convergence criteria selected - just damping by 0.5 for w, t_rad and t_inner') convergence_config_dict['type'] = 'damped' for convergence_variable in convergence_variables: convergence_parameter_name = convergence_variable convergence_config_dict[convergence_parameter_name] = dict(damping_constant=0.5) if lock_t_inner_cycles is None: logger.warning('t_inner update lock cycles not set - defaulting to 1') lock_t_inner_cycles = 1 if t_inner_update_exponent is None: logger.warning('t_inner update exponent not set - defaulting to -0.5') t_inner_update_exponent = -0.5 convergence_config_dict['lock_t_inner_cycles'] = lock_t_inner_cycles convergence_config_dict['t_inner_update_exponent'] = t_inner_update_exponent montecarlo_config_dict['convergence'] = convergence_config_dict ###### END of convergence section reading if 'last_no_of_packets' not in montecarlo_section: montecarlo_section['last_no_of_packets'] = None if 'no_of_virtual_packets' not in montecarlo_section: montecarlo_section['no_of_virtual_packets'] = 0 montecarlo_config_dict.update(montecarlo_section) disable_electron_scattering = plasma_section.get('disable_electron_scattering', False) if disable_electron_scattering is False: logger.info("Electron scattering switched on") montecarlo_config_dict['sigma_thomson'] =6.652486e-25 / (u.cm**2) else: logger.warn('Disabling electron scattering - this is not physical') montecarlo_config_dict['sigma_thomson'] = 1e-200 / (u.cm**2) montecarlo_config_dict['enable_reflective_inner_boundary'] = False montecarlo_config_dict['inner_boundary_albedo'] = 0.0 if 'inner_boundary_albedo' in montecarlo_section: montecarlo_config_dict['inner_boundary_albedo'] = montecarlo_section['inner_boundary_albedo'] if 'enable_reflective_inner_boundary' not in montecarlo_section: logger.warn('inner_boundary_albedo set, however enable_reflective_inner_boundary option not specified ' '- defaulting to reflective inner boundary') montecarlo_config_dict['enable_reflective_inner_boundary'] = True if 'enable_reflective_inner_boundary' in montecarlo_section: montecarlo_config_dict['enable_reflective_inner_boundary'] = montecarlo_section['enable_reflective_inner_boundary'] if montecarlo_section['enable_reflective_inner_boundary'] == True and 'inner_boundary_albedo' not in montecarlo_section: logger.warn('enabled reflective inner boundary, but "inner_boundary_albedo" not set - defaulting to 0.5') montecarlo_config_dict['inner_boundary_albedo'] = 0.5 if 'black_body_sampling' in montecarlo_section: black_body_sampling_section = montecarlo_section.pop('black_body_sampling') sampling_start, sampling_end = parse_spectral_bin(black_body_sampling_section['start'], black_body_sampling_section['stop']) montecarlo_config_dict['black_body_sampling']['start'] = sampling_start montecarlo_config_dict['black_body_sampling']['end'] = sampling_end montecarlo_config_dict['black_body_sampling']['samples'] = np.int64(black_body_sampling_section['num']) else: logger.warn('No "black_body_sampling" section in config file - using defaults of ' '50 - 200000 Angstrom (1e6 samples)') montecarlo_config_dict['black_body_sampling'] = {} montecarlo_config_dict['black_body_sampling']['start'] = 50 * u.angstrom montecarlo_config_dict['black_body_sampling']['end'] = 200000 * u.angstrom montecarlo_config_dict['black_body_sampling']['samples'] = np.int64(1e6) config_dict['montecarlo'] = montecarlo_config_dict ##### End of MonteCarlo section ##### spectrum section ###### spectrum_section = raw_dict.pop('spectrum') spectrum_config_dict = {} spectrum_frequency = parse_quantity_linspace(spectrum_section).to('Hz', u.spectral()) if spectrum_frequency[0] > spectrum_frequency[1]: spectrum_frequency = spectrum_frequency[::-1] spectrum_config_dict['start'] = parse_quantity(spectrum_section['start']) spectrum_config_dict['end'] = parse_quantity(spectrum_section['stop']) spectrum_config_dict['bins'] = spectrum_section['num'] spectrum_frequency = np.linspace(spectrum_config_dict['end'].to('Hz', u.spectral()).value, spectrum_config_dict['start'].to('Hz', u.spectral()).value, num=spectrum_config_dict['bins'] + 1) * u.Hz spectrum_config_dict['frequency'] = spectrum_frequency.to('Hz') config_dict['spectrum'] = spectrum_config_dict return cls(config_dict, atom_data)
def _test_element_symbol2atomic_number(element_string, atomic_number): assert element_symbol2atomic_number(element_string) == atomic_number
def from_config(cls, config): """ Create a new Radial1DModel instance from a Configuration object. Parameters ---------- config : tardis.io.config_reader.Configuration Returns ------- Radial1DModel """ time_explosion = config.supernova.time_explosion.cgs structure = config.model.structure if structure.type == 'specific': velocity = quantity_linspace(structure.velocity.start, structure.velocity.stop, structure.velocity.num + 1).cgs homologous_density = HomologousDensity.from_config(config) elif structure.type == 'file': if os.path.isabs(structure.filename): structure_fname = structure.filename else: structure_fname = os.path.join(config.config_dirname, structure.filename) time_0, velocity, density_0 = read_density_file( structure_fname, structure.filetype) density_0 = density_0.insert(0, 0) homologous_density = HomologousDensity(density_0, time_0) else: raise NotImplementedError # Note: This is the number of shells *without* taking in mind the # v boundaries. no_of_shells = len(velocity) - 1 if config.plasma.initial_t_rad > 0 * u.K: t_radiative = np.ones(no_of_shells) * config.plasma.initial_t_rad else: t_radiative = None if config.plasma.initial_t_inner < 0.0 * u.K: luminosity_requested = config.supernova.luminosity_requested t_inner = None else: luminosity_requested = None t_inner = config.plasma.initial_t_inner abundances_section = config.model.abundances if abundances_section.type == 'uniform': abundance = pd.DataFrame(columns=np.arange(no_of_shells), index=pd.Index(np.arange(1, 120), name='atomic_number'), dtype=np.float64) for element_symbol_string in abundances_section: if element_symbol_string == 'type': continue z = element_symbol2atomic_number(element_symbol_string) abundance.ix[z] = float( abundances_section[element_symbol_string]) elif abundances_section.type == 'file': if os.path.isabs(abundances_section.filename): abundances_fname = abundances_section.filename else: abundances_fname = os.path.join(config.config_dirname, abundances_section.filename) index, abundance = read_abundances_file( abundances_fname, abundances_section.filetype) abundance = abundance.replace(np.nan, 0.0) abundance = abundance[abundance.sum(axis=1) > 0] norm_factor = abundance.sum(axis=0) if np.any(np.abs(norm_factor - 1) > 1e-12): logger.warning("Abundances have not been normalized to 1." " - normalizing") abundance /= norm_factor return cls(velocity=velocity, homologous_density=homologous_density, abundance=abundance, time_explosion=time_explosion, t_radiative=t_radiative, t_inner=t_inner, luminosity_requested=luminosity_requested, dilution_factor=None, v_boundary_inner=structure.get('v_inner_boundary', None), v_boundary_outer=structure.get('v_outer_boundary', None))
def test_element_symbol2atomic_number(element_symbol, atomic_number): assert element_symbol2atomic_number(element_symbol) == atomic_number with pytest.raises(MalformedElementSymbolError): element_symbol2atomic_number('Hx')
def from_config(cls, config): """ Create a new Radial1DModel instance from a Configuration object. Parameters ---------- config : tardis.io.config_reader.Configuration Returns ------- Radial1DModel """ time_explosion = config.supernova.time_explosion.cgs structure = config.model.structure if structure.type == 'specific': velocity = quantity_linspace(structure.velocity.start, structure.velocity.stop, structure.velocity.num + 1).cgs homologous_density = HomologousDensity.from_config(config) elif structure.type == 'file': if os.path.isabs(structure.filename): structure_fname = structure.filename else: structure_fname = os.path.join(config.config_dirname, structure.filename) time_0, velocity, density_0 = read_density_file( structure_fname, structure.filetype) density_0 = density_0.insert(0, 0) homologous_density = HomologousDensity(density_0, time_0) else: raise NotImplementedError # Note: This is the number of shells *without* taking in mind the # v boundaries. no_of_shells = len(velocity) - 1 if config.plasma.initial_t_rad > 0 * u.K: t_radiative = np.ones(no_of_shells) * config.plasma.initial_t_rad else: t_radiative = None if config.plasma.initial_t_inner < 0.0 * u.K: luminosity_requested = config.supernova.luminosity_requested t_inner = None else: luminosity_requested = None t_inner = config.plasma.initial_t_inner abundances_section = config.model.abundances if abundances_section.type == 'uniform': abundance = pd.DataFrame(columns=np.arange(no_of_shells), index=pd.Index(np.arange(1, 120), name='atomic_number'), dtype=np.float64) for element_symbol_string in abundances_section: if element_symbol_string == 'type': continue z = element_symbol2atomic_number(element_symbol_string) abundance.ix[z] = float(abundances_section[element_symbol_string]) elif abundances_section.type == 'file': if os.path.isabs(abundances_section.filename): abundances_fname = abundances_section.filename else: abundances_fname = os.path.join(config.config_dirname, abundances_section.filename) index, abundance = read_abundances_file(abundances_fname, abundances_section.filetype) abundance = abundance.replace(np.nan, 0.0) abundance = abundance[abundance.sum(axis=1) > 0] norm_factor = abundance.sum(axis=0) if np.any(np.abs(norm_factor - 1) > 1e-12): logger.warning("Abundances have not been normalized to 1." " - normalizing") abundance /= norm_factor return cls(velocity=velocity, homologous_density=homologous_density, abundance=abundance, time_explosion=time_explosion, t_radiative=t_radiative, t_inner=t_inner, luminosity_requested=luminosity_requested, dilution_factor=None, v_boundary_inner=structure.get('v_inner_boundary', None), v_boundary_outer=structure.get('v_outer_boundary', None))