Determine coefficients of quadratic equation using gnuplot - gnuplot

I have created my first graph based on the input on stackoverflow. So my code is,
set title "Approximation Graph"
set term png
set output 'plot.png'
f0_h(x) = a0_h * x**2 + b0_h * x + c0_h
fit f0_h(x) 'clk0_h' via 'clk0_h_c'
f1_h(x) = a1_h * x**2 + b1_h * x + c1_h
fit f1_h(x) 'clk1_h' via 'clk1_h_c'
f0_s(x) = a0_s * x**2 + b0_s * x + c0_s
fit f0_s(x) 'clk0_s' via 'clk0_s_c'
f1_s(x) = a1_s * x**2 + b1_s * x + c1_s
fit f1_s(x) 'clk1_s' via 'clk1_s_c'
set style data lines
plot "clk0_h" using 1:2, f0_h(x), "clk1_h" using 1:2, f1_h(x), "clk0_s" using 1:2, f0_s(x), "clk1_s" using 1:2, f1_s(x)
The graph is:
So I have major and minor question.
Major : is it possible to determine coefficient using gnuplot. As of
now, I determine manually. (some reason, I can not use numpy in python
for determine coefficient)
Minor : Can anyone refer me line property. 1) increase line width
2) change color 3) add a title for each line (to differentiate if they have same
color) 4) like I should have 8 line but some are overwrite

Concerning your first question: This is what fit actually does. In your script, by using via 'file.par' you only set starting values and specify the variables which are to be used for the fitting.
Just try the following:
f0_h(x) = a0_h * x**2 + b0_h * x + c0_h
fit f0_h(x) 'clk0_h' via a0_h, b0_h, c0_h
and see, if the coefficients come out well. By default, the starting values are assumed to be 1. If it doesn't work out, you may need to set the correct order of magnitude (set e.g. a0_h = 10 before fitting).
Regarding the minor stuff, use linewidth, linecolor etc. for the line properties. To specify the title, use title :).
You can define a linestyle for each function/data combination and use the line for the fit, and points for the data:
set style line 1 linecolor rgb 'red' linewidth 2 pointtype 4 linetype -1
set style line 2 linecolor rgb '#ff7700' pointtype 7 linetype 2
...
In this case, if you specify linecolor and linetype, the first determines the color, the second one the dash pattern (it the terminal supports it, see Gnuplot line types).
For the plotting, with the above kind of line style definitions, use e.g.
set style data points
set style func lines # these two settings are default
plot "clk0_h" using 1:2 linestyle 1 title 'clk0_h, data', \
f0_h(x) linestyle 1 title 'clk0_h, fit'
...
And you should consider using the pngcairo terminal, which creates much nicers graphics. Or, preferably, use a vector-based terminal, like pdfcairo.

Related

translate palette defined to rgb variable

