|
| 1 | +using Dierckx |
| 2 | + |
1 | 3 | # Convenience function for wavelength conversion |
2 | 4 | @inline aa_to_invum(wave::Real) = 10000 / wave |
3 | 5 |
|
@@ -228,3 +230,143 @@ function gcc09_invum(x::Real, Rv::Real) |
228 | 230 |
|
229 | 231 | return a + b / Rv |
230 | 232 | 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 |
0 commit comments