Gradient colored polar curve - gnuplot

I'm trying to do the following in gnuplot: color with gradient an ellipse. Each point of the
ellipse has its z-value given by the function
charge_density(t,beta) = -sin(t)*beta*(sqrt(1-(beta**2)))/(1-((sin(t)*beta)**2))
The radius function of the ellipse is given by a similar function:
radius(t,beta) = sqrt(1-(beta**2))/sqrt(1-((sin(t)*beta)**2))
Where beta is just a parameter satisfying 0<beta<1, and t is the angle.
Well, I tried to use the "+" special file with the lc rgb variable option, but it doesn't work with polar coordinates.
I also tried the set mapping cylindrical, but nothing happened.
Is this possible only with cartesian coordinates? In this case, I'll have to do 2 graphics and modify the above functions...
Or will I have to create a data file with angle, radius, z data?
I'd like to do this with pm3d and the following palette:
set palette model RGB defined (-1 "blue", 0 "black", 1 "red")

here is the code:
beta =0.5
charge_density(t,beta) = -sin(t)*beta*(sqrt(1-(sin(t)*beta)**2))/(1-((sin(t)*beta)**2))
radius(t,beta) = sin(t*beta) # your function equals 1!
# convert polar to carthesian
r_x(t)=radius(t,beta)*cos(t)
r_y(t)=radius(t,beta)*sin(t)
set palette model RGB defined (-1 "blue", 0 "black", 1 "red")
set size ratio -1 # same unit length in x and y
# number of sample points.
# increase if curve has edges
set samples 100
#decouple range of "+" and xrange
set parametric
plot [0:3*pi] "+" u (r_x($1)):(r_y($1)):(charge_density($1,beta))\
with lines linewidth 3 linecolor palette
and there the result:
NOTE: Your radius equals to 1, so I took another function. Also, your charge_density has one extra closing parenthesis.
Some comments:
if you plot with lc rgb variable, a 24bit RGB color value is expected:
(red*256^2 + green*256 + blue) with red, green, blue = 0...255
If you want gnuplot to use the color according to the palette, write lc palette
gnuplot 4.6 does not support "+" for polar. Also, the mapping sets the behavior for 3D plots. However, as your formula calculates a radius for an angle, you can easily transform this to carthesian coordinates and plot these. There is still one drawback: The range given in the plot sets the xrange, too. This also means that the "length" of your curve changes when you change the xrange. You can solve this by set parametric which causes gnuplot to use a dedicated variable u instead of x when plotting functions. It is nice (and helps you) that this affects the special file "+", too. I do not know if this is a (positive) bug or a feature.

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:

Gnuplot: transparency of data points when using palette

Is there a way to plot transparent data points when using palette?
I currently have the following code:
set style fill transparent solid 0.2 noborder
set palette rgb 22,13,-22
plot 'mydata.dat' u 1:2:3 ps 0.3 palette
My feeling is that transparency is overwritten by the arguments of the plot command.
Is there a way to plot transparent data points when using palette?
If you check help palette you will not find (or I overlooked) a statement about transparency in the palette. It looks like you can set the palette in different ways for RGB, but not for ARGB (A=alpha channel for transparency). So, I assume it is not possible with palette to have transparency (please correct me if I am wrong).
As workaround you have to set your transparency "manually" by setting the color with some transparency.
You can find the formulae behind the palettes by typing show palette rgbformulae.
The following examples creates a plot with random point positions in xrange[0:1] and yrange[0:1] and random points size (from 2 to 6) and random transparency (from 0x00 to 0xff). The color is determined by x according to your "manual palette". I hope you can adapt this example to your needs.
Code:
### "manual" palette with transparency
reset session
# These are the rgb formulae behind palette 22,13,-22
set angle degrees
r(x) = 3*x-1 < 0 ? 0: (3*x-1 > 1) ? 1 : 3*x-1
g(x) = sin(180*x)
b(x) = 1-(3*x-1) < 0 ? 0: (1-(3*x-1) > 1) ? 1 : 1-(3*x-1)
set xrange [0:1]
set yrange[-0.1:1.1]
RandomSize(n) = rand(0)*4+2 # random size from 2 to 6
RandomTransp(n) = int(rand(0)*0xff)<<24 # random transparency from 0x00 to 0xff
myColor(x) = (int(r(x)*0xff)<<16) + (int(g(x)*0xff)<<8) + int(b(x)*0xff) + RandomTransp(0)
set samples 200
plot '+' u (x=rand(0)):(rand(0)):(RandomSize(0)):(myColor(x)) w p pt 7 ps var lc rgb var not
### end of code
Result:
New answer for Dev version 5.5
The new function set colormap allows to define a transparent palette. First, one defines the fully opaque palette in the usual way, then creates a copy of it and adds transparency to all points:
set palette rgb 22,13,-22
set colormap new MYPALETTE
transparency = 0.5
do for [i=1:|MYPALETTE|] {MYPALETTE[i] = MYPALETTE[i] + (int(transparency*0xff)<<24)}
func(x,y) = x*y
splot func(x,y) w pm3d fillcolor palette MYPALETTE
Of course, this will also work for points, the command in your case will be
plot 'mydata.dat' u 1:2:3 ps 0.3 lc palette MYPALETTE

