1
1

I have trouble with finding something that will generate a nice looking heatmap (something like this one: https://commons.wikimedia.org/wiki/File:Amsterdam_heat_map_OSM.png ) For example http://www.websitedev.de/temp/openlayers-heatmap-layer.html and http://gnuplot.sourceforge.net/demo/heatmaps.html seem unable to generate nice looking images (or nobody bothered to produce a nice looking example).

asked 17 Dec '13, 21:25

Bulwersator's gravatar image

Bulwersator
408111624
accept rate: 14%

Can’t you make one or a script based on OSM yourself ? It seems to me that’s not a specific OSM question, besides that you want OSM data as basement. Feel free to do so.

(17 Dec '13, 22:40) Hendrikklaas

2 Answers:
5

"nice looking" is obviously always a matter of taste, but I gave it a try. Regular gnuplot heatmaps need data on a grid, not a collection of random points. To get around this limitation I convert the data to an analytic expression and then use "splot". So assume that you start with data, that looks like this:

#x y v
3 2 1
5 6 0.2
8 5 0.5

I used to following python script to create a gnuplot script

#!/usr/bin/python
import sys
import os
import csv

def main(argv):
    # check arguments
    if len(argv) == 0:
            print "Usage: heatmap.py inputfilename"
            sys.exit(1)

    # find and open input file
    inputfilename = argv[0]
    try:
            inputfile = open(inputfilename)
    except:
            print "Can't read "+inputfilename
            sys.exit(1)

    # open output file carefully
    outputfilemode = os.O_WRONLY | os.O_CREAT | os.O_EXCL
    outputdir = os.path.dirname(os.path.abspath(inputfilename))
    outputbasename = os.path.splitext(os.path.basename(inputfilename))[0]
    outputfilename = os.path.join(outputdir, outputbasename+".gp")
    try:
            fd = os.open(outputfilename, outputfilemode, 0744)
    except:
            print "Can't create "+outputfilename
            sys.exit(1)

    outputfile = os.fdopen(fd, "w")

    # write settings to output file
    outputfile.write("#!/usr/bin/gnuplot\n")
    outputfile.write("set terminal pngcairo size 800,600 enhanced\n")
    outputfile.write("set output 'heatmap.png'\n")
    outputfile.write("set palette defined ( 0 'black', 1 'red', 2 'yellow', 2.1 'white' )\n")
    outputfile.write("set isosamples 100, 100\n")
    outputfile.write("set style function pm3d\n")
    outputfile.write("set pm3d map\n")
    outputfile.write("unset colorbox\n")
    outputfile.write("unset tics\n")
    outputfile.write("set format x ''\n")
    outputfile.write("set format y ''\n")
    outputfile.write("set lmargin at screen 0\n")
    outputfile.write("set rmargin at screen 1\n")
    outputfile.write("set bmargin at screen 0\n")
    outputfile.write("set tmargin at screen 1\n")
    # intensity of the dot depending on value
    outputfile.write("w(v)=v\n")
    # size of the dot depending on value
    outputfile.write("s(v)=sqrt(v)\n")

    # collect points to plot from dat file
    p = []
    dat_xmin = float('inf')
    dat_xmax = float('-inf')
    dat_ymin = float('inf')
    dat_ymax = float('-inf')

    reader = csv.reader(inputfile, delimiter=" ")
    for r in reader:
            if r[0].startswith("#"):
                    continue

            x = float(r[0])
            y = float(r[1])
            v = float(r[2])
            dat_xmin = min(dat_xmin, x)
            dat_xmax = max(dat_xmax, x)
            dat_ymin = min(dat_ymin, y)
            dat_ymax = max(dat_ymax, y)
            p.append("w("+str(v)+")/exp(((x-("+str(x)+"))**2 + (y-("+str(y)+"))**2)/s("+str(v)+"))")

    #calculate range
    plot_xmin = dat_xmin - 0.2*(dat_xmax - dat_xmin)
    plot_xmax = dat_xmax + 0.2*(dat_xmax - dat_xmin)
    plot_ymin = dat_ymin - 0.2*(dat_ymax - dat_ymin)
    plot_ymax = dat_ymax + 0.2*(dat_ymax - dat_ymin)

    # write plot command
    outputfile.write("splot ")
    outputfile.write("["+str(plot_xmin)+":"+str(plot_xmax)+"]["+str(plot_ymin)+":"+str(plot_ymax)+"] ")
    outputfile.write("+".join(p))
    outputfile.write( " notitle\n")

    # close output file
    outputfile.close()

    print "Done. Now run "+outputfilename

if __name__ == "__main__":
    main(sys.argv[1:])

Running the resulting gnuplot script generates the following image

alt text

Color palette, size, and relative intensity of the dots can be tweaked but this should at least give you an idea how to generate heatmaps.

permanent link

answered 17 Dec '13, 23:08

petschge's gravatar image

petschge
8.0k207197
accept rate: 21%

2
permanent link

answered 17 Dec '13, 23:09

Jfact0ry's gravatar image

Jfact0ry
346151730
accept rate: 0%

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×201
×12
×5
×1

question asked: 17 Dec '13, 21:25

question was seen: 5,444 times

last updated: 17 Dec '13, 23:09

powered by OSQA