AoG "range step cannot be zero"

I don’t have an MWE but maybe someone has a guess what this means?

ERROR: ArgumentError: range step cannot be zero
Stacktrace:
  [1] (::Colon)(start::Float32, step::Float32, stop::Float32)
    @ Base ./twiceprecision.jl:401
  [2] get_minor_tickvalues(i::IntervalsBetween, scale::Function, tickvalues::Vector{Float32}, vmin::Float32, vmax::Float32)
    @ Makie.MakieLayout ~/.julia/packages/Makie/NL7Xw/src/makielayout/lineaxis.jl:623
  [3] (::Makie.MakieLayout.var"#182#213"{Observable{Vector{Float32}}, Observable{Any}, Attributes})(tickvalues::Vector{Float32}, minorticks::IntervalsBetween)
    @ Makie.MakieLayout ~/.julia/packages/Makie/NL7Xw/src/makielayout/lineaxis.jl:239
  [4] (::Observables.OnUpdate{Makie.MakieLayout.var"#182#213"{Observable{Vector{Float32}}, Observable{Any}, Attributes}, Tuple{Observable{Vector{Float32}}, Observable{Any}}})(#unused#::Vector{Float32})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:334
  [5] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
  [6] invokelatest
    @ ./essentials.jl:714 [inlined]
  [7] notify
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88 [inlined]
  [8] setindex!(observable::Observable{Vector{Float32}}, val::Vector{Float64})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:248
  [9] (::Makie.MakieLayout.var"#178#209"{Observable{Vector{AbstractString}}, Observable{Vector{Point{2, Float32}}}, Observable{Vector{Float32}}, Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observable{Any}, Attributes})(tickvalues_labels_unfiltered::Tuple{Vector{Float64}, Vector{String}}, reversed::Bool)
    @ Makie.MakieLayout ~/.julia/packages/Makie/NL7Xw/src/makielayout/lineaxis.jl:214
 [10] (::Observables.OnUpdate{Makie.MakieLayout.var"#178#209"{Observable{Vector{AbstractString}}, Observable{Vector{Point{2, Float32}}}, Observable{Vector{Float32}}, Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observable{Any}, Attributes}, Tuple{Observable{Tuple{Vector{Float64}, Vector{String}}}, Observable{Any}}})(#unused#::Tuple{Vector{Float64}, Vector{String}})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:334
 [11] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [12] invokelatest
    @ ./essentials.jl:714 [inlined]
 [13] notify
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88 [inlined]
 [14] setindex!(observable::Observable{Tuple{Vector{Float64}, Vector{String}}}, val::Tuple{Vector{Float64}, Vector{String}})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:248
 [15] (::Observables.MapUpdater{Makie.MakieLayout.var"#177#208", Tuple{Vector{Float64}, Vector{String}}})(::Tuple{Float32, Tuple{Float32, Float32}, Bool}, ::Vararg{Any})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:372
 [16] (::Observables.OnUpdate{Observables.MapUpdater{Makie.MakieLayout.var"#177#208", Tuple{Vector{Float64}, Vector{String}}}, Tuple{Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}}})(#unused#::Tuple{Float32, Float32})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:334
 [17] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [18] invokelatest
    @ ./essentials.jl:714 [inlined]
 [19] notify
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88 [inlined]
 [20] setindex!
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:248 [inlined]
 [21] (::Observables.var"#3#4"{Any, Observable{Any}})(value::Tuple{Float32, Float32})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:58
 [22] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [23] invokelatest
    @ ./essentials.jl:714 [inlined]
 [24] notify
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88 [inlined]
 [25] setindex!
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:248 [inlined]
 [26] (::Makie.MakieLayout.var"#254#285"{Observable{Tuple{Float32, Float32}}, Observable{Tuple{Float32, Float32}}})(lims::GeometryBasics.HyperRectangle{2, Float32})
    @ Makie.MakieLayout ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:207
 [27] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [28] invokelatest
    @ ./essentials.jl:714 [inlined]
 [29] notify
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88 [inlined]
 [30] setindex!
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:248 [inlined]
 [31] adjustlimits!(la::Axis)
    @ Makie.MakieLayout ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:916
 [32] #268
    @ ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:447 [inlined]
 [33] (::Observables.OnUpdate{Makie.MakieLayout.var"#268#301"{Axis}, Tuple{Observable{GeometryBasics.HyperRectangle{2, Int64}}, Observable{GeometryBasics.HyperRectangle{2, Float32}}}})(#unused#::GeometryBasics.HyperRectangle{2, Float32})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:334
 [34] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [35] invokelatest
    @ ./essentials.jl:714 [inlined]
 [36] notify
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88 [inlined]
 [37] setindex!
    @ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:248 [inlined]
 [38] reset_limits!(ax::Axis; xauto::Bool, yauto::Bool, zauto::Bool)
    @ Makie.MakieLayout ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:547
 [39] reset_limits!
    @ ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:472 [inlined]
 [40] plot!(::Axis, ::Type{Lines}, ::Attributes, ::Vector{Rational{Int64}}, ::Vararg{Any}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie.MakieLayout ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:664
 [41] plot!
    @ ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:653 [inlined]
 [42] #plot!#318
    @ ~/.julia/packages/Makie/NL7Xw/src/makielayout/layoutables/axis.jl:670 [inlined]
 [43] plot!(ae::AxisEntries)
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/IVn8U/src/entries.jl:117
 [44] foreach(f::typeof(plot!), itr::Matrix{AxisEntries})
    @ Base ./abstractarray.jl:2694
 [45] plot!(fig::Axis, s::AlgebraOfGraphics.Layers; axis::NamedTuple{(), Tuple{}}, palettes::NamedTuple{(), Tuple{}})
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/IVn8U/src/algebra/layers.jl:151
 [46] draw!(fig::Axis, s::AlgebraOfGraphics.Layers; axis::NamedTuple{(), Tuple{}}, palettes::NamedTuple{(), Tuple{}})
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/IVn8U/src/algebra/layers.jl:191
 [47] draw!

It means what it says, that the package is trying to create a range with a step size of zero, which is not possible. A simple reproducer of the error is

julia> Float32(1):Float32(0):Float32(2)
ERROR: ArgumentError: range step cannot be zero
Stacktrace:
 [1] (::Colon)(start::Float32, step::Float32, stop::Float32)
   @ Base ./twiceprecision.jl:412
 [2] top-level scope
   @ REPL[1]:1

Clearly you can’t create a range with start=1, stop=2 and step=0. How you got here might be clear from an MWE, as this should normally not be reached.

Check this thread:

Perhaps the workaround does it for you too.

I think it’s basically what happens when you try to plot a constant field with Makie.
It’s unfortunate but it seems that trying to plot a field without spatial variation is (so far) not possible. Since there are no variations in the data, step is becomes 0 and it simply errors. One has to add a trend or a noise to the data… Please correct me if I’m wrong.

I don’t quite understand what you mean. I can plot a constant value like this

lines(1:10, fill(5, 10))

May also be misunderstanding, but plotting constant heatmaps seems to be supported I think:

using AlgebraOfGraphics, CairoMakie

z = ones(5, 5)

mapping([z]) |> draw # or mapping([z]) * visual(Heatmap) |> draw

This currently happens if the limit range is non-zero but tiny, in that case during tick calculation some ranges will have step 0 because of the loss of precision when dealing with Float32, leading to this error. A zero range has special behavior built in, which is why the straight line works…

1 Like

@icweaver and @jar1 thanks a lot for the follow up. Since I don’t wan’t to hijack your thread and since my problem may be unrelated, I’ve made a separate thread:

1 Like

I can’t reproduce the error with tiny floats:

julia>  floatmin(Float64) .* [1,2,3]
3-element Vector{Float64}:
 2.2250738585072014e-308
 4.450147717014403e-308
 6.675221575521604e-308

julia> lines(1:3, floatmin(Float64) .* [1,2,3])

Hm probably add a large constant to the y-values to trigger it.

No error

julia> lines(1:3, floatmin(Float64) .* [1,2,3] .+ 100)

I got the error with the following code

julia> using GLMakie

julia> b = 2.0^(-150)
7.006492321624085e-46

julia> Float32(b) # notice that `b` is the smallest `Float64` such that `Float32(b) != 0.0f0`
1.0f-45

julia> Float32(prevfloat(b)) # here you can see that efectively taking just the previous number bellow `b`, then `Float32(b) == 0.0`
0.0f0

julia> lines([b, b]) # this lines triggers the error

As for the error, it is here

julia> lines([b, b])
Error showing value of type Makie.FigureAxisPlot:
ERROR: ArgumentError: range step cannot be zero
Stacktrace:
  [1] (::Colon)(start::Float32, step::Float32, stop::Float32)
    @ Base ./twiceprecision.jl:412
  [2] get_minor_tickvalues(i::IntervalsBetween, scale::Function, tickvalues::Vector{Float32}, vmin::Float32, vmax::Float32)
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/makielayout/lineaxis.jl:670
  [3] (::Makie.var"#1179#1192"{Attributes, Observable{Vector{Float32}}, Observable{Tuple{Float32, Float32}}})(tickvalues::Vector{Float32}, minorticks::IntervalsBetween)
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/makielayout/lineaxis.jl:394
  [4] (::Observables.var"#callback#13"{Makie.var"#1179#1192"{Attributes, Observable{Vector{Float32}}, Observable{Tuple{Float32, Float32}}}, Tuple{Observable{Vector{Float32}}, Observable{Any}}})(x::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:339
  [5] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
  [6] invokelatest
    @ ./essentials.jl:726 [inlined]
  [7] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
  [8] setindex!(observable::Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
  [9] update_tickpos_string(closure_args::Tuple{Observable{Vector{AbstractString}}, Observable{Vector{Point{2, Float32}}}, Observable{Vector{Float32}}, Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observable{Tuple{Float32, Float32}}}, tickvalues_labels_unfiltered::Tuple{Vector{Float64}, Vector{String}}, reversed::Bool, scale::typeof(identity))
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/makielayout/lineaxis.jl:191
 [10] (::Observables.var"#callback#13"{typeof(Makie.update_tickpos_string), Tuple{Observable{Tuple{Observable{Vector{AbstractString}}, Observable{Vector{Point{2, Float32}}}, Observable{Vector{Float32}}, Observable{Tuple{Float32, Tuple{Float32, Float32}, Bool}}, Observable{Tuple{Float32, Float32}}}}, Observable{Tuple{Vector{Float64}, Vector{String}}}, Observable{Any}, Observable{Any}}})(x::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:339
 [11] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [12] invokelatest
    @ ./essentials.jl:726 [inlined]
 [13] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
 [14] setindex!(observable::Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
 [15] #15
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:393 [inlined]
--- the last 6 lines are repeated 1 more time ---
 [22] (::Observables.var"#callback#13"{Observables.var"#15#16"{Makie.var"#1169#1182", Observable{Tuple{Float32, Float32}}}, Tuple{Observable{Any}}})(x::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:339
 [23] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [24] invokelatest
    @ ./essentials.jl:726 [inlined]
 [25] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
 [26] setindex!(observable::Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
 [27] (::Observables.var"#6#7"{Observable{Any}})(x::Tuple{Float32, Float32})
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:114
 [28] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [29] invokelatest
    @ ./essentials.jl:726 [inlined]
 [30] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
 [31] setindex!(observable::Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
 [32] #15
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:393 [inlined]
 [33] (::Observables.var"#callback#13"{Observables.var"#15#16"{typeof(Makie.ylimits), Observable{Tuple{Float32, Float32}}}, Tuple{Observable{GeometryBasics.HyperRectangle{2, Float32}}}})(x::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:339
 [34] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [35] invokelatest
    @ ./essentials.jl:726 [inlined]
 [36] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
 [37] setindex!(observable::Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
 [38] adjustlimits!(la::Axis)
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/makielayout/blocks/axis.jl:977
 [39] #1235
    @ ~/.julia/packages/Makie/Ppzqh/src/makielayout/blocks/axis.jl:498 [inlined]
 [40] (::Observables.var"#callback#13"{Makie.var"#1235#1265"{Axis}, Tuple{Observable{GeometryBasics.HyperRectangle{2, Int64}}, Observable{GeometryBasics.HyperRectangle{2, Float32}}}})(x::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:339
 [41] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [42] invokelatest
    @ ./essentials.jl:726 [inlined]
 [43] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
 [44] setindex!(observable::Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
 [45] reset_limits!(ax::Axis; xauto::Bool, yauto::Bool, zauto::Bool)
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/makielayout/blocks/axis.jl:623
 [46] reset_limits!
    @ ~/.julia/packages/Makie/Ppzqh/src/makielayout/blocks/axis.jl:547 [inlined]
 [47] update_state_before_display!(ax::Axis)
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/makielayout/blocks/axis.jl:1351
 [48] update_state_before_display!(f::Figure)
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/figureplotting.jl:177
 [49] update_state_before_display!
    @ ~/.julia/packages/Makie/Ppzqh/src/figureplotting.jl:173 [inlined]
 [50] backend_display(s::Makie.FigureAxisPlot; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/display.jl:50
 [51] backend_display
    @ ~/.julia/packages/Makie/Ppzqh/src/display.jl:49 [inlined]
 [52] #display#932
    @ ~/.julia/packages/Makie/Ppzqh/src/display.jl:72 [inlined]
 [53] display(fig::Makie.FigureAxisPlot)
    @ Makie ~/.julia/packages/Makie/Ppzqh/src/display.jl:66
 [54] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [55] invokelatest
    @ ./essentials.jl:726 [inlined]
 [56] print_response(errio::IO, response::Any, show_value::Bool, have_color::Bool, specialdisplay::Union{Nothing, AbstractDisplay})
    @ REPL ~/.julia/juliaup/julia-1.8.1+0.x64/share/julia/stdlib/v1.8/REPL/src/REPL.jl:296
 [57] (::REPL.var"#45#46"{LineEditREPL, Pair{Any, Bool}, Bool, Bool})(io::Any)
    @ REPL ~/.julia/juliaup/julia-1.8.1+0.x64/share/julia/stdlib/v1.8/REPL/src/REPL.jl:278
 [58] with_repl_linfo(f::Any, repl::LineEditREPL)
    @ REPL ~/.julia/juliaup/julia-1.8.1+0.x64/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
 [59] print_response(repl::AbstractREPL, response::Any, show_value::Bool, have_color::Bool)
    @ REPL ~/.julia/juliaup/julia-1.8.1+0.x64/share/julia/stdlib/v1.8/REPL/src/REPL.jl:276
 [60] (::REPL.var"#do_respond#66"{Bool, Bool, REPL.var"#77#87"{LineEditREPL, REPL.REPLHistoryProvider}, LineEditREPL, REPL.LineEdit.Prompt})(s::REPL.LineEdit.MIState, buf::Any, ok::Bool)
    @ REPL ~/.julia/juliaup/julia-1.8.1+0.x64/share/julia/stdlib/v1.8/REPL/src/REPL.jl:857
 [61] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [62] invokelatest
    @ ./essentials.jl:726 [inlined]
 [63] run_interface(terminal::REPL.Terminals.TextTerminal, m::REPL.LineEdit.ModalInterface, s::REPL.LineEdit.MIState)
    @ REPL.LineEdit ~/.julia/juliaup/julia-1.8.1+0.x64/share/julia/stdlib/v1.8/REPL/src/LineEdit.jl:2510
 [64] run_frontend(repl::LineEditREPL, backend::REPL.REPLBackendRef)
    @ REPL ~/.julia/juliaup/julia-1.8.1+0.x64/share/julia/stdlib/v1.8/REPL/src/REPL.jl:1248
1 Like
1 Like

In case this can be useful, here’s another MWE:

using CairoMakie
let 
    n = 10
    θ = 62.143438338297955*ones(n)  #.+ rand(n).*1e-9
    f   = Figure()
    ax2 = Axis( f[1, 1] )
    lines!(ax2, θ, 1:n)
    display(f)
end

By uncommenting the contribution from rand(), the problem appears. In my case, this leads to unpredictables crashes in simulations where patterns arise from initially homogeneous fields.

Makie currently only detects if the limits are zero-width, and in this case will auto-expand them. If you have tiny limits that are effectively zero in Float32, then you get the error when computing ticks (this one could also be improved I guess, but such tiny limits would also lead to projection problems anyway). So your best bet right now is to manually choose appropriate limits when your data range falls below some threshold you define.

simulations where patterns arise from initially homogeneous fields

Right, but usually from a visualization perspective, it’s important to show the homogeneity, and for that you need larger limits. Otherwise you would stretch any noise floor across the whole axis, leading to misleading graphics anyway. So for animations or so where something arises from zero (or very near zero in your case), I usually choose some limits that are appropriate from the get go.