Gnuplot: oscilloscope-like line style?

Is it possible in Gnuplot to emulate the drawing style of an analogue oscilloscope, meaning thinner+dimmisher lines on larger amplitudes, like this:?
The effect you see in the oscilloscope trace is not due to amplitude, it is due to the rate of change as the trace is drawn. If you know that rate of change and can feed it to gnuplot as a third column of values, then you could use it to modulate the line color as it is drawn:
plot 'data' using 1:2:3 with lines linecolor palette z
I don't know what color palette would work best for your purpose, but here is an approximation using a function with an obvious, known, derivative.
set palette gray
set samples 1000
plot '+' using ($1):(sin($1)):(abs(cos($1))) with lines linecolor palette
For thickness variations, you could shift the curve slightly up and down, and fill the area between them.
f(x) = sin(2*x) * sin(30*x)
dy = 0.02
plot '+' u 1:(f(x)+dy):(f(x)-dy) w filledcurves ls 1 notitle
This does not allow variable colour, but the visual effect is similar.
Another approach:
As #Ethan already stated, the intensity is somehow proportional to the speed of movement, i.e. the derivative. If you have sin(x) as waveform, the derivative is cos(x). But what if you have given data? Then you have to calculate the derivative numerically.
Furthermore, depending on the background the line should fade from white (minimal derivative) to fully transparent (maximum derivative), i.e. you should change the transparency with the derivative.
Code:
### oscilloscope "imitation"
reset session
set term wxt size 500,400 butt # option butt, otherwise you will get overlap points
set size ratio 4./5
set samples 1000
set xrange[-5:5]
# create some test data
f(x) = 1.5*sin(15*x)*(cos(1.4*x)+1.5)
set table $Data
plot '+' u 1:(f($1)) w table
unset table
set xtics axis 1 format ""
set mxtics 5
set grid xtics ls -1
set yrange[-4:4]
set ytics axis 1 format ""
set mytics 5
set grid ytics ls -1
ColorScreen = 0x28a7e0
set obj 1 rect from screen 0,0 to screen 1,1 behind
set obj 1 fill solid 1.0 fc rgb ColorScreen
x0=y0=NaN
Derivative(x,y) = (dx=x-x0,x0=x,x-dx/2,dy=y-y0,y0=y,dy/dx) # approx. derivative
# get min/max derivative
set table $Dummy
plot n=0 $Data u (d=abs(Derivative($1,$2)),n=n+1,n<=2? (dmin=dmax=d) : \
(dmin>d ? dmin=d:dmin), (dmax<d?dmax=d:dmax)) w table
unset table
myColor(x,y) = (int((abs(Derivative(column(x),column(y)))-dmin)/(dmax-dmin)*0xff)<<24) +0xffffff
plot $Data u 1:2:(myColor(1,2)) w l lw 1.5 lc rgb var not
### 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.

Histogram in GNUplot, each bar with a different color

I am trying to make a barplot with GNUplot, were each bar has a different color. I have found out in the manual that it can be done using lc rgbcolor variable.
My data folder looks like this,
ACB 0.106372
ASW 0.10909
BEB 0.110973
CDX 0.106577
CEU 0.102091
CHB 0.108829
CHS 0.110807
CLM 0.108803
My plot script is as follows,
set style histogram gap 2
set autoscale y
set style fill solid
set xtics rotate by 90 offset 0,-1.2
rgb(r,g,b) = 65536 * int(r*10) + 256 * int(g*10) + int(b*10)
set boxwidth .5
set output "Plot.eps"
plot "plot.tsv" using 2:xticlabels(1):(rgb($2,$2,$2)) with boxes lc rgb variable
I have used the rgb function that is shown in the GNUplot manual. But it shows the following error.
plot "plot.tsv" using 2:xticlabels(1):(rgb($2,$2,$2)) with boxes lc rgb variable
^
"#Plot.plt", line 18: x range is invalid
I can't figure out what the error means.
Please help.
Thanks in advance.
You are actually plotting with style "boxes", not "histograms". That probably is what you want, but whereas for histograms the x coordinate is implicit, for boxes you have to provide an x coordinate in the first column even if you're OK with the ordinal numbers 0,1,2,3,...
So
plot "plot.tsv" using 0:2:xticlabels(1):(rgb($2,$2,$2)) with boxes lc rgb variable
Oh, and you probably want to set the fillstyle also so that the colors are visible:
set style fill solid

Resources