Skip to content

Commit

Permalink
format files
Browse files Browse the repository at this point in the history
  • Loading branch information
BeastyBlacksmith committed Jun 23, 2022
1 parent e8e6463 commit 5effa77
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 70 deletions.
170 changes: 101 additions & 69 deletions src/ticks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ function bounding_order_of_magnitude(xspan::T) where {T}

a = step = 1
while xspan < base^a * one_dt
function bounding_order_of_magnitude(xspan::DT) where DT
one_dt = oneunit(DT)

a = 1
step = 1
while xspan < 10.0^a * one_dt
a -= step
end

Expand Down Expand Up @@ -48,7 +42,7 @@ struct Ticks{T} <: AbstractRange{T}
q::Int
z::Int
step::Float64
Ticks{T}(u,q,z) where T = new(u, q, z, q * 10.0^z)
Ticks{T}(u, q, z) where {T} = new(u, q, z, q * 10.0^z)
end

fallback_ticks(x_min::T, x_max::T, k_min, k_max) where {T} = (
Expand All @@ -60,33 +54,32 @@ fallback_ticks(x_min::T, x_max::T, k_min, k_max) where {T} = (
)

Base.size(t::Ticks) = size(t.u)
Base.step(t::Ticks{T}) where T = t.step * oneunit(T)
Base.getindex(t::Ticks{T}, i::Integer) where T = round(t.u[i]*t.step; digits=-t.z) * oneunit(T)
Base.step(t::Ticks{T}) where {T} = t.step * oneunit(T)
Base.getindex(t::Ticks{T}, i::Integer) where {T} =
round(t.u[i] * t.step; digits = -t.z) * oneunit(T)
_ticks_str(t::Ticks) = "($(t.q*t.u))*10^$(t.z)"
Base.show(io::IO, t::Ticks{<:AbstractFloat}) = print(io, _ticks_str(t))
Base.show(io::IO, t::Ticks{T}) where T = print(io, _ticks_str(t), " * ", oneunit(T))

Base.show(io::IO, t::Ticks{T}) where {T} = print(io, _ticks_str(t), " * ", oneunit(T))

function restrict_ticks(t::Ticks{T}, from, to) where T
function restrict_ticks(t::Ticks{T}, from, to) where {T}
tickspan = step(t)
u_start = max(first(t.u), ceil(Int64, from / tickspan))
u_end = min(last(t.u), floor(Int64, to / tickspan))
t = Ticks{T}(u_start:u_end,t.q,t.z)
t = Ticks{T}(u_start:u_end, t.q, t.z)

# Fix possible floating-point errors (may occur in division above, or due
# rounding in (::Ticks)[::Int] when endpoints are near a round number)
while u_start <= u_end && t[1] < from
u_start += 1
t = Ticks{T}(u_start:u_end,t.q,t.z)
t = Ticks{T}(u_start:u_end, t.q, t.z)
end
while u_start <= u_end && t[end] > to
u_end -= 1
t = Ticks{T}(u_start:u_end,t.q,t.z)
t = Ticks{T}(u_start:u_end, t.q, t.z)
end
t
end


# Empty catchall
optimize_ticks() = Any[]

Expand Down Expand Up @@ -179,27 +172,56 @@ and the variables here are:
* `i`: index of `q` in `Q`.
* `v`: 1 if label range includes 0, 0 otherwise.
"""
function optimize_ticks(x_min::T, x_max::T; extend_ticks::Bool=false,
Q=[(10,1.0), (50, 0.9), (20, 0.7), (25, 0.5), (30, 0.2)],
k_min::Int=2, k_max::Int=10, k_ideal::Int=5,
granularity_weight::Float64=1/4, simplicity_weight::Float64=1/6,
coverage_weight::Float64=1/3, niceness_weight::Float64=1/4,
strict_span=true, span_buffer = nothing) where T

function optimize_ticks(
x_min::T,
x_max::T;
extend_ticks::Bool = false,
Q = [(10, 1.0), (50, 0.9), (20, 0.7), (25, 0.5), (30, 0.2)],
k_min::Int = 2,
k_max::Int = 10,
k_ideal::Int = 5,
granularity_weight::Float64 = 1 / 4,
simplicity_weight::Float64 = 1 / 6,
coverage_weight::Float64 = 1 / 3,
niceness_weight::Float64 = 1 / 4,
strict_span = true,
span_buffer = nothing,
) where {T}
Qv = [(Int(q[1]), Float64(q[2])) for q in Q]
optimize_ticks_typed(x_min, x_max, extend_ticks, Qv, k_min, k_max, k_ideal,
granularity_weight, simplicity_weight,
coverage_weight, niceness_weight, strict_span, span_buffer)
optimize_ticks_typed(
x_min,
x_max,
extend_ticks,
Qv,
k_min,
k_max,
k_ideal,
granularity_weight,
simplicity_weight,
coverage_weight,
niceness_weight,
strict_span,
span_buffer,
)
end

function optimize_ticks_typed(x_min::T, x_max::T, extend_ticks,
Q::Vector{Tuple{Int,Float64}}, k_min,
k_max, k_ideal,
granularity_weight::Float64, simplicity_weight::Float64,
coverage_weight::Float64, niceness_weight::Float64,
strict_span, span_buffer) where T
function optimize_ticks_typed(
x_min::T,
x_max::T,
extend_ticks,
Q::Vector{Tuple{Int,Float64}},
k_min,
k_max,
k_ideal,
granularity_weight::Float64,
simplicity_weight::Float64,
coverage_weight::Float64,
niceness_weight::Float64,
strict_span,
span_buffer,
) where {T}
one_t = oneunit(T)
if x_max - x_min < eps()*one_t
if x_max - x_min < eps() * one_t
R = typeof(1.0 * one_t)
return R[x_min], x_min - one_t, x_min + one_t
end
Expand Down Expand Up @@ -233,11 +255,11 @@ function optimize_ticks_typed(
high_score = -Inf
best_ticks = nothing

max_q_exponent = ceil(Int,log10(maximum(q[1] for q in Q)))
while 2k_max * 10.0^(z+max_q_exponent) * one_t > xspan
for (ik, k) in enumerate(k_min:2k_max)
max_q_exponent = ceil(Int, log10(maximum(q[1] for q in Q)))
while 2k_max * 10.0^(z + max_q_exponent) * one_t > xspan
for (ik, k) in enumerate(k_min:(2k_max))
for (q, qscore) in Q
stp = q*10.0^z
stp = q * 10.0^z
if stp < eps()
continue
end
Expand All @@ -250,51 +272,52 @@ function optimize_ticks_typed(

r = ceil(Int64, (x_max - span) / tickspan)

while r*tickspan <= x_min
u = extend_ticks ? (r-k:r+2k-1) : (r:r+k-1)
while r * tickspan <= x_min
u = extend_ticks ? ((r - k):(r + 2k - 1)) : (r:(r + k - 1))
ticks = Ticks{T}(u, q, z)

if strict_span
viewmin = max(r*tickspan, x_min)
viewmax = min((r+k-1)*tickspan, x_max)
viewmin = max(r * tickspan, x_min)
viewmax = min((r + k - 1) * tickspan, x_max)
buf = something(span_buffer, 0) * (viewmax - viewmin)

ticks = restrict_ticks(ticks,viewmin-buf,viewmax+buf)
ticks = restrict_ticks(ticks, viewmin - buf, viewmax + buf)
if length(ticks) < k_min
r += 1
continue
end
end
nticks = length(ticks)

# evaluate quality of ticks
has_zero = r <= 0 && abs(r) < k
# evaluate quality of ticks
has_zero = r <= 0 && abs(r) < k

# simplicity
s = has_zero && nice_scale ? 1 : 0
# simplicity
s = has_zero && nice_scale ? 1 : 0

# granularity
g = 0 < len < 2k_ideal ? 1 - abs(len - k_ideal) / k_ideal : F(0)
# granularity
g = 0 < len < 2k_ideal ? 1 - abs(len - k_ideal) / k_ideal : F(0)

# granularity
g = 0 < nticks < 2k_ideal ? 1 - abs(nticks - k_ideal) / k_ideal : 0.0

# coverage
effective_span = (nticks-1) * tickspan
c = 1.5 * xspan/effective_span

score = granularity_weight * g +
simplicity_weight * s +
coverage_weight * c +
niceness_weight * qscore

# strict limits on coverage
if strict_span && span > xspan
score -= 10000
end
if span >= 2xspan
score -= 1000
end
effective_span = (nticks - 1) * tickspan
c = 1.5 * xspan / effective_span

score =
granularity_weight * g +
simplicity_weight * s +
coverage_weight * c +
niceness_weight * qscore

# strict limits on coverage
if strict_span && span > xspan
score -= 10000
end
if span >= 2xspan
score -= 1000
end

if score > high_score && (k_min <= nticks <= k_max)
best_ticks = ticks
Expand All @@ -309,12 +332,21 @@ function optimize_ticks_typed(
if best_ticks === nothing
if strict_span
@warn("No strict ticks found")
return optimize_ticks_typed(x_min, x_max, extend_ticks,
Q, k_min,
k_max, k_ideal,
granularity_weight, simplicity_weight,
coverage_weight, niceness_weight,
false, span_buffer)
return optimize_ticks_typed(
x_min,
x_max,
extend_ticks,
Q,
k_min,
k_max,
k_ideal,
granularity_weight,
simplicity_weight,
coverage_weight,
niceness_weight,
false,
span_buffer,
)
else
R = typeof(1.0 * one_t)
return R[x_min], x_min - one_t, x_min + one_t
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ end
ticks, = optimize_ticks(x, y)
@test issorted(ticks)
@test allunique(ticks)
if (x,y) [(1.0,1.0+eps()), (1.0-eps(),1.0)] # known failures
if (x, y) [(1.0, 1.0 + eps()), (1.0 - eps(), 1.0)] # known failures
@test_broken all(x .<= ticks .<= y)
else
@test all(x .<= ticks .<= y)
Expand Down

0 comments on commit 5effa77

Please sign in to comment.