How to preserve xformatter when adding a vline

I have a series recipe that formats the x-axis ticks. When I add a vline, the formatting is reset to the default, i.e. my custom formatting disappears.

Is it possible for vline to respect and preserve the formatting of the xticks that already exists?
And, more generally, why is xformatter an attribute of the series and not of the subplot or the axis?

Here is an example code to demonstrate this:

@recipe function _myseries(::Type{Val{:myseries}}, x, y, z)
    xformatter --> function (d)
        yr = floor(Int, d)
        qr = 1 + floor(Int, 4 * (d - yr))
        return "$(yr)Q$(qr)"
    end
    seriestype := :path
end

dates = collect(2021:0.25:2024-0.1)
yvals = rand(length(dates))
plt = plot(dates, yvals, label="y", seriestype=:myseries)

plot_1

If I add the vline, I get this:

vline!(plt, [2022.5], label="2022Q3", lc=:black)

plot_2

I can fix the formatting by forcing the xformatter like this:

plt = plot(dates, yvals, label="y", seriestype=:myseries)
vline!(plt, [2022.5], label="2022Q3", lc=:black, xformatter=plt.series_list[1][:xformatter])

plot_3

I am developing a library, so I don’t want my users to have to do this.

Thanks,
Boyan

1 Like

Could you define the formatter function:

function xfmt(d)
    yr = floor(Int, d)
    qr = 1 + floor(Int, 4 * (d - yr))
    return "$(yr)Q$(qr)"
end

and then use it when calling vline!()?

vline!(plt, [2022.5], label="2022Q3", lc=:black, xformatter=xfmt)

Thanks Rafael. My question is about vline!() respecting the existing xformatter without having to specify it again in the vline!() call. The reason I need this is because the formatter function is internal in my package and the users don’t have access to it. Plus, I think this is not something they should have to worry about.

Ok, I just found out that there is an open issue about this:
[BUG] vline! overrides previously set formatter · Issue #4538 · JuliaPlots/Plots.jl (github.com)
Cheers!