1

I'd like to colour the background of my timeseries (a few 10^5 s, so several days) plot depending on the time of day. White for the day regions, a, say, dark blue for the night, and perhaps some transition inbetween.

Continously changing colour would be nice, but a more "blocky" design is also fine. The dataset has a resolution of ten seconds (and many columns), so the plot is already a bit slow.

I'll figure out the math myself (length of day changes over the year), for the moment a sinus (or 0/1 rectangle) with frequency of 1 d is fine, but how do I plot it so the ordinate becomes a background colour instead of vertical screen coordinate?

And, of course there is a hitch, I want everything, the actual graph and background colour, in one plot command so I can still zoom. This

set multi
unset colorbox
gamma = 2.2; color(gray) = gray**(1./gamma)
set palette model RGB functions color(gray), color(gray), color(gray)
set pm3d map; splot [0:20] sin(x); unset pm3d

plot ....

looks super nice, after you adjust the margins etc., and is about what I'm dreaming of. I'd be happy with a black box per night, too.

enter image description here

3 Answers 3

2

I think the easiest way is to create a background gradient of your choice as a png file. The size does not matter so long as it has enough horizontal pixels to encode your desired smooth color variation. So minimally, say, 128x1. But a full screen image would be fine also.

Now you can use that png image as a background using the pixmap commands in gnuplot. I attach a simple example using a linear gradient in "gradient.png"

set pixmap 1 "gradient.png" at graph 0,0 size graph 1,1
set pixmap 1 behind
plot sin(x)

the gradient the plot

Sign up to request clarification or add additional context in comments.

3 Comments

This is certainly another (easy) option to put a bitmap in the background, however, as I understand the question, then you would have to create (more or less) 365 bitmaps, one for each day of the year.
I don't think we know enough about what the plot properties are. If the plot spans N days starting at a fixed time of day, you would only need a single pixmap representing 24 hours. You would place N copies of that pixmap specifying the original of copy i at the start of day i along the x axis and giving a width of 24 hours.
Thanks, nice and simple solution, and easy to write a script using a mapped 2D splot to generate that gradient (or anything a bit more complex). I think I also found a nice solution that works without a prefabricated background using the boxxy style and pseodofile "+", see below.
1

If I understood your question correctly, you would like to have a gradient background depending on the daytime (0-24h) which allows also zoom-in in an interactive terminal.

You can plot a "background" with the plotting style with boxxyerrorbar (check help boxxerrorbar). For this style you have to provide ymin and ymax, so either you have a known fixed y-range or here I used -9e99 to 9e99 and option noautoscale.

The challenge is to find suitable color formulae for the RGB components, but you said you can figure this out yourself. Below is one suggestion. Maybe you can do something easier and more user friendly with a defined palette and the function palette() which is available since gnuplot 5.4.

In order to avoid aliasing effects (brighter lines) you need to play with the variables N and overlap. Optimal values probably also depend on the graph size. For the example below N=200 and overlap=0.5 seem to be good values for a graph with of 640 pixels.

Script:

### gradient background
reset session

# formulae for RGB components
red(t)       = int((t<7 ? t/7. : t>18 ? -(t-18)/6.+1 : 1)*0xff)
green(t)     = int((t<7 ? t/7. : t>18 ? -(t-18)/6.+1 : 1)*0xff)
blue(t)      = int((t<7 ? -(t-7)**2/49.+1 : t>18 ? -(t-18)**2/36.+1 : 1)*0xff)
myBgColor(t) = (red(t)<<16) + (green(t)<<8) + blue(t)

set print $Background
    N = 200
    Overlap = 0.5
    do for [i=0:N-1] {
        t = i*24./N
        print sprintf("%g %g %0.f",t,t+(1+Overlap)*24./N,myBgColor(t))
    }
set print

set style fill solid 1.0 noborder
set xrange[0:24]
set yrange[0:10]
set xtics 4 out
set mxtics 4
set key top center

plot [0:24] $Background u 1:2:1:2:(-9e99):(9e99):3 w boxxy lc rgb var noautoscale, \
     sin(x)+5
### end of script

Result:

enter image description here

2 Comments

There is sth. wrong with your math for the colours. Between 18 and 24h, the values are > 255 for red and green, and you get a colour value that is >> 16.8 million.
@Karl you are absolutely right. -(t-18)/6.+6 is wrong, it should be -(t-18)/6.+1. I've corrected it.
0

Theozh's answer above gave me the right hints, and boxes style is the key:

My solution here also works on data that spans more than one day, and gets rid of the prefabricated colourbar dataset, making the whole graph zoomable.

Same colour palette as theoz:

red(t)       = int((t<7 ? t/7. : t>18 ? -(t-18)/6.+1 : 1)*0xff)
green(t)     = int((t<7 ? t/7. : t>18 ? -(t-18)/6.+1 : 1)*0xff)
blue(t)      = int((t<7 ? -(t-7)**2/49.+1 : t>18 ? -(t-18)**2/36.+1 : 1)*0xff)

Take time modulo 24h to calculate the colour

mod(a,b) = a - floor(a/b)*b;
myBgColor(t) = (red(mod(t,24))<<16) + (green(mod(t,24))<<8) + blue(mod(t,24));

, and use the pseudofile '+' to plot with style "boxes", so the background has always same range as the plot

setsample 400
set style fill solid
set xtics 24
plot '+' u 1:(9e99):(myBgColor($1)) w boxes lc rgb var noautoscale, 1-cos(x/24*pi*2)

alternatively with "candlesticks" you can let the boxes extend below zero (the candles or whiskers have length zero here)

set boxwidth 1 relative # 
plot '+' u 1:(-5):(5):(-5):(5):(myBgColor($1)) w candlesticks fill solid lc rgb var noautoscale, 1-cos(x/24*pi*2) 

enter image description here

4 Comments

As you noticed, if you zoom-in the samples of '+' will be distributed within the new zoom range, that's why I used a datablock which doesn't require a replot. However, if you zoom-in too much (i.e. smaller than the width of the boxxy) the "background" will disappear. I also observed a green line, I guess it is a floating point rounding artefact.
@theozh You comment set me on the right track: regular "boxes" with "set style fill solid" do exactly what is needed.
regular boxes will always start from 0. Since I didn't know what you y-range is I went for boxxyerror. If you'll figure out how to avoid the green bars could you maybe post your final solution?
@theozh "candlesticks" with zero whisker lenght are the ticket there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.