gnuplot: compact axis label format - format

Tell me how in gnuplot to properly form the inscriptions in the axis (as shown in the picture).
1) I do not know the values of the y axis
2) I need to set the exponent (power 10) in the axis label automatically

You need to know the order of magnitude before you are plotting. You can get this via stats. Then divide your y-values by a factor which (in the example below) is chosen such that the axis tics should show values between 0 and 100.
The code:
### automatic prefactor in axis scaling and axis label
reset session
# generate some random data
set samples 20
RandomMagnitude = floor(rand(0)*20-10)
RandomValue = rand(0)
set table $Data
plot '+' u 0:(RandomValue*10**RandomMagnitude/($0)) with table
unset table
# get the maximum via stats
stats $Data u 2 nooutput
Max = STATS_max
PrefactorLog = ceil(log10(Max))-2
Prefactor = 10**PrefactorLog
set ylabel sprintf("Y-title, x 10^{%d} units",PrefactorLog)
set format y "%g"
set boxwidth 0.7 relative
plot $Data u 1:($2/Prefactor) with boxes fs solid 1.0 fc rgb "red" ti sprintf("Max value %.2e", Max)
### end of code
The result:

Related

How to add time dependent labels in Gnuplot

A datafile contains three columns with the first and second representing the x & y position of a circle at a time (in seconds) given by the third column. For example, the first two lines in "data.txt" give the position of two circles at time=0, followed by two blank lines then the position of the two circles at time=0.1 sec and so forth. The first few lines of data.txt are:
0 0 0
-1 -1 0
1 1.0 0.1
-1 -0.5 0.1
1.2 1.25 0.2
-0.5 -0.25 0.2
...
The Gnuplot code producing a series of frames (a movie) with the position of the two circles in time is:
set terminal gif size 1200,1200 animate delay 500
set output "movie.gif"
stats "data.txt" u 1:2 name "A"
set style circle radius graph 0.025; set style fill solid
set xrange [A_min_x*1.1:A_max_x*1.1]
set yrange [A_min_y*1.1:A_max_y*1.1]
do for [i=0:A_blocks-2] {
plot "data.txt" index i u 1:2 w circle
}
I'm trying to add a label or textbox of the form "Time=?" to each frame where the question mark is replaced by the number from the third column. Any suggestions on how to do it?
This answer requires the current version of gnuplot (5.4)
Assuming that all the column 3 entries in a given data block are the same, it should be sufficient to say
plot "data.txt" index i u 1:(FOO=strcol(3),column(2)) w circle title sprintf("Time = %s",FOO)
This updates the value of FOO for each line used. The title uses whatever the final update was for that plot. If you must specifically choose the column 3 value from a particular line within the block, or calculate something like an average, that's a harder problem. In that case please clarify.
Edit:
The reason this requires 5.4 is that earlier versions evaluated the title before reading the data for that plot. Version 5.4 evaluates the title after reading the data.
The first (not too obvious) solution which comes to my mind: plot your data in a loop and assign the value of the 3rd column to a variable, e.g. t. Use keyenty to print the legend with your time re-using the variable t. In order to avoid a symbol in the legend use plotting style with points and a point with pointsize 0.
Code:
### animation with time label
reset session
$Data <<EOD
0 0 0
-1 -1 0
1 1.0 0.1
-1 -0.5 0.1
1.2 1.25 0.2
-0.5 -0.25 0.2
EOD
set terminal gif size 400,400 animate delay 100
set output "SO70474478.gif"
stats $Data u 1:2 name "A" nooutput
set style circle radius graph 0.025; set style fill solid
set xrange [A_min_x*1.1:A_max_x*1.1]
set yrange [A_min_y*1.1:A_max_y*1.1]
set key top left
do for [i=0:A_blocks-1] {
plot $Data index i u 1:(t=$3,$2) w circle notitle, \
keyentry w points ps 0 ti sprintf("Time: %.1f",t)
}
set output
### end of code
Result:

How to plot histogram using gnuplot

I have a file contains wire length ranging from 300-1000. How do I use GNUPLOT to make a histogram with length on X-axis (With interval of 100) and number of wires on Y-axis?
For example:
250 wire_0
350 wire_1
360 wire_2
800 wire_3
I want a bar with height of 1 representing wire_0, a bar with height of 2 representing wire_1 and wire_2 and a bar with height of 1 representing wire_3.
Edit #1
Based on both this and this answers, your could try:
binwidth = 100
bin(x, width) = width*floor(x/width)
set tics out nomirror
set style fill transparent solid 0.5 border lt -1
set xrange [0:1000]
set xtics binwidth
set boxwidth binwidth
set yrange [0:3]
$data <<EOD
250 wire_0
350 wire_1
360 wire_2
800 wire_3
EOD
plot $data u (bin($1,binwidth)):(1.0) smooth freq with boxes notitle
Result
Edit #2
If you need the of values above the boxes, you can use.
set table $data2
plot $data u (bin($1,binwidth)):(1.0) smooth freq with boxes;
unset table
plot $data2 u 1:2 w boxes notitle , "" u 1:2:2 w labels offset 0,1 notitle
Result

