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

Adds ability to scale Tilemap heatmap intensity values #6014

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
63 changes: 33 additions & 30 deletions src/plugins/kbn_vislib_vis_types/public/editors/tile_map.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
<!-- vis type specific options -->
<div class="form-group">
<label>Map type</label>
<select name="agg"
<select name="agg"
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
&nbsp;<kbn-info placement="right" info="Size of heatmap dots. Default: 25"></kbn-info>
</label>
<div class="vis-editor-agg-form-row">
<input
name="heatRadius"
<input name="heatRadius"
ng-model="vis.params.heatRadius"
required
class="form-control"
type="range"
min="5"
max="50"
step="1"
>
step="1">
<div class="form-group vis-editor-agg-form-value">
{{vis.params.heatRadius}}
</div>
Expand All @@ -38,16 +49,14 @@
&nbsp;<kbn-info placement="right" info="Amount of blur applied to dots. Default: 15"></kbn-info>
</label>
<div class="vis-editor-agg-form-row">
<input
name="heatBlur"
<input name="heatBlur"
ng-model="vis.params.heatBlur"
required
class="form-control"
type="range"
min="1"
max="25"
step="1"
>
step="1">
<div class="form-group vis-editor-agg-form-value">
{{vis.params.heatBlur}}
</div>
Expand All @@ -59,16 +68,14 @@
&nbsp;<kbn-info placement="right" info="Map zoom at which all dots are displayed at full intensity. Default: 16"></kbn-info>
</label>
<div class="vis-editor-agg-form-row">
<input
name="heatMaxZoom"
<input name="heatMaxZoom"
ng-model="vis.params.heatMaxZoom"
required
class="form-control"
type="range"
min="1"
max="18"
step="1"
>
step="1">
<div class="vis-editor-agg-form-value">
{{vis.params.heatMaxZoom}}
</div>
Expand All @@ -80,16 +87,14 @@
&nbsp;<kbn-info placement="right" info="Minimum opacity of dots. Default: 0.1"></kbn-info>
</label>
<div class="vis-editor-agg-form-row">
<input
name="heatMinOpacity"
<input name="heatMinOpacity"
ng-model="vis.params.heatMinOpacity"
required
class="form-control"
type="range"
min="0"
max="1.0"
step="0.01"
>
step="0.01">
<div class="vis-editor-agg-form-value">
{{vis.params.heatMinOpacity}}
</div>
Expand Down Expand Up @@ -131,9 +136,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 +147,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 +156,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 +166,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 +175,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,10 +193,8 @@
</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>


</div>
7 changes: 6 additions & 1 deletion src/plugins/kbn_vislib_vis_types/public/tile_map.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
101 changes: 63 additions & 38 deletions src/ui/public/vislib/__tests__/visualizations/tile_maps/markers.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var bounds = {};
let MarkerType;
let map;

angular.module('MarkerFactory', ['kibana']);

function setBounds(southWest, northEast) {
bounds.southWest = L.latLng(southWest || defaultSWCoords);
bounds.northEast = L.latLng(northEast || defaultNECoords);
Expand Down Expand Up @@ -66,7 +64,7 @@ describe('Marker Tests', function () {
describe('Base Methods', function () {
let MarkerClass;

beforeEach(ngMock.module('MarkerFactory'));
beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (Private) {
MarkerClass = Private(VislibVisualizationsMarkerTypesBaseMarkerProvider);
markerLayer = createMarker(MarkerClass);
Expand Down Expand Up @@ -200,9 +198,11 @@ describe('Marker Tests', function () {
});

describe('Shaded Circles', function () {
beforeEach(ngMock.module('MarkerFactory'));
var MarkerClass;

beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (Private) {
var MarkerClass = Private(VislibVisualizationsMarkerTypesShadedCirclesProvider);
MarkerClass = Private(VislibVisualizationsMarkerTypesShadedCirclesProvider);
markerLayer = createMarker(MarkerClass);
}));

Expand All @@ -219,12 +219,13 @@ describe('Marker Tests', function () {

describe('Scaled Circles', function () {
let zoom;
let MarkerClass;

beforeEach(ngMock.module('MarkerFactory'));
beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (Private) {
zoom = _.random(1, 18);
sinon.stub(mockMap, 'getZoom', _.constant(zoom));
var MarkerClass = Private(VislibVisualizationsMarkerTypesScaledCirclesProvider);
MarkerClass = Private(VislibVisualizationsMarkerTypesScaledCirclesProvider);
markerLayer = createMarker(MarkerClass);
}));

Expand Down Expand Up @@ -267,47 +268,71 @@ describe('Marker Tests', function () {
});

describe('Heatmaps', function () {
beforeEach(ngMock.module('MarkerFactory'));
var MarkerClass;

beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (Private) {
var MarkerClass = Private(VislibVisualizationsMarkerTypesHeatmapProvider);
MarkerClass = Private(VislibVisualizationsMarkerTypesHeatmapProvider);
markerLayer = createMarker(MarkerClass);
}));

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

beforeEach(function () {
max = mapData.properties.allmax;
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];
var intensityScale;

scaleTypes.forEach(function (scale) {
var min = Math.min.apply(null, features);
var max = Math.max.apply(null, features);

if (scale !== 'log') {
it('should return the min and max value of the dataset for each scale type', function () {
intensityScale = markerLayer._getDomain(features, scale, callback);
expect(_.first(intensityScale)).to.be.eql(min);
expect(_.last(intensityScale)).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 () {
intensityScale = markerLayer._getDomain(features, scale, callback);
expect(_.first(intensityScale)).to.be.within(1e-9, Infinity);
});

it('should default the max value to 1 for log scales when the max value is less than 1', function () {
intensityScale = markerLayer._getDomain(features, scale, callback);
expect(_.last(intensityScale)).to.be.within(1, Infinity);
});
}
});
});

it('should return an array or values for each feature', function () {
var arr = markerLayer._dataToHeatArray(max);
expect(arr).to.be.an('array');
expect(arr).to.have.length(mapData.features.length);

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

scaleTypes.forEach(function (scaleType) {
it('should return a function', function () {
intensityScale = markerLayer._heatmapScale(features, scaleType, callback);
expect(intensityScale).to.be.a('function');
});

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 a value between 0 and 1', function () {
intensityScale = markerLayer._heatmapScale(features, scaleType, callback);
expect(intensityScale(features[index])).to.be.within(0, 1);
});
});
});

it('should return an array item with lat, lng, normalized metric 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 = feature.properties.value / max;
var featureArr = feature.geometry.coordinates.slice(0).concat(featureValue);
expect(arr[index]).to.eql(featureArr);
describe('dataToHeatArray', function () {
it('should return an array or values for each feature', function () {
var arrs = markerLayer._dataToHeatArray();
expect(arrs).to.be.an('array');
expect(arrs).to.have.length(mapData.features.length);
arrs.forEach(function (arr) {
expect(arr).to.have.length(3); // [lat, lon, heatIntensity]
});
});
});
Expand Down
Loading