Frederico Schardong
Frederico Schardong

Reputation: 2095

gnuplot do not overlap lines

The folowing graph is generated with gnuplot: enter image description here

It shows 5 (but it can be more or less) waves. However, what I need is display each wave separately, like this (I did with gimp):

enter image description here

Is there a way to do this with gnuplot? I also need that each wave be a different colour, as I have now.

Here is gnuplot script used: http://pastebin.com/vAD2syTS

Here is the python script that gnuplot script uses to fix my data: http://pastebin.com/WEncNjDA

Here is the data: http://pastebin.com/ewBpvHWM

Here is the data after python script fixes it: http://pastebin.com/cgimMyr9

Upvotes: 2

Views: 1799

Answers (2)

andyras
andyras

Reputation: 15910

I had some fun with this one. My strategy involves plotting the first, last and intermediate plots with slightly different settings in order to get the borders to line up. I also define some functions to ensure that all the plot colors will indeed be different unless you have upwards of ~16 million data sets to plot.

### indices: change this parameter to equal the number of data sets to be plotted
indices = 8 
# h: height of output in pixels
h = 150.0*indices
# d: top and bottom margin in pixels
d = 75.0

### define functions to help set top/bottom margins
top(i,n,h,d) = 1.0 - (d+(h-2*d)*(i-1)/n)/h
bot(i,n,h,d) = 1.0 - (d+(h-2*d)*i/n)/h

### define some fun RGB code converter functions

# round: crude rounding function (gnuplot doesn't have this?)
# assumes a float, returns an int
round(x) = x-int(x)>=0.5?ceil(x):floor(x)

# i2h: converts a (decimal) integer between 0 and 15 to hex.
# returns a string, 0-F corresponding to 0-15
i2h(i) = i==10?'A':i==11?'B':i==12?'C':i==13?'D':i==14?'E':i==15?'F':sprintf('%d',i)

# i2r: converts an integer to an RGB code.
# returns a string (RGB code) of length 6, 000000-FFFFFF corresponding to 0-16777215
# changing the last division to 15 instead of 16 prevents colors being too faint
i2r5(i) = i2h(i/(15**5))
i2r4(i) = i2h(i%(16**5)/(15**4))
i2r3(i) = i2h(i%(16**5)%(16**4)/(15**3))
i2r2(i) = i2h(i%(16**5)%(16**4)%(16**3)/(15**2))
i2r1(i) = i2h(i%(16**5)%(16**4)%(16**3)%(16**2)/(15**1))
i2r0(i) = i2h(i%(16**5)%(16**4)%(16**3)%(16**2)%(16**1))
i2r(i) = i2r5(i).i2r4(i).i2r3(i).i2r2(i).i2r1(i).i2r0(i)

# rgb_iter: returns the i-th of n RGB codes, evenly spaced across the spectrum
rgb_iter(i, n) = '#'.i2r(round((i-1)*(16777215.0/(n-1))))

### first set up some basic plot parameters
set term png enhanced size 800,h font 'Courier-Bold,14'
set output 'waves.png'

set title 'Wave propagation by geophones'
set ylabel 'Wave'

set xrange [1400:]
set yrange [-0.15:0.15]
set ytics ('-0.1' -0.1, '0.0' 0.0, '0.1' 0.1)

set key out right

### now make plots
set multiplot layout indices,1

### first plot
set border 14
set tmargin at screen top(1,indices,h,d)
set bmargin at screen bot(1,indices,h,d)
unset xtics
plot 'temp.dat' index 0 w lines lw 3 lc rgb rgb_iter(1,indices) title 'Geophone 1'
unset title

### intermediate plots
set border 10
unset xlabel
do for [i=1:indices-2] {
 set tmargin at screen top(i+1,indices,h,d)
 set bmargin at screen bot(i+1,indices,h,d)
 plot 'temp.dat' index i w lines lw 3 lc rgb rgb_iter(i+1,indices) title sprintf('Geophone %d', i + 1)
}

### last plot
set border 11
set tmargin at screen top(indices,indices,h,d)
set bmargin at screen bot(indices,indices,h,d)
set xtics nomirror
set xlabel 'Iterations'
plot 'temp.dat' index (indices-1) w lines lw 3 lc rgb rgb_iter(indices,indices) title sprintf('Geophone %d', indices)

unset multiplot

The output on your sample data set looks like this: enter image description here

The sizes of the top/bottom plots aren't quite perfect, and as mgilson said it would probably take some fiddling with set xmargin at screen ... commands to make all the plot sizes equal.

(If nothing else those int->RGB converter can be handy for specialized applications; I also have functions going from RGB codes to ints.)

EDIT: I updated the script so all the plots will have the same height.

Upvotes: 6

mgilson
mgilson

Reputation: 309929

If you know the number of plots ahead of time (gnuplot 4.6):

NUM_PLOTS = 6
set multiplot layout NUM_PLOTS,1
do for [i=1:NUM_PLOTS]{
   plot 'temp.dat' index i w lines lw 3 title sprintf('Geophone %d', i + 1)
}
unset multiplot

If you really want to get fancy to make sure your borders and axes line up, you could use a combination of set lmargin at screen ..., set rmargin at screen ..., set tmargin at screen ..., and set bmargin at screen ... where the ... are some function of i and NUM_PLOTS, although probably setting lmargin and rmargin at some constant position would be good enough (gnuplot should take care of aligning from top to bottom if you don't need to share axes).

set border 10 will remove the top and bottom border lines if you really want that, but it's probably not necessary.

I'd recommend something like:

NUM_PLOTS = 6
set multiplot layout NUM_PLOTS,1
set lmargin at screen 0.1
set rmargin at screen 0.9
do for [i=1:NUM_PLOTS]{
   plot 'temp.dat' index i w lines lw 3 title sprintf('Geophone %d', i + 1)
}
unset multiplot

Upvotes: 5

Related Questions