Gnuplot: power notation axis - gnuplot

I set the y-axis in power notation (1.0e+5 or 1.0 * 1.0^5) but I would like to report the power just on top of the axis to save space. In particular I would like to report at the end of the axis as reported in the link

Try use this commented code:
# Creating some 'x y' data to plot and
# save output using 'table' and
# datablock named 'data'
set table $data
plot (1E-5 + sin(x)*1E-5)
unset table
# Performs statistics using 'y' column
# to find max value, turn off output, and
# set prefix name 'data' to stats results
stats $data u 2 nooutput name 'data'
set tmargin at screen 0.94 # Change the top margin
# Define a label containing the power to base 10
# of max value from data and put on top-left
# using the same value of top margin
# but using offset on y axis
set label gprintf('×10^{%T}',data_max) at graph 0.0, screen 0.94 offset 0,0.75
set format y '%.2t' # Format for 'y' values using mantissa
# to base 10 and 2 decimal places
set xlabel 't' # label to 'x' axis
set ylabel 'Ω' # label to 'y' axis
unset key # Turn off key (legend)
set tics nomirror # Turn off upper and right tic marks
# The plot itself
plot $data using 1:2 w l
Produces

I guess is very common to put the prefactor in the label (instead of top of the axis). If you absolutely need it on top, let me know. One way would be the following. There would also be ways to determine the prefactor automatically.
Code:
### prefactor for axis
reset session
Power = 5
set format y "%.2f"
set ylabel sprintf("Ω [10^%d rpm]", Power) enhanced
f(x) = 3e4*sin(x)+1.2e5
plot f(x)/10**Power w l notitle
### end of code
Result:

Related

Place tics at values stored in variables

