Skip to content

Commit c30f719

Browse files
authored
Merge pull request #30 from icweaver/F99
2 parents ad510f3 + 2101f98 commit c30f719

File tree

10 files changed

+1026
-5
lines changed

10 files changed

+1026
-5
lines changed

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
name = "DustExtinction"
22
uuid = "fb44c06c-c62f-5397-83f5-69249e0a3c8e"
33
license = "MIT"
4-
version = "0.7.0"
4+
version = "0.8.0"
55

66
[deps]
77
DataDeps = "124859b0-ceae-595e-8997-d05f6a7a8dfe"
8+
Dierckx = "39dd38d3-220a-591b-8e3c-4c3a8c710a94"
89
FITSIO = "525bcba6-941b-5504-bd06-fd0dc1a4d2eb"
910
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
1011
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
1112
UnitfulAstro = "6112ee07-acf9-5e0f-b108-d242c714bf9f"
1213

1314
[compat]
1415
DataDeps = "0.7"
16+
Dierckx = "0.4"
1517
FITSIO = "0.13.0, 0.14, 0.15"
1618
Parameters = "0.12"
1719
Unitful = "0.17.0, 1"

docs/plots.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using Plots, LaTeXStrings
2-
import DustExtinction: ccm89_ca, ccm89_cb, od94_ca, od94_cb, cal00_invum, ccm89_invum, vcg04_invum, gcc09_invum, FM90
2+
import DustExtinction: ccm89_ca, ccm89_cb, od94_ca, od94_cb, cal00_invum, ccm89_invum, vcg04_invum, gcc09_invum, f99_invum, FM90
33

44
dir = joinpath(@__DIR__, "src", "assets")
55

@@ -102,3 +102,16 @@ plot!(w, m4, label = "FUV rise term")
102102
xlabel!(L"\mu m ^{-1}")
103103
ylabel!(L"E(\lambda - V)/E(B - V)")
104104
savefig(joinpath(dir, "FM90_plot.svg"))
105+
106+
#--------------------------------------------------------------------------------
107+
# F99
108+
109+
w = range(0.3, 10.0, length=1000)
110+
plot()
111+
for rv in [2.0, 3.1, 4.0, 5.0, 6.0]
112+
m = f99_invum.(w, rv)
113+
plot!(w, m, label="Rv=$rv")
114+
end
115+
xlabel!(L"x\ \left[\mu m ^{-1}\right]")
116+
ylabel!(L"A(x)/A(V)")
117+
savefig(joinpath(dir, "F99_plot.svg"))

docs/src/assets/F99_plot.svg

Lines changed: 798 additions & 0 deletions
Loading

