knightrider
knightrider

Reputation: 2143

gnuplot change color of the connecting lines

I am using gnuplot for the following. I have n equations which I want to plot based on the xaxis value. Here is a sample

set xrange[0:25]
f1(x) = x
f2(x) = 3*x
f3(x) = 10*x
plot (x>0)&&(x<10)?f1(x):(x<20)?f2(x):f3(x)

I know that we can set the color of the line easily by using the below. But it changes the whole color

set style line 1 lt 1 lw 3 pt 3 lc rgb "blue"

But what I want is to make the connecting lines a different color. ie if you plot the above graph you will 5 lines. 3 original lines (from the function) and 2 lines (the almost vertical lines) connecting them. I want to change the color of the connecting lines.

Note 1: These functions are automatically generated by a program, and the number of functions could be large. Even the exact plot command is automatically generated

Note 2: I want a way to differentiate my original lines with the interpolated lines which joins my original lines.

Any help is appreciated

Upvotes: 2

Views: 2616

Answers (4)

theozh
theozh

Reputation: 25704

When reading the comments, I'm not sure if it is wise to add another solution...
But for fun... another solution which differs from the given ones:

  • does not require a datafile with 3 columns (@andyras)
  • does not depend on set samples
  • does not require to set a dx or lim which depend on the samples (@Bernhard, @Christoph)

The simple idea is to tell gnuplot in a variable c1 in which piece of the function you currently are and change the color if you're going from one piece to the next piece. So, it's a kind of a compact mix of @andyras' and @Christoph's solution.

Script: (works with gnuplot>=4.4.0, March 2010)

### plot transitions between piecewise function in different color
reset

set xrange[0:25]
f1(x) = x
f2(x) = 3*x
f3(x) = 10*x

x1 = 10   # break points for piecewise function
x2 = 20

f(x)  = x<x1 ? (c1=1,f1(x)) : x<x2 ? (c1=2,f2(x)) : (c1=3,f3(x))

plot c1=1 '+' u (c0=c1,$1):(f($1)):(c0==c1 ? 0x0000ff : 0xff0000) w l lc rgb var notitle
### end of script

Addition: In case you might want to let the red lines disappear...

  • for gnuplot>=5.0.0 you can set a fully transparent color, e.g. 0xff123456
  • for gnuplot>=4.4.0 & <5.0.0 you could set it to white 0xffffff (if this is your background)

Result:

Standard set samples is 100. That's why the red lines are not fully vertical. You can get them "more vertical", e.g. if you set samples 1000.

enter image description here

Upvotes: 0

Christoph
Christoph

Reputation: 48390

If it is ok to skip the connecting lines, then you can use a simplified version of @andyras second variant. Just define all functions to be 1/0 when outside a specified range:

set style data lines
unset key

f1(x) = (x > 0) && (x < 10) ? x : 1/0
f2(x) = (x > 10) && (x < 20) ? 3*x : 1/0
f3(x) = (x > 20) ? 10*x : 1/0

plot [0:25] f1(x), f2(x), f3(x)

Following yet another possibility. This assumes, that you can select a sampling high enough, so that the "jumps" which connect the functions are always greater than inside a function:

set style data lines
unset key

set xrange[0:25]
f1(x) = x
f2(x) = 3*x
f3(x) = 10*x
f(x) = ( (x>0)&&(x<10)?f1(x):(x<20)?f2(x):f3(x) )

set samples 1000

curr = 0
prev = 0
lim = 1
plot '+' using (prev = curr, curr=f($1), $1):(f($1)):(abs(curr-prev) < lim ? 0 : 1) lc var

enter image description here

Upvotes: 2

Bernhard
Bernhard

Reputation: 3694

You can define a secondary function to define the breakpoints of your function, which is automatically coloring the right linepiece. The below code is easy to extend to different functions and breakpoints (i.e., you can just change x1 or x2). Adding multiple points is also straightforward.

xmin=0.
xmax=25.
x0=0.
x1=10.
x2=20.
nsample=200.


dx=(xmax-xmin)/nsample
print dx
set xrange[xmin:xmax]
set sample nsample
f1(x) = x
f2(x) = 3*x
f3(x) = 10*x
f4(x) = (x>x0)&&(x<x1)?f1(x):(x<x2)?f2(x):f3(x)
f5(x) = x
f5(x) = ( (x>x1&&x<=x1+dx) || (x>x2&&x<=x2+dx) )?1:0

set cbrange [0:1]
unset key

plot '+' using 1:(f4($1)):(f5($1)) lc variable with lines

Not that I have use the special filename '+', which just constructs a data file with equally space datapoints (following nsample).

Sample output

Upvotes: 3

andyras
andyras

Reputation: 15910

What you actually have is one line defined piecewise, and there isn't an easy way to define colors for line segments within a piecewise line in gnuplot.

Easy way (plot a data file)

I would recommend making a data file looking like this:

# x y color
0   0   0
10  10  0
10  10  1
10  30  1
10  30  0
20  60  0
20  60  1
20  200 1
20  200 0
25  250 0

Notice the double points at x=10 and x=20. This is so the line segments meet at the transitions.

Now plot it with linecolor variable:

#!/usr/bin/env gnuplot

reset

set terminal pdfcairo enhanced color dashed rounded lw 5 size 3,2 font 'Arial,14'
set output 'output2.pdf'

set style data lines
set key top left
set tics scale 0.5 out nomirror

plot 'data.dat' u 1:2:3 lc variable

It looks like this:

enter image description here

You can change the palette (set palette) to determine the colors, and you can have more than 2 color values in the data file if you want.

Harder way (only OK for few segments)

You could define 2n-1 separate lines and connect them:

#!/usr/bin/env gnuplot

reset

set terminal pdfcairo enhanced color dashed rounded lw 5 size 3,2 font 'Arial,14'
set output 'output.pdf'

set style data lines
set key top left
set tics scale 0.5 out nomirror

# points every 0.001 units in the range 0:25
set samples 25001

# main lines
f1(x) = (x <= 9.999)                   ? x    : 1/0
f3(x) = (x >= 10.001) && (x <= 19.999) ? 3*x  : 1/0
f5(x) = (x >= 20.001)                  ? 10*x : 1/0

# define slopes and y-offsets of connecting lines
m2 = (f3(10.001)-f1(9.999))/0.002
b2 = (30.0-10.0)/2.0 + 10.0
m4 = (f5(20.001)-f3(19.999))/0.002
b4 = (200.0-60.0)/2.0 + 60.0

# connecting functions
f2(x) = (x >= 9.999) && (x <= 10.001)  ? m2*(x-10) + b2 : 1/0
f4(x) = (x >= 19.999) && (x <= 20.001) ? m4*(x-20) + b4 : 1/0

plot [0:25] f1(x), f2(x), f3(x), f4(x), f5(x)

Which looks like this:

enter image description here

Upvotes: 3

Related Questions