Skip to content

Commit

Permalink
Merge pull request #168 from TidierOrg/0.10.0-dev
Browse files Browse the repository at this point in the history
0.10.0 dev
  • Loading branch information
rdboyes authored Feb 8, 2025
2 parents 9e2472b + a331ec5 commit 4c536bd
Show file tree
Hide file tree
Showing 18 changed files with 337 additions and 243 deletions.
12 changes: 8 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ uuid = "337ecbd1-5042-4e2a-ae6f-ca776f97570a"
authors = [
"Randall Boyes <33524191+rdboyes@users.noreply.github.com> and contributors",
]
version = "0.10.0"
version = "0.11.0"

[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Expand All @@ -15,9 +15,11 @@ Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
Format = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8"
GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
KernelDensity = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b"
Loess = "4345ca2d-374a-55d4-8d30-97f9976e7612"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
Parquet2 = "98572fba-bba0-415d-956f-fa77e587d26d"
PooledArrays = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand All @@ -27,18 +29,20 @@ TidierData = "fe2206b3-d496-4ee9-a338-6a095c4ece80"
CairoMakie = "0.12, 0.13"
CategoricalArrays = "0.10"
ColorSchemes = "3.24"
Colors = "0.12, 0.13"
DataFrames = "1.5"
Colors = "0.13"
DataFrames = "1.7"
Dates = "1.10"
FixedPointNumbers = "0.8"
Format = "1.3"
GLM = "1.9"
Images = "0.26.2"
KernelDensity = "0.6"
Loess = "0.6"
Makie = "0.21, 0.22"
PooledArrays = "1.4"
Reexport = "1.2"
Test = "1.10"
TidierData = "0.15, 0.16, 0.17, 0.18"
TidierData = "0.16"
julia = "1.10"

[extras]
Expand Down
Binary file added assets/makie_legend.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 40 additions & 15 deletions src/addplots.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@

function get_options(geom_list)
options = Dict()
palette = Dict()
legend = Dict()
for geom in geom_list
merge!(options, geom.axis_options)
merge!(options, geom.axis_options.opt)
merge!(palette, geom.axis_options.palette)
merge!(legend, geom.axis_options.legend_options)
end
return options
return AxisOptions(options, palette, legend)
end

function Base.:+(x::GGPlot, y::Union{Geom,Vector{Geom},Aesthetics,AxisOptions,FacetOptions,Attributes}...)::GGPlot
Expand All @@ -15,33 +18,55 @@ function Base.:+(x::GGPlot, y::Union{Geom,Vector{Geom},Aesthetics,AxisOptions,Fa
facet = [i for i in y if i isa FacetOptions]
facet_options = length(facet) == 0 ? nothing : facet[end]

legend_options = x.legend_options
for legend in [i.legend_options for i in y if i isa AxisOptions]
for (scale, options) in legend
opt = x.axis_options.opt
palette = x.axis_options.palette
legend_options = x.axis_options.legend_options

for item in [i for i in y if typeof(i) <:
Union{Geom,Vector{Geom},AxisOptions}]

if item isa Vector{Geom}
item = get_options(item)
end

o = item isa AxisOptions ? item.opt :
item.axis_options.opt
p = item isa AxisOptions ? item.palette :
item.axis_options.palette
l = item isa AxisOptions ? item.legend_options :
item.axis_options.legend_options

opt = merge(opt, o)

for (scale, options) in p
palette[scale] = options
end

for (scale, options) in l
if haskey(legend_options, scale)
merge!(legend_options[scale], options)
legend_options[scale] = merge(legend_options[scale], options)
else
legend_options[scale] = options
end
end
end

combined_axis_options = AxisOptions(
opt,
palette,
legend_options
)

result = GGPlot(
vcat(x.geoms, # if there are geoms or lists of geoms, append them to the ggplot's geoms
[i for i in y if i isa Geom],
[i for i in y if i isa Vector{Geom}]...),
merge(x.default_aes, # if there are aes specs, make them the ggplot's defaults
[i.named for i in y if i isa Aesthetics]...),
x.data, # the default data is passed on to the final ggplot
merge(x.axis_options, # get any axis options out of the geoms into one location
[i.axis_options for i in y if i isa Geom]...,
[get_options(i) for i in y if i isa Vector{Geom}]...,
[i.opt for i in y if i isa AxisOptions]...),
combined_axis_options,
theme,
legend_options,
facet_options,
merge(x.palette,
[i.palette for i in y if i isa AxisOptions]...)
facet_options
)

return result
Expand Down
1 change: 0 additions & 1 deletion src/attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ const _ggplot_to_makie = Dict{Symbol,Symbol}(
:glow => :glowwidth,
:glowcolour => :glowcolor,
:errorbar_direction => :direction,
:label => :text,
:palette => :colormap
);

Expand Down
12 changes: 8 additions & 4 deletions src/convert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ try_convert(::Type{Any}, v, ::Any, ::Any) = v

function try_convert(T::Type, v::S, arg, fname) where {S}
try
if typeof(v) == T
return v
end

retvalue = typeof(v) <: T || T == Symbol ?
T(v) :
parse(T, v)
Expand Down Expand Up @@ -58,26 +62,26 @@ end

# aes_col is a Number

function convert_aes_type(aes_col::AbstractVector{T}, ::Type{Colors.Colorant}, col::Symbol) where {T <: Number}
function convert_aes_type(aes_col::AbstractVector{T}, ::Type{Colors.Colorant}, col::Symbol) where {T<:Number}
verbose[] && println("Converting $col to Colorant")
return _default_continuous_palette(aes_col)
end

function convert_aes_type(aes_col::AbstractVector{T}, ::Type{Integer}, col::Symbol) where {T <: Number}
function convert_aes_type(aes_col::AbstractVector{T}, ::Type{Integer}, col::Symbol) where {T<:Number}
verbose[] && println("Converting $col to Integer")
return round.(Int, aes_col)
end

# aes_col is a String

function convert_aes_type(aes_col::AbstractVector{T}, ::Type{Colorant}, col::Symbol) where
{T <: AbstractString}
{T<:AbstractString}
verbose[] && println("Converting $col to Colorant")
return _default_discrete_palette(aes_col)
end

function convert_aes_type(aes_col::AbstractVector{T}, ::Type{Integer}, col::Symbol) where
{T <: AbstractString}
{T<:AbstractString}
verbose[] && println("Converting $col to Integer")
return levelcode.(CategoricalArray(aes_col))
end
Expand Down
42 changes: 28 additions & 14 deletions src/draw.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function as_GridLayout(plot::GGPlot)

# makie does not show strokes by default
if haskey(aes_dict_makie, :strokecolor) &&
!haskey(args_dict, "strokewidth")
!haskey(args_dict, "strokewidth")
args_dict["strokewidth"] = 1
end

Expand All @@ -80,8 +80,21 @@ function as_GridLayout(plot::GGPlot)
end

if !isnothing(plot.facet_options)
push!(aes_df_list,
DataFrame(facet=plot_data[!, plot.facet_options.wrap]))
if !isnothing(plot.facet_options.wrap)
# facet_wrap
push!(aes_df_list,
DataFrame(facet=plot_data[!, plot.facet_options.wrap]))
else
# facet_grid
rows = isnothing(plot.facet_options.rows) ?
repeat([nothing], nrow(plot_data)) :
plot_data[!, plot.facet_options.rows]
cols = isnothing(plot.facet_options.cols) ?
repeat([nothing], nrow(plot_data)) :
plot_data[!, plot.facet_options.cols]
push!(aes_df_list,
DataFrame(facet=[(r, c) for (r, c) in zip(rows, cols)]))
end
end

aes_df = hcat(aes_df_list...)
Expand Down Expand Up @@ -130,7 +143,7 @@ function as_GridLayout(plot::GGPlot)

# default palettes

plot_palette = plot.palette
plot_palette = plot.axis_options.palette

for palette_aes in intersect([:strokecolor, :color], Symbol.(names(aes_df)))
if !haskey(plot_palette, palette_aes)
Expand Down Expand Up @@ -187,7 +200,8 @@ function as_GridLayout(plot::GGPlot)
facet_positions, facet_labels, facet_boxes =
position_facets(facet_names,
plot.facet_options.nrow,
plot.facet_options.ncol)
plot.facet_options.ncol,
plot.facet_options.labels)
typed_aes_df.facet = [facet_positions[k] for k in typed_aes_df.facet]
end

Expand Down Expand Up @@ -231,7 +245,7 @@ function as_GridLayout(plot::GGPlot)

push!(optional_aes_data, Symbol(a) => data)

palette_function = get(plot.palette, :color, nothing)
palette_function = get(plot.axis_options.palette, :color, nothing)

isnothing(palette_function) && continue
!haskey(_legend_geom_symbols,
Expand All @@ -242,10 +256,10 @@ function as_GridLayout(plot::GGPlot)
labels_for_this_aes = subset(labels_aes_df,
:col_name => ByRow(x -> x == a))

if haskey(plot.legend_options, :color)
l_type = get(plot.legend_options[:color], :type, "na")
legend_title = get(plot.legend_options[:color], :name, " ")
draw_colorbar = get(plot.legend_options[:color], :guide, :auto)
if haskey(plot.axis_options.legend_options, :color)
l_type = get(plot.axis_options.legend_options[:color], :type, "na")
legend_title = get(plot.axis_options.legend_options[:color], :name, " ")
draw_colorbar = get(plot.axis_options.legend_options[:color], :guide, :auto)
if draw_colorbar == :auto
if l_type in ["continuous", "binned"]
draw_colorbar = :colorbar
Expand All @@ -261,8 +275,8 @@ function as_GridLayout(plot::GGPlot)
if draw_colorbar == :colorbar

colorbar_kwargs[:colormap] =
plot.legend_options[:color][:type] == "continuous" ? Symbol(plot.legend_options[:color][:palette]) :
cgrad(Symbol(plot.legend_options[:color][:palette]), 5, categorical=true)
plot.axis_options.legend_options[:color][:type] == "continuous" ? Symbol(plot.axis_options.legend_options[:color][:palette]) :
cgrad(Symbol(plot.axis_options.legend_options[:color][:palette]), 5, categorical=true)

colorbar_lowlim = min(
minimum(labels_for_this_aes.original_value), colorbar_lowlim)
Expand Down Expand Up @@ -316,7 +330,7 @@ function as_GridLayout(plot::GGPlot)
end

# rename and correct types on all axis options
for (arg, value) in plot.axis_options
for (arg, value) in plot.axis_options.opt
if !(Symbol(arg) in _internal_geom_options)
ex_type = get(_makie_expected_type, arg, Any)
converted_value = try_convert(ex_type, value, arg, "ggplot")
Expand Down Expand Up @@ -362,7 +376,7 @@ function as_GridLayout(plot::GGPlot)
l = (1, 2) => Makie.SpecApi.GridLayout(
Makie.SpecApi.Legend(elems, labels, title))
else
title = get(plot.legend_options[:color], :name, " ")
title = get(plot.axis_options.legend_options[:color], :name, " ")
l = (1, 2) => Makie.SpecApi.GridLayout(
Makie.SpecApi.Colorbar(; colorbar_kwargs...,
limits=(colorbar_lowlim, colorbar_highlim), label=title))
Expand Down
Loading

4 comments on commit 4c536bd

@rdboyes
Copy link
Member Author

@rdboyes rdboyes commented on 4c536bd Feb 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator Register

Release notes:

Added support for facet_grid

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error while trying to register: Action not recognized: Register

@rdboyes
Copy link
Member Author

@rdboyes rdboyes commented on 4c536bd Feb 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes/breaking changes:

added support for facet_grid
changes behaviour when multiple scales are added for the same aes

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/124593

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.11.0 -m "<description of version>" 4c536bda3bfebf6ac6b731bcaf81bde350ac50bf
git push origin v0.11.0

Please sign in to comment.