gnuplot animation 2D vector fields

I'm trying to animate 2D vector with gnuplot. I want to show one line i.e, one vector at a time.
My Data Structure is as follows: They x,y,u,v
2.24448 0.270645 1.00 1.00
3.24448 0.270645 0.500 1.20
I'm able to create a static plot sing following command:
plot "datam.dat" using 1:2:3:4 with vectors filled head lw 3
Here is the output:
Here is my question: I would like to animate and show one row (i.e,) one vector at a time, how to accomplish this in GNU plot using GIF?
Thanks
Animated GIFs are created with set terminal gif animate. Check help gif for details.
Below is a simple example (tested with gnuplot 5.2). You have to make a new plot for each frame. So, put your plot command into a do for-loop. With every ::i::i you are plotting only the ith line (check help every). If you don't know the total number of lines of your datafile, do stats "YourFile.dat" and the variable STATS_records will tell you this number.
Code:
### animated graph with vectors
reset session
set term gif size 300,300 animate delay 12 loop 0 optimize
set output "AnimateVectors.gif"
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
do for [i=0:N-1] {
plot $Data u 1:2:3:4 every ::i::i w vectors lw 2 lc rgb "red" notitle
}
set output
### end of code
Result:
Addition:
This would be the non-animated version, e.g. in a wxt-terminal.
Code:
### non-animated graph with vectors
reset session
set term wxt size 400,400
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
plot $Data u 1:2:3:4 w vectors lw 1.5 lc rgb "red" notitle
### end of code
Result:
Addition2:
Do you maybe mean something like this? A "semi"-animated arrow? By the way, as you can see the arrow look quite different in gif and wxt terminal.
Code:
### "semi"-animated graph with vectors
reset session
set term gif size 300,300 animate delay 12 loop 0 optimize
set output "AnimateVectorsSemi.gif"
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
do for [i=0:N-1] {
plot $Data u 1:2:3:4 every ::0::i w vectors lw 1.5 lc rgb "red" notitle
}
set output
### end of code
Result:

Centering labels on a pie chart

I am following this post to make a pie chart using Gnuplot. The only problem with the approach is that I can't align my percentage labels. What am I missing here?
DATA FILE:
"Others" 1.085117e-01 3.904323e-02
"D_o" 2.894902e-01 6.145359e-01
"{/Symbol b}_o" 5.760601e-01 3.760299e-01
"O_h" 5.393108e-01 1.000000e+00
"D_p" 6.743313e-01 2.284404e-01
"{/Symbol a}_p" 1.000000e+00 1.271822e-01
"{/Symbol b}_f" 4.020115e-01 2.233656e-01
"D_m" 2.389996e-01 8.577689e-02
"{/Symbol a}_m" 3.601146e-01 1.033153e-01
"{/Symbol b}_m" 5.596836e-01 1.947165e-01
CODE:
#!/usr/bin/gnuplot
# Terminal & Encoding
set terminal epscairo enhanced color dashed rounded size 8.5, 4.5
set output 'mu_piechart.eps'
set termoption enhanced
set encoding utf8
# Get Status
filename = './datafile.dat'
stats filename u 2 noout
# Get Angles & Percentages
ANG(x)=x*360.0/STATS_sum
PER(x)=x*100.0/STATS_sum
# Square Canvas
set size square
set xrange [-1:1.5]
set yrange [-1.25:1.25]
set style fill solid 1
# Remove Base Properties (Titles, Tics, Axis, Palette)
unset key
unset tics
unset border
unset colorbox
# Initial Angle, Mid Angle, Initial Color
A = 0.0; M = 0.0; i = 0;
# Palette
set palette defined (1 1 0.788 0.055, 2 0.090 0.161 0.659)
# Plot
plot for [i=0:STATS_records-1] filename u (0):(0):(1):(A):(A=A+ANG($2)):(i) every ::i::i with circle linecolor palette,\
filename u (M=A+ANG($2), A=2*M-A, M=M*pi/360.0, -0.5*cos(M)):(-0.5*sin(M)):(PER($2) > 8.00 ? sprintf('%.1f\%', PER($2)) : " ") every ::1 w labels center font ',10',\
for [i=0:STATS_records-1] filename u (1.45):(i*0.25)-1.11:($1) every ::i::i with labels left,\
for [i=0:STATS_records-1] '+' u (1.3):(i*0.25)-1.11:(i) pt 5 ps 4 lc palette
exit
OUTPUT:
The percentages positions are not correct in the figure generated by the script.
Your labels are at wrong positions, because your label plot starts at 1, i.e. you skip the first entry.
Also, what I don't understand is, why you plot the pie parts counterclockwise, and the labels clockwise.
Here is a working version of you script, without some parts which are superfluous for demonstration. Both labels and pie parts are plotted starting at an angle of A = 0 (note the second initialization between the two plots):
reset
# Get Status
filename = './datafile.dat'
stats filename u 2 noout
# Get Angles & Percentages
ANG(x)=x*360.0/STATS_sum
PER(x)=x*100.0/STATS_sum
# Y position of key point and label
YLBL(row) = 2.0 * (row - 0.5*(STATS_records - 1))/(STATS_records - 1)
# Square Canvas
set size square
set xrange [-1:1.5]
set yrange [-1.25:1.25]
set style fill solid 1
# Remove Base Properties (Titles, Tics, Axis, Palette)
unset key
unset tics
unset border
unset colorbox
# Palette
set palette defined (1 1 0.788 0.055, 2 0.090 0.161 0.659)
# Plot
A = 0.0
plot filename u (0):(0):(1):(A):(A=A+ANG($2)):0 with circle linecolor palette,\
A = 0,\
filename u (M=A+ANG($2), A=2*M-A, M=M*pi/360.0, 0.5*cos(M)):(0.5*sin(M)):(PER($2) > 8.0 ? sprintf('%.1f\%', PER($2)) : "" ) w labels center,\
filename u (1.3):(YLBL($0)):1 with labels offset char 3 left ,\
filename u (1.3):(YLBL($0)):0 pt 5 ps 4 lc palette
The script contains some other improvements:
You don't need to iterate over STATS_records
The text and point for the key are plotted at the same position, the label is shifted with the offset parameter by three character units (offset char 3). That makes fine-tuning easier.

