diff --git a/Project.toml b/Project.toml index 4c12dca..b3f3df8 100644 --- a/Project.toml +++ b/Project.toml @@ -10,10 +10,20 @@ FITSIO = "525bcba6-941b-5504-bd06-fd0dc1a4d2eb" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" UnitfulAstro = "6112ee07-acf9-5e0f-b108-d242c714bf9f" +[weakdeps] +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + +[extensions] +MakieExt = "Makie" + [compat] BSplineKit = "0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19" DataDeps = "0.7" FITSIO = "0.13.0, 0.14, 0.15, 0.16.1, 0.17" +Makie = "0.21.18, 0.22" Unitful = "0.17.0, 1" UnitfulAstro = "0.3.0, 0.4, 1" julia = "1.6" + +[extras] +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" diff --git a/docs/Project.toml b/docs/Project.toml index 6700a49..920993b 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,9 +1,9 @@ [deps] +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" DustExtinction = "fb44c06c-c62f-5397-83f5-69249e0a3c8e" LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" -Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" UnitfulAstro = "6112ee07-acf9-5e0f-b108-d242c714bf9f" @@ -11,7 +11,6 @@ UnitfulAstro = "6112ee07-acf9-5e0f-b108-d242c714bf9f" Documenter = "1" LaTeXStrings = "1" Measurements = "2" -Plots = "1" Unitful = "1" UnitfulAstro = "1" diff --git a/docs/make.jl b/docs/make.jl index aff14ef..55563b0 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,11 +1,15 @@ using Documenter using DustExtinction +using CairoMakie + +CairoMakie.activate!(type="png", px_per_unit=3) DocMeta.setdocmeta!(DustExtinction, :DocTestSetup, :(using DustExtinction); recursive = true) +MakieExt = Base.get_extension(DustExtinction, :MakieExt) include("pages.jl") makedocs(; - modules = [DustExtinction], + modules = [DustExtinction, MakieExt], sitename = "DustExtinction.jl", format = Documenter.HTML(; prettyurls = get(ENV, "CI", nothing) == "true", diff --git a/docs/pages.jl b/docs/pages.jl index dc1aaf7..03b8fae 100644 --- a/docs/pages.jl +++ b/docs/pages.jl @@ -1,5 +1,6 @@ pages = [ "Home" => "index.md", "Color Laws" => "color_laws.md", - "Dust Maps" => "dust_maps.md" -] \ No newline at end of file + "Dust Maps" => "dust_maps.md", + "Plotting" => "plotting.md", +] diff --git a/docs/plots.jl b/docs/plots.jl deleted file mode 100644 index 3957e79..0000000 --- a/docs/plots.jl +++ /dev/null @@ -1,187 +0,0 @@ -using Plots, LaTeXStrings -import DustExtinction: ccm89_ca, ccm89_cb, od94_ca, od94_cb, - # TODO: replace deprecated invum functions - ccm89_invum, vcg04_invum, gcc09_invum, m14_invum, - f99_invum, f04_invum, f19_invum, - CAL00, FM90, G16, SFD98Map, - # Kludge until Makie PR merged - aa_to_invum - -dir = joinpath(@__DIR__, "src", "assets") - -#-------------------------------------------------------------------------------- -# ccm89 - -w = range(0.3, 10.0, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = ccm89_invum.(w, rv, Ref(ccm89_ca), Ref(ccm89_cb)) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "ccm89_plot.svg")) - -#-------------------------------------------------------------------------------- -# od94 - -w = range(0.3, 10.0, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = ccm89_invum.(w, rv, Ref(od94_ca), Ref(od94_cb)) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "od94_plot.svg")) - -#-------------------------------------------------------------------------------- -# cal00 - -w = range(0.46, 8.3, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.0, 4.05, 5.0, 6.0] - m = CAL00(Rv=rv).(aa_to_invum.(w)) # kludge until Makie - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "cal00_plot.svg")) - -#-------------------------------------------------------------------------------- -# sfd98 - -l = range(-pi, pi, length=400) -b = range(-pi/64, pi/64, length=300) -dustmap = SFD98Map() -m = [dustmap(li, bj) for li in l, bj in b] -heatmap(l, b, m, label="", transpose=true, colorbar_title="E(B-V)") -xlabel!("l (rad)") -ylabel!("b (rad)") -savefig(joinpath(dir, "sfd98_plot.svg")) - -#-------------------------------------------------------------------------------- -# gcc09 - -w = range(3.3, 11.0, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = gcc09_invum.(w, rv) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "gcc09_plot.svg")) - -#-------------------------------------------------------------------------------- -# vcg04 - -w = range(3.3, 8.0, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = vcg04_invum.(w, rv) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "vcg04_plot.svg")) - -#-------------------------------------------------------------------------------- -# F99 - -w = range(0.3, 10.0, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = f99_invum.(w, rv) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "F99_plot.svg")) - -#-------------------------------------------------------------------------------- -# F04 - -w = range(0.3, 10.0, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = f04_invum.(w, rv) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "F04_plot.svg")) - -#-------------------------------------------------------------------------------- -# F19 - -w = range(0.3, 8.7, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = f19_invum.(w, rv) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "F19_plot.svg")) - -#-------------------------------------------------------------------------------- -# M14 - -w = range(0.3, 3.3, length=1000) -plot(legend=:topleft) -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = m14_invum.(w, rv) - plot!(w, m, label="Rv=$rv") -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "M14_plot.svg")) - -#-------------------------------------------------------------------------------- -# FM90 - -w = range(3.8, 8.6, step = 0.001) -x = 1e4 ./ w -plot(legend=:top) - -m1 = FM90().(x) -plot!(w, m1, label = "total") - -m2 = FM90(c3=0.0, c4=0.0).(x) -plot!(w, m2, label = "linear term") - -m3 = FM90(c1=0.0, c2=0.0, c4=0.0).(x) -plot!(w, m3, label = "bump term") - -m4 = FM90(c1=0.0, c2=0.0, c3=0.0).(x) -plot!(w, m4, label = "FUV rise term") - -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"E(x - V)/E(B - V)") -savefig(joinpath(dir, "FM90_plot.svg")) - -#-------------------------------------------------------------------------------- -# G16 - -# Fixed f_A = 1.0, variable Rv -w = range(0.3, 10.0, length=1000) -x = 1e4 ./ w -plot() -for rv in [2.0, 3.1, 4.0, 5.0, 6.0] - m = G16(Rv=rv, f_A=1.0).(x) - plot!(w, m, label="Rv=$rv", legendtitle="f_A = 1.0", legend=:topleft) -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "G16_fixed_f_A_plot.svg")) - -# Fixed Rv = 3.1, variable f_A -plot() -for f_A in [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] - m = G16(Rv=3.1, f_A=f_A).(x) - plot!(w, m, label="f_A=$f_A", legendtitle="Rv = 3.1", legend=:topleft) -end -xlabel!(L"x\ \left[\mu m ^{-1}\right]") -ylabel!(L"A(x)/A(V)") -savefig(joinpath(dir, "G16_fixed_Rv_plot.svg")) diff --git a/docs/src/assets/F04_plot.svg b/docs/src/assets/F04_plot.svg deleted file mode 100644 index d976f6c..0000000 --- a/docs/src/assets/F04_plot.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/F19_plot.svg b/docs/src/assets/F19_plot.svg deleted file mode 100644 index ad47d9d..0000000 --- a/docs/src/assets/F19_plot.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/F99_plot.svg b/docs/src/assets/F99_plot.svg deleted file mode 100644 index 79ed36c..0000000 --- a/docs/src/assets/F99_plot.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/FM90_plot.svg b/docs/src/assets/FM90_plot.svg deleted file mode 100644 index 8d42d0f..0000000 --- a/docs/src/assets/FM90_plot.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/G16_fixed_Rv_plot.svg b/docs/src/assets/G16_fixed_Rv_plot.svg deleted file mode 100644 index 07f34e6..0000000 --- a/docs/src/assets/G16_fixed_Rv_plot.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/G16_fixed_f_A_plot.svg b/docs/src/assets/G16_fixed_f_A_plot.svg deleted file mode 100644 index 9c6e3e2..0000000 --- a/docs/src/assets/G16_fixed_f_A_plot.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/M14_plot.svg b/docs/src/assets/M14_plot.svg deleted file mode 100644 index a4cfe64..0000000 --- a/docs/src/assets/M14_plot.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/cal00_plot.svg b/docs/src/assets/cal00_plot.svg deleted file mode 100644 index cca66da..0000000 --- a/docs/src/assets/cal00_plot.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/ccm89_plot.svg b/docs/src/assets/ccm89_plot.svg deleted file mode 100644 index 6931812..0000000 --- a/docs/src/assets/ccm89_plot.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/gcc09_plot.svg b/docs/src/assets/gcc09_plot.svg deleted file mode 100644 index 4dc35e5..0000000 --- a/docs/src/assets/gcc09_plot.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/logo.svg b/docs/src/assets/logo.svg deleted file mode 100644 index a6002a1..0000000 --- a/docs/src/assets/logo.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/docs/src/assets/od94_plot.svg b/docs/src/assets/od94_plot.svg deleted file mode 100644 index 5fc5d16..0000000 --- a/docs/src/assets/od94_plot.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/sfd98_plot.svg b/docs/src/assets/sfd98_plot.svg deleted file mode 100644 index c2abce4..0000000 --- a/docs/src/assets/sfd98_plot.svg +++ /dev/null @@ -1,1593 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/vcg04_plot.svg b/docs/src/assets/vcg04_plot.svg deleted file mode 100644 index 239c465..0000000 --- a/docs/src/assets/vcg04_plot.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/color_laws.md b/docs/src/color_laws.md index 096fa5a..91c9376 100644 --- a/docs/src/color_laws.md +++ b/docs/src/color_laws.md @@ -1,3 +1,8 @@ +```@setup plotting +using DustExtinction, CairoMakie +using DustExtinction: ExtinctionLaw +include("./plotting.jl") +``` # [Color laws](@id laws) @@ -56,7 +61,7 @@ true ``` -## Advanced Usage +## [Advanced Usage](@id color_laws_advanced_usage) The color laws also have built-in support for uncertainties using [Measurements.jl](https://github.com/juliaphysics/measurements.jl). @@ -138,7 +143,9 @@ and is loosely associated with the size of the dust grains in the interstellar m ### Clayton, Cardelli and Mathis (1989) -![](assets/ccm89_plot.svg) +```@example plotting +lplot(CCM89) # hide +``` ```@docs CCM89 @@ -146,7 +153,9 @@ CCM89 ### O'Donnell 1994 -![](assets/od94_plot.svg) +```@example plotting +lplot(OD94) # hide +``` ```@docs OD94 @@ -154,7 +163,9 @@ OD94 ### Calzetti et al. (2000) -![](assets/cal00_plot.svg) +```@example plotting +lplot(CAL00) # hide +``` ```@docs CAL00 @@ -162,7 +173,9 @@ CAL00 ### Valencic, Clayton, & Gordon (2004) -![](assets/vcg04_plot.svg) +```@example plotting +lplot(VCG04) # hide +``` ```@docs VCG04 @@ -170,7 +183,9 @@ VCG04 ### Gordon, Cartledge, & Clayton (2009) -![](assets/gcc09_plot.svg) +```@example plotting +lplot(GCC09) # hide +``` ```@docs GCC09 @@ -178,7 +193,9 @@ GCC09 ### Fitzpatrick (1999) -![](assets/F99_plot.svg) +```@example plotting +lplot(F99) # hide +``` ```@docs F99 @@ -186,7 +203,9 @@ F99 ### Fitzpatrick (2004) -![](assets/F04_plot.svg) +```@example plotting +lplot(F04) # hide +``` ```@docs F04 @@ -194,7 +213,9 @@ F04 ### Fitzpatrick (2019) -![](assets/F19_plot.svg) +```@example plotting +lplot(F19) # hide +``` ```@docs F19 @@ -202,46 +223,55 @@ F19 ### Maiz Apellaniz et al. (2014) -![](assets/M14_plot.svg) - -```@docs -M14 +```@example plotting +lplot(M14) # hide ``` -## API/Reference - ```@docs -redden -deredden -DustExtinction.ExtinctionLaw -DustExtinction.bounds -DustExtinction.checkbounds +M14 ``` -### Fittable Extinction Laws +## Fittable Extinction Laws -#### Fitzpatrick & Massa (1990) +### Fitzpatrick & Massa (1990) -![](assets/FM90_plot.svg) +```@example plotting +lplot(FM90) # hide +``` ```@docs FM90 ``` -### Mixture Extinction Laws +## Mixture Extinction Laws -#### Gordon et al. (2003) +### Gordon et al. (2003) ```@docs G03_SMCBar G03_LMCAve ``` -#### Gordon et al. (2016) +### Gordon et al. (2016) -![](assets/G16_fixed_f_A_plot.svg) -![](assets/G16_fixed_Rv_plot.svg) +```@example plotting +mplot(G16, (2.0, 3.1, 4.0, 5.0, 6.0), 1.0) # hide +``` + +```@example plotting +mplot(G16, 3.1, 0.0:0.2:1.0) # hide +``` ```@docs G16 ``` + +## API/Reference + +```@docs +redden +deredden +DustExtinction.ExtinctionLaw +DustExtinction.bounds +DustExtinction.checkbounds +``` diff --git a/docs/src/dust_maps.md b/docs/src/dust_maps.md index 2326eab..3b322d1 100644 --- a/docs/src/dust_maps.md +++ b/docs/src/dust_maps.md @@ -1,3 +1,9 @@ +```@setup plotting +using DustExtinction, CairoMakie +using DustExtinction: ExtinctionLaw +include("./plotting.jl") +``` + # [Dust Maps](@id maps) ## Usage @@ -31,6 +37,10 @@ julia> [dustmap(l[i], b[j]) for i in 1:length(l), j in 1:length(b)] ``` +```@example plotting +dplot() # hide +``` + ## Advanced Usage Our dust maps also have native support for `Unitful.jl` and `Measurements.jl`. @@ -56,10 +66,6 @@ julia> dustmap(l, b) ## API/Reference -### Schlegel, Finkbeiner and Davis (1998) - -![](assets/sfd98_plot.svg) - ```@docs SFD98Map ``` diff --git a/docs/src/plotting.jl b/docs/src/plotting.jl new file mode 100644 index 0000000..3129123 --- /dev/null +++ b/docs/src/plotting.jl @@ -0,0 +1,124 @@ +""" + lplot(law::ExtinctionLaw; args...) + +Rv law plot with automatic axis labels. +""" +lplot(law::ExtinctionLaw; args...) = Makie.lines( + law; + axis = (; + xlabel = Makie.rich("x [μm", Makie.superscript("-1"), "]"), + ylabel = Makie.rich("A(x) / A(V)"), + ), + args..., +) + +""" + lplot(law::Type{<:ExtinctionLaw}; args...) + +Rv law series plot with automatic axis labels. +""" +function lplot(law::Type{<:ExtinctionLaw}; args...) + # Dummy plot + fig, ax, p = lplot(law()) + + for Rv in (2.0, 3.1, 4.0, 5.0, 6.0) + Makie.lines!(ax, law(Rv); label=Makie.rich("Rv = $(Rv)"), args...) + end + + Makie.axislegend(ax; position=:lt) + + fig +end + +""" + lplot(law::FM90; args...) + +Fittable law plot with automatic axis labels. +""" +lplot(law::FM90; args...) = Makie.lines(law; + axis = (; + xlabel = Makie.rich("x [μm", Makie.superscript("-1"), "]"), + ylabel = Makie.rich("(E(λ) - V) / E(B - V)"), + ), + args..., +) + +""" + lplot(law::FM90; args...) + +Fittable law series plot with automatic axis labels. +""" +function lplot(law::Type{<:FM90}; args...) + # m1 + fig, ax, p = lplot(law(); label="total") + + # m2 + Makie.lines!(ax, law(c3=0.0, c4=0.0); label="linear term") + + # m3 + Makie.lines!(ax, law(c1=0.0, c2=0.0, c4=0.0); label="bump term") + + # m4 + Makie.lines!(ax, law(c1=0.0, c2=0.0, c3=0.0); label="FUV rise term") + + # for Rv in (2.0, 3.1, 4.0, 5.0, 6.0) + # Makie.lines!(ax, law(Rv); label=Makie.rich("Rv = $(Rv)"), args...) + # end + + Makie.axislegend(ax; position=:lt) + + fig +end + +""" + mplot(law::Type{G16}, Rvs, f_A::Real; args...) + +Mixture law plot with automatic axis labels. +""" +function mplot(law::Type{G16}, Rvs, f_A::Real; args...) + # Dummy plot + fig, ax, p = lplot(law()) + + for Rv in Rvs + Makie.lines!(ax, law(; Rv, f_A); label=Makie.rich("Rv = $(Rv)"), args...) + end + + Makie.axislegend(ax, "f_A = $(f_A)"; position=:lt) + + fig +end + +""" + mplot(law::Type{G16}, Rvs, f_A::Real; args...) + +Mixture law series plot with automatic axis labels. +""" +function mplot(law::Type{G16}, Rv::Real, f_As; args...) + # Dummy plot + fig, ax, p = lplot(law()) + + for f_A in f_As + Makie.lines!(ax, law(; Rv, f_A); label=Makie.rich("f_A = $(f_A)"), args...) + end + + Makie.axislegend(ax, "Rv = $(Rv)"; position=:lt) + + fig +end + +""" + dplot(dustmap=SFD98Map(); lrange=(-3, 3), brange=(-1, 1)) + +Heatmap of the given `dustmap`, with galactic longitude ``(l)`` on the x-axis and galactic latitude ``(b)`` on the y-axis. Angles are displayed in degrees by default. The plot axis ranges for both are set by `lrange` and `brange`, respectively. +""" +function dplot(dustmap=SFD98Map(); lrange=(-3, 3), brange=(-1, 1)) + l = range(lrange..., length=400) + b = range(brange..., length=300) + + fig, ax, p = heatmap(l, b, dustmap; colorrange=(0, 3), colormap=:cividis) + ax.xlabel = "l [°]" + ax.ylabel = "b [°]" + Colorbar(fig[1, 2], p; label="E(B - V) [mag]") + + fig +end diff --git a/docs/src/plotting.md b/docs/src/plotting.md new file mode 100644 index 0000000..ac99369 --- /dev/null +++ b/docs/src/plotting.md @@ -0,0 +1,105 @@ +# [Plotting](@id plotting) + +DustExtinction.jl is designed to work automatically with many of Makie.jl's core plotting functions, which can then be composed together to form more complex figures. Below we show a few practical applications. + +!!! note + By default, all plots adopt the wavelength limits (in units of 1/μm) defined by [`DustExtinction.bounds`](@ref). + +## Model plot example +For a given [`DustExtinction.ExtinctionLaw`](@ref), Makie's usual PointBased plotting functions (e.g., [lines](https://docs.makie.org/stable/reference/plots/lines), [scatter](https://docs.makie.org/stable/reference/plots/scatter), [stairs](https://docs.makie.org/stable/reference/plots/stairs), etc.) should work right out-of-the-box: + +```@example a +using DustExtinction, CairoMakie +``` + +```@example a +model = CCM89() +``` + +```@example a +# Automatic limits defined by model +lines(model; linewidth=3, color=:cornflowerblue) # Or plot(model; [plot options]) +``` + +```@example a +# Custom limits +fig = Figure() +ax1 = Axis(fig[1, 1]) +ax2 = Axis(fig[1, 2]; limits=(3, 6, 0, 5)) + +lines!(ax1, model) +stairs!(ax2, model; color=:orange) + +linkyaxes!(ax1, ax2) + +fig +``` + +A predefined vector of wavelengths can also be passed to these plotting functions directly. Let's combine this with Makie's integration with Measurements.jl to visualize the underlying uncertainty in our data: + +```@example a +using Measurements, Unitful, UnitfulAstro + +wavs = let + x = range(2_000, 3_000; length=1_000) + x = x .± 1e5 * inv.(ustrip.(x)) # "Å" +end + +extinction = model.(wavs) # mag + +wavs_sampled, extinction_sampled = let + N_samples = 7 + wavs[range(begin, step=end ÷ N_samples; length=N_samples)], + extinction[range(begin, step=end ÷ N_samples; length=N_samples)] +end + +fig, ax, p = band(wavs, extinction; alpha=0.5, label="model uncertainty") + +lines!(ax, wavs, extinction; label="model: CCM89") + +scatter!(ax, wavs_sampled, extinction_sampled; color=:orange, label="observations") + +# Currently ambiguous for both x and y being Measurements +# so we focus on the y-uncertainty instead +errorbars!(ax, Measurements.value.(wavs_sampled), extinction_sampled; + whiskerwidth = 10, + color = :orange, + label = "obs. uncertainty", +) + +axislegend() +ax.xlabel = "Wavelength [Å]" +ax.ylabel = "A(x) / A(V) [mag]" + +fig +``` + +## Dust map example +A [`heatmap`](https://docs.makie.org/stable/reference/plots/heatmap#heatmap) plot also works automatically for [`DustExtinction.SFD98Map`](@ref): + +```@example a +dustmap = SFD98Map() + +heatmap(dustmap; colorrange=(0, 3), colormap=:cividis) # Or plot(dustmap; [plot kwargs]) +``` + +Similarly to the extinction law plots, we can create our own custom dust map plots. Here is an example using [Unitful.jl](https://painterqubits.github.io/Unitful.jl/stable/)'s integration: + +```@example a +using Unitful + +lrange = range(-1, 1; length=400)u"°" +brange = range(-0.25, 0.25; length=300)u"°" + +fig, ax, p = heatmap(lrange, brange, dustmap; colorrange=(0, 3), colormap=:cividis) + +ax.xlabel = "l [°]" +ax.ylabel = "b [°]" + +Colorbar(fig[1, 2], p; label="E(B - V) [mag]") + +fig +``` + +!!! tip + See [plotting.jl](https://github.com/JuliaAstro/DustExtinction.jl/blob/docs-makie/docs/src/plotting.jl) for more plotting examples. The convenience functions defined there are used to generate the other figures shown in this documentation. diff --git a/ext/MakieExt.jl b/ext/MakieExt.jl new file mode 100644 index 0000000..61d81f1 --- /dev/null +++ b/ext/MakieExt.jl @@ -0,0 +1,37 @@ +module MakieExt + using DustExtinction + import DustExtinction: bounds, aa_to_invum, ExtinctionLaw + import Makie as M + + # Ex: plot(CCM89()) + function M.convert_arguments(P::M.PointBased, law::ExtinctionLaw) + aa = range(bounds(law)...; length=1_000) + m = map(law, aa) + invum = map(aa_to_invum, aa) + return M.convert_arguments(P, invum, m) + end + M.plottype(::ExtinctionLaw) = M.Lines + + # Ex: plot(wavs, CCM89()) + function M.convert_arguments(P::M.PointBased, x, law::ExtinctionLaw) + m = map(law, x) + M.convert_arguments(P, x, m) + end + M.plottype(x, ::ExtinctionLaw) = M.Lines + + # Ex: heatmap(SFD98Map()) + function M.convert_arguments(P::M.CellGrid, dustmap::SFD98Map) + l = range(-3, 3; length=400) + b = range(-1, 1; length=300) + m = [dustmap(li, bj) for li in l, bj in b] + return M.convert_arguments(P, l, b, m) + end + M.plottype(::SFD98Map) = M.Heatmap + + # Ex: heatmap(lrange, brange, SFD98Map()) + function M.convert_arguments(P::M.CellGrid, lrange, brange, dustmap::SFD98Map) + m = [dustmap(li, bj) for li in lrange, bj in brange] + return M.convert_arguments(P, lrange, brange, m) + end + M.plottype(x, y, ::SFD98Map) = M.Heatmap +end diff --git a/test/Project.toml b/test/Project.toml index 0bd039d..18d1eff 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,5 +1,6 @@ [deps] DataDeps = "124859b0-ceae-595e-8997-d05f6a7a8dfe" +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/makie_recipes.jl b/test/makie_recipes.jl new file mode 100644 index 0000000..edbc223 --- /dev/null +++ b/test/makie_recipes.jl @@ -0,0 +1,33 @@ +import Makie: Makie as M + +law = CCM89() +aa = range(bounds(law)...; length=1_000) +xs = invum = map(DustExtinction.aa_to_invum, aa) +ys = map(law, aa) +law_plot_args(wavs, vals) = (M.Point{2, Float64}[[x, y] for (x, y) in zip(wavs, vals)], ) + +@testset "PointBased" begin + @test all(M.convert_arguments(M.PointBased(), law) .≈ law_plot_args(xs, ys)) + @test all(M.convert_arguments(M.PointBased(), aa, law) .≈ law_plot_args(aa, ys)) + @test M.plottype(law) == M.Lines + @test M.plottype(aa, law) == M.Lines +end + +lrange = range(-3, 3; length=400) +(lmin, lmax), llength, lstep = extrema(lrange), length(lrange) + 1, step(lrange) +lrange_plot = range(lmin - lstep/2, lmax + lstep/2; length=llength) |> collect + +brange = range(-1, 1; length=300) +(bmin, bmax), blength, bstep = extrema(brange), length(brange) + 1, step(brange) +brange_plot = range(bmin - bstep/2, bmax + bstep/2; length=blength) |> collect + +dustmap = SFD98Map() +m_plot = Float32[dustmap(li, bj) for li in lrange, bj in brange] +dustmap_plot_args = (lrange_plot, brange_plot, m_plot, ) + +@testset "CellGrid" begin + @test all(M.convert_arguments(M.CellGrid(), dustmap) .≈ dustmap_plot_args) + @test all(M.convert_arguments(M.CellGrid(), lrange, brange, dustmap) .≈ dustmap_plot_args) + @test M.plottype(dustmap) == M.Heatmap + @test M.plottype(lrange, brange, dustmap) == M.Heatmap +end diff --git a/test/runtests.jl b/test/runtests.jl index 3557455..2efdcc7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -10,6 +10,7 @@ using Test, Measurements, Unitful, UnitfulAstro, Random include("dust_maps.jl") include("fittable_laws.jl") include("mixture_laws.jl") + VERSION ≥ v"1.9" && include("makie_recipes.jl") @testset "interfaces" begin for LAW in [CCM89, OD94, CAL00, GCC09, VCG04, FM90, G16, F99, F04, F19, M14]