Skip to content
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
957e6f5
Closes #5946. Init commit. Adding ability to scale heatmap intensity …
stormpython Jan 26, 2016
15397a4
cleaning up unused code and setting the range for d3 scales to [0, 1]
stormpython Jan 26, 2016
3574e6e
correcting bug in tile_map.html file, removing normalized if block si…
stormpython Jan 27, 2016
a84ce56
adding tests, renaming scale parameter
stormpython Jan 27, 2016
b556b29
Merge branch 'master' into issue/5946
stormpython Jan 27, 2016
4c1ffff
small code change
stormpython Jan 28, 2016
4f1f64c
Merge branch 'master' into issue/5946
stormpython Feb 29, 2016
364eeaf
troubleshooting test failures
stormpython Feb 29, 2016
1da8129
reverting the previous change
stormpython Feb 29, 2016
4830a49
resolving conflict
stormpython Feb 29, 2016
a9af4a1
removing the max param from the _dataToHeatArray function
stormpython Mar 1, 2016
bbabc29
Merge branch 'master' into issue/5946
stormpython Mar 1, 2016
66a4489
syntax changes
stormpython Mar 1, 2016
685d211
fixing failing tests
stormpython Mar 2, 2016
4780ff3
Merge branch 'master' into issue/5946
stormpython Mar 2, 2016
ebda8a3
Merge branch 'master' into issue/5946
stormpython Mar 2, 2016
edef654
Merge branch 'master' into issue/5946
stormpython Mar 7, 2016
0530f22
Merge branch 'master' into issue/5946
stormpython Mar 7, 2016
69a107d
Merge branch 'master' into issue/5946
stormpython Mar 23, 2016
cf34b9c
Merge branch 'master' into issue/5946
stormpython Mar 24, 2016
264f4df
refactoring based on reviews
stormpython Mar 24, 2016
bfbe6fd
removing commented line
stormpython Mar 28, 2016
3ad307c
Merge branch 'master' into issue/5946
stormpython Mar 28, 2016
6bfd0d0
Merge branch 'master' into issue/5946
stormpython Mar 29, 2016
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
35 changes: 24 additions & 11 deletions src/plugins/kbn_vislib_vis_types/public/editors/tile_map.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,25 @@
class="form-control"
ng-model="vis.params.mapType"
ng-init="vis.params.mapType || vis.type.params.mapTypes[0]"
ng-options="mapType as mapType for mapType in vis.type.params.mapTypes"
>
ng-options="mapType as mapType for mapType in vis.type.params.mapTypes">
</select>
</div>

<div ng-if="vis.params.mapType === 'Heatmap'" class="form-group">
<div>
<label>
Intensity Scale
&nbsp;<kbn-info placement="right" info="Heatmap intensity data transformation scale. Default: linear"></kbn-info>
</label>
<div class="vis-editor-agg-form-row">
<select name="scale"
class="form-control"
ng-model="vis.params.intensityScale"
ng-init="vis.params.intensityScale || vis.type.params.intensityScales[0].name"
ng-options="scale.value as scale.name for scale in vis.type.params.intensityScales">
</select>
</div>
</div>
<div>
<label>
Radius
Expand Down Expand Up @@ -131,9 +144,9 @@

<div ng-show="vis.params.wms.enabled" class="well">
<div class="vis-option-item form-group">

<p>
WMS maps are 3rd party mapping services that have not been verified to work with Kibana.
WMS maps are 3rd party mapping services that have not been verified to work with Kibana.
These should be considered expert settings.
</p>

Expand All @@ -142,7 +155,7 @@
</label>
<input type="text" class="form-control"
name="wms.url"
ng-model="vis.params.wms.url">
ng-model="vis.params.wms.url">
</div>

<div class="vis-option-item form-group">
Expand All @@ -151,7 +164,7 @@
</label>
<input type="text" class="form-control"
ng-require="vis.params.wms.enabled"
ng-model="vis.params.wms.options.layers"
ng-model="vis.params.wms.options.layers"
name="wms.options.layers">
</div>

