UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

156 lines 5.29 kB
import { logger } from "../../core/logging"; import { SelectionManager } from "../../core/selection_manager"; import { Signal, Signal0 } from "../../core/signaling"; import { assert } from "../../core/util/assert"; import { uniq } from "../../core/util/array"; import { is_NDArray } from "../../core/util/ndarray"; import { keys, values, entries, dict, clone } from "../../core/util/object"; import { isBoolean, isNumber, isString, isArray } from "../../core/util/types"; import { SelectionPolicy, UnionRenderers } from "../selections/interaction_policy"; import { Selection } from "../selections/selection"; import { DataSource } from "./data_source"; export class ColumnarDataSource extends DataSource { static __name__ = "ColumnarDataSource"; get_array(key) { const data = dict(this.data); let column = data.get(key); if (column == null) { data.set(key, column = []); } else if (!isArray(column)) { data.set(key, column = Array.from(column)); } return column; } _select; inspect; selection_manager = new SelectionManager(this); constructor(attrs) { super(attrs); } static { this.define(({ Ref, Dict, Unknown }) => ({ default_values: [Dict(Unknown), {}], selection_policy: [Ref(SelectionPolicy), () => new UnionRenderers()], })); this.internal(({ AnyRef }) => ({ inspected: [AnyRef(), () => new Selection()], })); } initialize() { super.initialize(); this._select = new Signal0(this, "select"); this.inspect = new Signal(this, "inspect"); } get inferred_defaults() { const defaults = new Map(); for (const [name, array] of entries(this.data)) { const value = (() => { if (is_NDArray(array)) { switch (array.dtype) { case "bool": return false; case "uint8": case "int8": case "uint16": case "int16": case "uint32": case "int32": case "float32": case "float64": return 0; case "object": return null; } } else if (isArray(array) && array.length != 0) { const [item] = array; if (item === null) { return null; } else if (isBoolean(item)) { return false; } else if (isNumber(item)) { return 0; } else if (isString(item)) { return ""; } else if (isArray(item)) { return []; } } return undefined; })(); if (value !== undefined) { defaults.set(name, value); } } return defaults; } get(name) { const column = this.get_column(name); assert(column != null, `unknown column '${name}' in ${this}`); return column; } set(name, column) { dict(this.data).set(name, column); } get_column(name) { const data = dict(this.data); return data.get(name) ?? null; } get_row(index) { const i = isNumber(index) ? index : index.index; const result = {}; for (const [column, array] of entries(this.data)) { result[column] = array[i]; } return result; } columns() { // return the column names in this data source return keys(this.data); } get_length(soft = true) { const lengths = uniq(values(this.data).map((v) => is_NDArray(v) ? v.shape[0] : v.length)); switch (lengths.length) { case 0: { return null; // XXX: don't guess, treat on case-by-case basis } case 1: { return lengths[0]; } default: { const msg = "data source has columns of inconsistent lengths"; if (soft) { logger.warn(msg); return lengths.sort()[0]; } else { throw new Error(msg); } } } } get length() { return this.get_length() ?? 0; } clear() { const data = clone(this.data); const proxy = dict(data); for (const [name, column] of proxy) { const empty = new column.constructor(0); proxy.set(name, empty); } this.data = data; } stream(new_data, rollover, { sync } = {}) { this.stream_to(this.properties.data, new_data, rollover, { sync }); } patch(patches, { sync } = {}) { this.patch_to(this.properties.data, patches, { sync }); } } //# sourceMappingURL=columnar_data_source.js.map