Plotting a line between two points in gnuplot - plot

I have a csv file with a following format having four columns (as a MWE):
xcoord1,ycoord1,xcoord2,ycoord2
0.1,0.2,0.4,0.3
0.5,0.3,0.7,0.5
I want to plot a line from each xcoord1,ycoord1 to xcoord2,ycoord2 using gnuplot. For example in this case, I would draw two lines from 0.1,0.2 to 0.4,0.3 and 0.5,0.3 to 0.7,0.5.
How is it possible?

Plot the lines as vectors without arrow heads:
plot "file" using 1:2:($3-$1):($4-$2) with vectors nohead

one solution would be to preprocess your file and generate a Gnuplot script which would employ the set arrow command. Alternatively one can plot the input file directly with a little preprocessing. The trick is to convert each line in the data file into a separate block, e.g.,
xcoord1,ycoord1,xcoord2,ycoord2
0.1,0.2,0.4,0.3
0.5,0.3,0.7,0.5
would be converted into
0.1 0.2
0.4 0.3
0.5 0.3
0.7 0.5
Gnuplot will then connect only points within one block. To achieve this, you could do:
plotCmd(fname)=sprintf("<gawk -F, 'NR>1{printf \"%%s\\t%%s\\n%%s\\t%%s\\n\\n\",$1,$2,$3,$4}' %s", fname)
plot plotCmd('input.csv') w lp

Related

Autoscale axis in Gnuplot pm3d map

I have a 4 column file with x,y,z data (the 4th column is just a row counter) and I am trying to make an animation with pm3d map in gnuplot. Each frame is given by 10000 points in the file (the file I shared contains only 3 frames). I am able to plot the first frame with the following command:
splot 'data.txt' u 1:2:3 every:::0::10198
However, if I try to plot the second frame, for example, with the following command:
splot 'data.txt' u 1:2:3 every:::10100::20198
I am given the message:
Warning: No usable data in this plot to auto-scale axis range.
It tells me it can't auto scale any of the axis and if i try to scale it manually, it just doesn't work. First I thought I was just plotting the wrong rows, so I added the row counter, still doesn't work though.
What is funny is that if I make this plot in the traditional splot, everything works fine. I could just go with that, but this is a terrible visualizaiton of data in my opinion, so I'd really like to use pm3d map.
Here is the GDrive folder with 3 frames data, first frame in pm3d and the traditional splot animation
Thanks in advance.
Because you have to try plot not the first, second, third... 10000 data-points but the first 10000 data-sets.
every A:B:C:D:E:F
A - every Ath datapoint
B - every Bth data-set
C,D - first data-point/set
E,F - last data-point/set

Gnuplot histogram 3d

I'm looking for a way to plot histograms in 3d to produce something like this figure http://www.gnuplot.info/demo/surface1.17.png but where each series is a histogram.
I'm using the procedure given here https://stackoverflow.com/a/19596160 and http://www.gnuplotting.org/calculating-histograms/ to produce histograms, and it works perfectly in 2d.
Basically, the commands I use are
hist = 'u (binwidth*(floor(($2-binstart)/binwidth)+0.5)+binstart):(1) smooth freq w boxes
plot 'data.txt' #hist
Now I would just like to add multiple histograms in the same plot, but because they overlap in 2d, I would like to space them out in a 3d plot.
I have tried to do the following command (using above procedure)
hist = 'u (1):(binwidth*(floor(($2-binstart)/binwidth)+0.5)+binstart):(1) smooth freq w boxes
splot 'data.txt' #hist
But gnuplot complains that the z values are undefined.
I don't understand why this would not put a histogram along the value 1 on the x-axis with the bins along the y-axis, and plot the height on the z-axis.
My data is formatted simply in two columns:
Index angle
0 92.046
1 91.331
2 86.604
3 88.446
4 85.384
5 85.975
6 88.566
7 90.575
I have 10 files like this, and since the values in the files are close to each other, they will completely overlap if I plot them all in one 2d histogram. Therefore, I would like to see 10 histograms behind each other in a sort of 3d perspective.
This second answer is distinct from my first. Whereas the first addresses what the OP was trying to accomplish, this second provides an alternative approach which address the underlying problem the OP was trying to overcome.
I have posted an answer that addresses the ability to do this in 3d. However, this isn't usually the best way to do this with multiple histograms like this. A 3d graph like that will be difficult to compare.
We can address the overlap in 2D by stagnating the position of the boxes. With default settings, the boxes will spread out to touch. We can turn that off and adjust the position of the boxes to allow more than 1 histogram on a graph. Remember, that the coordinates you supply are the center of the boxes.
Suppose that I have the data you have provided and this additional data set
Index Angle
0 85.0804
1 92.2482
2 90.0384
3 99.2974
4 87.729
5 94.6049
6 86.703
7 97.9413
We can set the boxwidth to 2 units with set boxwidth 2 (your bins are 4 units wide). Additionally, we will turn on box filling with set style fill solid border lc black.
Then I can issue
plot datafile1 u (binwidth*(floor(($2-binstart)/binwidth)+0.5)+binstart):(1) smooth freq w boxes, \
datafile2 u (binwidth*(floor(($2-binstart)/binwidth)+0.5)+binstart+1):(1) smooth freq w boxes
The second plot command is identical to the first, except for the +1 after binstart. This will shift this box 1 unit to the right. This produces
Here, the two series are clear. Keeping track of which box is associated with each is easy because of the overlap, but it is not enough to mask the other series.
We can even move them next to each other, with no overlap, by subtracting 1 from the first plot command:
plot datafile1 u (binwidth*(floor(($2-binstart)/binwidth)+0.5)+binstart-1):(1) smooth freq w boxes, \
datafile2 u (binwidth*(floor(($2-binstart)/binwidth)+0.5)+binstart+1):(1) smooth freq w boxes
producing
This first answer is distinct from my second. This answer address what the OP was trying to accomplish whereas the second addresses the underlying problem the OP was trying to overcome.
Gnuplot isn't going to be able to do this on it's own, as the relevant styles (boxes and histograms) only work in 2D. You would have to do it using an external program.
For example, using your data and your 2d command (your first command), we get (using your data and the linked values of -100 and 4 for binstart and binwidth)
To draw these boxes on the 3d grid, we will need to use the line style and have four points for each: lower left, upper left, upper right, and lower right. We can use the previous command and capture to a table, but this will only gives the upper center point. We can use an external program to pre-process, however. The following python program, makehist.py, does just that.
from sys import argv
import re
from math import floor
pat = re.compile("\s+")
fname = argv[1]
binstart = float(argv[2])
binwidth = float(argv[3])
data = [tuple(map(float,pat.split(x.strip()))) for x in open(fname,"r").readlines()[1:]]
counts = {}
for x in data:
bn = binwidth*(floor((x[-1]-binstart)/binwidth)+0.5)+binstart
if not bn in counts: counts[bn] = 0
counts[bn]+=1
for x in sorted(counts.keys()):
count = counts[x]
print(x-binwidth/2,0)
print(x-binwidth/2,count)
print(x+binwidth/2,count)
print(x+binwidth/2,0)
print(max(counts.keys())+binwidth/2,0)
print(min(counts.keys())-binwidth/2,0)
Essentially, this program does the same thing as the smooth frequency option does, but instead of getting the upper center of each box, we get the four previously mentioned points along with two points to draw a line along the bottom of all the boxes.
Running the following command,
plot "< makehist.py data.txt -100 4" u 1:2 with lines
produces
which looks very similar to the original graph. We can use this in a 3d plot
splot "< makehist.py data.txt -100 4" u (1):1:2 with lines
which produces
This isn't all that pretty, but does lay the histogram out on a 3d plot. The same technique can be used to add multiple data files onto it spread out. For example, with the additional data
Index Angle
0 85.0804
1 92.2482
2 90.0384
3 99.2974
4 87.729
5 94.6049
6 86.703
7 97.9413
We can use
splot "< makehist.py data.txt -100 4" u (1):1:2 with lines, \
"< makehist.py data2.txt -100 4" u (2):1:2 with lines
to produce

