histograms with filters

This commit is contained in:
javi 2015-11-18 11:05:04 +01:00
parent b210ba8b22
commit d95f044ffc
3 changed files with 119 additions and 33 deletions

View File

@ -17,6 +17,31 @@ L.Mixin.TileLoader = {
this._removeTiles(); this._removeTiles();
}, },
visibleTiles: function() {
if (!this._map) { return []; }
var j, i, point, tiles = [];
var bounds = this._map.getPixelBounds(),
zoom = this._map.getZoom(),
tileSize = this.options.tileSize;
var nwTilePoint = new L.Point(
Math.floor(bounds.min.x / tileSize),
Math.floor(bounds.min.y / tileSize)),
seTilePoint = new L.Point(
Math.floor(bounds.max.x / tileSize),
Math.floor(bounds.max.y / tileSize)),
tileBounds = new L.Bounds(nwTilePoint, seTilePoint);
for (j = tileBounds.min.y; j <= tileBounds.max.y; j++) {
for (i = tileBounds.min.x; i <= tileBounds.max.x; i++) {
tiles.push({ x: i, y: j, z: zoom });
}
}
return tiles;
},
_updateTiles: function () { _updateTiles: function () {
if (!this._map) { return; } if (!this._map) { return; }

View File

@ -212,24 +212,9 @@ L.TorqueLayer = L.CanvasLayer.extend({
} }
}, },
getHistogramForVisibleRegion: function(varName, callback){ getHistogramForVisibleRegion: function(varName, start, end, bins, callback){
var tiles= [] var tiles = this.visibleTiles();
for(var key in this._tiles){ this.provider.getHistogramForTiles(varName, start, end, bins, tiles, callback);
if (this._tiles[key]) {
tiles.push(this._tiles[key].coord)
}
}
var tilesFilter = this.provider._generateBoundsQuery(tiles);
this.provider.tablesForFilter(tilesFilter, function(tables) {
// select the table with less than 100k records
var table = tables.filter(function(f) {
return f.nrows < 50000;
})
table = table.length ? table[0].table_name: this.options.overview_tables[this.options.overview_tables.length - 1]
this.provider.getHistogramForTiles(varName, tiles, table, callback)
}.bind(this));
}, },
getHistogram:function(variable,callback,noBins){ getHistogram:function(variable,callback,noBins){

View File

@ -439,7 +439,6 @@ var Profiler = require('../profiler');
sql = sql.join(' ') sql = sql.join(' ')
var query = format(sql,{ var query = format(sql,{
x: tile.x, x: tile.x,
y: tile.y, y: tile.y,
@ -618,18 +617,48 @@ var Profiler = require('../profiler');
}).join(" or ") }).join(" or ")
}, },
getHistogramForTiles: function(varName, tiles, table, callback){ getHistogramForTiles: function(varName, start, end, bins, tiles, callback) {
var tilesFilter = this._generateBoundsQuery(tiles);
this.tablesForFilter(tilesFilter, function(tables) {
// select the table with less than 100k records
var table = tables.filter(function(f) {
return f.nrows < 50000;
})
table = table.length ? table[0].table_name: this.options.overview_tables[this.options.overview_tables.length - 1]
this._getHistogramForTiles(varName, start, end, bins, tiles, table, callback)
}.bind(this));
},
_getHistogramForTiles: function(varName, start, end, bins, tiles, table, callback){
var sql = [ var sql = [
'with source as (', 'with source as (',
'select {varName} from {table} where ({bounds}) {filters}', 'select {varName} from {table} {tiles} where {bounds} {filters}',
'),', '),'
]
if (start !== undefined) {
sql = sql.concat([
'width as (', 'width as (',
'select min({varName}) as min,', 'select {start} as min,',
'max({varName}) as max,', '{end} as max,',
'{bins} as buckets',
'),'
])
} else {
start = start === undefined ? 'min(' + varName + ')': start;
end = end === undefined ? 'max(' + varName + ')': end;
bins = bins === undefined ? 100: bins;
sql = sql.concat([
'width as (',
'select {start} as min,',
'{end} as max,',
'{bins} as buckets', '{bins} as buckets',
'from source', 'from source',
'),', '),'
])
}
sql = sql.concat([
'_bw as ( select (max - min)/buckets as bw from width ),', '_bw as ( select (max - min)/buckets as bw from width ),',
'histogram as (', 'histogram as (',
'select width_bucket({varName}, min, max, buckets) as bucket,', 'select width_bucket({varName}, min, max, buckets) as bucket,',
@ -640,16 +669,35 @@ var Profiler = require('../profiler');
'order by bucket', 'order by bucket',
')', ')',
'select bucket*bw as start, (bucket+1)*bw as end, bucket as bin, lower(range) as min, upper(range) as max, freq from histogram, _bw;' 'select bucket*bw as start, (bucket+1)*bw as end, bucket as bin, lower(range) as min, upper(range) as max, freq from histogram, _bw;'
] ]);
var filters = this._generateFiltersSQL(false, [varName]) ? " and "+ this._generateFiltersSQL(false, [varName]) : "" var filters = this._generateFiltersSQL(false, [varName]) ? " and "+ this._generateFiltersSQL(false, [varName]) : ""
var tiles_query = tiles.map(function (t, i) {
return "xyz2range(" + t.x + "," + t.y + "," + t.z + ") q" + i;
}).join(',')
if (tiles_query) {
tiles_query = "," + tiles_query
}
var bounds = tiles.map(function(t, i) {
return format("(quadkey between q{i}.min and q{i}.max)", { i: i })
}).join('or')
if (bounds) {
bounds = '(' + bounds + ')';
}
var query = format(sql.join('\n'), { var query = format(sql.join('\n'), {
varName: varName, varName: varName,
table: table, table: table,
tiles: tiles_query,
filters: filters, filters: filters,
bounds: this._generateBoundsQuery(tiles), bounds: bounds,
bins: 20 bins: bins,
start: start,
end: end
}); });
var self = this; var self = this;
@ -663,6 +711,34 @@ var Profiler = require('../profiler');
}); });
}, },
getCatHistogramForTiles: function(varName, tiles, table, callback){
var sql = [
'select {varName}, count(1) from {table} where ({bounds}) {filters} group by 1 order by 2 desc limit {num_cats}',
]
var filters = this._generateFiltersSQL(false, [varName]) ? " and "+ this._generateFiltersSQL(false, [varName]) : ""
var query = format(sql.join('\n'), {
varName: varName,
table: table,
filters: filters,
bounds: this._generateBoundsQuery(tiles),
num_cats: 20
});
var self = this;
this.sql(query, function (data) {
if (data) {
var rows = JSON.parse(data.responseText).rows;
callback(rows);
} else {
callback(null);
}
});
},
tablesForFilter: function(filter, callback) { tablesForFilter: function(filter, callback) {
var filters = this._generateFiltersSQL() var filters = this._generateFiltersSQL()
if (filters) { if (filters) {