Expand All @@ -161,7 +174,7 @@
</label>
<input type="text" class="form-control"
name="wms.options.version"
ng-model="vis.params.wms.options.version">
ng-model="vis.params.wms.options.version">
</div>

<div class="vis-option-item form-group">
Expand All @@ -170,16 +183,16 @@
</label>
<input type="text" class="form-control"
name="wms.options.format"
ng-model="vis.params.wms.options.format">
ng-model="vis.params.wms.options.format">
</div>

<div class="vis-option-item form-group">
<label>
WMS attribution <kbn-info info="Attribution string for the lower right corner<"></kbn-info>
</label>
<input type="text" class="form-control"
name="wms.options.attribution"
ng-model="vis.params.wms.options.attribution">
ng-model="vis.params.wms.options.attribution">
</div>

<div class="vis-option-item form-group">
Expand All @@ -188,7 +201,7 @@
</label>
<input type="text" class="form-control"
name="wms.options.styles"
ng-model="vis.params.wms.options.styles">
ng-model="vis.params.wms.options.styles">
</div>

<p>* if this parameter is incorrect, maps will fail to load.</p>
Expand Down
7 changes: 6 additions & 1 deletion src/plugins/kbn_vislib_vis_types/public/tileMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@ export default function TileMapVisType(Private, getAppState, courier, config) {
heatMinOpacity: 0.1,
heatRadius: 25,
heatBlur: 15,
heatNormalizeData: true,
intensityScale: 'linear',
wms: config.get('visualization:tileMap:WMSdefaults')
},
intensityScales: [
{name: 'Linear', value: 'linear'},
{name: 'Logarithmic', value: 'log'},
{name: 'Square root', value: 'sqrt'}
],
mapTypes: ['Scaled Circle Markers', 'Shaded Circle Markers', 'Shaded Geohash Grid', 'Heatmap'],
canDesaturate: !!supports.cssFilters,
editor: tileMapTemplate
Expand Down
62 changes: 46 additions & 16 deletions src/ui/public/vislib/__tests__/visualizations/tile_maps/markers.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,49 @@ describe('Marker Tests', function () {
markerLayer = createMarker(MarkerClass);
}));

describe('getDomain', function () {
var scaleTypes = ['linear', 'log', 'sqrt'];
var callback = function (d) { return d; };
var features = [-50000, -40000, -3000, -200, -10, 0, 10, 200, 3000, 40000, 500000];

scaleTypes.forEach(function (scale) {
var scaleDomain = markerLayer._getDomain(features, scale, callback);
var min = Math.min(features);
var max = Math.max(features);

if (scale !== 'log') {
it('should return the min and max value of the dataset for each scale type', function () {
expect(scaleDomain[0]).to.be.eql(min);
expect(scaleDomain[1]).to.be.eql(max);
});
} else {
it('should default the min value to 1e-9 for log scales when the min value is less than 1e-9', function () {
expect(scaleDomain[0]).to.be.gte(1e-9);
});

it('should default the max value to 1 for log scales when the max value is less than 1', function () {
expect(scaleDomain[1]).to.be.gte(1);
});
}
});
});

describe('heatmapScale', function () {
var scaleType = 'linear';
var callback = function (d) { return d; };
var features = [10, 20, 30, 40, 50];
var index = features.length - 1;
var intensityScale = markerLayer._heatmapScale(features, scaleType, callback);

it('should return a function', function () {
expect(intensityScale).to.be.a('function');
});

it('should return a value between 0 and 1', function () {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a test to verify linear/log/sqrt intensities?

expect(intensityScale(features[index])).to.be.within(0, 1);
});
});