With palette it is easy to create color gradients
set view map
set samp 50,50
set palette defined (0 "blue", 1 "green", 2 "red")
spl "++" us 1:2:1 palette pt 5
Now I would like to apply transparency in vertical direction. The option lc rbg variable supports transparency via the alpha channel (see also here):
spl "++" us 1:2:1:(int(($2+5)/10*255)<<24) lc rgb var pt 5
But how can I translate the palette colors into rgb colors?
A second question: why I get only 10 horizontal rows, albeit I specified 50 in samp?
Easy answer first: When there is 2-dimensional sampling, either automatically from splot or explicitly from plot '++', the number of samples in the first dimension is controlled by set sample and the number of samples in the second dimension is controlled by set isosample.
Now the harder one. In gnuplot versions through the current 5.2.8 you cannot add transparency directly to the palette. You can, however, go through a multi-step process of saving the palette into a file or datablock and then reading it back it as an array of RGB colors. Once you have that array you can add an alpha channel value so that it expresses transparency as well. I will show this process using the datablock created by the command test palette. In older versions of gnuplot you may have to instead use the file created by set print "palette.save"; show palette palette 256;.
# save current palette to a datablock as a list of 256 RGB colors, one per line
set palette defined (0 "blue", 1 "green", 2 "red")
test palette
# print one line to show the format (cbval R G B NTSCval)
print $PALETTE[4]
# Create an array of packed RGB values
array RGB[256]
do for [i=1:256] {
Red = int(255. * word($PALETTE[i],2))
Green = int(255. * word($PALETTE[i],3))
Blue = int(255. * word($PALETTE[i],4))
RGB[i] = Red << 16 | Green << 8 | Blue
}
# Sample from '++' are generated to span ranges on the u and v axes
# I choose 1:256 so that the y coordinates match the range of array indices
set sample 50
set isosample 50
set urange [1:256]
set vrange [1:256]
set xrange [*:*] noextend
set yrange [*:*] noextend
# Now you can use colors stored in the array via colorspec `rgb variable`
# which will also accept an alpha channel in the high bits
plot "++" using 1:2:(RGB[int($2)]) with points pt 5 lc rgb variable
# The final step is to add an alpha channel as a function of y
# Here I go from opaque (Alpha = 0) to 50% transparent (Alpha = 127)
# This works because I know y will run from 1-256
ARGB(y) = RGB[int(y)] + (int(y/2)<<24)
plot "++" using 1:2:(ARGB($2)) with points pt 5 lc rgb variable
Output shown below.
The required command sequence, as you can see, is a mess.
It will be much easier in the next gnuplot release (5.4). The new version will provide a function palette(z) that converts from the current palette directly to a packed RGB value. Note that the palette() function isn't in the -rc1 testing version but will be in -rc2. So in version 5.4 all that palette/array/RGB manipulation can be replaced by
plot '++' using 1:2:(palette($2) + (int($2)<<24)) with points pt 5 lc rgb variable
Check also this: Gnuplot: transparency of data points when using palette
First of all, you can check what your defined palette is doing:
set palette defined (0 "blue", 1 "green", 2 "red")
test palette
You will get this:
Each channel (R,G,B) has a function with an input range [0:1] and an output range [0:1]. In this case it is a linear gradient.
So, you have to define such a function and put the channels together with the transparency (alpha) channel using the bit shift (see help operators binary).
The nice thing about a palette is that gnuplot takes care about the range. Here, you have to know minimum and maximum in advance and scale the color accordingly. You could use stats for this.
Code:
### your own palette with transparency
reset session
r(x) = x < 0.5 ? 0 : 2*x -1
g(x) = x < 0.5 ? 2*x : 2-2*x
b(x) = x < 0.5 ? 1-2*x : 0
a(y) = y
myColor(x,y) = (int(a((y-yMin)/(yMax-yMin))*0xff)<<24) + \
(int(r((x-xMin)/(xMax-xMin))*0xff)<<16) + \
(int(g((x-xMin)/(xMax-xMin))*0xff)<<8) + \
int(b((x-xMin)/(xMax-xMin))*0xff)
set samples 50
set isosamples 50
set size square
xMin=-5; xMax=5
yMin=-5; yMax=5
plot '++' u 1:2::(myColor($1,$2)) w p pt 5 ps 0.5 lc rgb var notitle
### end of code
Result:

How to make dashed grid lines intersect making crosshairs in gnuplot?

I'm plotting some data and I want to use dashed grid lines.
Any dashed grid line would suffice, but I prefer a "long dash, short dash, long dash" format.
For example, given the following code
set grid lc rgb "#000000" lt 1 dt (50, 25, 20, 25)
plot x**2
I get this result
But I would rather the grid lines intersection to happen always at the middle of two dashes, like this
If I could make horizontal grid lines different to vertical grid lines and I could add some offset to each one, then I'd imagine there's a way to accomplish this. But I can't seem to do that either.
It looks like gnuplot cannot have two different dashstyles for x-grid and y-grid.
One workaround I see currently is to plot two identical plot on top of each other. One with appropriate x-grid lines and the other with appropriate y-grid lines.
If you want a dash pattern with proportions of (50-25-20-25), this correspond to (25-25-20-25-25-0) or (5-5-4-5-5-0) between two tics.
Furthermore, the dash and gap length numbers, e.g. in dt (50,25,20,25), seem to be in a fixed relation to the graph size. The "empirical" factor is 11 with good approximation (at least for the wxt terminal which I tested under gnuplot 5.2.6).
Edit: actually, the code below gives different results with a qt terminal. And it's not just a different factor. It's more complicated and probably difficult to solve without insight into the source code. So, the fact that the following seems to work with wxt terminal (maybe even just under Windows?) was probably a lucky strike.
With this you can create your dash lines automatically resulting in crosshairs at the intersections of the major grid lines.
Assumptions are:
your first and last tics are on the borders
you know the number of x- and y-intervals
You also need to know the graph size. These values are stored in the variables GPVAL_TERM..., but only after plotting. That's why you have to replot to get the correct values.
This workaround at least should give always crosshairs at the intersection of the major grid lines.
Edit 2: just for "completeness". The factors to get the same (or similar) looking custom dashed pattern on different terminals varies considerably. wxt approx. 11, qt approx. 5.6, pngcairoapprox. 0.25. This is not what I would expect. Furthermore, it looks like the factors slightly depend on x and y as well as graph size. In order to get "exact" crosshairs you might have to tweak these numbers a little further.
Code:
### dashed grid lines with crosshairs at intersections
reset session
TERM = "wxt" # choose terminal
if (TERM eq "wxt") {
set term wxt size 800,600
FactorX = 11. # wxt
FactorY = 11. # wxt
}
if (TERM eq "qt") {
set term qt size 800,600
FactorX = 5.58 # qt
FactorY = 5.575 # qt
}
if (TERM eq "pngcairo") {
set term pngcairo size 800,600
set output "tbDashTest.png"
FactorX = 0.249 # pngcairo
FactorY = 0.251 # pngcairo
}
set multiplot
set ticscale 0,0
Units = 24 # pattern (5,5,4,5,5,0) are 24 units
# set interval and repetition parameters
IntervalsY = 10
RepetitionsY = 1
IntervalsX = 4
RepetitionsX = 3
# initial plot to get graph size
plot x**2
gX = real(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)/IntervalsY/Units/FactorY/RepetitionsY
gY = real(GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)/IntervalsX/Units/FactorX/RepetitionsX
# first plot with x-grid lines
set grid xtics lt 1 lc rgb "black" dt (gX*5,gX*5,gX*4,gX*5,gX*5,0)
replot
unset grid
# second plot with y-grid lines
set grid ytics lt 1 lc rgb "black" dt (gY*5,gY*5,gY*4,gY*5,gY*5,0)
replot
unset multiplot
set output
### end of code
Result:
Not really. The closest I can think of is
set grid x y mx my
set grid lt -1 lc "black" lw 1 , lt -1 lc bgnd lw 16
set ticscale 1.0, 0.01
set mxtics 4
plot x**2 lw 2
But that leaves the vertical grid lines solid.

