Gnuplot read line style from data file column - gnuplot

I'd like to draw an impulse graph from a text file that looks like this:
II 5 0 0 288.40 1.3033e+14
II 6 0 0 289.60 1.5621e+14
II 1 4 0 302.70 3.0084e+13
II 2 4 0 303.40 4.0230e+13
II 1 5 1 304.40 3.4089e+13
The plot conceptually should be plot "datafile.dat" using 5:6 w impulses ls $2.
Basically, given a previously defined set of line styles, I'd like to input the line style number from column 2 for every couple of plotted points from column 5 and 6.
Also I'd like to create a text box, for every plotted point, taking strings from the first four columns.
Does somebody know if that's possible?

To use the data from column two as line style use set style increment user and linecolor variable:
set style increment user
plot "datafile.dat" using 5:6:2 with impulses lc var
In order to place a label, use the labels plotting style:
plot "datafile.dat" using 5:6:1 with labels offset 0,1
Putting everything together, you have:
set style increment user
set for [i=1:6] style line i lt i
set yrange [0:*]
set offsets 0,0,graph 0.1,0
plot "datafile.dat" using 5:6:2 with impulses lc var, "" using 5:6:1 with labels offset 0,1
The result with 4.6.3 is:

Thanks for the helpful answer above. It almost solved my problem
I'm actually trying to use a column from my data file to specify a linestyle (dot, squares,triangles, whatever as long as it's user-defined), and not a linecolor. Is there any way to do that?
This line works : I get points with different colors (specified in column 4), but the point style is the same.
plot "$file" u 1:2:4 w p notitle lc var, "" using 1:2:3 with labels offset 0,1 notitle
Replacing lc with ls after defining my own styles doesn't work (ls can't have variable as an option)
I can live without different linestyles, but it would be much prettier.

You only have to replace the lineset for [i=1:6] style line i lt i for set for [i=1:6] style line i lt i pt %, Where % can be any type of point you want

Related

How to remove line between "jumping" values, in gnuplot?

