oompahloompah
oompahloompah

Reputation: 9333

Plotting arrows with gnuplot

I have data generated in a simulation. The generated data file looks something like this:

1990/01/01 99
1990/01/02 92.7
1990/01/03 100.3
1990/01/04 44.2
1990/01/05 71.23
...
2100/01/01 98.25

I can create a chart (trivially), by simply issuing the (long versioned) command:

plot "simulation.dat" using 1:2 with line

I want to add a third column which will add arrow information. The encoding for the third column would be as follows:

I am just starting to learn gnuplot, and will appreciate help in how I can use gnuplot to create the arrows on the first plot?

Upvotes: 7

Views: 20063

Answers (3)

Christoph
Christoph

Reputation: 48390

Although the question is quite old, here is my answer.

One can use the vectors plotting style, which can use variable arrowstyles based on a column's value:

set style arrow 1 backhead
set style arrow 2 head
set yrange[0:*]
set xdata time
set timefmt "%Y/%m/%d"
plot "simulation.dat" using 1:2 with line,\
     "" using 1:2:(0):(-$2):($3 == 0 ? 1/0 : $3) with vectors arrowstyle variable

It the value of a column is 1/0, the point is considered as undefined and is skipped.

Upvotes: 2

Martin
Martin

Reputation: 1114

I dont think there is an automatic way to create all your arrows at the same time based on the third column. You will have to execute the following for each arrow that you want:

set arrow xval1,yval1 to xval2,yval2

You can also use relative arrows

set arrow xval1,yval1 rto 1,0

This will draw a horizontal arrow from xval1,yval1 to (xval1+1),yval1

There are plenty of options associated with the set arrow command:

Upvotes: 4

Tom
Tom

Reputation: 5299

If you didn't want the arrow head then you might try the impulses style (with impulses rather than with lines) (If you still want the lines on top then you can plot twice).

If you really want the arrow heads then the following might help: It uses a for loop (or sorts) to add vertical arrows to a plot.

Gnuplot script, for loop within or adding to existing plot

Specifically:

create a file simloop.gp which looks like the following:

count  = count+1
#save the count to count.gp
system 'echo '.count.' > count.gp'
#load the simloop shell
system "./simloop.sh"

#draw the arrow
load 'draw_arrow.gp'

if(count<max) reread

Then create a simloop.sh file that looks something like so

#!/bin/bash

#read the count
count=$(awk -F, '{print $1}' count.gp)
#read the file
xcoord=$(awk -v count=$count -F, 'BEGIN{FS=" ";}{ if(NR==count) print $1}' simulation.dat)
ycoord=$(awk -v count=$count -F, 'BEGIN{FS=" "}{ if(NR==count) print $2}' simulation.dat)
dir=$(awk -v count=$count -F, 'BEGIN{FS=" "}{ if(NR==count) print $3}' simulation.dat)

#choose the direction of the arrow
if [ \"$dir\" == \"0\" ]; then
    echo '' > draw_arrow.gp
fi

if [ \"$dir\" == \"1\" ]; then
  echo 'set arrow from ' $xcoord' ,0 to '$xcoord','$ycoord' head' > draw_arrow.gp
fi

if [ \"$dir\" == \"2\" ]; then
 echo 'set arrow from '$xcoord',0 to '$xcoord','$ycoord' backhead' > draw_arrow.gp
fi

Then create a simulation.gp file that looks something like so:

count = 0;
max = 5;
load "simloop.gp"
set yrange[0:*]
plot "simulation.dat" u 1:2 w l

Make sure the shell file has executable permissions (chmod +wrx simloop.sh), load up gnuplot and type

load "./simulation.gp"

This worked for me with the data file

1  99   0
2  92.7 1
3 100.3 2
4 44.2  0
5 71.23 1

(For testing I got rid of the time formatting You should be able to put it back without too much trouble.)

Then I got this graph: enter image description here

Which I think is more or less what you want.

Upvotes: 3

Related Questions