Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added custom Checkpoint and Restore tools #110

Merged
merged 3 commits into from
Jun 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions earthsim/annotators.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from geoviews.data.geopandas import GeoPandasInterface
from geoviews import Polygons, Points, WMTS, TriMesh

from .custom_tools import CheckpointTool, RestoreTool


def poly_to_geopandas(polys, columns):
"""
Expand All @@ -40,6 +42,19 @@ def poly_to_geopandas(polys, columns):
return gpd.GeoDataFrame(rows, columns=columns+['geometry'])


def initialize_tools(plot, element):
"""
Initializes the Checkpoint and Restore tools.
"""
cds = plot.handles['source']
checkpoint = plot.state.select(type=CheckpointTool)
restore = plot.state.select(type=RestoreTool)
if checkpoint:
checkpoint[0].sources.append(cds)
if restore:
restore[0].sources.append(cds)


class GeoAnnotator(param.Parameterized):
"""
Provides support for drawing polygons and points on top of a map.
Expand Down Expand Up @@ -68,10 +83,12 @@ def __init__(self, polys=None, points=None, crs=None, **params):
polys = [] if polys is None else polys
points = [] if points is None else points
crs = ccrs.GOOGLE_MERCATOR if crs is None else crs
self.polys = self.path_type(polys, crs=crs)
tools = [CheckpointTool(), RestoreTool()]
opts = dict(tools=tools, finalize_hooks=[initialize_tools])
self.polys = self.path_type(polys, crs=crs).options(**opts)
self.poly_stream = PolyDraw(source=self.polys, data={})
self.vertex_stream = PolyEdit(source=self.polys)
self.points = Points(points, self.polys.kdims, crs=crs)
self.points = Points(points, self.polys.kdims, crs=crs).options(**opts)
self.point_stream = PointDraw(source=self.points, data={})

def pprint(self):
Expand Down
29 changes: 29 additions & 0 deletions earthsim/custom_tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import os

from bokeh.core.properties import Instance, List
from bokeh.core.enums import Dimensions
from bokeh.models import Tool, ColumnDataSource

fpath = os.path.dirname(__file__)


class CheckpointTool(Tool):
"""
Checkpoints the data on the supplied ColumnDataSources, allowing
the RestoreTool to restore the data to a previous state.
"""

__implementation__ = os.path.join(fpath, 'custom_tools.ts')

sources = List(Instance(ColumnDataSource))


class RestoreTool(Tool):
"""
Restores the data on the supplied ColumnDataSources to a previous
checkpoint created by the CheckpointTool
"""

__implementation__ = os.path.join(fpath, 'custom_tools.ts')

sources = List(Instance(ColumnDataSource))
102 changes: 102 additions & 0 deletions earthsim/custom_tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import * as p from "core/properties"
import {ActionTool, ActionToolView} from "models/tools/actions/action_tool"
import {ColumnDataSource} from "models/sources/column_data_source"
import {copy} from "core/util/array"

export class CheckpointToolView extends ActionToolView {
model: CheckpointTool

doit(): void {
for (var source of this.model.sources) {
if (source.buffer == undefined) { source.buffer = [] }
let data_copy = {};
for (const key in source.data) {
const column = source.data[key];
if (Array.isArray(column) || (ArrayBuffer.isView(column))) {
const new_column = []
for (const arr of column) {
new_column.push(copy(arr))
}
data_copy[key] = new_column;
} else {
data_copy[key] = copy(column);
}
}
source.buffer.push(data_copy)
}
}
}

export namespace CheckpointTool {
export interface Attrs extends ActionTool.Attrs {}

export interface Props extends ActionTool.Props {}
}

export interface CheckpointTool extends CheckpointTool.Attrs {}

export class CheckpointTool extends ActionTool {
properties: CheckpointTool.Props
sources: ColumnDataSource[]

constructor(attrs?: Partial<CheckpointTool.Attrs>) {
super(attrs)
}

static initClass(): void {
this.prototype.type = "CheckpointTool"
this.prototype.default_view = CheckpointToolView

this.define({
sources: [ p.Array, [] ],
})
}

tool_name = "Checkpoint"
icon = "bk-tool-icon-save"
}
CheckpointTool.initClass()

export class RestoreToolView extends ActionToolView {
model: RestoreTool

doit(): void {
for (var source of this.model.sources) {
if ((source.buffer == undefined) || (source.buffer.length == 0)) { continue; }
source.data = source.buffer.pop();
source.change.emit();
source.properties.data.change.emit();
}
}
}

export namespace RestoreTool {
export interface Attrs extends ActionTool.Attrs {}

export interface Props extends ActionTool.Props {}
}

export interface RestoreTool extends RestoreTool.Attrs {}

export class RestoreTool extends ActionTool {
properties: RestoreTool.Props
sources: ColumnDataSource[]

constructor(attrs?: Partial<RestoreTool.Attrs>) {
super(attrs)
}

static initClass(): void {
this.prototype.type = "RestoreTool"
this.prototype.default_view = RestoreToolView

this.define({
sources: [ p.Array, [] ],
})
}

tool_name = "Restore"
icon = "bk-tool-icon-undo"
}

RestoreTool.initClass()