@bokeh/bokehjs
Version:
Interactive, novel data visualization
146 lines • 5.3 kB
JavaScript
import { Model } from "../../model";
import { View } from "../../core/view";
import { Indices } from "../../core/types";
import { Filter } from "../filters/filter";
import { AllIndices } from "../filters/all_indices";
import { IntersectionFilter } from "../filters/intersection_filter";
export class CDSViewView extends View {
static __name__ = "CDSViewView";
initialize() {
super.initialize();
this.compute_indices();
}
connect_signals() {
super.connect_signals();
const compute_indices = () => {
this.compute_indices();
};
const connect_filter = (filter) => {
this.connect(filter.change, compute_indices);
};
const disconnect_filter = (filter) => {
this.disconnect(filter.change, compute_indices);
};
let { filter } = this.model;
connect_filter(filter);
this.on_change(this.model.properties.filter, () => {
disconnect_filter(filter);
filter = this.model.filter;
connect_filter(filter);
compute_indices();
});
const connect_data_source = (data_source) => {
this.connect(data_source.change, compute_indices);
this.connect(data_source.streaming, compute_indices);
this.connect(data_source.patching, compute_indices);
this.connect(data_source.properties.data.change, compute_indices);
};
const disconnect_data_source = (data_source) => {
this.disconnect(data_source.change, compute_indices);
this.disconnect(data_source.streaming, compute_indices);
this.disconnect(data_source.patching, compute_indices);
this.disconnect(data_source.properties.data.change, compute_indices);
};
let data_source = this.parent.data_source.get_value();
connect_data_source(data_source);
this.on_change(this.parent.data_source, () => {
disconnect_data_source(data_source);
data_source = this.parent.data_source.get_value();
connect_data_source(data_source);
compute_indices();
});
}
compute_indices() {
// XXX: if the data source is empty, there still may be one
// index originating from glyph's scalar values.
const source = this.parent.data_source.get_value();
const size = source.get_length() ?? 1;
const indices = Indices.all_set(size);
const filtered = this.model.filter.compute_indices(source);
indices.intersect(filtered);
this.model.indices = indices;
this.model._indices_map_to_subset();
}
}
export class CDSView extends Model {
static __name__ = "CDSView";
constructor(attrs) {
super(attrs);
}
static {
this.prototype.default_view = CDSViewView;
this.define(({ Ref }) => ({
filter: [Ref(Filter), () => new AllIndices()],
}));
this.internal(({ Ref, Int, Arrayable, Nullable }) => ({
indices: [Ref(Indices)],
indices_map: [Arrayable(Int), []],
masked: [Nullable(Ref(Indices)), null],
}));
}
_indices;
_indices_map_to_subset() {
this._indices = this.indices.ones();
const { _indices } = this;
// _indices are sorted thus we can use the last value
const n_map = _indices.length > 0 ? _indices.at(-1) + 1 : 0;
const indices_map = new Array(n_map).fill(-1);
const n = _indices.length;
for (let i = 0; i < n; i++) {
indices_map[_indices[i]] = i;
}
this.indices_map = indices_map;
}
get_subset_index(index) {
const subset_index = this.indices_map[index];
return subset_index !== undefined && subset_index != -1 ? subset_index : undefined;
}
has_subset_index(index) {
return this.get_subset_index(index) !== undefined;
}
convert_selection_from_subset(selection_subset) {
return selection_subset.map((i) => this._indices[i]);
}
convert_selection_to_subset(selection_full) {
return selection_full.map((i) => this.get_subset_index(i)); // XXX ?? NaN
}
convert_indices_from_subset(indices) {
return indices.map((i) => this._indices[i]);
}
get_reference_point(array, value) {
const { _indices } = this;
const n = _indices.length;
for (let i = 0; i < n; i++) {
if (array[_indices[i]] == value) {
return this.get_subset_index(_indices[i]);
}
}
return null;
}
/** @deprecated */
get filters() {
const { filter } = this;
if (filter instanceof IntersectionFilter) {
return filter.operands;
}
else if (filter instanceof AllIndices) {
return [];
}
else {
return [filter];
}
}
/** @deprecated */
set filters(filters) {
if (filters.length == 0) {
this.filter = new AllIndices();
}
else if (filters.length == 1) {
this.filter = filters[0];
}
else {
this.filter = new IntersectionFilter({ operands: filters });
}
}
}
//# sourceMappingURL=cds_view.js.map