Gnuplot: plotting only specific values of the dataset using lines or linespoints

Let's suppose my dataset is like this:
0 0.3
1 0.12
2 0.4
3 0.6
4 0.9
...
10 0.23
11 0.6
...
20 0.34
21 0.4
...
and I'd like to plot values of both columns only if $1 % 10 == 0, i.e., (0,0.3), (10,0.23), (20,0.34) and so on... Now, I've written the following conditional script:
plot "data.csv" using 1:(int($1)%10==0?$2:0/0) title 'r=1' with linespoints linewidth 3 linecolor rgb 'blue'
The problem is that lines are not shown, but only points.
This is because, for all rows where the condition is not satisfied, the corresponding value is undefined. Anyway, what I need is quite different; I want those specific values to be just ignored, not to set to undefined. Is there a way to do that just using gnuplot (not awk and so on)?
In case you have all intermediate steps, i.e., full data for number (which is suspect based on your axis labelled iterations), you best use the every option
plot "data.csv" every 10 with linespoints
Otherwise, I would use awk inside your script for simplicity
plot "<awk '$1%10==0' data8" with linespoints
The probably with your original script, is that the points are shown, but with value infinity. It is a feature that these lines are not shown.

Have names on the spheres built by rgl package plot3d

Is there a way to have the names shown when use plot3d(rgl) in R to build a 3d graph, cause it's hard to locate which entry the sphere belongs to when I have many spheres to plot on the same coordinate. For example, I have the data:
x y z
A 0.1 -0.5 3.2
B -1.1 1.2 0.8
C 2.0 2.1 0.6
......
plot3d(data,type="s",radius=0.025)
But, I want to have the name A, B, C shown on the graph as it's easier to observe.
Or to have the name shown only when I put the mouse onto one specific sphere.
I have tried to use different colors, but when I have like 20 spheres, it seems it will run out of colors or colors are too close to distinguish.
There is a function text3d() in library rgl that can be used to plot texts inside plot. This example shows how to plot row names as texts.
plot3d(data,type="s",radius=0.025)
text3d(data$x,data$y,data$z,text=rownames(data))
You can also combine the use of text3d with identify3d() to identify points you want to label interactively with your mouse

Gnuplot: plot with circles of a defined radius

I know on gnuplot you can plot some data with circles as the plot points:
plot 'data.txt' using 1:2 ls 1 with circles
How do I then set the size of the circles? I want to plot several sets of data but with different size circles for each data set.
If you have a third column in your data, the third column specifies the size of the circles. In your case, you could have the third column have the same value for all the points in each data set. For example:
plot '-' with circles
1 1 0.2
e
will plot a circle at (1,1) with radius 0.2. Note that the radius is in the same units as the data. (The special file name '-' lets you input data directly; typing 'e' ends the input. Type help special at the gnuplot console for more info.)
You can look here for more ideas of how to use circles.
I used:
plot "file" using 1:2:($2*0+10) with circles
This will fake a the third column specifying the sizes - it is probably possible to write it simpler, but this worked for me.

Resources