UNPKG

@quartic/bokehjs

Version:

Interactive, novel data visualization

335 lines (334 loc) 13.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var extend1 = function (child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty, indexOf = [].indexOf || function (item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; var renderer_1 = require("./renderer"); var remote_data_source_1 = require("../sources/remote_data_source"); var logging_1 = require("core/logging"); var p = require("core/properties"); var array_1 = require("core/util/array"); var object_1 = require("core/util/object"); exports.GlyphRendererView = (function (superClass) { extend1(GlyphRendererView, superClass); function GlyphRendererView() { return GlyphRendererView.__super__.constructor.apply(this, arguments); } GlyphRendererView.prototype.initialize = function (options) { var base_glyph, decimated_glyph, glyph_attrs, has_fill, has_line, hover_glyph, mk_glyph, muted_glyph, nonselection_glyph, selection_glyph; GlyphRendererView.__super__.initialize.call(this, options); base_glyph = this.model.glyph; has_fill = indexOf.call(base_glyph.mixins, "fill") >= 0; has_line = indexOf.call(base_glyph.mixins, "line") >= 0; glyph_attrs = object_1.clone(base_glyph.attributes); delete glyph_attrs.id; mk_glyph = function (defaults) { var attrs; attrs = object_1.clone(glyph_attrs); if (has_fill) { object_1.extend(attrs, defaults.fill); } if (has_line) { object_1.extend(attrs, defaults.line); } return new base_glyph.constructor(attrs); }; this.glyph = this.build_glyph_view(base_glyph); selection_glyph = this.model.selection_glyph; if (selection_glyph == null) { selection_glyph = mk_glyph({ fill: {}, line: {} }); } else if (selection_glyph === "auto") { selection_glyph = mk_glyph(this.model.selection_defaults); } this.selection_glyph = this.build_glyph_view(selection_glyph); nonselection_glyph = this.model.nonselection_glyph; if (nonselection_glyph == null) { nonselection_glyph = mk_glyph({ fill: {}, line: {} }); } else if (nonselection_glyph === "auto") { nonselection_glyph = mk_glyph(this.model.nonselection_defaults); } this.nonselection_glyph = this.build_glyph_view(nonselection_glyph); hover_glyph = this.model.hover_glyph; if (hover_glyph != null) { this.hover_glyph = this.build_glyph_view(hover_glyph); } muted_glyph = this.model.muted_glyph; if (muted_glyph != null) { this.muted_glyph = this.build_glyph_view(muted_glyph); } decimated_glyph = mk_glyph(this.model.decimated_defaults); this.decimated_glyph = this.build_glyph_view(decimated_glyph); this.xmapper = this.plot_view.frame.x_mappers[this.model.x_range_name]; this.ymapper = this.plot_view.frame.y_mappers[this.model.y_range_name]; this.set_data(false); if (this.model.data_source instanceof remote_data_source_1.RemoteDataSource) { return this.model.data_source.setup(this.plot_view, this.glyph); } }; GlyphRendererView.prototype.build_glyph_view = function (model) { return new model.default_view({ model: model, renderer: this, plot_view: this.plot_view }); }; GlyphRendererView.prototype.bind_bokeh_events = function () { this.listenTo(this.model, 'change', this.request_render); this.listenTo(this.model.data_source, 'change', this.set_data); this.listenTo(this.model.data_source, 'patch', this.set_data); this.listenTo(this.model.data_source, 'stream', this.set_data); this.listenTo(this.model.data_source, 'select', this.request_render); if (this.hover_glyph != null) { this.listenTo(this.model.data_source, 'inspect', this.request_render); } this.listenTo(this.model.glyph, 'transformchange', function () { return this.set_data(); }); return this.listenTo(this.model.glyph, 'propchange', function () { this.glyph.set_visuals(this.model.data_source); return this.request_render(); }); }; GlyphRendererView.prototype.have_selection_glyphs = function () { return (this.selection_glyph != null) && (this.nonselection_glyph != null); }; GlyphRendererView.prototype.set_data = function (request_render, arg) { var dt, i, j, k, length, lod_factor, ref, results, source, t0; if (request_render == null) { request_render = true; } t0 = Date.now(); source = this.model.data_source; this.glyph.model.setv({ x_range_name: this.model.x_range_name, y_range_name: this.model.y_range_name }, { silent: true }); this.glyph.set_data(source, arg); this.glyph.set_visuals(source); this.decimated_glyph.set_visuals(source); if (this.have_selection_glyphs()) { this.selection_glyph.set_visuals(source); this.nonselection_glyph.set_visuals(source); } if (this.hover_glyph != null) { this.hover_glyph.set_visuals(source); } if (this.muted_glyph != null) { this.muted_glyph.set_visuals(source); } length = source.get_length(); if (length == null) { length = 1; } this.all_indices = (function () { results = []; for (var j = 0; 0 <= length ? j < length : j > length; 0 <= length ? j++ : j--) { results.push(j); } return results; }).apply(this); lod_factor = this.plot_model.plot.lod_factor; this.decimated = []; for (i = k = 0, ref = Math.floor(this.all_indices.length / lod_factor); 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) { this.decimated.push(this.all_indices[i * lod_factor]); } dt = Date.now() - t0; logging_1.logger.debug(this.glyph.model.type + " GlyphRenderer (" + this.model.id + "): set_data finished in " + dt + "ms"); this.set_data_timestamp = Date.now(); if (request_render) { return this.request_render(); } }; GlyphRendererView.prototype.render = function () { var ctx, dtmap, dtmask, dtrender, dtselect, dttot, glsupport, glyph, i, indices, inspected, j, k, len, len1, lod_threshold, nonselected, nonselection_glyph, selected, selected_mask, selection_glyph, t0, tmap, tmask, trender, tselect; if (!this.model.visible) { return; } t0 = Date.now(); glsupport = this.glyph.glglyph; tmap = Date.now(); this.glyph.map_data(); dtmap = Date.now() - t0; tmask = Date.now(); indices = this.glyph.mask_data(this.all_indices); dtmask = Date.now() - tmask; ctx = this.plot_view.canvas_view.ctx; ctx.save(); selected = this.model.data_source.selected; if (!selected || selected.length === 0) { selected = []; } else { if (selected['0d'].glyph) { selected = indices; } else if (selected['1d'].indices.length > 0) { selected = selected['1d'].indices; } else { selected = []; } } inspected = this.model.data_source.inspected; if (!inspected || inspected.length === 0) { inspected = []; } else { if (inspected['0d'].glyph) { inspected = indices; } else if (inspected['1d'].indices.length > 0) { inspected = inspected['1d'].indices; } else { inspected = []; } } lod_threshold = this.plot_model.plot.lod_threshold; if (this.plot_view.interactive && !glsupport && (lod_threshold != null) && this.all_indices.length > lod_threshold) { indices = this.decimated; glyph = this.decimated_glyph; nonselection_glyph = this.decimated_glyph; selection_glyph = this.selection_glyph; } else { glyph = this.model.muted && (this.muted_glyph != null) ? this.muted_glyph : this.glyph; nonselection_glyph = this.nonselection_glyph; selection_glyph = this.selection_glyph; } if ((this.hover_glyph != null) && inspected.length) { indices = array_1.difference(indices, inspected); } if (!(selected.length && this.have_selection_glyphs())) { trender = Date.now(); glyph.render(ctx, indices, this.glyph); if (this.hover_glyph && inspected.length) { this.hover_glyph.render(ctx, inspected, this.glyph); } dtrender = Date.now() - trender; } else { tselect = Date.now(); selected_mask = {}; for (j = 0, len = selected.length; j < len; j++) { i = selected[j]; selected_mask[i] = true; } selected = new Array(); nonselected = new Array(); for (k = 0, len1 = indices.length; k < len1; k++) { i = indices[k]; if (selected_mask[i] != null) { selected.push(i); } else { nonselected.push(i); } } dtselect = Date.now() - tselect; trender = Date.now(); nonselection_glyph.render(ctx, nonselected, this.glyph); selection_glyph.render(ctx, selected, this.glyph); if (this.hover_glyph != null) { this.hover_glyph.render(ctx, inspected, this.glyph); } dtrender = Date.now() - trender; } this.last_dtrender = dtrender; dttot = Date.now() - t0; logging_1.logger.debug(this.glyph.model.type + " GlyphRenderer (" + this.model.id + "): render finished in " + dttot + "ms"); logging_1.logger.trace(" - map_data finished in : " + dtmap + "ms"); if (dtmask != null) { logging_1.logger.trace(" - mask_data finished in : " + dtmask + "ms"); } if (dtselect != null) { logging_1.logger.trace(" - selection mask finished in : " + dtselect + "ms"); } logging_1.logger.trace(" - glyph renders finished in : " + dtrender + "ms"); return ctx.restore(); }; GlyphRendererView.prototype.map_to_screen = function (x, y) { return this.plot_view.map_to_screen(x, y, this.model.x_range_name, this.model.y_range_name); }; GlyphRendererView.prototype.draw_legend = function (ctx, x0, x1, y0, y1, field, label) { var index; index = this.model.get_reference_point(field, label); return this.glyph.draw_legend_for_index(ctx, x0, x1, y0, y1, index); }; GlyphRendererView.prototype.hit_test = function (geometry) { return this.glyph.hit_test(geometry); }; return GlyphRendererView; })(renderer_1.RendererView); exports.GlyphRenderer = (function (superClass) { extend1(GlyphRenderer, superClass); function GlyphRenderer() { return GlyphRenderer.__super__.constructor.apply(this, arguments); } GlyphRenderer.prototype.default_view = exports.GlyphRendererView; GlyphRenderer.prototype.type = 'GlyphRenderer'; GlyphRenderer.prototype.get_reference_point = function (field, value) { var data, i, index; index = 0; if ((field != null) && (this.data_source.get_column != null)) { data = this.data_source.get_column(field); if (data) { i = data.indexOf(value); if (i > 0) { index = i; } } } return index; }; GlyphRenderer.define({ x_range_name: [p.String, 'default'], y_range_name: [p.String, 'default'], data_source: [p.Instance], glyph: [p.Instance], hover_glyph: [p.Instance], nonselection_glyph: [p.Any, 'auto'], selection_glyph: [p.Any, 'auto'], muted_glyph: [p.Instance], muted: [p.Bool, false] }); GlyphRenderer.override({ level: 'glyph' }); GlyphRenderer.prototype.selection_defaults = { fill: {}, line: {} }; GlyphRenderer.prototype.decimated_defaults = { fill: { fill_alpha: 0.3, fill_color: "grey" }, line: { line_alpha: 0.3, line_color: "grey" } }; GlyphRenderer.prototype.nonselection_defaults = { fill: { fill_alpha: 0.2, line_alpha: 0.2 }, line: {} }; return GlyphRenderer; })(renderer_1.Renderer);