Trouble with plot matrix with image and xrange

I have trouble with xrange. When I put 'set autoscale xfix' image is ok but information axis not. When i put xrange [-1:1] i get info ok but images is damage. Second trouble is flip image. In my data stored in file upper left corner is -1 on image is +1, why?
my data is:
-0.999770 -0.998743 0.946455 0.999678 0.999777
-0.699447 -0.999784 -0.999565 -0.076214 0.999467
0.999921 -0.717181 -0.999790 -0.999734 -0.959481
0.999943 0.999920 -0.733798 -0.999793 -0.999786
0.999943 0.999943 0.999920 -0.749453 -0.999794
my code is:
set terminal png transparent enhanced font "arial,10" fontscale 1.0 size 600, 400
set output 'out.png'
set xtics 0.25
set ytics 0.25
set xrange [-1:1]
set yrange [-1:1]
set cbrange [-1:1]
plot 'data.txt' matrix with image
My image is -1 to 1 step 0.5
if I add set xrange [-1:1] and set yrange [-1:1] I get
$ gnuplot -V
gnuplot 5.0 patchlevel 3
the thing is that your data file is interpreted as a uniform matrix. In this case:
gnuplot> help matrix
Gnuplot can interpret matrix data input in two different ways.
The first of these assumes a uniform grid of x and y coordinates and assigns
each value in the input matrix to one element M[i,j] of this uniform grid.
The assigned x coordinates are the integers [0:NCOLS-1].
The assigned y coordinates are the integers [0:NROWS-1].
So this means that the datapoints in the first row of your file will have y-coordinate set to 0, second row 1, etc. However, since the y-axis by default points upwards, the resulting image is therefore flipped. Also, these points define the centers of the elementary color squares/boxes in the plot. So that's way the "effective x/y-range" is in your case [-0.5:4.5].
To "fix" the y-axis, you could use
set yr [] reverse
Here, [] specifies that the axis is still autoscaled.
Finally, to rescale your image from [0,4] into the [-1,1] range, you could use:
fn(x) = x/2. - 1
plot 'data.txt' matrix u (fn($1)):(fn($2)):3 w image
So in total:
set terminal png transparent enhanced font "arial,10" fontscale 1.0 size 600, 400
set output 'out.png'
set xtics 0.25
set ytics 0.25
set xrange [-1:1]
set yrange [-1:1] reverse
set cbrange [-1:1]
fn(x)=x/2-1
plot 'data.txt' matrix u (fn($1)):(fn($2)):3 w image
EDIT:
One could also adapt the script above to deal with a matrix of a priori unknown size:
set terminal png transparent enhanced font "arial,10" fontscale 1.0 size 600, 400
set output 'out.png'
set xrange [-1:1]
set yrange [-1:1] reverse
set cbrange [-1:1]
fName = 'data.txt'
stats fName nooutput
N = STATS_records - 1
set xtics 1./N
set ytics 1./N
fn(x)=(2*x/N)-1
plot fName matrix u (fn($1)):(fn($2)):3 w image
Here, the stats command first scans the file and stores the number of records into a special variable STATS_records. The function fn then rescales the range [0:STATS_records-1] on [-1:1]. Also, the x/y-tics are adapted automatically.

Resources