Skip to content
This repository was archived by the owner on Jul 13, 2021. It is now read-only.

Commit 930e3d4

Browse files
authored
jk/tick fixes (#695)
1 parent 76e77c5 commit 930e3d4

File tree

4 files changed

+108
-83
lines changed

4 files changed

+108
-83
lines changed

src/makielayout/MakieLayout.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ using ..AbstractPlotting.Keyboard
77
using ..AbstractPlotting.Mouse
88
using ..AbstractPlotting: ispressed, is_mouseinside, get_scene, FigureLike
99
using ..AbstractPlotting: OpenInterval, Interval
10+
using ..AbstractPlotting: Automatic, automatic
1011
using Observables: onany
1112
import Observables
1213
import Formatting
@@ -84,7 +85,7 @@ export Textbox
8485
export linkxaxes!, linkyaxes!, linkaxes!
8586
export AxisAspect, DataAspect
8687
export autolimits!, limits!, reset_limits!
87-
export LinearTicks, WilkinsonTicks, MultiplesTicks, IntervalsBetween
88+
export LinearTicks, WilkinsonTicks, MultiplesTicks, IntervalsBetween, LogTicks
8889
export hidexdecorations!, hideydecorations!, hidedecorations!, hidespines!
8990
export tight_xticklabel_spacing!, tight_yticklabel_spacing!, tight_ticklabel_spacing!, tightlimits!
9091
export layoutscene

src/makielayout/lineaxis.jl

Lines changed: 62 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function LineAxis(parent::Scene; kwargs...)
4444
decorations[:minorticklines] = minorticklines
4545

4646
realticklabelalign = lift(ticklabelalign, pos_extents_horizontal, flipped, ticklabelrotation, typ = Any) do al, (pos, ex, hor), fl, rot
47-
if al !== AbstractPlotting.automatic
47+
if al !== automatic
4848
return al
4949
end
5050
if rot == 0 || !(rot isa Real)
@@ -112,7 +112,7 @@ function LineAxis(parent::Scene; kwargs...)
112112
actual_ticklabelspace = attrs[:actual_ticklabelspace]
113113

114114
onany(ticklabel_ideal_space, ticklabelspace) do idealspace, space
115-
s = if space == AbstractPlotting.automatic
115+
s = if space == automatic
116116
idealspace
117117
else
118118
space
@@ -437,21 +437,17 @@ function get_ticks(ticks, scale, formatter, vmin, vmax)
437437
end
438438

439439
# automatic with identity scaling uses WilkinsonTicks by default
440-
get_tickvalues(::AbstractPlotting.Automatic, ::typeof(identity), vmin, vmax) = get_tickvalues(WilkinsonTicks(5, k_min = 3), vmin, vmax)
440+
get_tickvalues(::Automatic, ::typeof(identity), vmin, vmax) = get_tickvalues(WilkinsonTicks(5, k_min = 3), vmin, vmax)
441441

442442
# fall back to identity if not overloaded scale function is used with automatic
443-
get_tickvalues(::AbstractPlotting.Automatic, F, vmin, vmax) = get_tickvalues(AbstractPlotting.automatic, identity, vmin, vmax)
443+
get_tickvalues(::Automatic, F, vmin, vmax) = get_tickvalues(automatic, identity, vmin, vmax)
444444

445445
# fall back to non-scale aware behavior if no special version is overloaded
446446
get_tickvalues(ticks, scale, vmin, vmax) = get_tickvalues(ticks, vmin, vmax)
447447

448-
# get_tickvalues(::AbstractPlotting.Automatic, ::typeof(log10), vmin, vmax) = get_tickvalues(Log10Ticks(), vmin, vmax)
449448

450-
# get_tickvalues(::AbstractPlotting.Automatic, ::typeof(log2), vmin, vmax) = get_tickvalues(Log2Ticks(), vmin, vmax)
451449

452-
# get_tickvalues(::AbstractPlotting.Automatic, ::typeof(log), vmin, vmax) = get_tickvalues(LogTicks(), vmin, vmax)
453-
454-
function get_ticks(ticks_and_labels::Tuple{Any, Any}, any_scale, ::AbstractPlotting.Automatic, vmin, vmax)
450+
function get_ticks(ticks_and_labels::Tuple{Any, Any}, any_scale, ::Automatic, vmin, vmax)
455451
n1 = length(ticks_and_labels[1])
456452
n2 = length(ticks_and_labels[2])
457453
if n1 != n2
@@ -475,55 +471,51 @@ _logbase(::typeof(log10)) = "10"
475471
_logbase(::typeof(log2)) = "2"
476472
_logbase(::typeof(log)) = "e"
477473

474+
475+
function get_ticks(::Automatic, scale::Union{typeof(log10), typeof(log2), typeof(log)},
476+
any_formatter, vmin, vmax)
477+
get_ticks(LogTicks(WilkinsonTicks(5, k_min = 3)), scale, any_formatter, vmin, vmax)
478+
end
479+
478480
# log ticks just use the normal pipeline but with log'd limits, then transform the labels
479-
function get_ticks(x, scale::Union{typeof(log10), typeof(log2), typeof(log)}, any_formatter, vmin, vmax)
480-
ticks_scaled = get_tickvalues(x, identity, scale(vmin), scale(vmax))
481+
function get_ticks(l::LogTicks, scale::Union{typeof(log10), typeof(log2), typeof(log)}, ::Automatic, vmin, vmax)
482+
ticks_scaled = get_tickvalues(l.linear_ticks, identity, scale(vmin), scale(vmax))
481483

482484
ticks = AbstractPlotting.inverse_transform(scale).(ticks_scaled)
483485

484-
if any_formatter === AbstractPlotting.automatic
485-
# here we assume that the labels are normal numbers, and we just superscript them
486-
labels_scaled = get_ticklabels(AbstractPlotting.automatic, ticks_scaled)
487-
labels = _logbase(scale) .* AbstractPlotting.UnicodeFun.to_superscript.(labels_scaled)
488-
else
489-
# otherwise the formatter has to handle the real tick numbers
490-
labels = get_ticklabels(any_formatter, ticks)
491-
end
486+
labels_scaled = get_ticklabels(automatic, ticks_scaled)
487+
labels = _logbase(scale) .* AbstractPlotting.UnicodeFun.to_superscript.(labels_scaled)
492488

493489
(ticks, labels)
494490
end
495491

496-
# logit ticks
497-
function get_ticks(x, scale::typeof(AbstractPlotting.logit), any_formatter, vmin, vmax)
492+
# function get_ticks(::Automatic, scale::typeof(AbstractPlotting.logit), any_formatter, vmin, vmax)
493+
# get_ticks(LogitTicks(WilkinsonTicks(5, k_min = 3)), scale, any_formatter, vmin, vmax)
494+
# end
495+
496+
logit_10(x) = log10(x / (1 - x))
497+
expit_10(x) = 1 / (1 + exp10(-x))
498498

499-
logit_10(x) = log10(x / (1 - x))
500-
expit_10(x) = 1 / (1 + exp10(-x))
501-
ticks_scaled = get_tickvalues(x, identity, logit_10(vmin), logit_10(vmax))
499+
# function get_ticks(l::LogitTicks, scale::typeof(AbstractPlotting.logit), ::Automatic, vmin, vmax)
500+
501+
# ticks_scaled = get_tickvalues(l.linear_ticks, identity, logit_10(vmin), logit_10(vmax))
502502

503-
ticks = expit_10.(ticks_scaled)
504-
505-
if any_formatter === AbstractPlotting.automatic
506-
base_labels = get_ticklabels(AbstractPlotting.automatic, ticks_scaled)
507-
508-
labels = map(ticks_scaled, base_labels) do t, bl
509-
if t == 0
510-
"¹/₂"
511-
elseif t < 0
512-
"10" * AbstractPlotting.UnicodeFun.to_superscript(bl)
513-
else
514-
"1-10" * AbstractPlotting.UnicodeFun.to_superscript("-" * bl)
515-
end
516-
end
517-
# # here we assume that the labels are normal numbers, and we just superscript them
518-
# labels_scaled = get_ticklabels(AbstractPlotting.automatic, ticks_scaled)
519-
# labels = _logbase(scale) .* AbstractPlotting.UnicodeFun.to_superscript.(labels_scaled)
520-
else
521-
# otherwise the formatter has to handle the real tick numbers
522-
labels = get_ticklabels(any_formatter, ticks)
523-
end
503+
# ticks = expit_10.(ticks_scaled)
524504

525-
(ticks, labels)
526-
end
505+
# base_labels = get_ticklabels(automatic, ticks_scaled)
506+
507+
# labels = map(ticks_scaled, base_labels) do t, bl
508+
# if t == 0
509+
# "¹/₂"
510+
# elseif t < 0
511+
# "10" * AbstractPlotting.UnicodeFun.to_superscript(bl)
512+
# else
513+
# "1-10" * AbstractPlotting.UnicodeFun.to_superscript("-" * bl)
514+
# end
515+
# end
516+
517+
# (ticks, labels)
518+
# end
527519

528520
"""
529521
get_tickvalues(lt::LinearTicks, vmin, vmax)
@@ -533,31 +525,31 @@ Runs a common tick finding algorithm to as many ticks as requested by the
533525
"""
534526
get_tickvalues(lt::LinearTicks, vmin, vmax) = locateticks(vmin, vmax, lt.n_ideal)
535527

536-
# function get_tickvalues(::Log10Ticks, vmin, vmax)
537-
# exp10.(ceil(log10(vmin)):floor(log10(vmax)))
538-
# end
539-
540-
# function get_tickvalues(::Log2Ticks, vmin, vmax)
541-
# exp2.(ceil(log2(vmin)):floor(log2(vmax)))
542-
# end
543-
544-
# function get_tickvalues(::LogTicks, vmin, vmax)
545-
# exp.(ceil(log(vmin)):floor(log(vmax)))
546-
# end
547528

548529
"""
549530
get_tickvalues(tickvalues, vmin, vmax)
550531
551532
Convert tickvalues to a float array by default.
552533
"""
553-
get_tickvalues(tickvalues, vmin, vmax) = Float64.(tickvalues)
534+
get_tickvalues(tickvalues, vmin, vmax) = convert(Vector{Float64}, tickvalues)
535+
536+
537+
# function get_tickvalues(l::LogitTicks, vmin, vmax)
538+
# ticks_scaled = get_tickvalues(l.linear_ticks, identity, logit_10(vmin), logit_10(vmax))
539+
# expit_10.(ticks_scaled)
540+
# end
541+
542+
function get_tickvalues(l::LogTicks, scale, vmin, vmax)
543+
ticks_scaled = get_tickvalues(l.linear_ticks, scale(vmin), scale(vmax))
544+
AbstractPlotting.inverse_transform(scale).(ticks_scaled)
545+
end
554546

555547
"""
556-
get_ticklabels(::AbstractPlotting.Automatic, values)
548+
get_ticklabels(::Automatic, values)
557549
558550
Gets tick labels by applying `Showoff.showoff` to `values`.
559551
"""
560-
get_ticklabels(::AbstractPlotting.Automatic, values) = Showoff.showoff(values)
552+
get_ticklabels(::Automatic, values) = Showoff.showoff(values)
561553

562554
"""
563555
get_ticklabels(formatfunction::Function, values)
@@ -574,7 +566,7 @@ Gets tick labels by formatting each value in `values` according to a `Formatting
574566
get_ticklabels(formatstring::AbstractString, values) = [Formatting.format(formatstring, v) for v in values]
575567

576568

577-
function get_ticks(m::MultiplesTicks, any_scale, ::AbstractPlotting.Automatic, vmin, vmax)
569+
function get_ticks(m::MultiplesTicks, any_scale, ::Automatic, vmin, vmax)
578570
dvmin = vmin / m.multiple
579571
dvmax = vmax / m.multiple
580572
multiples = MakieLayout.get_tickvalues(LinearTicks(m.n_ideal), dvmin, dvmax)
@@ -584,18 +576,15 @@ end
584576

585577

586578
function get_minor_tickvalues(i::IntervalsBetween, scale, tickvalues, vmin, vmax)
587-
vals = Float32[]
579+
vals = Float64[]
588580
length(tickvalues) < 2 && return vals
589581
n = i.n
590582

591583
if i.mirror
592584
firstinterval = tickvalues[2] - tickvalues[1]
593585
stepsize = firstinterval / n
594586
v = tickvalues[1] - stepsize
595-
while v >= vmin
596-
pushfirst!(vals, v)
597-
v -= stepsize
598-
end
587+
prepend!(vals, v:-stepsize:vmin)
599588
end
600589

601590
for (lo, hi) in zip(@view(tickvalues[1:end-1]), @view(tickvalues[2:end]))
@@ -612,18 +601,16 @@ function get_minor_tickvalues(i::IntervalsBetween, scale, tickvalues, vmin, vmax
612601
lastinterval = tickvalues[end] - tickvalues[end-1]
613602
stepsize = lastinterval / n
614603
v = tickvalues[end] + stepsize
615-
while v <= vmax
616-
push!(vals, v)
617-
v += stepsize
618-
end
604+
append!(vals, v:stepsize:vmax)
619605
end
620606

621607
vals
622608
end
623609

624610
# for log scales, we need to step in log steps at the edges
625-
function get_minor_tickvalues(i::IntervalsBetween, scale::Union{typeof(log), typeof(log2), typeof(log10), typeof(AbstractPlotting.logit)}, tickvalues, vmin, vmax)
626-
vals = Float32[]
611+
function get_minor_tickvalues(i::IntervalsBetween, scale::Union{typeof(log), typeof(log2), typeof(log10)}, tickvalues, vmin, vmax)
612+
613+
vals = Float64[]
627614
length(tickvalues) < 2 && return vals
628615
n = i.n
629616

@@ -635,10 +622,7 @@ function get_minor_tickvalues(i::IntervalsBetween, scale::Union{typeof(log), typ
635622
prevtick = invscale(scale(tickvalues[1]) - firstinterval_scaled)
636623
stepsize = (tickvalues[1] - prevtick) / n
637624
v = tickvalues[1] - stepsize
638-
while v >= vmin
639-
pushfirst!(vals, v)
640-
v -= stepsize
641-
end
625+
prepend!(vals, v:-stepsize:vmin)
642626
end
643627

644628
for (lo, hi) in zip(@view(tickvalues[1:end-1]), @view(tickvalues[2:end]))
@@ -656,10 +640,7 @@ function get_minor_tickvalues(i::IntervalsBetween, scale::Union{typeof(log), typ
656640
nexttick = invscale(scale(tickvalues[end]) + lastinterval_scaled)
657641
stepsize = (nexttick - tickvalues[end]) / n
658642
v = tickvalues[end] + stepsize
659-
while v <= vmax
660-
push!(vals, v)
661-
v += stepsize
662-
end
643+
append!(vals, v:stepsize:vmax)
663644
end
664645

665646
vals

src/makielayout/types.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,26 @@ struct MultiplesTicks
5050
suffix::String
5151
end
5252

53-
struct Log10Ticks end
53+
54+
# """
55+
# LogitTicks{T}(linear_ticks::T)
56+
57+
# Wraps any other tick object.
58+
# Used to apply a linear tick searching algorithm on a logit-transformed interval.
59+
# """
60+
# struct LogitTicks{T}
61+
# linear_ticks::T
62+
# end
63+
64+
"""
65+
LogTicks{T}(linear_ticks::T)
66+
67+
Wraps any other tick object.
68+
Used to apply a linear tick searching algorithm on a log-transformed interval.
69+
"""
70+
struct LogTicks{T}
71+
linear_ticks::T
72+
end
5473

5574
"""
5675
IntervalsBetween(n::Int, mirror::Bool = true)

test/unit_tests/makielayout.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,28 @@ end
103103
@test_throws ErrorException Colorbar(f[1, 3], p; Dict(attr => nothing)...)
104104
end
105105
end
106+
end
107+
108+
@testset "Tick functions" begin
109+
automatic = AbstractPlotting.automatic
110+
Automatic = AbstractPlotting.Automatic
111+
112+
get_ticks = MakieLayout.get_ticks
113+
get_tickvalues = MakieLayout.get_tickvalues
114+
get_ticklabels = MakieLayout.get_ticklabels
115+
116+
for func in [identity, log, log2, log10, AbstractPlotting.logit]
117+
tup = ([1, 2, 3], ["a", "b", "c"])
118+
@test get_ticks(tup, func, automatic, 0, 5) == tup
119+
120+
rng = 1:5
121+
@test get_ticks(rng, func, automatic, 0, 5) == ([1, 2, 3, 4, 5], ["1", "2", "3", "4", "5"])
122+
123+
numbers = [1.0, 1.5, 2.0]
124+
@test get_ticks(numbers, func, automatic, 0, 5) == (numbers, ["1.0", "1.5", "2.0"])
125+
126+
@test get_ticks(numbers, func, xs -> string.(xs) .* "kg", 0, 5) == (numbers, ["1.0kg", "1.5kg", "2.0kg"])
127+
128+
@test get_ticks(WilkinsonTicks(5), identity, automatic, 1, 5) == ([1, 2, 3, 4, 5], ["1", "2", "3", "4", "5"])
129+
end
106130
end

0 commit comments

Comments
 (0)