Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #3,#11,#12,#15 resolves #2,#14,#23 couple of perfomance tweaks #20

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c019a23
Stop points bleeding into pixels outside of radius
kwauchope May 2, 2014
8267ff4
added weight functionality
Jul 28, 2014
52204d6
added option to input flat array so no flattenign required
Jul 28, 2014
1eaf322
Update setup.py
kwauchope Aug 1, 2014
7a93ae1
fixed error with weights and _range, only found when use KML and weights
Aug 3, 2014
d1e241c
fixed issue of other data types with _ranges, only visible when use KML
Aug 3, 2014
4c0af00
changed internal class storage of points to flat
Aug 3, 2014
0bcd40c
fixed east and west mixed up which breaks KML, added area test which …
Aug 3, 2014
b51c151
better crs support
Jul 28, 2014
9f83cee
fixed crs support for overriding area
Jul 28, 2014
1612242
allowed for None setting for epsg
Jul 28, 2014
7182684
No projection as default to not break current usage. Selectable outpu…
Jul 29, 2014
778fd78
describe dstepsg and srcepsg better
Jul 29, 2014
d255a53
made pyproj optional, not sure if like stderr with tests though, bett…
Aug 1, 2014
0cd1d37
fix typos
Aug 1, 2014
4c42ae7
cleaned up test requirements
Aug 1, 2014
8f517bd
fix issue with using internal points for _ranges, need to clone if co…
Aug 3, 2014
638c2a1
nicer looking test for proj, weight at 0,0 highlights current transla…
Aug 3, 2014
a370450
happy with projection results now
Aug 4, 2014
5f524ea
cleaned up setup for distutils and setuputils
Aug 4, 2014
b0e5f30
cleaned up some lengthy chucnks of code
Aug 4, 2014
9933c68
added test for all possible datatypes
Aug 4, 2014
c50a822
added pyproj to requirements for pip/travis
Aug 4, 2014
d916f33
adding python3 support
Aug 16, 2014
6674193
fixed ISO C90 compatabliity so will work on windows, highlighted by 3…
Aug 16, 2014
04337bd
ctypes searching fixes required to run on the travis ci python3 env, …
Aug 16, 2014
fededde
added better coverage for tests as well as python version test for >=2.6
Aug 20, 2014
76a3a75
fixed tests for older versions of unittest, uses function assignment …
Aug 20, 2014
49bdbce
cleaner to include rather than omit in coveragerc
Aug 21, 2014
dbabd09
added back version code
Aug 21, 2014
5ac16e7
cleaned up srcepsg and dstepsg docco
Aug 21, 2014
d5d1cf7
added image comaparison tests and split out the repeated saveKML func…
Aug 21, 2014
c64a7d5
removed forced exit if not python 2.6+, added trove classifiers
Aug 22, 2014
45266f8
removed no longer needed import
Aug 22, 2014
170173f
no need to malloc if initialising anyway
Aug 23, 2014
ec26754
small cleanup of typos and extra test not needed
Aug 23, 2014
a74b078
cleaned up docco and a few tiny tweaks
Aug 23, 2014
32a5206
add another parameter check and shift break further up
Aug 23, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[run]
branch=True
include=*heatmap*
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pip-log.txt
.coverage
.tox
nosetests.xml
/htmlcov

# Translations
*.mo
Expand All @@ -44,4 +45,4 @@ nosetests.xml
.DS_Store

*.png
*.kml
*.kml
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"

# command to install dependencies
install:
Expand Down
2 changes: 1 addition & 1 deletion examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
pts = []
for x in range(400):
pts.append((random.random(), random.random()))
print "Processing %d points..." % len(pts)
print("Processing %d points..." % len(pts))
hm = heatmap.Heatmap()
img = hm.heatmap(pts).save("classic.png")
4 changes: 2 additions & 2 deletions heatmap/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
try:
__version__ = __import__('pkg_resources').get_distribution(__name__).version
except Exception, e:
except Exception as e:
__version__ = 'unknown'

from heatmap import Heatmap
from .heatmap import Heatmap
66 changes: 43 additions & 23 deletions heatmap/heatmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include <math.h>
#include <string.h>

float constant = 50.0;
float multiplier = 200.0;

struct info
{
float minX;
Expand All @@ -12,6 +15,7 @@ struct info

int width;
int height;
int cPixels;
int dotsize;
};

Expand All @@ -33,7 +37,7 @@ BOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to DLL module
#endif

