Plots: Using multiple colours in title

Using Plots.jl, is it possible to use multiple colours in the title? Here is an example of the sort of thing I am trying to do. Thanks very much in advance.

The answer is yes using also LaTeXStrings:

See some syntax examples here and just add colors by encapsulating text within: \textcolor{blue}{text}

1 Like

Thanks for your answer. Would you mind sharing your code? I can get LaTeXString titles to work as expected, but I cannot change the color of the text. For example, when I run plot(1:3, title = L"\textcolor{blue}{text}"), the title of the plot is ?bluetext.

Please use Plots.jl pgfplotsx() backend.

Code example
using LaTeXStrings, Printf, Plots; pgfplotsx()

plot_font = "Computer Modern";
default(fontfamily=plot_font,framestyle=:box, label=nothing, grid=false, tickfontsize=7)

u = 15  # persistent wind speed in m/s  (~30 knot)
st0 =  "Significant wave height vs persistent wind speed ("
st1 =  @sprintf(":  u = %i m/s  → ", u)
st2 =  @sprintf(" = %.1f m", 0.24*u^2/9.8)
plot(title=L"\textcolor{blue}{\textbf{%$st0} \mathbf{H_s \approx 0.24 u^2/g} )} \textit{%$st1}
     \textcolor{red}{{H_s} \textit{%$st2}}", titlefont=font(8,plot_font), ylims=(0,30))
1 Like

Thanks for your suggestion and for providing example code. It’s unfortunate that the backend needs to change, as I’ve already written (lots of) code using the default gr() backend (I should have mentioned that in my original question). I’ve played around with using pgfplotsx(), and it seems that using it would require many changes to the code I already have.

There is a way with annotate but it is not pretty.

Just a thought: You can save your plot with an empty title in a vector format and re-import it to add colored titles…

1 Like

You can save with the title and just change the colors (for example in Inkscape)

Thanks for all of your suggestions! All good options. In the end, I decided to use annotate. Indeed, it is a major hack and not the prettiest, but it works well for my purposes (I have 9 sets of 6 x 6 grids with no space left for a legend, and I only need to use the title to identify which colour corresponds to each group.)

In case someone needs to do something similar in the future, here is the code that I used (note that I used this stack overflow answer as a starting point):


"""
	coloured_title(
	p, group_names, colours;
	horizontal_shift = -0.25, vertical_shift = 0,
	size = 18, title_spacing_constant = 4, title_proportion = 0.02
	)

Adds a rudimentary coloured title to `p`. The title is constructed by colouring
each element of `group_names` with the corresponding element of `colours`, and
joining the results. The remaining arguments allow the title to be 'tweaked' as
needed.
"""
function coloured_title(
	p, group_names::Vector{String}, colours::Vector{String};
	horizontal_shift = -0.25, vertical_shift = 0,
	size = 18, title_spacing_constant = 4, title_proportion = 0.02
	)

	@assert length(group_names) == length(colours)
	@assert -1 < horizontal_shift < 1
	@assert -1 < vertical_shift < 1
	@assert 0 < title_proportion < 1
	@assert title_spacing_constant >= 0

    # Empty plot that will be used for the title
    y = ones(3)
    title_plot = scatter(
        y,
        xlims = (-1, 1),
        ylims = (-1, 1),
        marker=0, markeralpha=0,axis=false, grid=false, leg=false,
        framestyle = nothing, showaxis = false, xticks = false, yticks = false
    )

    # Add coloured text in the middle of the plot; each subsequent group name
    # is shifted by an amount that is proportional to maximum(length.(group_names))
    for i ∈ eachindex(group_names)
        max_len = maximum(length.(group_names))
        current_title = repeat(" ", title_spacing_constant * max_len * (i - 1)) * group_names[i]
        annotate!(title_plot, horizontal_shift, vertical_shift, Plots.text(current_title, colours[i], size))
    end

	# layout for the title plot and your real plot
	l = grid(2, 1, heights = [title_proportion, 1 - title_proportion])

    # combine the 'title' plot with your real plots
    return plot(title_plot, p, layout = l)
end

And here is an example of its use:

# Generate toy data
n = 20 # number of observations per group
x = repeat(1:n, outer = 2)
y = repeat([0, 10], inner = n) .+ randn(2n)
group_names = ["Group 1", "Group 2"]
colours = ["green", "orange"]
c = repeat(colours, inner = n)

# real plot
p = plot(x, y, group = c, colour = c, legend = :none)

coloured_title(p, group_names, colours)

toy

1 Like

This comment certainly does not contribute much but I wanted throw in that these kind of customisations are exactly the reason why I prefer PGFPlotsX.jl directly, without any other layers between code and plots.
You only have to learn one framework and PGF/tikz are extremely well documented with an immense amount of examples and together with LaTeX you can do everything.

3 Likes