Commit 1fc63145 authored by Médéric Boquien's avatar Médéric Boquien

Add two new attenuation modules based on modified Charlot & Fall (2000) and Calzetti (2000) laws.

parent ecb82506
......@@ -4,7 +4,8 @@
### Added
- It is now possible to optionally indicate the distance in Mpc in the input file. If present it will be used in lieu of the distance computed from the redshift. This is especially useful in the nearby universe where the redshift is a very poor indicator of the actual distance. (Médéric Boquien)
- It is now possible to fit any physical property indicated by the code (e.g. equivalent width, dust luminosity, etc.). For this the physical property needs to be given in the input file and the properties to be fitted must be given in the properties filed in pcigale.ini. (Héctor Salas & Médéric Boquien)
- It is now possible to fit emission lines. For this the line has to be indicated in the same way as any other band both in the input flux file (in units of W/m²) and in the list of bands in `pcigale.ini`. Lines are prefixed with `line.` followed by the name of the line, for instance `line.H-alpha` for Hɑ. The following lines are supported at the moment: `Ly-alpha`, `CII-133.5`, `SiIV-139.7`, `CIV-154.9`, `HeII-164.0`, `OIII-166.5`, `CIII-190.9`, `CII-232.6`, `MgII-279.8`, `OII-372.7`, `H-10`, `H-9`, `NeIII-386.9` `HeI-388.9`, `H-epsilon`, `SII-407.0`, `H-delta`, `H-gamma`, `H-beta`, `OIII-495.9`, `OIII-500.7`, `OI-630.0`, `NII-654.8`, `H-alpha`, `NII-658.4`, `SII-671.6`, `SII-673.1`.
- It is now possible to fit emission lines. For this the line has to be indicated in the same way as any other band both in the input flux file (in units of W/m²) and in the list of bands in `pcigale.ini`. Lines are prefixed with `line.` followed by the name of the line, for instance `line.H-alpha` for Hɑ. The following lines are supported at the moment: `Ly-alpha`, `CII-133.5`, `SiIV-139.7`, `CIV-154.9`, `HeII-164.0`, `OIII-166.5`, `CIII-190.9`, `CII-232.6`, `MgII-279.8`, `OII-372.7`, `H-10`, `H-9`, `NeIII-386.9` `HeI-388.9`, `H-epsilon`, `SII-407.0`, `H-delta`, `H-gamma`, `H-beta`, `OIII-495.9`, `OIII-500.7`, `OI-630.0`, `NII-654.8`, `H-alpha`, `NII-658.4`, `SII-671.6`, `SII-673.1`. (Médéric Boquien)
- Two new dust attenuation modules have been added: `dustatt\_modified\_CF00` and `dustatt\_modified\_starburst`. The former implements a modified 2-component Charlot & Fall (2000) model whereas the latter implements a modified starburst law with the continuum attenuated with a Calzetti (2000) curve and the lines extincted with a Milky Way or a Magellanic Cloud law. The previous models `dustatt\_powerlaw`, `dustatt\_2powerlaws`, and `dustatt\_calzleit` are still available but are deprecated. (Médéric Boquien & David Corre)
### Changed
- The `sfhdelayed` module has been extended to optionally include an exponential burst to model the latest episode of star formation. (Médéric Boquien & Barbara Lo Faro)
......
# -*- coding: utf-8 -*-
# Licensed under the CeCILL-v2 licence - see Licence_CeCILL_V2-en.txt
"""
Modified Charlot & Fall 2000 dust attenuation module
===================================
This module implements an attenuation law combining the birth cloud (BC)
attenuation and the interstellar medium (ISM) attenuation, each one modelled by
a power law. The young star emission is attenuated by the BC and the ISM
attenuations whereas the old star emission is only affected by the ISM. This
simple model was proposed by Charlot & Fall (2000).
Parameters available for analysis
---------------------------------
- attenuation.Av_ISM: Av attenuation in the interstellar medium
- attenuation.mu: Av_ISM / (Av_BV+Av_ISM)
- attenuation.slope_BC: slope of the power law in the birth clouds
- attenuation.slope_ISM: slope of the power law in the ISM
- attenuation.<NAME>: amount of total attenuation in the luminosity
contribution <NAME>
- attenuation.<FILTER>: total attenuation in the filter
"""
from collections import OrderedDict
import numpy as np
from . import SedModule
def alambda_av(wl, delta):
"""Compute the complete attenuation curve A(λ)/Av
Attenuation curve of the form (λ / 550 nm) ** δ. The Lyman continuum is not
attenuated.
Parameters
----------
wl: array of floats
The wavelength grid in nm.
delta: float
Slope of the power law.
Returns
-------
attenuation: array of floats
The A(λ)/Av attenuation at each wavelength of the grid.
"""
attenuation = (wl / 550.) ** delta
# Lyman continuum not attenuated.
attenuation[wl <= 91.2] = 0.
return attenuation
class ModCF00Att(SedModule):
"""Two power laws attenuation module
Attenuation module combining the birth cloud (BC) attenuation and the
interstellar medium (ISM) one.
The attenuation can be computed on the whole spectrum or on a specific
contribution and is added to the SED as a negative contribution.
"""
parameter_list = OrderedDict([
("Av_ISM", (
"cigale_list(minvalue=0)",
"V-band attenuation in the interstellar medium.",
1.
)),
("mu", (
"cigale_list(minvalue=.0001, maxvalue=1.)",
"Av_ISM / (Av_BC+Av_ISM)",
0.44
)),
("slope_ISM", (
"cigale_list()",
"Power law slope of the attenuation in the ISM.",
-0.7
)),
("slope_BC", (
"cigale_list()",
"Power law slope of the attenuation in the birth clouds.",
-1.3
)),
("filters", (
"string()",
"Filters for which the attenuation will be computed and added to "
"the SED information dictionary. You can give several filter "
"names separated by a & (don't use commas).",
"V_B90 & FUV"
))
])
def _init_code(self):
self.Av_ISM = float(self.parameters['Av_ISM'])
self.mu = float(self.parameters['mu'])
self.slope_ISM = float(self.parameters['slope_ISM'])
self.slope_BC = float(self.parameters['slope_BC'])
self.filter_list = [item.strip() for item in
self.parameters["filters"].split("&")]
self.Av_BC = self.Av_ISM * (1. - self.mu) / self.mu
self.contatt = {}
self.lineatt = {}
def process(self, sed):
"""Add the dust attenuation to the SED.
Parameters
----------
sed: pcigale.sed.SED object
"""
wl = sed.wavelength_grid
# Compute the attenuation curves on the continuum wavelength grid
if len(self.contatt) == 0:
self.contatt['old'] = 10. ** (-.4 * alambda_av(wl, self.slope_ISM) *
self.Av_ISM)
# Emission from the young population is attenuated by both
# components
self.contatt['young'] = 10. ** (-.4 * alambda_av(wl, self.slope_BC) *
self.Av_BC) * self.contatt['old']
# Compute the attenuation curves on the line wavelength grid
if len(self.lineatt) == 0:
names = [k for k in sed.lines]
linewl = np.array([sed.lines[k][0] for k in names])
old_curve = 10. ** (-.4 * alambda_av(linewl, self.slope_ISM) *
self.Av_ISM)
young_curve = 10. ** (-.4 * alambda_av(linewl, self.slope_BC) *
self.Av_BC) * old_curve
for name, old, young in zip(names, old_curve, young_curve):
self.lineatt[name] = (old, young)
# Fλ fluxes in each filter before attenuation.
flux_noatt = {filt: sed.compute_fnu(filt) for filt in self.filter_list}
dust_lumin = 0.
contribs = [contrib for contrib in sed.contribution_names if
'absorption' not in contrib]
for contrib in contribs:
age = contrib.split('.')[-1].split('_')[-1]
luminosity = sed.get_lumin_contribution(contrib)
attenuation_spectrum = luminosity * (self.contatt[age] - 1.)
dust_lumin -= np.trapz(attenuation_spectrum, wl)
sed.add_module(self.name, self.parameters)
sed.add_contribution("attenuation." + contrib, wl,
attenuation_spectrum)
for name, (linewl, old, young) in sed.lines.items():
sed.lines[name] = (linewl, old * self.lineatt[name][0],
young * self.lineatt[name][1])
sed.add_info('attenuation.Av_ISM', self.Av_ISM)
sed.add_info('attenuation.Av_BC', self.Av_BC)
sed.add_info('attenuation.mu', self.mu)
sed.add_info('attenuation.slope_BC', self.slope_BC)
sed.add_info('attenuation.slope_ISM', self.slope_ISM)
# Total attenuation
if 'dust.luminosity' in sed.info:
sed.add_info("dust.luminosity",
sed.info["dust.luminosity"] + dust_lumin, True, True)
else:
sed.add_info("dust.luminosity", dust_lumin, True)
# Fλ fluxes (only in continuum) in each filter after attenuation.
flux_att = {filt: sed.compute_fnu(filt) for filt in self.filter_list}
# Attenuation in each filter
for filt in self.filter_list:
att = -2.5 * np.log10(flux_att[filt] / flux_noatt[filt])
sed.add_info("attenuation." + filt, max(0., att))
# CreationModule to be returned by get_module
Module = ModCF00Att
This diff is collapsed.
......@@ -274,7 +274,9 @@ class Configuration(object):
('nebular', ['nebular']),
('dust attenuation', ['dustatt_calzleit',
'dustatt_powerlaw',
'dustatt_2powerlaws']),
'dustatt_2powerlaws',
'dustatt_modified_CF00',
'dustatt_modified_starburst']),
('dust emission', ['casey2012', 'dale2014',
'dl2007', 'dl2014',
'themis']),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment