# Can I paint the background of a plot?

I would like to make a function `f(x,y)` that returns a color and give that to `plot` to create the background of the plot.

Is there something close to this on one of the plotting packages?

Thanks.

1 Like

You can just make a `heatmap` for example?
EDIT: eg using Plots.jl

I want to give the plot a color to use at each x,y location, not a scalar that gets mapped to a color.

I did try `heatmap` of `Plots.jl` just in case it magically works, but it says it can’t convert `ColorTypes.RGB` to `Float64`.

Imagine I want to plot on one of these:

I realize this doesn’t do what you want, but maybe it’s helpful?

``````using ColorSchemes
using Makie

f(x,y) = RGB(x/255,y/255,x/2/255)

xs = 0:255
ys = 0:255
zs = xs .* ys'

colors = ColorScheme([f(x,y) for x in xs for y in ys])

image(xs,ys,zs, colormap=colors)
``````

Outputs:

3 Likes

Oh that wasn’t clear.

In that case, do `using Images` and make a matrix of your RGB objects. It should display as an image with those colours.

1 Like

Oh yes, I used `Colors.jl` functions to make the chromaticity diagram image I shared. I would like to be able to plot various things on top of that image, preferably in the x,y space so that axes are sensible.

However I’m fighting with blue screens of death tonight which isn’t making anything easier.

Would you be happy to share the code for that? It’s very nice.

Plots uses palettes. There should be a way to encode the colours into a palette so you can do the same with heatmap with axes.

There’s some hard coded scaling that could be generalized and I dislike the C,M,Y seams that appear more prominently in this than in other implementations but here you go:.

``````### A Pluto.jl notebook ###
# v0.12.18

using Markdown
using InteractiveUtils

# ╔═╡ 5ba5d640-5cd0-11eb-24d0-e3dbc6ed284b
begin
import Pkg
Pkg.activate(mktempdir())
end

# ╔═╡ 982fe8a0-5cd8-11eb-3690-316355a4724a
monochromatic_locus = convert.( xyY, colormatch.(360:780))

# ╔═╡ d68fa790-5cef-11eb-062e-af9940a5a224
begin
polygon = [[c.x,c.y] for c in monochromatic_locus]
push!(polygon, polygon[1])
end;

# ╔═╡ c20e8ca0-5d12-11eb-114a-572c90ef9920
function chrom(x,y)
if inpolygon((x,y), polygon)==1
c = RGB(xyY(x,y,1e-6))
k = 1.0/maximum((c.r, c.g, c.b))
c = RGB(k*c.r, k*c.g, k*c.b)
else
c = RGB(0,0,0)
end
end

# ╔═╡ e8b02b80-5cf3-11eb-3882-a742b74e5f5c
chromdiag = let
chromdiag = fill(RGB(0,0,0),900, 800)
for x ∈ 1:800
for y ∈ 1:900
xf = x/1000
yf = y/1000
chromdiag[900-y+1,x] = chrom(xf,yf)
end
end
chromdiag
end

# ╔═╡ Cell order:
# ╠═e8b02b80-5cf3-11eb-3882-a742b74e5f5c
# ╠═c20e8ca0-5d12-11eb-114a-572c90ef9920
# ╠═d68fa790-5cef-11eb-062e-af9940a5a224
# ╠═982fe8a0-5cd8-11eb-3690-316355a4724a
# ╠═5ba5d640-5cd0-11eb-24d0-e3dbc6ed284b
``````
2 Likes

This is excellent.
GR plots the resulting RGB array directly. Only setting the y-axis is a bit tricky because of the flipped y-axis due to the way chromdiag was constructed:

``````plot((1:800)/1000, (1:900)/1000, reverse(chromdiag,dims=1),xlabel="x",ylabel="y",yflip=false)
``````

On this topic, the wikipedia article on CIE 1931 color space is worth taking a look at.

1 Like

Awesome! Is the key to making that work that your x and y ranges match the image dimensions exactly?

Looks like exactly what I needed. Thanks!