describe('dataToHeatArray', function () {
var max;

Expand All @@ -284,30 +327,17 @@ describe('Marker Tests', function () {
var arr = markerLayer._dataToHeatArray(max);
expect(arr).to.be.an('array');
expect(arr).to.have.length(mapData.features.length);

});

it('should return an array item with lat, lng, metric for each feature', function () {
_.times(3, function () {
var arr = markerLayer._dataToHeatArray(max);
var index = _.random(mapData.features.length - 1);
var feature = mapData.features[index];
var featureValue = feature.properties.value;
var featureArr = feature.geometry.coordinates.slice(0).concat(featureValue);
expect(arr[index]).to.eql(featureArr);
});
});

it('should return an array item with lat, lng, normalized metric for each feature', function () {
it('should return an array item with lat, lng, normalized metric between 0 and 1 for each feature', function () {
_.times(5, function () {
markerLayer._attr.heatNormalizeData = true;

var arr = markerLayer._dataToHeatArray(max);
var index = _.random(mapData.features.length - 1);
var feature = mapData.features[index];
var featureValue = parseInt(feature.properties.value / max * 100);
var featureValue = feature.properties.value / max;
var featureArr = feature.geometry.coordinates.slice(0).concat(featureValue);
expect(arr[index]).to.eql(featureArr);
expect(arr[index]).to.be.within(0, 1);
});
});
});
Expand Down
91 changes: 60 additions & 31 deletions src/ui/public/vislib/visualizations/marker_types/heatmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,65 @@ export default function HeatmapMarkerFactory(Private) {
return nearest;
};

/**
* Returns the domain for the heatmap scale
*
* @method _getDomain
* @param features {geoJson Object}
* @param scaleType {String}
* @param callback {Function}
* @return {Array}
*/
HeatmapMarker.prototype._getDomain = function (features, scaleType, callback) {
var isLog = Boolean(scaleType === 'log');
var extent = d3.extent(features, callback);

// Log scales cannot have numbers <= 0. Default min value is 1e-9 and max value is 1.
if (isLog) return [ Math.max(1e-9, extent[0]), Math.max(1, extent[1]) ];
return extent;
};

/**
* Returns a scale function which determines the heatmap intensity at a given
* point. Linear scale by default.
*
* @method _heatmapScale
* @param features {Array}
* @param scaleType {String}
* @param callback {Function}
* @return {Function}
*/
HeatmapMarker.prototype._heatmapScale = function (features, scaleType, callback) {
return d3.scale[scaleType]()
.domain(this._getDomain(features, scaleType, callback))
.range([0, 1]) // Heatmap plugin expects output between 0 and 1
.clamp(true); // Clamps the output to keep it between 0 and 1
};

/**
* returns data for data for heat map intensity
*
* @method _dataToHeatArray
* @param max {Number}
* @return {Array}
*/
HeatmapMarker.prototype._dataToHeatArray = function (max) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The max value is no longer being used, and can be removed

var self = this;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed?

var scaleType = this._attr.intensityScale || 'linear';
var features = this.geoJson.features;
var intensityScale = this._heatmapScale(features, scaleType, function (d) {
return scaleType === 'log' ? Math.abs(d.properties.value) : d.properties.value;
});

return features.map(function (feature) {
var lat = feature.properties.center[0];
var lng = feature.properties.center[1];
var heatIntensity = intensityScale(feature.properties.value);

return [lat, lng, heatIntensity];
});
};

/**
* display tooltip if feature is close enough to event latlng
*
Expand Down Expand Up @@ -172,38 +231,8 @@ export default function HeatmapMarkerFactory(Private) {
var testScale = d3.scale.pow().exponent(0.2)
.domain([1, 18])
.range([1500000, 50]);
return showTip;
};


/**
* returns data for data for heat map intensity
* if heatNormalizeData attribute is checked/true
• normalizes data for heat map intensity
*
* @method _dataToHeatArray
* @param max {Number}
* @return {Array}
*/
HeatmapMarker.prototype._dataToHeatArray = function (max) {
var self = this;
var mapData = this.geoJson;

return this.geoJson.features.map(function (feature) {
var lat = feature.properties.center[0];
var lng = feature.properties.center[1];
var heatIntensity;

if (!self._attr.heatNormalizeData) {
// show bucket value on heatmap
heatIntensity = feature.properties.value;
} else {
// show bucket value normalized to max value
heatIntensity = parseInt(feature.properties.value / max * 100);
}

return [lat, lng, heatIntensity];
});
return showTip;
};

return HeatmapMarker;
Expand Down