I have used the stats command to store the x-postion of absolute maxima in my plot of seven datasets in seven variables, grN_pos_max_y with N that goes from 1 to 7. Can I place the tics in the x-axis at the positions specified by these variables?
I tried using
$maxima << EOD
gr1_pos_max_y
gr2_pos_max_y
gr3_pos_max_y
gr4_pos_max_y
gr5_pos_max_y
gr6_pos_max_y
gr7_pos_max_y
EOD
and then
plot ..., \
$maxima u 1:(NaN):xticlabel(1) notitle
but I don't know how to read variables into a data block (if I replace the variable names by their values, however, it works).
Edit: This is what I want (I plotted it using Ethan's answer)
I'm not entirely sure I understand what you want, but this may get you partway there:
set xtics add (gr1_pos_max_y, gr2_pos_max_y, gr3_pos_max_y, gr4_pos_max_y, gr5_pos_max_y, gr6_pos_max_y, gr7_pos_max_y)
plot 'whatever'
That will get you plain (unlabeled) tic marks in addition to whatever tic marks and labels are being generated automatically.
If you want only these marks and no auto-generated marks, remove the keyword add.
If you want to place labels to go with these new tics, change it to:
set xtics add ( "Max 1" gr1_pos_maxy, "Max 2" gr2_pos_maxy, ...
This is all assuming you want these tics to label a plot that contains something other than the tics themselves. If you want only a plot of these y values, perhaps as impulses?, please re-phrase the question or show a sketch of what you want it to look like.
There is no need for awk, you can do it all in gnuplot.
put stats into a loop and write the STATS values into a datablock $Maxima
plot your data and $Maxima as Ethan suggested with impulses
you can also plot the maxima y-value as labels in the graph
The script needs to be adapted depending on your file naming scheme.
Script:
### extract maxima from several files
reset session
N = 7
myFile(n) = sprintf("SO72750257_%d.dat",n)
# create some "random" test data
do for [n=1:N] {
set table myFile(n)
f(x) = -a*(x-x0)**2 +y0
x0 = (n-1)*10./N + rand(0)*10./N
a = rand(0)*50+10
y0 = rand(0)*80+20
plot [0:10] '+' u 1:(f(x))
unset table
}
# extract maxima
set print $Maxima
do for [n=1:N] {
stats myFile(n) u 1:2 nooutput
print sprintf("%.1f %.1f", STATS_pos_max_y, STATS_max_y)
}
set print
set yrange[0:]
set offsets graph 0.05, graph 0.05, graph 0.1, 0
set xtics () # remove all xtics
set key out noautotitle
plot for [i=1:N] myFile(i) u 1:2 w l ti sprintf("Set %d",i), \
$Maxima u 1:2:($0+1):xtic(1) w impulses lc var dt 2, \
$Maxima u 1:2:2 w labels offset 0, char 1
### end of script
Result:

How to add data labels to Gnuplot histogram (smooth freq)?

I have data of protein molecular weights in column 6 of my file. The column in question looks like this:
MW [kDa]
16.8214045562515
101.41770820613989
24.332255496943485
43.946599899844436
210.58276787970942
57.987597263605494
27.384315650885558
119.02857910337919
8.962938979036466
I would like to plot a histogram and I am doing it using Gnuplot's smooth frequency function:
echo n=20 >$gnuplot #number of intervals
echo max=100 >> $gnuplot #max value
echo min=-0 >> $gnuplot #min value
echo width=\(max-min\)\/n >> $gnuplot #interval width
echo hist\(x,width\)=width*floor\(x\/width\)+width\/2.0 >> $gnuplot
echo plot \"$dataFile\" using \(hist\(\$6,width\)\)\:\(1.0\) smooth freq w boxes lc rgb\"blue\" notitle >> $gnuplot
How do I add a data label representing the count for each bin on top of each histogram bar? I cannot seem to find a way to do it.
I would plot the histogram data into a table first and then use this table for plotting the histogram itself and the labels.
Check the following example. If you have a file, e.g. 'myData.dat', skip the random data generation lines, instead add the line FILE = 'myData.dat' and replace all $Data with FILE. As #Eldrad mentioned in the comments, use the plotting style with labels for the labels. Check help labels and help table.
Code:
### histogram with labeled bins
reset session
# create some random test data
set print $Data
do for [i=1:2000] {
print sprintf("%g",(invnorm(rand(0))+10)*20)
}
set print
stats $Data u 1 nooutput
xmin = STATS_min
xmax = STATS_max
N = 20
myWidth = (xmax-xmin)/N
bin(col) = myWidth*floor(column(col)/myWidth)+myWidth/2.
set key noautotitle
set style fill solid 0.3
set boxwidth myWidth
set grid x,y
set offsets graph 0,0,0.05,0 # l,r,t,b
set table $Histo
plot $Data u (bin(1)) smooth freq
unset table
plot $Histo u 1:2 w boxes lc rgb "blue", \
'' u 1:2:2 w labels offset 0,0.7
### end of code
Result:

Gnuplot smoothing data in loglog plot

I would like to plot a smoothed curve based on a dataset which spans over 13 orders of magnitude [1E-9:1E4] in x and 4 orders of magnitude [1E-6:1e-2] in y.
MWE:
set log x
set log y
set xrange [1E-9:1E4]
set yrange [1E-6:1e-2]
set samples 1000
plot 'data.txt' u 1:3:(1) smooth csplines not
The smooth curve looks nice above x=10. Below, it is just a straight line down to the point at x=1e-9.
When increasing samples to 1e4, smoothing works well above x=1. For samples 1e5, smoothing works well above x=0.1 and so on.
Any idea on how to apply smoothing to lower data points without setting samples to 1e10 (which does not work anyway...)?
Thanks and best regards!
JP
To my understanding sampling in gnuplot is linear. I am not aware, but maybe there is a logarithmic sampling in gnuplot which I haven't found yet.
Here is a suggestion for a workaround which is not yet perfect but may act as a starting point.
The idea is to split your data for example into decades and to smooth them separately.
The drawback is that there might be some overlaps between the ranges. These you can minimize or hide somehow when you play with set samples and every ::n or maybe there is another way to eliminate the overlaps.
Code:
### smoothing over several orders of magnitude
reset session
# create some random test data
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
set logscale x
set logscale y
set format x "%g"
set format y "%g"
set samples 100
pMin = -9
pMax = 3
set table $Smoothed
myFilter(col,p) = (column(col)/10**p-1) < 10 ? column(col) : NaN
plot for [i=pMin:pMax] $Data u (myFilter(1,i)):2 smooth cspline
unset table
plot $Data u 1:2 w p pt 7 ti "Data", \
$Smoothed u 1:2 every ::3 w l ti "cspline"
### end of code
Result:
Addition:
Thanks to #maij who pointed out that it can be simplified by simply mapping the whole range into linear space. In contrast to #maij's solution I would let gnuplot handle the logarithmic axes and keep the actual plot command as simple as possible with the extra effort of some table plots.
Code:
### smoothing in loglog plot
reset session
# create some random test data
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
set samples 500
set table $SmoothedLog
plot $Data u (log10($1)):(log10($2)) smooth csplines
set table $Smoothed
plot $SmoothedLog u (10**$1):(10**$2) w table
unset table
set logscale x
set logscale y
set format x "%g"
set format y "%g"
set key top left
plot $Data u 1:2 w p pt 7 ti "Data", \
$Smoothed u 1:2 w l lc "red" ti "csplines"
### end of code
Result:
Using a logarithmic scale basically means to plot the logarithm of a value instead of the value itself. The set logscale command tells gnuplot to do this automatically:
read the data, still linear world, no logarithm yet
calculate the splines on an equidistant grid (smooth csplines), still linear world
calculate and plot the logarithms (set logscale)
The key point is the equidistant grid. Let's say one chooses set xrange [1E-9:10000] and set samples 101. In the linear world 1e-9 compared to 10000 is approximately 0, and the resulting grid will be 1E-9 ~ 0, 100, 200, 300, ..., 9800, 9900, 10000. The first grid point is at 0, the second one at 100, and gnuplot is going to draw a straight line between them. This does not change when afterwards logarithms of the numbers are plotted.
This is what you already have noted in your question: you need 10 times more points to get a smooth curve for smaller exponents.
As a solution, I would suggest to switch the calculation of the logarithms and the calculation of the splines.
# create some random test data, code "stolen" from #theozh (https://stackoverflow.com/a/66690491)
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
# this makes the splines smoother
set samples 1000
# manually account for the logarithms in the tic labels
set format x "10^{%.0f}" # for example this format
set format y "1e{%+03.0f}" # or this one
set xtics 2 # logarithmic world, tic distance in orders of magnitude
set ytics 1
# just "read logarithm of values" from file, before calculating splines
plot $Data u (log10($1)):(log10($2)) w p pt 7 ti "Data" ,\
$Data u (log10($1)):(log10($2)) ti "cspline" smooth cspline
This is the result:

gnuplot histogram bins divided by volume

I am simulating points in a sphere volume with radius 1. I generated 1.000.000 monte-carlo based points in this volume. To make a gnuplot histogram i calculated the length of each vector (every vector length is between 0 and 1). With 100 bins the histogram looks like:
gnuplot data histogram.
If someone is wondering why there no points greater than 0.91 are generated, i also dont know, but this is not the question here.
This is my gnuplot Code:
n=100 #number of intervals
max=1.0 #max value
min=0.0 #min value
width=(max-min)/n #interval width
#function used to map a value to the intervals
hist(x,width)=width*floor(x/width)+width/2.0
#settings
set xlabel "Radius"
set ylabel "Primarys/Intervall"
set xrange [-0.1:1.1]
set yrange [0:32000]
set boxwidth width*0.8
set style fill solid 0.5 #fillstyle
set tics out nomirror
#plot
plot "primaryPosition(1).csv" u (hist($1,width)):(1.0) smooth freq w boxes lc rgb"green"
In general: A Volume grows by r^3 to Radius r.
In my histrogram every spherical shell is one bin and the bin number is 100. So, as the bin number increases, the volume of each sperical shell grows cubically (with r^3). From this point of view, the histogram looks good.
But what i want to do is to plot the density of points per volume: points/shellvolume.
This should be a linear distribution from the center of the sphere to its border.
How can i tell gnuplot to divide each bin by its corresponding volume, which depends on the outer and the inner radius of each spherical shell?
The formula is: (4/3)pi(R^3-r^3) with R outer and r inner radius a shell.
The following example creates some random test data (should be 20'000 equally distributed random points).
One possibility would be that you first you create your histogram data via binning into a table and then you divide it by the volume of the shell.
By the way, the volume of a sphere shell is (4./3)*pi*(R**3-r**3), not the formula you've given. And why are you setting max < min? Maybe you want to fine tune the binning to your exact needs.
Code:
### histogram normalized by sphere shell volume
reset session
set view equal xyz
# create some test data
set print $Data
do for [i=1:20000] {
x = rand(0)*2-1
y = rand(0)*2-1
z = rand(0)*2-1
r = sqrt(x**2 + y**2 + z**2)
if (r <= 1) { print sprintf("%g %g %g %g",x,y,z,r) }
}
set print
n = 100 # number of intervals
min = 0.0 # max value
max = 1.0 # min value
myWidth=(max-min)/n # interval width
bin(x)=myWidth*floor(x/myWidth)
ShellVolume(r) = (4./3)*pi*((r+myWidth)**3-r**3)
set boxwidth myWidth absolute
set table $Histo
plot $Data u (bin($4)):(1) smooth freq
unset table
set multiplot layout 2,1
plot $Histo u 1:2 w boxes ti "Occurrences"
plot $Histo u 1:($2/ShellVolume($1)) w boxes ti "Density"
unset multiplot
### end of code
Result:

How can I make a filled region in the x direction in gnuplot?

I know that gnuplot has the great type of plot that is filledcurve, which you can make a filled region between two curves that are presented like 1:2:3, it will make a curve between columns $2 and $3 for the same x value $1. But how can I fill this region in the graph below in gnuplot? The range is in x direction like x1:x2:y, same value of y.
My data it's in form like:
# rho1 rho2 C
0.8022651311239721 0.8299444680667378 0.00005011872336272725
0.8022624676512962 0.8299464715046031 0.00004466835921509635
0.8022618998639025 0.8299490455369624 0.000039810717055349695
0.8022533810411624 0.8299390462160209 0.000035481338923357534
...
But I can separate that in two archives too.
Here is a useful trick that uses the 3D plotting style with zerror and then sets the view angle so that it looks like a 2D x/y plot. I don't have enough of your data to replicate the plot you show so I use a junk data file just for the purpose of showing how the plot works:
# 3D plot style "with zerror" takes 5 columns of input
# x y z zlow zhigh
# We will choose a view angle such that "z/zlow/zhigh" is the horizontal axis
# "x" is the vertical axis
# "y" is unused because it is along the line of sight
# For your data as described
rho1 = 1 # column 1
rho2 = 2 # column 2
c = 3 # nominal y value, we use it for X
junk = 0 # unused constant coordinate
rhomean(c) = (column(rho1) + column(rho2)) / 2.
set view 270, 0
set view azimuth -90
unset ytics
set zlabel "ρ" # horizontal axis in this projection
set xlabel "C" # vertical axis in this projection
set zrange [0:50] # Note how this affects the horizontal axis!
splot "data" using c:(junk):(rhomean(c)):rho1:rho2 with zerror lt black fc "gold"
The with zerror plot style and the set view azimuth command both require a reasonbly current version of gnuplot.

Resources