8

I want to reproduce this effect in gnuplot:

neon effect

How can I achive it? If it can't be done, what software can I use to reproduce it?

Notlikethat
  • 20,095
  • 3
  • 40
  • 77
RedPointyJackson
  • 675
  • 8
  • 17
  • 1
    What software was used to produce that image in the first place? – Matthew Apr 07 '16 at 23:04
  • @Matthew I'm not sure, the plot is not mine, but I have seen similar plots in the newest Excel: [Excel glow](http://excel.demist-it.com/wp-content/uploads/2015/02/final-graph-hidden-rows.png) – RedPointyJackson Apr 09 '16 at 14:43

3 Answers3

6

Using a 2d kernel for every pixel can be done inside gnuplot. That way, more dense accumulations get brighter than single pixels. Check show palette rgbformulae and the respective chapter in the help to change the colours.

  set term wxt size 300,300 background rgb 0
  set view map
  set samp 140                                       
  set dgrid3d 180,180, gauss kdensity2d 0.2,0.2   
  set palette rgbform 4,4,3   
  splot "+" us 1:(sin($1/3)**2*20):(1)  with pm3d notitle
Karl
  • 2,117
  • 13
  • 26
4

Disclaimer: It can be done with gnuplot as instructed in this answer but you should probably consider a different tool to draw this particular type of plot.

There is at least one way to do it, with preprocessing of the data. The idea is to mimic the glow effect by using a Gaussian kernel to smear the data points. Consider the following data, contained in a file called data:

1   2
1   2.1
1.1 2.2
2   3
3   4

I have purposely placed the first 3 points close to each other to be able to observe the intensified glow of neighboring points. These data look like this:

enter image description here

Now we smear the data points using a 2D Gaussian kernel. I have written the following python code to help with this. The code has a cutoff of 4 standard deviations (sx and sy) around each point. If you want the glow to be a circle, you should choose the standard deviations so that the sx / sy ratio is the same as the ratio of the x/y axes lengths in gnuplot. Otherwise the points will look like ellipses. This is the code:

import numpy as np
import sys

filename = str(sys.argv[1])
sx = float(sys.argv[2])
sy = float(sys.argv[3])

def f(x,y,x0,y0,sx,sy):
    return np.exp(-(x-x0)**2/2./sx**2 -(y-y0)**2/2./sy**2)

datafile = open(filename, 'r')

data = []
for datapoint in datafile:
    a, b = datapoint.split()
    data.append([float(a),float(b)])

xmin = data[0][0]
xmax = data[0][0]
ymin = data[0][1]
ymax = data[0][1]
for i in range(1, len(data)):
    if(data[i][0] < xmin):
        xmin = data[i][0]
    if(data[i][0] > xmax):
        xmax = data[i][0]
    if(data[i][1] < ymin):
        ymin = data[i][1]
    if(data[i][1] > ymax):
        ymax = data[i][1]

xmin -= 4.*sx
xmax += 4.*sx
ymin -= 4.*sy
ymax += 4.*sy

dx = (xmax - xmin) / 250.
dy = (ymax - ymin) / 250.

for i in np.arange(xmin,xmax+dx, dx):
    for j in np.arange(ymin,ymax+dy, dy):
        s = 0.
        for k in range(0, len(data)):
            d2 = (i - data[k][0])**2 + (j - data[k][1])**2
            if( d2 < (4.*sx)**2 + (4.*sy)**2):
                s += f(i,j,data[k][0],data[k][1],sx,sy)
        print i, j, s

It is used as follows:

python script.py data sx sy

where script.py is the name of the file where the code is located, data is the name of the data file, and sx and sy are the standard deviations.

Now, back to gnuplot, we define a palette that mimics a glowing pattern. For isolated points, the summed Gaussians yield 1 at the position of the point; for overlapping points it yields values higher than 1. You must consider that when defining the palette. The following is just an example:

set cbrange [0:3]
unset colorbox
set palette defined (0 "black", 0.5 "blue", 0.75 "cyan", 1 "white", 3 "white")
plot "< python script.py data 0.05 0.05" w image

enter image description here

You can see that the points are actually ellipses, because the ratio of the axes lengths is not the same as that of the standard deviations along the different directions. This can be easily fixed:

plot "< python script.py data 0.05 0.06" w image

enter image description here

Miguel
  • 7,497
  • 2
  • 27
  • 46
1

Set a black background, and then plot your dataset several time in different colours with decreasing pointsize.

  set term wxt backgr rgb "black"
  plot sin(x) w p pt 7 ps 2 lc rgb 0x00003f not, \
       sin(x) w p pt 7 ps 1.5 lc rgb 0x00007f not, \
       sin(x) w p pt 7 ps 1 lc rgb 0x0000af not,  \
       sin(x) w p pt 7 ps .5 lc rgb 0x0000ff

Alternatively, some combination of splot with pm3d,set dgrid3d gauss kdensity2d, and set view map, combined with a suitable palette, can be used, see my other answer.

Karl
  • 2,117
  • 13
  • 26
  • The problem with this approach is that the glow from neighboring dots does not "merge". I was thinking about posting an approach that does work but is very clumsy to implement: perform a convolution with a 2D Gaussian function of all the points in the XY plane (each Gaussian centered at its corresponding point), then sum all the Gaussians. Now plot a 3D color map with the color palette mimicking the glowing effect. I tested this with a couple of points and it does work: for arbitrary numbers of points one would need to rely on an external (e.g. Python) program, so I didn't post it. – Miguel Apr 09 '16 at 07:22
  • @Miguel If it works, you should post it. It might be that the only way to do this is with the help of an external program. I tried using the same approach as this answer, but I had set an alpha lower than opaque so that my points would merge. I wasn't completely happy with it, however. It didn't look quite as smooth as the provided image. I'm hoping the OP will answer my question about what was used in the first place, because looking at how it is done there may provide insight into how to do it with gnuplot. – Matthew Apr 09 '16 at 07:51
  • @Matthew I have posted my solution and a Python script to do the preprocessing, but I'm not satisfied with it: it's too complicated to do what should be very simple. – Miguel Apr 09 '16 at 13:22
  • You're undertaxing gnuplot. ;-) Check my other answer. – Karl Apr 09 '16 at 17:38
  • @Karl Yes, that's more what I had in mind. I routinely use 1D Gaussian kernels but didn't know a 2D option was implemented. It would be interesting to know for many points whether the gnuplot procedure gets very slow. I know Python is suboptimal for doing this kind of stuff, I would usually write this kind of stuff in Fortran but a Fortran code would have put off most users checking this out here in SO. – Miguel Apr 09 '16 at 20:44
  • I guess the speed scales with 1/n, and I notice very quickly that it's slow. Gnuplot probably recalculates the kernel for every point and every pixel, because the positions of data points are not rasterised. – Karl Apr 10 '16 at 09:21