tags:

views:

602

answers:

3

I am looking to build a static KML (Google Earth markup) file which displays a heatmap-style rendering of a few given data sets in the form of [lat, lon, density] tuples.

A very straightforward data set I have is for population density.

My requirements are:

  • must be able to feed in data for a given lat, lon
  • must be able to specific the given density of the data at that lat, lon
  • must export to KML

The requirements are language agnostic for this project as I will be generating these files offline in order to build the KML used elsewhere.

I have looked at a few projects, most notably heatmap.py, which is a port of gheat in Python with KML export. I have hit a brick wall in the sense that the projects I have found to date all rely on building the heatmap from the density of [lat, lon] points fed into the algorithm.

If I am missing an obvious way to adapt my data set to feed in just the [lat, lon] tuples but adjusting how I feed them using the density values I have, I would love to know!

A: 

I think one way to do this is to create a (larger) list of tuples with each point repeated according to the density at that point. A point with a high density is represented by lots of points on top of each other while a point with a low density has few points. So instead of: [(120.7, 82.5, 2), (130.6, 81.5, 1)] you would use [(120.7, 82.5), (120.7, 82.5), (130.6, 81.5)] (a fairly dull dataset).

One possible issue is that your densities may well be floats, not integers, so you should normalize and round the data. One way to do the conversion is something like this:

def dens2points (dens_tups):
    min_dens = dens_tups[0][2]
    for tup in dens_tups:
        if (min_dens > tup[2]):
           min_dens = tup[2]
    print min_dens

    result = []
    for tup in dens_tups:
        for i in range(int(tup[2]/min_dens)):
            result.append((tup[0],tup[1]))
    return result

if __name__ == "__main__":
    input = [(10, 10, 20.0),(5, 5, 10.0),(10,10,0.9)]
    output = dens2points(input)
    print input
    print output

(which isn't very pythonic, but seems to work for the simple test case). This subroutine should convert your data into a form that is accepted by heatmap.py. With a little effort I think the subroutine can be reduced to two lines.

Andrew Walker
A: 

Hey Will, heatmap.py is me. Your request is a common-enough one and is on my list of things to address. I'm not quite sure yet how to do so in a general fashion; in heatmap.py parlance, it would be straightforward to have a per-point dotsize instead of a global dotsize as it is now, but I'm not sure that will address the true need. I'm aiming for a summer 2010 release, but you could probably make this mod yourself.

You may try searching for Kernel Density Estimator tools; that's what the statisticians call heatmaps. R has some good built-in tools you can use that might satisfy your need more quickly.

good luck!

J.J.
Brilliant, thanks J.J.!
Will Croft
I've found that Zoom 0-9 should have the floor dotsize, Zoom 15-19 have ceiling, and scale in between. I've found at 0-9, only 1-pixel dots are viable and at 15-19, it doesn't make sense to be over 64px. Do you see a way to incorporate this range into your KML methodology?
nessence
A: 

Hi Will, I updated the heatmap.py script so you can specify a density for each point. I uploaded my changes to my blog. Not sure if it'll do exactly what you want though!

Cheers, Alex

Alex Little
Brilliant - thanks Alex! I'll check it out.
Will Croft