Discrete heat map with GNUPLOT

I'm trying to make something as a heat map with GNUPLOT but I need that my palette takes discrete colors for defined values.
I mean, my data file has three columns, for example:
x y value
0.0 0.0 10
0.0 0.5 2
0.0 1.0 2
0.5 1.0 10
1.0 0.0 -1
1.0 1.0 -1
I need that each point has one color depending of its value. Traditional heat map mixes point making regions of continuos colors, but I need it in a discrete form.
If your data forms a "matrix", i.e., there are M x-samples, N y-samples, and you have the data for all MxN points, then probably the easiest solution is to use
plot ... w rgbimage u 1:2:(r($3)):(g($3)):(b($3))
and supply the r,g,b values as three additional columns as shown above.
However, if your data is "sparse" (only some of the samples are available as shown in your question) and there are not many points, one might be tempted to generate the elementary squares forming the plot manually. To this end, one could proceed as:
set terminal png enhanced
set output 'plot.png'
#custom value -> color mapping
rgb(r, g, b) = 65536 * int(r) + 256 * int(g) + int(b)
fn(val) = rgb(100 + val*10, 0, 0)
#square size
delta = 0.5
set xr [-delta/2:1+delta/2]
set yr [-delta/2:1+delta/2]
set xtics 0,delta/2,1 out nomirror
set ytics 0,delta/2,1 out nomirror
set format x "%.2f"
set format y "%.2f"
set size ratio 1
unset key
fName="test.dat"
load sprintf("<gawk -v d=%f -f parse.awk %s", delta, fName)
plot fName u 1:2:3 w labels tc rgb 'white'
This script assumes the presence of auxiliary gawk script parse.awk in the same directory:
{
printf "set object rectangle from %f,%f to %f,%f fc rgb fn(%d) fs solid\n",
$1-d/2, $2-d/2, $1+d/2, $2+d/2, $3
}
This scripts accepts the required square size (-v d=%f in the invocation of gawk) and generates for each point a statement generating the corresponding square. These statements are consequently executed by the load command.
Mapping of the colors is done via the function fn defined in the main Gnuplot script. It takes the passed value and generates a rgb value which is then used with fc rgb in the rectangle specification.
Together, this then produces:
This might do what you want, after some fiddling:
set view map
set style fill transparent solid noborder
splot 'data' u 1:2:3:(100+200*$3) pt 5 lc rgbcolor var ps 14
The pt 5 will plot a square (at least in the x11 term) at each point in the datafile, colored according to a transformation on the last column.

Different number of samples for different functions

