Skip to content

Commit

Permalink
Finalize migration to Indices interface
Browse files Browse the repository at this point in the history
  • Loading branch information
mattpap committed Feb 17, 2024
1 parent c14ccbe commit 5ca5d3c
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 29 deletions.
26 changes: 24 additions & 2 deletions bokehjs/src/lib/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,31 @@ export type Interval = {
end: number
}

export type Indices = {
export interface Indices {
[Symbol.iterator](): Iterator<number>
select<T>(array: Arrayable<T>): Arrayable<T>

readonly count: number
readonly size: number

clone(): Indices

get(k: number): boolean
set(k: number, v?: boolean): void
unset(k: number): void

select<T>(array: Arrayable<T>): Arrayable<T>

// in-place ops
invert(): void
add(other: Indices): void
intersect(other: Indices): void
subtract(other: Indices): void
symmetric_subtract(other: Indices): void

// cloning ops
inversion(): Indices
union(other: Indices): Indices
intersection(other: Indices): Indices
difference(other: Indices): Indices
symmetric_difference(other: Indices): Indices
}
4 changes: 2 additions & 2 deletions bokehjs/src/lib/core/util/bitset.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type {Equatable, Comparator} from "./eq"
import {equals} from "./eq"
import type {Arrayable, ArrayableNew} from "../types"
import type {Arrayable, ArrayableNew, Indices} from "../types"
import {assert, AssertionError} from "./assert"
import {has_refs} from "core/util/refs"

const WORD_LENGTH = 32
const FULL_WORD = 0xffffffff

export class BitSet implements Equatable {
export class BitSet implements Indices, Equatable {
readonly [Symbol.toStringTag] = "BitSet"

static readonly [has_refs] = false
Expand Down
122 changes: 112 additions & 10 deletions bokehjs/src/lib/core/util/indices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,51 @@ export type PackedIndices = BitSet

export class OpaqueIndices implements Indices {

protected readonly _array: number[]
protected readonly _indices: Set<number>

constructor(readonly size: number, init: Iterable<number> | 1 | 0 = 0) {
if (init == 0) {
this._array = []
this._indices = new Set()
} else if (init == 1) {
this._array = range(0, size)
this._indices = new Set(range(0, size))
} else {
this._array = [...init]
this._indices = new Set(init)
}
this.count = this._array.length
this.count = this._indices.size
}

readonly count: number

get array(): number[] { // TODO readonly
return this._array
get array(): number[] {
return [...this._indices]
}

static from_packed(indices: PackedIndices): OpaqueIndices {
static from(indices: Indices): OpaqueIndices {
return new OpaqueIndices(indices.size, indices)
}

*[Symbol.iterator](): Iterator<number> {
yield* this._array
yield* this._indices
}

clone(): OpaqueIndices {
return new OpaqueIndices(this.size, this._indices)
}

get(k: number): boolean {
return this._indices.has(k)
}

set(k: number, v: boolean = true): void {
if (v) {
this._indices.add(k)
} else {
this._indices.delete(k)
}
}

unset(k: number): void {
this.set(k, false)
}

select<T>(array: Arrayable<T>): Arrayable<T> {
Expand All @@ -43,7 +63,7 @@ export class OpaqueIndices implements Indices {
} else {
const result = new (array.constructor as ArrayableNew)<T>(n)
let i = 0
for (const j of this._array) {
for (const j of this._indices) {
result[i++] = array[j]
}
return result
Expand All @@ -55,4 +75,86 @@ export class OpaqueIndices implements Indices {
throw new AssertionError(`Size mismatch (${this.size} != ${other.length})`)
}
}

invert(): void {
const {_indices, size} = this
for (let i = 0; i < size; i++) {
if (!_indices.has(i)) {
this._indices.add(i)
} else {
this._indices.delete(i)
}
}
}

add(other: Indices): void {
const {_indices} = this
for (const i of other) {
_indices.add(i)
}
}

intersect(other: Indices): void {
const {_indices} = this
for (const i of _indices) {
if (!other.get(i)) {
_indices.delete(i)
}
}
}

subtract(other: Indices): void {
const {_indices} = this
for (const i of other) {
_indices.delete(i)
}
}

symmetric_subtract(other: Indices): void {
const {_indices} = this
const set0 = new Set(_indices)
const set1 = other
_indices.clear()

for (const i of set0) {
if (!set1.get(i)) {
_indices.add(i)
}
}
for (const i of set1) {
if (!set0.has(i)) {
_indices.add(i)
}
}
}

inversion(): OpaqueIndices {
const result = this.clone()
result.invert()
return result
}

union(other: Indices): OpaqueIndices {
const result = this.clone()
result.add(other)
return result
}

intersection(other: Indices): OpaqueIndices {
const result = this.clone()
result.intersect(other)
return result
}

difference(other: Indices): OpaqueIndices {
const result = this.clone()
result.subtract(other)
return result
}

symmetric_difference(other: Indices): OpaqueIndices {
const result = this.clone()
result.symmetric_subtract(other)
return result
}
}
4 changes: 2 additions & 2 deletions bokehjs/src/lib/core/util/spatial.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import FlatBush from "flatbush"

import type {Rect, TypedArray} from "../types"
import type {Rect, TypedArray, Indices} from "../types"
import {PackedIndices} from "./indices"
import {empty} from "./bbox"

Expand Down Expand Up @@ -117,7 +117,7 @@ export class SpatialIndex {

indices(rect: Rect): Indices {
if (this.index == null)
return new Indices(0)
return new PackedIndices(0)
else {
const {x0, y0, x1, y1} = this._normalize(rect)
return this.index.search_indices(x0, y0, x1, y1)
Expand Down
4 changes: 2 additions & 2 deletions bokehjs/src/lib/models/annotations/arrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {FloatArray} from "core/types"
import {ScreenArray} from "core/types"
import type {IterViews} from "core/build_views"
import {build_view} from "core/build_views"
import {Indices} from "core/types"
import {PackedIndices} from "core/util/indices"
import * as p from "core/properties"
import {atan2} from "core/util/math"

Expand Down Expand Up @@ -55,7 +55,7 @@ export class ArrowView extends DataAnnotationView {

override set_data(source: ColumnarDataSource): void {
super.set_data(source)
const indices = Indices.all_set(this._x_start.length)
const indices = PackedIndices.all_set(this._x_start.length)
this.start?.set_data(source, indices)
this.end?.set_data(source, indices)
}
Expand Down
4 changes: 2 additions & 2 deletions bokehjs/src/lib/models/annotations/whisker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {UpperLower, UpperLowerView} from "./upper_lower"
import type {ArrowHeadView} from "./arrow_head"
import {ArrowHead, TeeHead} from "./arrow_head"
import type {ColumnarDataSource} from "../sources/columnar_data_source"
import {Indices} from "core/types"
import {PackedIndices} from "core/util/indices"
import type {Context2d} from "core/util/canvas"
import type {IterViews} from "core/build_views"
import {build_view} from "core/build_views"
Expand Down Expand Up @@ -39,7 +39,7 @@ export class WhiskerView extends UpperLowerView {

override set_data(source: ColumnarDataSource): void {
super.set_data(source)
const indices = Indices.all_set(this._lower.length)
const indices = PackedIndices.all_set(this._lower.length)
this.lower_head?.set_data(source, indices)
this.upper_head?.set_data(source, indices)
}
Expand Down
4 changes: 2 additions & 2 deletions bokehjs/src/lib/models/glyphs/glyph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ export abstract class GlyphView extends View {
this._index = index
}

mask_data(): PackedIndices {
mask_data(): Indices {
/** Returns subset indices in the viewport. */
if (this._mask_data == null) {
return PackedIndices.all_set(this.data_size)
Expand All @@ -454,7 +454,7 @@ export abstract class GlyphView extends View {
}
}

protected _mask_data?(): PackedIndices
protected _mask_data?(): Indices

map_data(): void {
const {x_scale, y_scale} = this.renderer.coordinates
Expand Down
3 changes: 2 additions & 1 deletion bokehjs/src/lib/models/glyphs/multi_line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {inplace} from "core/util/projections"
import type {PointGeometry, SpanGeometry} from "core/geometry"
import {LineVector} from "core/property_mixins"
import type * as visuals from "core/visuals"
import type {Rect, RaggedArray, FloatArray} from "core/types"
import type {Rect, FloatArray} from "core/types"
import type {RaggedArray} from "core/util/ragged_array"
import * as hittest from "core/hittest"
import * as p from "core/properties"
import {minmax2} from "core/util/arrayable"
Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/renderers/glyph_renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export class GlyphRendererView extends DataRendererView {
async set_data(indices?: number[]): Promise<void> {
const source = this.model.data_source

this.all_indices = OpaqueIndices.from_packed(this.model.view.indices)
this.all_indices = OpaqueIndices.from(this.model.view.indices)
const {all_indices} = this

await this.glyph.set_data(source, all_indices, indices)
Expand Down
11 changes: 6 additions & 5 deletions bokehjs/src/lib/models/sources/cds_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type * as p from "core/properties"
import type {Selection} from "../selections/selection"
import {View} from "core/view"
import {PackedIndices} from "core/util/indices"
import type {Indices} from "core/types"
import {Filter} from "../filters/filter"
import {AllIndices} from "../filters/all_indices"
import {IntersectionFilter} from "../filters/intersection_filter"
Expand Down Expand Up @@ -91,9 +92,9 @@ export namespace CDSView {
export type Props = Model.Props & {
filter: p.Property<Filter>
// internal
indices: p.Property<PackedIndices>
indices: p.Property<Indices>
indices_map: p.Property<Map<number, number>>
masked: p.Property<PackedIndices | null>
masked: p.Property<Indices | null>
}
}

Expand All @@ -114,10 +115,10 @@ export class CDSView extends Model {
filter: [ Ref(Filter), () => new AllIndices() ],
}))

this.internal<CDSView.Props>(({Int, Mapping, Ref, Nullable}) => ({
indices: [ Ref(PackedIndices) ],
this.internal<CDSView.Props>(({Int, Mapping, AnyRef, Nullable}) => ({
indices: [ AnyRef<Indices>() ],
indices_map: [ Mapping(Int, Int), new Map() ],
masked: [ Nullable(Ref(PackedIndices)), null ],
masked: [ Nullable(AnyRef<Indices>()), null ],
}))
}

Expand Down

0 comments on commit 5ca5d3c

Please sign in to comment.