docs/src/assets/f99.bib

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@ARTICLE{1999PASP..111...63F,
2+
author = {{Fitzpatrick}, Edward L.},
3+
title = "{Correcting for the Effects of Interstellar Extinction}",
4+
journal = {\pasp},
5+
keywords = {ISM: DUST, EXTINCTION, Astrophysics},
6+
year = 1999,
7+
month = jan,
8+
volume = {111},
9+
number = {755},
10+
pages = {63-75},
11+
doi = {10.1086/316293},
12+
archivePrefix = {arXiv},
13+
eprint = {astro-ph/9809387},
14+
primaryClass = {astro-ph},
15+
adsurl = {https://ui.adsabs.harvard.edu/abs/1999PASP..111...63F},
16+
adsnote = {Provided by the SAO/NASA Astrophysics Data System}
17+
}

docs/src/color_laws.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ and is loosely associated with the size of the dust grains in the interstellar m
133133
- [`CAL00`](@ref)
134134
- [`VCG04`](@ref)
135135
- [`GCC09`](@ref)
136+
- [`F99`](@ref)
136137

137138
### Clayton, Cardelli and Mathis (1989)
138139

@@ -174,6 +175,14 @@ VCG04
174175
GCC09
175176
```
176177

178+
### Fitzpatrick (1999)
179+
180+
![](assets/F99_plot.svg)
181+
182+
```@docs
183+
F99
184+
```
185+
177186
## API/Reference
178187

179188
```@docs

docs/src/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ There are various citations relevant to this work. Please be considerate when us
3939
| [`GCC09`](@ref) | [Gordon, Cartledge, & Clayton (2009)](https://ui.adsabs.harvard.edu/abs/2009ApJ...705.1320G) | [download](assets/gcc09.bib) |
4040
| [`FM90`](@ref) | [Fitzpatrick & Massa (1990)](https://ui.adsabs.harvard.edu/abs/1990ApJS...72..163F) | [download](assets/fm90.bib) |
4141
| [`SFD98Map`](@ref) | [Schlegel, Finkbeiner and Davis (1998)](https://ui.adsabs.harvard.edu/abs/1998ApJ...500..525S) | [download](assets/sfd98.bib) |
42+
| [`F99`](@ref) | [Fitzpatrick (1999)](https://ui.adsabs.harvard.edu/abs/1999PASP..111...63F) | [download](assets/f99.bib) |
4243

4344
## Index
4445

src/DustExtinction.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export redden,
1313
OD94,
1414
GCC09,
1515
VCG04,
16+
F99,
1617
# Fittable laws
1718
FM90,
1819
# Dust maps
@@ -144,7 +145,7 @@ include("fittable_laws.jl")
144145
# at which point adding `(l::ExtinctionLaw)(wave::Quantity)` is possible, until then
145146
# using this code-gen does the trick but requires manually editing
146147
# instead of providing support for all <: ExtinctionLaw
147-
for law in [CCM89, OD94, CAL00, GCC09, VCG04, FM90]
148+
for law in [CCM89, OD94, CAL00, GCC09, VCG04, FM90, F99]
148149
(l::law)(wavelength::Quantity) = l(ustrip(u"Å", wavelength)) * u"mag"
149150
end
150151

src/color_laws.jl

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Dierckx
2+
13
# Convenience function for wavelength conversion
24
@inline aa_to_invum(wave::Real) = 10000 / wave
35

@@ -228,3 +230,143 @@ function gcc09_invum(x::Real, Rv::Real)
228230

229231
return a + b / Rv
230232
end
233+
234+
# x value above which FM90 parametrization used
235+
const f99_x_cutval_uv = aa_to_invum(2700)
236+
# required UV points for spline interpolation
237+
const f99_x_splineval_uv = aa_to_invum.((2700, 2600))
238+
239+
# Shape models used by F99 and F04
240+
function _curve_F99_method(
241+
x,
242+
Rv,
243+
c1,
244+
c2,
245+
c3,
246+
c4,
247+
x0,
248+
gamma,
249+
optnir_axav_x,
250+
optnir_axav_y,
251+
)
252+
253+
# add in required spline points, otherwise just spline points
254+
if x >= f99_x_cutval_uv
255+
xuv = (f99_x_splineval_uv..., x)
256+
else
257+
xuv = f99_x_splineval_uv
258+
end
259+
260+
# FM90 model and values
261+
fm90_model = FM90(c1=c1, c2=c2, c3=c3, c4=c4, x0=x0, gamma=gamma)
262+
# evaluate model and get results in A(x)/A(V)
263+
axav_fm90 = @. fm90_model(aa_to_invum(xuv)) / Rv + 1
264+
265+
# ignore the spline points
266+
if x >= f99_x_cutval_uv
267+
axav = last(axav_fm90)
268+
else
269+
# **Optical Portion**
270+
271+
# save spline points
272+
y_splineval_uv = axav_fm90
273+
274+
# spline points
275+
x_splineval_optir = (0.0, optnir_axav_x...)
276+
277+
# determine optical/IR values at spline points
278+
y_splineval_optir = (0.0, optnir_axav_y...)
279+
spline_x = (x_splineval_optir..., f99_x_splineval_uv...)
280+
spline_y = (y_splineval_optir..., y_splineval_uv...)
281+
spl = Spline1D(collect(spline_x), collect(spline_y), k=3)
282+
axav = spl(x)
283+
end
284+
285+
# return A(x)/A(V)
286+
return axav
287+
end
288+
289+
# spline points
290+
const f99_optnir_axav_x = aa_to_invum.((26500, 12200, 6000, 5470, 4670, 4110))
291+
const f99_nir_axebv_y_params = @. (0.265, 0.829) / 3.1
292+
293+
# c1-c2 correlation terms
294+
const f99_c3 = 3.23
295+
const f99_c4 = 0.41
296+
const f99_x0 = 4.596
297+
const f99_gamma = 0.99
298+
299+
"""
300+
F99(;Rv=3.1)
301+
302+
Fitzpatrick (1999) dust law.
303+
304+
Returns E(B-V) in magnitudes at the given wavelength relative to the
305+
extinction. This model applies to the UV and optical to NIR spectral range.
306+
The default support is [1000, 33333] Å. Outside of that range this will return
307+
0. Rv is the selective extinction and is valid over [2, 6]. A typical value for
308+
the Milky Way is 3.1.
309+
310+
# References
311+
[Fitzpatrick (1999)](https://ui.adsabs.harvard.edu/abs/1999PASP..111...63F/)
312+
"""
313+
@with_kw struct F99 <: ExtinctionLaw
314+
Rv::Float64 = 3.1
315+
end
316+
317+
function (law::F99)(wave::T) where T
318+
checkbounds(law, wave) || return zero(float(T))
319+
x = aa_to_invum(wave)
320+
return f99_invum(x, law.Rv)
321+
end
322+
323+
bounds(::Type{F99}) = (1000.0, 33333.3)
324+
325+
"""
326+
DustExtinction.f99_invum(x, Rv)
327+
328+
The algorithm used for the [`F99`](@ref) extinction law, given inverse microns and Rv. For more information, seek the original paper.
329+
"""
330+
function f99_invum(x::Real, Rv::Real)
331+
if !(0.3 <= x <= 10.0)
332+
error("out of bounds of F99, support is over $(bounds(F99)) angstrom")
333+
end
334+
335+
# terms depending on Rv
336+
c2 = @evalpoly (1. / Rv) -0.824 4.717
337+
# original F99 c1-c2 correlation
338+
c1 = @evalpoly c2 2.030 -3.007
339+
340+
# determine optical/IR values at spline points
341+
# Final optical spline point has a leading "-1.208" in Table 4
342+
# of F99, but that does not reproduce Table 3.
343+
# Additional indication that this is not correct is from
344+
# fm_unred.pro
345+
# which is based on FMRCURVE.pro distributed by Fitzpatrick.
346+
# --> confirmation needed?
347+
#
348+
# Also, fm_unred.pro has different coeff and # of terms,
349+
# but later work does not include these terms
350+
# --> check with Fitzpatrick?
351+
opt_axebv_y =
352+
(@evalpoly Rv -0.426 1.0044),
353+
(@evalpoly Rv -0.050 1.0016),
354+
(@evalpoly Rv 0.701 1.0016),
355+
(@evalpoly Rv 1.208 1.0032 -0.00033)
356+
357+
nir_axebv_y = @. f99_nir_axebv_y_params * Rv
358+
optnir_axebv_y = @. (nir_axebv_y..., opt_axebv_y...) / Rv
359+
360+
return _curve_F99_method(
361+
x,
362+
Rv,
363+
c1,
364+
c2,
365+
f99_c3,
366+
f99_c4,
367+
f99_x0,
368+
f99_gamma,
369+
f99_optnir_axav_x,
370+
optnir_axebv_y,
371+
)
372+
end

test/color_laws.jl

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ using DustExtinction: ccm89_invum,
55
gcc09_invum,
66
aa_to_invum,
77
ccm89_ca,
8-
ccm89_cb
8+
ccm89_cb,
9+
f99_invum
910

1011
@testset "helper" begin
1112
@test aa_to_invum(10000) 1
@@ -248,3 +249,40 @@ end
248249
@test ustrip.(reddening) ref_values[rv] rtol = 0.016
249250
end
250251
end
252+
253+
@testset "F99" begin
254+
# From Fitzpatrick (1999) Table 3
255+
256+
x_inv_microns = [0.377, 0.820, 1.667, 1.828, 2.141, 2.433, 3.704, 3.846]
257+
wave = 1e4 ./ x_inv_microns
258+
259+
ref_values = Dict(
260+
3.1 => [0.265, 0.829, 2.688, 3.055, 3.806, 4.315, 6.265, 6.591] ./ 3.1,
261+
)
262+
263+
# test defaults
264+
@test F99().(wave) ref_values[3.1] rtol = 0.016
265+
266+
for rv in keys(ref_values)
267+
law = F99(Rv = rv)
268+
output = @inferred map(law, wave)
269+
@test output ref_values[rv] rtol = 0.016
270+
271+
bad_waves = [100, 4e4]
272+
@test @inferred(map(law, bad_waves)) == zeros(length(bad_waves))
273+
@test_throws ErrorException f99_invum(aa_to_invum(bad_waves[1]), rv)
274+
@test_throws ErrorException f99_invum(aa_to_invum(bad_waves[2]), rv)
275+
276+
# uncertainties
277+
noise = rand(length(wave)) .* 0.01
278+
wave_unc = wave noise
279+
reddening = map(w -> @uncertain(law(w)), wave_unc)
280+
@test Measurements.value.(reddening) ref_values[rv] rtol = 1e-3
281+
282+
# Unitful
283+
wave_u = wave * u"angstrom"
284+
reddening = @inferred map(law, wave_u)
285+
@test eltype(reddening) <: Gain
286+
@test ustrip.(reddening) ref_values[rv] rtol = 0.016
287+
end
288+
end

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ include("dust_maps.jl")
1010
include("fittable_laws.jl")
1111

1212
@testset "interfaces" begin
13-
for LAW in [CCM89, OD94, CAL00, GCC09, VCG04, FM90]
13+
for LAW in [CCM89, OD94, CAL00, GCC09, VCG04, FM90, F99]
1414
@test bounds(LAW) == bounds(LAW())
1515
@test checkbounds(LAW, 1000) == checkbounds(LAW(), 1000)
1616
low, high = bounds(LAW)

0 commit comments

Comments
 (0)