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())
	Pkg.add("Colors"); using Colors
	Pkg.add("PlutoUI"); using PlutoUI
	Pkg.add("PolygonOps"); using PolygonOps
	Pkg.add("ImageShow"); using ImageShow
	Pkg.add("ImageIO"); using ImageIO
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!