```
julia> scatter(1:1.0:10, rand(10); axis=(; xscale=x->2.0*x))
ERROR: MethodError: no method matching defaultlimits(::var"#118#119")
Closest candidates are:
defaultlimits(::Tuple{Real, Real}, ::Any)
@ Makie ~/.julia/packages/Makie/gAmAB/src/makielayout/blocks/axis.jl:1333
defaultlimits(::NTuple{4, Real}, ::Any, ::Any)
@ Makie ~/.julia/packages/Makie/gAmAB/src/makielayout/blocks/axis.jl:1320
defaultlimits(::Tuple{Real, Nothing}, ::Any)
@ Makie ~/.julia/packages/Makie/gAmAB/src/makielayout/blocks/axis.jl:1334
```

You need to overload a couple methods for custom scales, thatâ€™s one of them

I hope itâ€™s ok if I hijack this thread, since I am trying (and failing) to do basically the same thing. I want to implement a general linear transform for axes. What I did was this:

```
struct LinearScale
a::Float64
b::Float64
end
(s::LinearScale)(x) = s.a * x + s.b
Makie.inverse_transform(s::LinearScale) = x->(x-s.b)/s.a
Makie.defined_interval(::LinearScale) = OpenInterval(-Inf, Inf)
Makie.defaultlimits(::LinearScale) = (0.0, 10.0)
```

Unfortunately it doesnâ€™t work. Both of these:

```
scatter(rand(10); axis=(;xscale=LinearScale(5, 5)))
scatter(collect(1:10), rand(10); axis=(;xscale=LinearScale(5, 5)))
```

produce a standard axis with x values 1 to 10. The same works perfectly fine with a log scale, though.

It does work, it just works differently than you expect I actually did exactly the same thing a couple years ago while playing around with the scales.

If you think about what the result is of setting `xscale = log10`

, if you plot data from 1 to 100 you still get the ticks from 1 to 100, not from 0 to 2 (which would be `log10(1)`

and `log10(100)`

). What happens is that the data is transformed, but the ticks are adjusted in accordance with that so that you know what the original values were.

So when you do this with your linear transformation, the data are linearly transformed, and the ticks adjusted such that you know what the original data was. However, that means the effect of the transform is canceled out.

Ok, thanks that does make sense.

Is there a different way to â€śtranslateâ€ť x values to a different scale? As an example, assume I have simulation steps starting at 1, but they represent months of years since 1957. Is there a way to let the axis show `(x/12)+1957`

instead of x? Iâ€™m aware that I could simply provide a vector of correct x values, but for a live graph displayed by a running simulation that would mean that I have to update x *and* y values with every time step. Itâ€™s not a huge issue, admittedly, but I thought maybe thereâ€™s a simpler way to do it.

Yes you can, you can make a new ticks type for that. Here is an example implementation, where I overload `get_ticks`

which returns both tick values and tick labels. We just transform the limits with our linear transformation, then pass them on to the actual tick finder (WilkinsonTicks, Makieâ€™s default).

We have to transform the found ticks back to our real limits at the end, otherwise they would not fit.

I havenâ€™t touched the tick finding algorithm or the formatting here, so of course this could be improved given that the numbers are supposed to be years or months.

```
using CairoMakie
struct LinearTransformationTicks{T}
ticks::T
offset::Float64
slope::Float64
end
function Makie.get_ticks(lt::LinearTransformationTicks, scale, formatter, vmin, vmax)
lims_transformed = (vmin, vmax) .* lt.slope .+ lt.offset
tickvals_transformed, ticklabels = Makie.get_ticks(lt.ticks, scale, formatter, lims_transformed...)
tickvals_untransformed = (tickvals_transformed .- lt.offset) ./ lt.slope
return tickvals_untransformed, ticklabels
end
lines(
1:24,
cumsum(randn(24)),
axis=(; xticks=LinearTransformationTicks(WilkinsonTicks(5), 1958.0, 1 / 12))
)
```

Cool, thanks! Iâ€™ll give that a try.