I would like to draw a line with plots that contain "jumping" values.
Here is an example: when we have plots of sin(x) for several cycles and plot it, unrealistic line will appear that go across from right to left (as shown in following figure).
One idea to avoid this might be using with linespoints (link), but I want to draw it without revising the original data file.
Do we have simple and robust solution for this problem?
Assuming that you are plotting a function, that is, for each x value there exists one and only one corresponding y value, the easiest way to achieve what you want is to use the smooth unique option. This smoothing routine will make the data monotonic in x, then plot it. When several y values exist for the same x value, the average will be used.
Example:
Data file:
0.5 0.5
1.0 1.5
1.5 0.5
0.5 0.5
Plotting without smoothing:
set xrange [0:2]
set yrange [0:2]
plot "data" w l
With smoothing:
plot "data" smooth unique
Edit: points are lost if this solution is used, so I suggest to improve my answer.
Here can be applied "conditional plotting". Suppose we have a file like this:
1 2
2 5
3 3
1 2
2 5
3 3
i.e. there is a backline between 3rd and 4th point.
plot "tmp.dat" u 1:2
Find minimum x value:
stats "tmp.dat" u 1:2
prev=STATS_min_x
Or find first x value:
prev=system("awk 'FNR == 1 {print $1}' tmp.dat")
Plot the line if current x value is greater than previous, or don't plot if it's less:
plot "tmp.dat" u ($0==0? prev:($1>prev? $1:1/0), prev=$1):2 w l
OK, it's not impossible, but the following is a ghastly hack. I really advise you add an empty line in your dataset at the breaks.
$dat << EOD
1 1
2 2
3 3
1 5
2 6
3 7
1 8
2 9
3 10
EOD
plot for [i=0:3] $dat us \
($0==0?j=0:j=j,llx=lx,lx=$1,llx>lx?j=j+1:j=j,i==j?$1:NaN):2 w lp notit
This plots your dataset three times (acually four, there is a small error in there. I guess i have to initialise all variables), counts how often the abscissa values "jump", and only plots datapoints if this counter j is equal to the plot counter i.
Check the help on the serial evaluation operator "a, b" and the ternary operator "a?b:c"
If you have data in a repetitive x-range where the corresponding y-values do not change, then #Miguel's smooth unique solution is certainly the easiest.
In a more general case, what if the x-range is repetitive but y-values are changing, e.g. like a noisy sin(x)?
Then compare two consecutive x-values x0 and x1, if x0>x1 then you have a "jump" and make the linecolor fully transparent, i.e. invisible, e.g. 0xff123456 (scheme 0xaarrggbb, check help colorspec). The same "trick" can be used when you want to interrupt a dataline which has a certain forward "jump" (see https://stackoverflow.com/a/72535613/7295599).
Minimal solution:
plot x1=NaN $Data u 1:2:(x0=x1,x1=$1,x0>x1?0xff123456:0x0000ff) w l lc rgb var
Script:
### plot "folded" data without connecting lines
reset session
# create some test data
set table $Data
plot [0:2*pi] for [i=1:4] '+' u 1:(sin(x)+rand(0)*0.5) w table
unset table
set xrange[0:2*pi]
set key noautotitle
set multiplot layout 1,2
plot $Data u 1:2 w l lc "red" ti "data as is"
plot x1=NaN $Data u 1:2:(x0=x1,x1=$1,x0>x1?0xff123456:0x0000ff) \
w l lc rgb var ti "\n\n\"Jumps\" removed\nwithout changing\ninput data"
unset multiplot
### end of script
Result:

Smooth command not supporting variable colors?

I am trying to make a plot in GNUplot using smooth csplines command. The data file can have many different sections to plot (not constant) and i wold like to use the lc variable option to differentiate them with different color. Am i wrong of is not supporting the lc variable option?
Correct, you cannot mix smooth and lc palette in a single plot command. You could write the smoothed data to an intermediate file with set table and then plot this data with lc palette.
Consider the example file test.txt:
1
3
2
5
4
6
Now plot this with:
set table 'tmp.txt'
plot 'test.txt' using 0:1 smooth cspline
unset table
And then plot the file tmp.txt with lc rgb variable or similar:
rgb(r,g,b) = 65536 * int(r) + 256 * int(g) + int(b)
plot 'test.txt' using 0:1 pt 7 t 'original', \
'tmp.txt' using 1:2:($2 < 4.2 ? rgb(255,0,0) : rgb(0,255,0)) with lines lc rgb var t 'smoothed'
Result with 4.6.4:
Note, that this doesn't allow you to use some criteria contained in an additional column of your original data for coloring (say, in the third column of test.txt). That would require much more fiddling.

Displaying markers on specific values in Gnuplot's line plot

I have data for a CDF in a file which looks like the following:
0.033 0.0010718113612
0.034 0.0016077170418
0.038 0.0021436227224
... ...
... ...
0.847 0.999464094319
0.862 1.0
First column is the X-axis value and the second column is the CDF value on Y-axis. I set the line style as follows:
set style line 1 lc rgb 'blue' lt 1 lw 2 pt 7 ps 0.75 # --- blue
and subsequently plot the line with the following:
plot file1 using 1:2 title 'Test Line CDF' with linespoints ls 1
This all works fine, the problem seems to be that my CDF file is pretty big (about 250 rows) and Gnuplot would plot the marker/point (a circle in this case) for every data point. This results in a very "dense" line because of the over-concentration of markers such that the underlying line is almost not visible as I show in an example image below:
How can I selectively draw the markers so that instead of having them on all data points, I plot them after every 50 data points, without having to decrease the number of data points (which I believe is what "every n" in the plot command would do) in my data file or decrease the marker size?
There is no need to use two plots commands, just use the pointinterval option:
plot 'data' pointinterval 5 with linespoints
That plots every line segment, but only every fifth point symbol.
The big advantage is, that you can control the behaviour with set style line:
set style line 1 lc rgb 'blue' lt 1 lw 2 pt 7 ps 0.75 pi 5
plot 'data' w lp ls 1
You can plot the same function twice, once with lines only, and then with points every n points. This will draw less points without decreasing the amount of segments. I think this is what you want to achieve. For this example I have done set table "data" ; plot sin(x) to generate numerical sampling of the sin(x) function.
What you have at the moment is:
plot "data" with linespoints pt 7
which gives
Now you can do the following:
plot "data" with lines, "data" every 10 with points pt 7 lc 1
which gives what you want:
You can change the styling to meet your needs.
Although #Miguel beat me to it, but I'm also posting my solution below:
The idea is to once draw the line and then draw the points with the "every n" specifier. I changed my own Gnuplot script in the following manner. A kind of hack but works:
set style line 1 lc rgb 'blue' lt 1 lw 2 pt 7 ps 0 # --- blue
plot file1 using 1:2 title '' with linespoints ls 1, "" using 1:2 every 20 title 'Test Line CDF' with points ls 1 ps 0.75
This retains the nice curve, without quantizing it too coarsely while also keeping the points much better spaced.

Trying to use line styles but see points

With the following simple data file
1 1
2 3
3 4
and this script
set style line 2 lt 3 lc rgb "red" lw 3
show style line
set xrange [0:5]
set yrange [0:5]
plot "test_data.txt" u 1:2 ls 1
I don't see the line. Instead I only see the points. More than that, I don't see (1 1). Why? I followed the same steps form here
You have a data file, the example you reference uses functions. In gnuplot you need to specify that you want to use lines (with lines or in short w l) if you want to join data points with lines. Also, I can see (1 1) on your graph. Also I noticed you defined style line 2 but then used ls 1 instead of ls 2 to plot your data (that is you're not using the style you previously defined). Try
plot "test_data.txt" u 1:2 w l ls 2
If you also want to see the points together with lines, then use with linespoints or w lp:
plot "test_data.txt" u 1:2 w lp ls 2

setting multiple labels at the top of the x-axis

After the answer got in my earlier post drawing vertical lines in between bezier curves, I have been trying to label the segments separated by the dotted lines. I used x2label but found out that if I use it multiple times then the data gets replaced though they are positioned in different places. Below is the script:
set term x11 persist
set title "Animation curves"
set xlabel "Time (secs.)"
set ylabel "Parameter"
set x2label "Phoneme1" offset -35
set pointsize 2
set key off
set style line 2 lt 0 lc 1 lw 2
plot [0.04:0.15] "curve.dat" u 1:2 smooth csplines ls 1, "" u 1:($2-0.2):(0):(0.3) w vectors nohead ls 2, \
"curve.dat" u 1:2 with points
The output is the following.
I want to label Phoneme1, Phoneme2...and so on.. on top of each segment. How would I do it? Also as I was suggested in my earlier post to play with the line "" u 1:($2-0.2):(0):(0.3) w vectors nohead ls 2 to get a top to bottom vertical lines. But that also did not work. How do I get the lines from top margin to bottom? Thank you.
The horizontal lines
The horizontal lines can be accomplished with setting the yrange to an explicit value. Otherwise gnuplot would try to get some space between the lines and the axis. You could choose the values
set yrange [0.3:1.2]
Then you simply modify the vector using directions like so:
"" u 1:(0.3):(0):(1.2) w vectors nohead ls 2
(see below for the complete script)
The labeling of the sections
A quick way of doing this with your set of data would be this:
set key off
set style line 2 lt 0 lc 1 lw 2
set yrange [0.3:1.2]
plot [0.04:0.15] "Data.csv" u 1:2 smooth csplines ls 1, \
"" u 1:(0.3):(0):(1.2) w vectors nohead ls 2, \
"" u ($1+0.005):(1):(sprintf("P %d", $0)) w labels
However, this will probably not look the way you want it to look. You could think of modifying your data file to also include some information about the labeling like:
#x-value y-value x-label y-label label
0.06 0.694821399177 0.65 0.1 Phoneme1
0.07 0.543022222222 0.75 0.1 Phoneme2
Then the labels line would simply look like:
"" u 3:4:5 w labels
The complete plot then looks like this:

Resources