Unable to change the tick font size when using ticks = :native with Plots.jl and pgfplotsx backend

I am relatively new to Julia (coming from python and matplotlib) and have been trying to generate some plots for a project I am working on.

It seems to be a known issue that Plots.jl does not produce ticks when there are 0 values in a plot with log-scale axis and a workaround seems to be passing ticks = :native which works with some of the back-ends I tried such as pgfplotsx and plotlyjs but not some like gr. The other workaround to specify the limits each time is quite cumbersome when generating a large number of plots and changing them.

However in this case, the tickfontsize parameter seems to have no effect on the size of the fonts. I am at a loss on how to proceed except to leave the convenience of Plots.jl and try out something like Makie which seems to be a work in progress still. Any help would be appreciated :slight_smile:

MWE:

using Plots
pgfplotsx()

x = 0:0.01:1
y = 10 .^ x
plot(x, y, ticks = :native, tickfontsize = 30)

I am using Julia 1.6, Plots v1.21.3 and PGFPlotsX v1.4.0

You probably need to add some condition for the log plots to handle the zeros.

For example, by automatically setting xlims based on positive data::

plot(x, y, xaxis=:log, tickfontsize=30, legend=false, xlims=extrema(x[x.>0]))

Or alternatively, without using xlims you could do:

ix = (x .> 0)
plot(x[ix], y[ix], xaxis=:log, tickfontsize=30, legend=false)

Thank you! I had no idea that something like extremaexisted. Unfortunately that doesn’t still let me change the tickfontsize when ticks = :native.

I am already using an index to resample my data. I tried to change that with,

x_new = x[my_ix]
yarr_new = yarr[my_ix, :] # I have series data

but I couldn’t do (quite naturally),

plot(x_new[x_new.>0] , yarr_new[yarr_new.>0], xscale = :log, yscale = :log)

Since where the zero values show up in x and each column of yarr are not idential for each series.

You then need a common index, something like ixy = (x .> 0) .& (y .> 0):

using Plots; pgfplotsx()
x = 0:0.01:1
y = (x .- 0.5).^2
ixy = (x .> 0) .& (y .> 0)
plot(x[ixy], y[ixy], axis=:log, tickfontsize=30, legend=false)

2 Likes

Thank you. That makes sense in general but for me specifically, I would need to generate a mask/index for every row for each matrix, and I need to plot a bunch of matrices like this. That seems so much hassle compared to simply being able to adjust the tickfontsize.

You probably could define a function to automate the process.

I can naively think of something like this;

function(fig, x, y_arr, l, c)
    for i in 1:size(y_arr)[2]
        ix = (x .> 0) .& (y_arr[:, i] .> 0)
        plot!(fig, x, y, label = l[i], color = c[i])
    end
end

However even with such index, using the default ticks yield weird results:

Could you provide some representative examples of the data you need to plot?

Unfortunately the data is really not mine to share without permission, however I cooked up a toy example with similar pathological behavior. Hope that helps a little at least.

x = [1, 2, 3]
y = [2E-2, 3E-2, 4E-1]

With automatic ticks no ticks are produced;

plot(x, y, yscale = :log10, ticks = :auto, ylims = extrema(y), legendtitle = "")

With native ticks everything is perfect except for the font size;

plot(x, y, yscale = :log10, ticks = :native, ylims = extrema(y), legendtitle = "")

Thank you for all your effort :slight_smile:

Not sure if presenting log scales with 10^-1.1 type of values is very orthodox, but it is difficult to read. What number is that without using a calculator?

We may be touching some additional bugs here.
In any case, the following is a quick & dirty example, trying to work around some possible bugs with the log scales in Plots.jl. In order to make it more general you will need to do more plumbing.

Code example using Plots; pgfplotsx() ...
using Plots; pgfplotsx()

