Merge branch 'bi_provider' of github.com:CartoDB/torque into bi_provider

This commit is contained in:
Stuart Lynn 2015-11-06 17:10:25 +00:00
commit 8ce2a629f1
3 changed files with 96 additions and 186 deletions

View File

@ -111,36 +111,42 @@ L.TorqueLayer = L.CanvasLayer.extend({
},
setFilters:function(){
setFilters: function() {
this.provider.setFilters(this._filters);
this._reloadTiles();
return this;
},
filterByRange:function(variableName,start,end){
this._filters[variableName] = {type: 'range', range: {start:start,end:end}}
filterByRange: function(variableName, start, end) {
this._filters[variableName] = {type: 'range', range: {start: start, end: end} }
this._filtersChanged()
this.fire('dataUpdate')
return this
},
filterByCat:function(variableName,categories){
filterByCat: function(variableName, categories) {
this._filters[variableName] = {type: 'cat', categories: categories}
this._filtersChanged()
return this
},
clearFilter: function(name){
if(name){
if(name) {
delete this._filters[name]
}
else{
else {
this._filters = {}
}
this._filtersChanged()
return this
},
_filtersChanged:function(){
this.provider._filters = this._filters;
this._clearTileCaches()
this._render()
},
_clearTileCaches: function() {
var t, tile;
for(t in this._tiles) {
@ -150,6 +156,7 @@ L.TorqueLayer = L.CanvasLayer.extend({
}
}
},
_clearCaches: function() {
this.renderer && this.renderer.clearSpriteCache();
this._clearTileCaches();
@ -335,6 +342,7 @@ L.TorqueLayer = L.CanvasLayer.extend({
canvas.width = canvas.width;
},
/*
_filterTile:function(tile){
var noPoints = tile.x.length
@ -366,6 +374,7 @@ L.TorqueLayer = L.CanvasLayer.extend({
}
return renderFlags
},
*/
/**
* render the selectef key
@ -396,7 +405,7 @@ L.TorqueLayer = L.CanvasLayer.extend({
this.renderer._ctx.drawImage(tile._tileCache, 0, 0);
} else {
tile.renderFlags=this._filterTile(tile)
//tile.renderFlags = this._filterTile(tile)
this.renderer.renderTile(tile, this.key);
}
}

View File

@ -86,8 +86,8 @@ var Profiler = require('../profiler');
var prof_point_count = Profiler.metric('ProviderJSON:point_count');
var prof_process_time = Profiler.metric('ProviderJSON:process_time').start()
// count number of dates
var dates = 0;
// count number of steps
var steps = 0;
var maxDateSlots = -1;
for (r = 0; r < rows.length; ++r) {
var row = rows[r];
@ -97,10 +97,15 @@ var Profiler = require('../profiler');
}
}
if(this.options.cumulative) {
steps = (1 + maxDateSlots) * rows.length;
}
// var type = Uint8Array;
// reserve memory for all the dates
// var timeIndex = new Int32Array(maxDateSlots + 1); //index-size
// var timeCount = new Int32Array(maxDateSlots + 1);
@ -110,8 +115,8 @@ var Profiler = require('../profiler');
prof_mem.inc(
4 * maxDateSlots + // timeIndex
4 * maxDateSlots + // timeCount
dates + //renderData
dates * 4
steps + //renderData
steps * 4
); //renderDataPos
prof_point_count.inc(rows.length);
@ -134,6 +139,40 @@ var Profiler = require('../profiler');
renderData[r*row.steps.length + i] = row.vals[i]
}
/*var lastDateSlot = dates[dates.length - 1];
y[r] = row.y * this.options.resolution;
}
var steps = row.steps;
var vals = row.vals;
if (!this.options.cumulative) {
for (var j = 0, len = steps.length; j < len; ++j) {
var rr = rowsPerSlot[steps[j]] || (rowsPerSlot[steps[j]] = []);
if(this.options.cumulative) {
vals[j] += prev_val;
}
prev_val = vals[j];
rr.push([r, vals[j]]);
}
} else {
var valByDate = {}
for (var j = 0, len = steps.length; j < len; ++j) {
valByDate[steps[j]] = vals[j];
}
var accum = 0;
// extend the latest to the end
for (var j = steps[0]; j <= maxDateSlots; ++j) {
var rr = rowsPerSlot[j] || (rowsPerSlot[j] = []);
var v = valByDate[j];
if (v) {
accum += v;
}
rr.push([r, accum]);
}
/*var lastDateSlot = steps[steps.length - 1];
>>>>>>> 4ad0dba547e2a57300064c484d42e196eb846356
for (var j = lastDateSlot + 1; j <= maxDateSlots; ++j) {
var rr = rowsPerSlot[j] || (rowsPerSlot[j] = []);
rr.push([r, prev_val]);
@ -163,33 +202,42 @@ var Profiler = require('../profiler');
// maxDate: maxDateSlots
};
},
_generateFilterSQLForCat:function(name,categories){
return name+" in "+categories;
},
_generateFilterSQLForRange:function(name,range){
var result = ""
if(range.start){
if (range.start) {
result += " " + name + " > " + range.start;
}
if(range.end){
if (range.end) {
if (range.start) {
result += " and "
}
result += " " + name + " < " + range.end;
}
return result
},
_setFilters:function(filters){
this.filters = filters
},
_generateFiltersSQL:function(){
_generateFiltersSQL: function() {
var self = this;
return Object.keys(this._filters).map(function(filterName){
var filter = this._filters[filterName]
if(filter){
if(filter.type == 'range'){
return this._generateFilterSQLForRange(filterName, filter.range)
var filter = self._filters[filterName]
if (filter) {
if (filter.type == 'range') {
return self._generateFilterSQLForRange(filterName, filter.range)
}
else if(filter.type == 'cat'){
return this._generateFilterSQLForCat(filterName, filter.categories)
else if (filter.type == 'cat') {
return self._generateFilterSQLForCat(filterName, filter.categories)
}
else{
else {
return ""
}
}
@ -198,6 +246,7 @@ var Profiler = require('../profiler');
}
}).join(" and ")
},
_host: function() {
var opts = this.options;
var port = opts.sql_api_port;
@ -307,10 +356,10 @@ var Profiler = require('../profiler');
var numTiles = 1 << zoom;
var column_conv = this.options.column;
if(this.options.is_time) {
column_conv = format("date_part('epoch', {column})", this.options);
}
//
// if(this.options.is_time) {
// column_conv = format("date_part('epoch', {column})", this.options);
// }
// var sql = "" +
// "WITH " +
@ -337,12 +386,15 @@ var Profiler = require('../profiler');
this.options.filters = this._generateFiltersSQL()
var sql = ""+
"SELECT * FROM torque_tile(x:={x}, y:={y}, z:={zoom}, aggr:=ARRAY['{columns}'], table_name:='{table}', where_clause:='{filters}');"
var query = format(sql, this.options, {
zoom: zoom,
x: coord.x,
y: coord.y,
column_conv: column_conv,
_sql: this.getSQL()
column: column_conv,
table: this.options.table,
filters: this._generateFiltersSQL()
});
@ -380,31 +432,6 @@ var Profiler = require('../profiler');
this.options.resolution = res;
},
idForRange: function(variable){
return this._mapping[variable].col_id
},
idsForCategory:function(variable){
return this._mapping[variable].col_ids
},
idForCategoryOption:function(variable, option){
return this._mapping[variable].col_ids.to_a.select(function(a){return option==a[0]})[0][1]
},
optionForId:function(id){
Object.keys(this._mapping).forEach(function(varaibleName){
var variable = this._mapping[variableName]
if(variable.type=='range' && variable.col_id==id){
return variableName
}
else if(variable.type=='cat') {
Object.keys(variable.col_ids).forEach(function(key){
if(variable.col_ids[key] == id){
}
}.bind(this))
}
}.bind(this))
return null;
},
// return true if tiles has been changed
setOptions: function(opt) {
var refresh = false;
@ -485,134 +512,8 @@ var Profiler = require('../profiler');
((opts.tiler_port != "") ? (":" + opts.tiler_port) : "");
},
_fetchUpdateAt: function(callback) {
var self = this;
var layergroup = {
"version": "1.0.1",
"stat_tag": this.options.stat_tag || 'torque',
"layers": [{
"type": "cartodb",
"options": {
"cartocss_version": "2.1.1",
"cartocss": "#layer {}",
"sql": this.getSQL()
}
}]
};
var url = this._tilerHost() + "/tiles/layergroup";
var extra = this._extraParams();
// tiler needs map_key instead of api_key
// so replace it
if (extra) {
extra = extra.replace('api_key=', 'map_key=');
}
url = url +
"?config=" + encodeURIComponent(JSON.stringify(layergroup)) +
"&callback=?" + (extra ? "&" + extra: '');
torque.net.jsonp(url, function (data) {
var query = format("select * from ({sql}) __torque_wrap_sql limit 0", { sql: self.getSQL() });
self.sql(query, function (queryData) {
if (data && queryData) {
callback({
updated_at: data.last_updated,
fields: queryData.fields
});
}
}, { parseJSON: true });
});
},
//
// the data range could be set by the user though ``start``
// option. It can be fecthed from the table when the start
// is not specified.
//
_fetchKeySpan: function() {
var self = this;
var max_col, min_col, max_tmpl, min_tmpl;
this._fetchUpdateAt(function(data) {
if (!data) return;
self.options.extra_params = self.options.extra_params || {};
self.options.extra_params.last_updated = data.updated_at || 0;
self.options.extra_params.cache_policy = 'persist';
self.options.is_time = data.fields[self.options.column].type === 'date';
var column_conv = self.options.column;
if (self.options.is_time){
max_tmpl = "date_part('epoch', max({column}))";
min_tmpl = "date_part('epoch', min({column}))";
column_conv = format("date_part('epoch', {column})", self.options);
} else {
max_tmpl = "max({column})";
min_tmpl = "min({column})";
}
max_col = format(max_tmpl, { column: self.options.column });
min_col = format(min_tmpl, { column: self.options.column });
/*var sql_stats = "" +
"WITH summary_groups as ( " +
"WITH summary as ( " +
"select (row_number() over (order by __time_col asc nulls last)+1)/2 as rownum, __time_col " +
"from (select *, {column} as __time_col from ({sql}) __s) __torque_wrap_sql " +
"order by __time_col asc " +
") " +
"SELECT " +
"max(__time_col) OVER(PARTITION BY rownum) - " +
"min(__time_col) OVER(PARTITION BY rownum) diff " +
"FROM summary " +
"), subq as ( " +
" SELECT " +
"st_xmax(st_envelope(st_collect(the_geom))) xmax, " +
"st_ymax(st_envelope(st_collect(the_geom))) ymax, " +
"st_xmin(st_envelope(st_collect(the_geom))) xmin, " +
"st_ymin(st_envelope(st_collect(the_geom))) ymin, " +
"{max_col} max, " +
"{min_col} min FROM ({sql}) __torque_wrap_sql " +
")" +
"SELECT " +
"xmax, xmin, ymax, ymin, a.max as max_date, a.min as min_date, " +
"avg(diff) as diffavg," +
"(a.max - a.min)/avg(diff) as num_steps " +
"FROM summary_groups, subq a " +
"WHERE diff > 0 group by xmax, xmin, ymax, ymin, max_date, min_date";
*/
var sql_stats = " SELECT " +
"st_xmax(st_envelope(st_collect(the_geom))) xmax, " +
"st_ymax(st_envelope(st_collect(the_geom))) ymax, " +
"st_xmin(st_envelope(st_collect(the_geom))) xmin, " +
"st_ymin(st_envelope(st_collect(the_geom))) ymin, " +
"count(*) as num_steps, " +
"{max_col} max_date, " +
"{min_col} min_date FROM ({sql}) __torque_wrap_sql ";
var sql = format(sql_stats, {
max_col: max_col,
min_col: min_col,
column: column_conv,
sql: self.getSQL()
});
self.sql(sql, function(data) {
//TODO: manage bounds
data = data.rows[0];
self.options.start = data.min_date;
self.options.end = data.max_date;
self.options.step = (data.max_date - data.min_date)/Math.min(self.options.steps, data.num_steps>>0);
self.options.data_steps = data.num_steps >> 0;
// step can't be 0
self.options.step = self.options.step || 1;
self.options.bounds = [
[data.ymin, data.xmin],
[data.ymax, data.xmax]
];
self._setReady(true);
}, { parseJSON: true, no_cdn: true });
}, { parseJSON: true, no_cdn: true})
this._setReady(true);
}
};

View File

@ -261,19 +261,19 @@ var Filters = require('./torque_filters');
for(var p = 0; p < activePixels; ++p) {
if(tile.renderFlags[p]){
var posIdx = p// tile.renderDataPos[pixelIndex + p];
var posIdx = tile.renderDataPos[pixelIndex + p];
var c = tile.renderData[pixelIndex + p];
if (c) {
var sp = sprites[c];
if (sp === undefined) {
var sp = sprites[c];
if (sp === undefined) {
sp = sprites[c] = this.generateSprite(shader, c, torque.extend({ zoom: tile.z, 'frame-offset': frame_offset }, shaderVars));
}
if (sp) {
}
if (sp) {
var x = tile.x[posIdx]- (sp.width >> 1) + anchor;
var y = tileMax - tile.y[posIdx] + anchor; // flip mercator
ctx.drawImage(sp, x, y - (sp.height >> 1));
}
}
}
}
}