-
Notifications
You must be signed in to change notification settings - Fork 8
Added P92 model #29
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
base: master
Are you sure you want to change the base?
Added P92 model #29
Changes from all commits
7f3bdb4
4aaace3
4c9ea45
db5f19f
db0b306
6eaa0aa
d047c1f
664075f
cf7e854
9b822a8
af0f6c6
d67ce71
3aa664c
d229b2c
aba857b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
@ARTICLE{1992ApJ...395..130P, | ||
author = {{Pei}, Yichuan C.}, | ||
title = "{Interstellar Dust from the Milky Way to the Magellanic Clouds}", | ||
journal = {\apj}, | ||
keywords = {Cosmic Dust, Intergalactic Media, Interstellar Extinction, Interstellar Matter, Magellanic Clouds, Milky Way Galaxy, Chemical Evolution, Far Ultraviolet Radiation, Kramers-Kronig Formula, Astrophysics, GALAXIES: INTERGALACTIC MEDIUM, GALAXIES: INTERSTELLAR MATTER, GALAXIES: MAGELLANIC CLOUDS, ISM: DUST, EXTINCTION}, | ||
year = 1992, | ||
month = aug, | ||
volume = {395}, | ||
pages = {130}, | ||
doi = {10.1086/171637}, | ||
adsurl = {https://ui.adsabs.harvard.edu/abs/1992ApJ...395..130P}, | ||
adsnote = {Provided by the SAO/NASA Astrophysics Data System} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,7 @@ the overall normalization, possibly changing the expected behavior of reddening | |
## References | ||
[Fitzpatrick & Massa (1990)](https://ui.adsabs.harvard.edu/abs/1990ApJS...72..163F) | ||
""" | ||
@with_kw struct FM90{T<:Number} <: ExtinctionLaw @deftype T | ||
@with_kw struct FM90{T<:Number} <: ExtinctionLaw @deftype T | ||
c1 = 0.10 | ||
c2 = 0.70 | ||
c3 = 3.23 | ||
|
@@ -77,3 +77,172 @@ function (law::FM90)(wave::T) where T | |
return exvebv | ||
end | ||
|
||
|
||
""" | ||
P92(BKG_amp=218.57, | ||
BKG_lambda=0.047, | ||
BKG_b=90.0, | ||
BKG_n=2.0, | ||
FUV_amp=18.54, | ||
FUV_lambda=0.07, | ||
FUV_b=4.0, | ||
FUV_n=6.5, | ||
NUV_amp=0.0596, | ||
NUV_lambda=0.22, | ||
NUV_b=-1.95, | ||
NUV_n=2.0, | ||
SIL1_amp=0.0026, | ||
SIL1_lambda=9.7, | ||
SIL1_b=-1.95, | ||
SIL1_n=2.0, | ||
SIL2_amp=0.0026, | ||
SIL2_lambda=18.0, | ||
SIL2_b=-1.8, | ||
SIL2_n=2.0, | ||
FIR_amp=0.0159, | ||
FIR_lambda=25.0, | ||
FIR_b=0.0, | ||
FIR_n=2.0) | ||
|
||
Pei (1992) generative extinction model applicable from the extreme UV to far-IR. | ||
|
||
## Parameters | ||
|
||
Background Terms | ||
* `BKG_amp` - amplitude | ||
* `BKG_lambda` - central wavelength | ||
* `BKG_b` - b coefficient | ||
* `BKG_n` - n coefficient | ||
|
||
Far-Ultraviolet Terms | ||
* `FUV_amp` - amplitude | ||
* `FUV_lambda` - central wavelength | ||
* `FUV_b` - b coefficent | ||
* `FUV_n` - n coefficient | ||
|
||
Near-Ultraviolet (2175 Å) Terms | ||
* `NUV_amp` - amplitude | ||
* `NUV_lambda` - central wavelength | ||
* `NUV_b` - b coefficent | ||
* `NUV_n` - n coefficient | ||
|
||
1st Silicate Feature (~10 micron) Terms | ||
* `SIL1_amp` - amplitude | ||
* `SIL1_lambda` - central wavelength | ||
* `SIL1_b` - b coefficent | ||
* `SIL1_n` - n coefficient | ||
|
||
2nd Silicate Feature (~18 micron) Terms | ||
* `SIL2_amp` - amplitude | ||
* `SIL2_lambda` - central wavelength | ||
* `SIL2_b` - b coefficient | ||
* `SIL2_n` - n coefficient | ||
|
||
Far-Infrared Terms | ||
* `FIR_amp` - amplitude | ||
* `FIR_lambda` - central wavelength | ||
* `FIR_b` - b coefficent | ||
* `FIR_n` - n coefficient | ||
|
||
If `λ` is a `Unitful.Quantity` it will be automatically converted to Å and the returned value will be `UnitfulAstro.mag`. | ||
|
||
## Examples | ||
```jldoctest | ||
julia> model = P92(); | ||
|
||
julia> model(1500) | ||
2.396291891812002 | ||
|
||
julia> P92(FUV_b = 2.0).([1000, 2000, 3000]) | ||
3-element Array{Float64,1}: | ||
3.8390886792306187 | ||
2.7304534614548697 | ||
1.806181164464396 | ||
|
||
``` | ||
|
||
## Default Parameter Values | ||
|
||
|Term |lambda|A|b|n| | ||
|:---:|:---:|:---:|:---:|:---:| | ||
|BKG |0.047 |218.57142857142858 |90 |2 | | ||
|FUV |0.07 |18.545454545454547 |4.0 |6.5| | ||
|NUV |0.22 |0.05961038961038961 |-1.95|2.0| | ||
|SIL1 |9.7 |0.0026493506493506496|-1.95|2.0| | ||
|SIL2 |18.0 |0.0026493506493506496|-1.8 |2.0| | ||
|FIR |25.0 |0.015896103896103898 |0.0 |2.0| | ||
|
||
|
||
## References | ||
[Pei (1992)](https://ui.adsabs.harvard.edu/abs/1992ApJ...395..130P) | ||
siddharthlal25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
@with_kw struct P92{T<:Number} <: ExtinctionLaw @deftype T | ||
BKG_amp = 165.0 * (1 / 3.08 + 1) | ||
BKG_lambda = 0.047 | ||
BKG_b = 90.0 | ||
BKG_n = 2.0 | ||
FUV_amp = 14.0 * (1 / 3.08 + 1) | ||
FUV_lambda = 0.07 | ||
FUV_b = 4.0 | ||
FUV_n = 6.5 | ||
NUV_amp = 0.045 * (1 / 3.08 + 1) | ||
NUV_lambda = 0.22 | ||
NUV_b = -1.95 | ||
NUV_n = 2.0 | ||
SIL1_amp = 0.002 * (1 / 3.08 + 1) | ||
SIL1_lambda = 9.7 | ||
SIL1_b = -1.95 | ||
SIL1_n = 2.0 | ||
SIL2_amp = 0.002 * (1 / 3.08 + 1) | ||
SIL2_lambda = 18.0 | ||
SIL2_b = -1.80 | ||
SIL2_n = 2.0 | ||
FIR_amp = 0.012 * (1 / 3.08 + 1) | ||
FIR_lambda = 25.0 | ||
FIR_b = 0.00 | ||
FIR_n = 2.0 | ||
@assert BKG_amp ≥ 0 "`BKG_amp` must be ≥ 0, got $BKG_amp" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm almost wondering if it would be easier to represent this struct hierarchically with tuples or named tuples struct Example
BKG = (165.0 * (1/3.08 + 1), 0.047, etc...)
# or
FIR = (A=0.012 * (1 / 3.08 + 1), lambda=25.0, b=0.0
end It's clear this struct has this hierarchical order and it seems organized a little better. The question is whether this is easier for the user or if it makes sense for the user. Perhaps we don't use this for the struct itself, but we add a constructor that allows this behavior, something like P92(BKG, FUV, NUV, SIL1, SIL2, FIR) = P92(BKG..., FUB..., NUV..., SIL1..., SILL2..., FIR...) We could make this a kwarg-only version, but we'd have to remove the Also, AFAIK this should have no performance impact (tuples and namedtuples are static and have lots of compiler opts. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your point is correct, that would make the struct quite organized, but let's think from the user's perspective who is trying to switch from DustExtinction (python) to this place, things like this could be intimidating to the user. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can have both. The user isn't necessarily going to interact with the struct directlyy, just with the constructors and the methods. We can organize the struct however we want and organize the constructors however we want. It may be easier to not worry about it |
||
@assert FUV_amp ≥ 0 "`FUV_amp` must be ≥ 0, got $FUV_amp" | ||
@assert 0.06 ≤ FUV_lambda ≤ 0.08 "`FUV_lambda` must be in between [0.06, 0.08], got $FUV_lambda" | ||
@assert NUV_amp ≥ 0 "`NUV_amp` must be ≥ 0, got $NUV_amp" | ||
@assert 0.20 ≤ NUV_lambda ≤ 0.24 "`NUV_lambda` must be in between [0.20, 0.24], got $NUV_lambda" | ||
@assert SIL1_amp ≥ 0 "`SIL1_amp` must be ≥ 0, got $SIL1_amp" | ||
@assert 7 ≤ SIL1_lambda ≤ 13 "`SIL1_lambda` must be in between [7, 13], got $SIL1_lambda" | ||
@assert SIL2_amp ≥ 0 "`SIL2_amp` must be ≥ 0, got $SIL2_amp" | ||
@assert 15 ≤ SIL2_lambda ≤ 21 "`SIL2_lambda` must be in between [15, 21], got $SIL2_lambda" | ||
@assert FIR_amp ≥ 0 "`FIR_amp` must be ≥ 0, got $FIR_amp" | ||
@assert 20 ≤ FIR_lambda ≤ 30 "`FIR_lambda` must be in between [20, 30], got $FIR_lambda" | ||
end | ||
|
||
P92(BKG_amp, BKG_lambda, BKG_b, BKG_n, FUV_amp, FUV_lambda, FUV_b, FUV_n, | ||
NUV_amp, NUV_lambda, NUV_b, NUV_n, SIL1_amp, SIL1_lambda, SIL1_b, | ||
SIL1_n, SIL2_amp, SIL2_lambda, SIL2_b, SIL2_n, FIR_amp, FIR_lambda, | ||
FIR_b, FIR_n) = | ||
P92(promote(BKG_amp, BKG_lambda, BKG_b, BKG_n, FUV_amp, FUV_lambda, FUV_b, FUV_n, | ||
NUV_amp, NUV_lambda, NUV_b, NUV_n, SIL1_amp, SIL1_lambda, SIL1_b, | ||
SIL1_n, SIL2_amp, SIL2_lambda, SIL2_b, SIL2_n, FIR_amp, FIR_lambda, | ||
FIR_b, FIR_n)...) | ||
|
||
bounds(::Type{<:P92}) = (10, 10000000) | ||
|
||
function (law::P92)(wave::T) where T | ||
checkbounds(law, wave) || return zero(float(T)) | ||
|
||
x = aa_to_invum(wave) | ||
lam = 1.0 / x # wavelength is in microns | ||
|
||
axav = _p92_single_term(lam, law.BKG_amp, law.BKG_lambda, law.BKG_b, law.BKG_n) | ||
axav += _p92_single_term(lam, law.FUV_amp, law.FUV_lambda, law.FUV_b, law.FUV_n) | ||
axav += _p92_single_term(lam, law.NUV_amp, law.NUV_lambda, law.NUV_b, law.NUV_n) | ||
axav += _p92_single_term(lam, law.SIL1_amp, law.SIL1_lambda, law.SIL1_b, law.SIL1_n) | ||
axav += _p92_single_term(lam, law.SIL2_amp, law.SIL2_lambda, law.SIL2_b, law.SIL2_n) | ||
axav += _p92_single_term(lam, law.FIR_amp, law.FIR_lambda, law.FIR_b, law.FIR_n) | ||
|
||
return axav | ||
end | ||
|
||
# function for calculating a single P92 term | ||
function _p92_single_term(x::Real, amplitude::Real, cen_wave::Real, b::Real, n::Real) | ||
l_norm = x / cen_wave | ||
return amplitude / (l_norm^n + inv(l_norm^n) + b) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll want to show that these are keyword arguments with the semicolon
(and propagate the spacing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I clicked on resolved by mistake. 😅