function logplot_ycols!(fig, x, Y; l="", minorgrid=true)
    yl = +Inf
    yh = -Inf
    for i in 1:size(Y,2)
        ixy = (Y[:,i].> 0)
        yi = Y[:,i][ixy]
        yli, yhi = extrema(log10.(yi))
        yli = 10 .^ floor(yli)
        yhi = 10 .^ ceil(yhi)
        (yli < yl) && (yl = yli)
        (yhi > yh) && (yh = yhi)
        if minorgrid
            yhi = round(Int, log10(yh))
            yli = round(Int, log10(yl))
            for i in yli:yhi
               y = [j*10.0^i for j in 2:9]
               hline!(y, ls=:dash, lw=0.25, lc=:lightgrey, label=false)
            end
        end
    end
    for i in 1:size(Y,2)
        ixy = (x .> 0) .& (Y[:,i].> 0)
        yi = Y[:,i][ixy]
        xi = x[ixy]
        plot!(fig, xi, yi, label=l, yscale=:log10)
    end
    plot!(fig, ylims=(yl,yh), grid=:true, widen=false)
    display(fig)
end

# EX.1:
x = [1, 2, 3]
Y = [2E-2, 3E-2, 4E-1]
fig = plot(title="log plot of vector")
logplot_ycols!(fig, x, Y)

# EX.2:
x = [1, 2, 3]
Y2 = [Y  Y .- 0.02  2*Y]
fig = plot(title="log plot of matrix columns")
logplot_ycols!(fig, x, Y2)

1 Like

Thank you! I don’t disagree on the readability. I would be completely happy to get the major ticks and some minor ticks.

I tried something similar like,

ylims = extrema(Y2[Y2 . > 0])

but ends up with the lines/scatter hitting the axes/plot edges without any extra space in the same fashion that yours also did.

I am also running into issue controlling the visibility of lens! frame and its position and unable to find much documentation. I have loved every bit of Julia so far except for Plots.jl and not being able to parallelize properly :frowning:

Matplotlib might be unexciting but it is very well documented and has little unexpected behavior. I tried PlotlyJS which works very well but does not support LateX strings. Makie is changing so much that I run into lots of unexpected behavior. Gadfly does not export PDFs because of issues with Cairo and Font config.

P.S.
I am not sure what this does. Is it checking if the limits are larger and storing it? I did not know logical and could do that!

Edit: Edited out a bunch of issues that are not solved but not relevant to this issue.

These lines update the lower and upper limits of the data to be plotted if the conditions on the left are true.
In Julia, if the first condition is true, then the second term is executed. Otherwise, if it is false, the second term is not evaluated.

1 Like

In the code provided, set widen = true instead of false, if that is what you prefer.

Better if you focus each post on a single/narrow problem/question.
For all the other new questions, open as many new posts as appropriate.

Hey,

I apologize for my rant! Was really frustrated with the plotting situation in Julia and it just came out.

I am not really how to actually proceed, make an issue on github for PGFPlotsX or Plots? But then I hear that Makie is supposed to replace Plots so does the previous options even make sense?

Thank you :slight_smile: widen = true helps with the edges.

After calming down, I spend some time diagnosing the issue and have narrowed it down. Plots cannot calculate ticks when using log scale for values that are spread minutely around a larger number. I tried to create a simple plots where values are in 1 +/ 2E-4 and the issue shows up. Would love to hear your thoughts on what is happening.

P. S pgfplotsx() also fails with ticks = :native when the spread is really really small. That is how I ended up finding out what the issue is;

plotlyjs() actually does well by producing logarithmic spaced ticks without the numbers in scientific notation with ticks = :native

With regards to Plots.jl, please visit the github repository and check the open issues related to this topic of log scales. For example, see a nice proposal here.

NB: just in case, have you checked the code I posted above hidden under the expandable section labelled “Code example using Plots; pgfplotsx() …”? That should work with gr() too.

I will checkout open issues on github, I initially did look there for tickfontsize and log but did not find anything relevant. The PR that you linked has already been merged hasn’t it?

I did. I just chose gr because pgfplotsx() fails totally to produce anything when it cannot compute ticks.

! Dimension too large.
<recently read> \pgf@yy 
        
l.157 \end{axis}

This is the result for the same plot with pgfplotsx(). It is by investigating this and looking at the stackexchange post linked that I understood what was happening.