plot x+3 , x**2+5*x+12
Is it possible to set x+3 to have only 2 samples and x**2+5*x+12 to have say 1000 samples in the same plot?
It can be done, but not out-of-the-box.
The first variant uses a temporary file to save one function with a low sampling rate and plotting it later together with the high-resolution function:
set samples 2
set table 'tmp.dat'
plot x+3
unset table
set samples 1000
plot 'tmp.dat' w lp t 'x+3', x**2 + 5*x + 12
This has the advantage, that you can use any sampling rates for both functions.
For you special case of 2 samples for one function, it can be done without an external file, but it involves quite some tricking:
set xrange [-10:10]
s = 1000
set samples s
f1(x) = x + 3
set style func linespoints
set style data linespoints
plot '+' using (x0 = (($0 == 0 || $0 == (s-1) )? $1 : x0), \
($0 < (s-2) ? 1/0 : x0)):(f1(x0)) t 'x+3',\
x**2 + 5*x + 12
What I did here is:
Use the special filename + to generate a set of coordinates in the current xrange. This must be set, no autoscaling is possible.
Skipping all points but the first and the last by giving them the value 1/0 doesn't work, because the two remaining points aren't connected.
So I store the first x-value (when $0, or column(0) equals 0) and use it when I encountered the second last points. For the last points, the usual values are used.
That works for your special case of 2 samples.
You must keep in mind, that the first function is treated as data, so you must use both set style data and set style func (just to show it).
The result with 4.6.4 is:
I am not sure if different samplings (as opposed to different ranges) are possible with gnuplot 5.x. If I missed that please let me know.
Here is a suggestion to have two different samplings in the same plot command without temporary files (or datablocks from gnuplot 5.0 on).
A requirement is a known xrange, i.e. it will work with autoscale only if you plot and replot the graph to automatically get xmin and xmax. For the second function you could also use '+' u 1:(f2($1)) w lp.
Script: (works for gnuplot>=4.4.0, March 2010)
### different samplings in one plot command
reset
set xrange[xmin=-10:xmax=10]
f1(x) = x+3
f2(x) = x**2 + 5*x + 12
s1 = 3 # sampling 1
s2 = 101 # sampling 2
set samples (s1>s2?s1:s2) # the higher value
dx1 = real(xmax-xmin)/(s1-1) # determine dx1 for f1
plot '+' u (x0=xmin+$0*dx1):(f1(x0)) every ::0::s1-1 w lp pt 7 ti sprintf("%d samples",s1), \
f2(x) w lp pt 7 ti sprintf("%d samples",s2)
### end of script
Result:

Gnuplot repeats colors in rowstack histograms

I am currently plotting some data using gnuplot with rowstacked histograms.
The problem is, that the colors start to repeat after 9 different colors have been chosen. One can see this also happening in the official gnuplot examples (see http://gnuplot.sourceforge.net/demo/histograms.html - Example 4 & 5)
Is there any way to tell gnuplot to use more different colors?
There is no fully automated way to do this, but you can define as many line styles as you want with set style line ... and then use them. Here, I just use a simple iteration to define several colors:
do for [i=1:20] {
set style line i linecolor rgb hsv2rgb(0.05*(i-1), 1, 1)
}
set style data histograms
set style histogram rowstacked
set style fill solid border -1
set boxwidth 0.75
plot for [i=1:20] 'mydata.dat' u 2 ls i t 'ls '.i
The data file contains just the values
1 0.1
2 0.2
3 0.3
Note, that the hsv2rgb function is defined only since 5.0. For earlier version you can use the following user-defined function to get the same functionality:
rgb2int(r,g,b) = int(255*r)*2**16 + int(255*g)*2**8 + int(255*b)
hsv2rgb(h,s,v) = (s == 0 ? rgb2int(v,v,v) : (HSV_h = h*6.0, HSV_i = int(floor(HSV_h)), HSV_f = HSV_h - HSV_i, HSV_p = v*(1.0 - s), HSV_q = v*(1.0-s*HSV_f), HSV_t = v*(1.0-s*(1.0-HSV_f)), (HSV_i%6 == 0 ? rgb2int(v,HSV_t,HSV_p) : (HSV_i%6 == 1 ? rgb2int(HSV_q,v,HSV_p) : (HSV_i%6 == 2 ? rgb2int(HSV_p,v,HSV_t) : (HSV_i%6 == 3 ? rgb2int(HSV_p,HSV_q,v) : (HSV_i%6 == 4 ? rgb2int(HSV_t,HSV_p,v) : rgb2int(v,HSV_p,HSV_q))))))))
To make it easier, you could put this code into a configuration file, or a third script hsv2rgb.gp and include it with load 'hsv2rgb.gp' before using the function.
Output with 4.6.3 is:
There is something a little more automated than Christoph's answer. You can use a color palette:
set palette rgb 7,5,15
unset colorbox
plot 'immigration.dat' using 2:xtic(1) title columnheader(2), \
for [i=3:22] '' using i lt palette frac i/22. title columnheader(i)
The trick is, to define frac based on the loop counter i. Be sure to devide by a float (in this case 22. to match the example) to get the right fractions of the color palette.
Or, for example 4:
plot 'immigration.dat' using (100.*$2/$24):xtic(1) t column(2), \
for [i=3:23] '' using (100.*column(i)/column(24)) lt palette frac i/23.\
title column(i)
Now, you only have to decide on a suitable color palette.

Resources