Skip to content

How to define custom function for axis scaling? #3089

@johnomotani

Description

@johnomotani

Thanks to @jkrumbiegel's hint, here is a correct example of how to define a custom function for an axis scale

module ScaleTest

export mylog

import Makie

function mylog(x)
    return log10(x)
end

function Makie.inverse_transform(::typeof(mylog))
    return x -> 10.0^x
end

Makie.defaultlimits(::typeof(mylog)) = (1.0, 1000.0)

Makie.defined_interval(::typeof(mylog)) = Makie.OpenInterval(0.0, Inf)

end

using CairoMakie
using .ScaleTest

x = collect(1.0:10.0)
y = rand(10)

fig, ax = lines(x,y)
ax.yscale = mylog

save("foo.pdf", fig)

=========================================================
Original post follows:

  • are you running newest version (version from docs) ? Yes, v0.19.7
  • can you reproduce the bug with a fresh environment ? (]activate --temp; add Makie) Yes
  • What platform + GPU are you on? Linux Mint 21.1, Julia-1.8.5

In the docs (https://docs.makie.org/stable/examples/blocks/axis/#yscale) it says

Can be any invertible function, some predefined options are identity, log, log2, log10, sqrt, logit, Makie.pseudolog10 and Makie.Symlog10. To use a custom function, you have to define appropriate methods for Makie.inverse_transform, Makie.defaultlimits and Makie.defined_interval.

How can those 'appropriate methods' be defined? My best guess is something like the following

module ScaleTest

export mylog

import Makie: inverse_transform, defaultlimits, defined_interval

function mylog(x)
    return log10(x)
end

function inverse_transform(::typeof(mylog))
    return x -> 10.0^x
end

defaultlimits(::typeof(mylog)) = (1.0, 1000.0)

defined_interval(::typeof(mylog)) = (0.0, Inf)

end

using CairoMakie
using .ScaleTest

x = collect(1.0:10.0)
y = rand(10)

fig, ax = lines(x,y)
ax.yscale = mylog

save("foo.pdf", fig)

But if I run that code, I get an error

ERROR: LoadError: Found invalid y-limits (0.013601727f0, 0.87287176f0) for scale mylog which is defined on the interval (0.0, Inf)

It would be nice if there was some explanation in the docs both of how to define those functions and of what they have to do.

Also, when I try to implement something similar within a larger project, the import of these functions fails (statement import Makie: inverse_transform, defaultlimits, defined_interval)

WARNING: could not import Makie.defaultlimits into CustomMakieScales
WARNING: could not import Makie.defined_interval into CustomMakieScales
ERROR: LoadError: UndefVarError: CustomMakieScales not defined

[CustomMakieScales was the module I tried to define containing a new scale.]

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions