## Wednesday, 29 July 2009

I think, it changes the impression a graph can make by quite a lot, if it looks sort of three-dimensional. Even a tiny twist to the boring 2D lookout can make a difference, though it doesn't give any new information to the reader. However, in a presentation, it is almost expected that one produces "exciting" graphs. Today, we will discuss an easy way to add a slight shadow to the key on a graph, as if it were lifted from the plane of the curves. At the end of our exercise, we will have the following figure

I believe the steps are quite straightforward, so I won't spend too much time on explaining every detail. Here is the script that we need

```reset

xl=0; xh=1; yl=-1; yh=1;
eps=0.01;
rx=0.6; ry=0.8; kw=0.35; kh=0.15
lh=0.06; al=0.1

key1="First function"
key2="Second function"

splot [xl:xh] [yl:yh] x/(xh-xl)
unset table

set object 1 rect from graph rx,ry rto kw,kh fc rgb "#aaaaaa" fs solid 1.0 front lw 0
set object 2 rect from graph rx-eps,ry+eps rto kw,kh front fs empty
set label 1 at graph 1.1*al+rx, ry+2*lh key1 front
set label 2 at graph 1.1*al+rx, ry+lh key2 front
set arrow from graph rx, ry+2*lh rto al, 0 lt 1 lw 1.5 nohead front
set arrow from graph rx, ry+lh rto al, 0 lt 3 lw 1.5 nohead front

unset colorbox
unset key
set palette defined (0 "#8888ff", 1 "#ffffff")
plot [xl:xh] [yl:yh] 'shadowkey.dat' w ima, \
x*x*exp(-x) lw 1.5, cos(13*x)*exp(-3*x) lt 3 lw 1.5```

I collected all variables at the beginning of the script, so that it will be easier to adapt it to any situations. The first four numbers define the xrange and the yrange. The next four numbers specify the position and the size of the key. We will have to make our own key, and the size of the key will depend on the particular terminal one uses. This is why it is handy to define them at the beginning of the script, so if you are not satisfied with the results, you can easily adjust both the position and the size. The next number (lh) gives the hight of one key line, while 'al' will be the length of the line which represents the curve. 'key1' and 'key2' are just two arbitrary strings, holding the text of the key.

The next three lines are necessary only if you want to draw the background gradient, but if you are happy with a white plot, you can skip this. I should also point out that the first four numbers that are needed for the xrange and yrange, are needed only because we have to "synchronise" the plot with its background. If you don't want the gradient, you can drop these definitions, and you haven't got to specify the range in the plot either. This might be useful, when you don't know the plotting range beforehand, and want to let gnuplot calculate it for you.

The next step is to draw two rectangles in the front of the graph: one gray, and one white. Note that the rectangle in gray has no boundary, i.e., that is set to zero width. Also note that we specify the coordinates in terms of the numbers we defined at the beginning, so both rectangles will change accordingly, if you change those numbers. This means that the white rectangle and its shadow will always be linked, given by the variable 'eps'. When we are done with the white rectangle, we can place the text of the keys, and the two lines representing our plots. For this purpose we draw two arrows without heads, and with the linetypes that we will use for plotting the curves.

The final step is to actually draw the curves. Before that, we plot our file, 'shadowkey.dat', so the graph will have a background gradient. If you skipped those three lines writing the data file to disc, you should replace the plotting command by

`plot [xl:xh] [yl:yh] x*x*exp(-x) lw 1.5, cos(13*x)*exp(-3*x) lt 3 lw 1.5`

It should go without saying that in this case, you can also drop the palette definition, for it will not be used. Well, this is it for today. I know that this was a simple trick, but we can't have something complicated every day!

1. As you can see, I am still hanging out in the simple parts of your blog. Very nice.

I suppose in the example script you left the key area empty intentionally to make the reader see what's going on? It's easily fixed, of course, so a good learning experience.

Is there a good way, to use the graph or screen coordinate systems to make things predictable (when the plot does not span [0:1][0:1])?

What is a position / good ratio y vs x epsilon to make the shadow be as much down as sideways, depending on what rmarging, bmargin etc are?

2. In the ps and eps terminals, I get a very thin black line around the gray shadow in gnuplot 4.4 (in spite of lw 0). Do you see the same? I have tried set style line # and ls # but that is not allowed as an option to an object. :(

3. I've deleted a few posts because I've been basically talking to myself here, and no-one wants to know the several iterations I went through for this.

There is an undocumented (in the built-in help) option "noborder" that can be prepended in front of the "front" attribute. [Also, border ls N lw M sets line style N for the border, and lw 0 is still ignored - gnuplot bug?]

I made a version with a real key, not one drawn by hand.

We can draw the rectangles as "behind" since the graph background is drawn separately.

I have tried to extract gnuplot's guess for character dimensions and scaled the key area accordingly. Try changing the font size and figure dimensions (first three variables in my script) to see what I mean.
___

#!/usr/bin/gnuplot -persist
pwid=5
phgt=3.5
pfnt=24

set term postscript enhanced eps color dashed size pwid,phgt "Helvetica" pfnt
set output "tricks-bkey.eps"

xl=0; xh=20; yl=-1; yh=1;
xofs=0.5
yofs=2.0
rmar=1.5
lmar=7.75-yofs
tmar=0.5
bmar=3.25-xofs

set xrange [xl:xh]
set yrange [yl:yh]

## tic length, character width, character height (gnuplot's estimate)
## (reverse engineered for term postscript eps Helvetica)
ticl=0.0075*5./pwid
chrw=0.02000*5./24.*pfnt/pwid
chrh=0.095/2*3.5/24.*pfnt/phgt

## key position, epsilon for shadow, width and height
kmag=0.05*pfnt/24; kx=1-rmar*chrw-kmag*phgt/pwid; ky=1-tmar*chrh-kmag/2
yeps=kmag/2; xeps=yeps*phgt/pwid;
delwidth=4; sampl=2;

keys1='y=sin(x)*exp(-x/10)'
keys2='Data set 2'
keys=2

keyl1=strlen(keys1)
keyl2=strlen(keys2)
max(x,y)=(x>y)?(x):(y)
keylen=max(keyl1, keyl2)

kw=(keylen+sampl+2-delwidth)*chrw+ticl;
kh=keys*chrh

f(x) = exp(-x/10.0)*sin(x)
g(x) = exp(-x/10.0)
h(x) = -exp(-x/10.0)

set sample 30
set table 'test.dat'
plot f(x)+(rand(0)-0.5)*0.2
unset table

set sample 128
set isosamples 2,128

set table 'background.dat'
splot (y-yl)/(yh-yl)
unset table

set multiplot

set rmargin 0
set lmargin 0
set tmargin 0
set bmargin 0

unset colorbox
unset border
unset xtics
unset ytics

set palette defined (0 "#68c068", 1 "#ffffff")
plot 'background.dat' w ima

set rmargin rmar
set lmargin lmar
set tmargin tmar
set bmargin bmar

set palette defined (0 "#e68080", 1 "#ffffff")
plot 'background.dat' w ima

set key at screen kx,ky reverse Left samplen sampl width -delwidth box
set object 1 rect from screen kx+xeps,ky-yeps rto screen -kw,-kh fc rgb "#aaaaaa" fs solid 1.0 noborder behind
set object 2 rect from screen kx,ky rto screen -kw,-kh fc rgb "white" fs solid 1.0 noborder behind

set xtics
set ytics
set xlabel 'Time [s]' offset 0,xofs
set ylabel 'Position [m]' offset yofs,0
set border 1+2+4+8

plot \
f(x) w l lt 3 lw 2 t keys1 \
, g(x) w l lt rgb "#008800" t '' \
, h(x) w l lt rgb "#008800" t '' \
, 'test.dat' u 1:2:(\$2-rand(0)*0.1-0.05):(\$2+rand(0)*0.1+0.05) t keys2 w errorb pt 13 lt 1 \

unset multiplot

!/bin/rm -f test.dat background.dat
!gv -scale=3 tricks-bkey.eps &