//walk the list of points, get the boundary values
void getBounds(struct info *inf, float *points, unsigned int cPoints)
void getBounds(struct info *inf, float *points, unsigned int cPoints, int weighted)
{
unsigned int i = 0;

Expand All @@ -43,8 +47,11 @@ void getBounds(struct info *inf, float *points, unsigned int cPoints)
float maxX = points[i];
float maxY = points[i+1];

int inc = 2;
if (weighted) inc = 3;

//then iterate over the list and find the max/min values
for(i = 0; i < cPoints; i=i+2)
for(i = 0; i < cPoints; i=i+inc)
{
float x = points[i];
float y = points[i+1];
Expand Down Expand Up @@ -86,31 +93,36 @@ struct point translate(struct info *inf, struct point pt)
return pt;
}

unsigned char* calcDensity(struct info *inf, float *points, int cPoints)
unsigned char* calcDensity(struct info *inf, float *points, int cPoints, int weighted)
{
int width = inf->width;
int height = inf->height;
int cPixels = inf->cPixels;
int dotsize = inf->dotsize;

unsigned char* pixels = (unsigned char *)calloc(width*height, sizeof(char));
unsigned char* pixels = (unsigned char *)malloc(cPixels*sizeof(char));

float midpt = dotsize / 2.f;
double radius = sqrt(midpt*midpt + midpt*midpt) / 2.f;
double dist = 0.0;
float radius = sqrt(midpt*midpt + midpt*midpt) / 2.f;
float dist = 0.0;
int pixVal = 0;
int j = 0;
int k = 0;
int i = 0;
int ndx = 0;
struct point pt = {0};

int inc = 2;
if (weighted) inc = 3;

// initialize image data to white
for(i = 0; i < (int)width*height; i++)
for(i = 0; i < cPixels; i++)
{
pixels[i] = 0xff;
}

for(i = 0; i < cPoints; i=i+2)

for(i = 0; i < cPoints; i=i+inc)
{
pt.x = points[i];
pt.y = points[i+1];
Expand All @@ -123,12 +135,21 @@ unsigned char* calcDensity(struct info *inf, float *points, int cPoints)
if (j < 0 || k < 0 || j >= width || k >= height) continue;

dist = sqrt( (j-pt.x)*(j-pt.x) + (k-pt.y)*(k-pt.y) );

pixVal = (int)(200.0*(dist/radius)+50.0);
if (pixVal > 255) pixVal = 255;

if(dist>radius) continue; // stop point contributing to pixels outside its radius

ndx = k*width + j;
if(ndx >= (int)width*height) continue; // ndx can be greater than array bounds
if(ndx >= cPixels) continue; // ndx can be greater than array bounds

if(weighted)
{
pixVal = (int)((multiplier*(dist/radius)+constant)/points[i+2]);
}
else
{
pixVal = (int)(multiplier*(dist/radius)+constant);
}
if (pixVal > 255) pixVal = 255;

#ifdef DEBUG
printf("pt.x: %.2f pt.y: %.2f j: %d k: %d ndx: %d\n", pt.x, pt.y, j, k, ndx);
Expand All @@ -145,16 +166,14 @@ unsigned char* calcDensity(struct info *inf, float *points, int cPoints)
unsigned char *colorize(struct info *inf, unsigned char* pixels_bw, int *scheme, unsigned char* pixels_color,
int opacity)
{
int width = inf->width;
int height = inf->height;
int dotsize = inf->dotsize;
int cPixels = inf->cPixels;

int i = 0;
int pix = 0;
int highCount = 0;
int alpha = opacity;

for(i = 0; i < (int)width*height; i++)
for(i = 0; i < cPixels; i++)
{
pix = pixels_bw[i];

Expand All @@ -170,7 +189,7 @@ unsigned char *colorize(struct info *inf, unsigned char* pixels_bw, int *scheme,
pixels_color[i*4+3] = alpha;
}

if (highCount > width*height*0.8)
if (highCount > cPixels*0.8)
{
fprintf(stderr, "Warning: 80%% of output pixels are over 95%% density.\n");
fprintf(stderr, "Decrease dotsize or increase output image resolution?\n");
Expand All @@ -190,23 +209,24 @@ unsigned char *tx(float *points,
unsigned char *pix_color,
int opacity,
int boundsOverride,
float minX, float minY, float maxX, float maxY)
float minX, float minY, float maxX, float maxY, int weighted)
{
unsigned char *pixels_bw = NULL;
struct info inf = {0};

//basic sanity checks to keep from segfaulting
if (NULL == points || NULL == scheme || NULL == pix_color ||
w <= 0 || h <= 0 || cPoints <= 1 || opacity < 0 || dotsize <= 0)
w <= 0 || h <= 0 || cPoints <= 1+weighted || cPoints % (2+weighted) != 0 ||
opacity < 0 || opacity > 255 || dotsize <= 0)
{
fprintf(stderr, "Invalid parameter; aborting.\n");
return NULL;
}

struct info inf = {0};

inf.dotsize = dotsize;
inf.width = w;
inf.height = h;
inf.cPixels = w*h;

// get min/max x/y values from point list
if (boundsOverride == 1)
Expand All @@ -216,7 +236,7 @@ unsigned char *tx(float *points,
}
else
{
getBounds(&inf, points, cPoints);
getBounds(&inf, points, cPoints, weighted);
}

#ifdef DEBUG
Expand All @@ -225,7 +245,7 @@ unsigned char *tx(float *points,

//iterate through points, place a dot at each center point
//and set pix value from 0 - 255 using multiply method for radius [dotsize].
pixels_bw = calcDensity(&inf, points, cPoints);
pixels_bw = calcDensity(&inf, points, cPoints, weighted);

//using provided color scheme and opacity, update pixel value to RGBA values
pix_color = colorize(&inf, pixels_bw, scheme, pix_color, opacity);
Expand Down
Loading