bokeh_model.coffee | |
---|---|
Setup Bokeh Module | if this.Bokeh
Bokeh = this.Bokeh
else
Bokeh = {}
this.Bokeh = Bokeh
Collections = Continuum.Collections |
MAIN BOKEH CLASSES | |
backbone assumes that valid attrs are any non-null, or non-defined value thats dumb, we only check for undefined, because null is perfectly valid | safebind = Continuum.safebind
HasParent = Continuum.HasParent
BokehView = Continuum.ContinuumView
HasProperties = Continuum.HasProperties
class Bokeh.ViewState extends HasParent |
This Viewstate has height/width/border_space information Primarily used by PlotViews | initialize : (attrs, options)->
super(attrs, options)
@register_property('outerwidth',
() -> @get('width') + 2 * @get('border_space')
, false)
@add_dependencies('outerwidth', this, ['width', 'border_space'])
@register_property('outerheight',
() -> @get('height') + 2 * @get('border_space')
, false)
@add_dependencies('outerheight', this, ['height', 'border_space'])
collections : Collections |
transform our coordinate space to the underlying device (svg) | xpos : (x) ->
return x
ypos : (y) ->
return @get('height') - y |
vectorized versions of xpos/ypos, operates in place | v_xpos : (xx) ->
return xx
v_ypos : (yy) ->
height = @get('height')
for y, idx in yy
yy[idx] = height - y
return yy |
transform underlying device (svg) to our coordinate space | rxpos : (x) ->
return x
rypos : (y) ->
return @get('height') - y |
compute a childs position in the underlying device | position_child_x : (childsize, offset) ->
return @xpos(offset)
position_child_y : (childsize, offset) ->
return @ypos(offset) - childsize
defaults :
parent : null
display_defaults:
width : 200
height : 200
position : 0
offset : [0,0]
border_space : 30
class Bokeh.GridViewState extends Bokeh.ViewState
setup_layout_properties : () =>
@register_property('layout_heights', @layout_heights, true)
@register_property('layout_widths', @layout_widths, true)
for row in @get('childviewstates')
for viewstate in row
@add_dependencies('layout_heights', viewstate, 'outerheight')
@add_dependencies('layout_widths', viewstate, 'outerwidth')
initialize : (attrs, options) ->
super(attrs, options)
@setup_layout_properties()
safebind(this, this, 'change:childviewstates', @setup_layout_properties)
@register_property('height', () ->
return _.reduce(@get('layout_heights'), ((x, y) -> x + y), 0)
, true)
@add_dependencies('height', @, 'layout_heights')
@register_property('width', () ->
return _.reduce(@get('layout_widths'), ((x, y) -> x + y), 0)
, true)
@add_dependencies('width', @, 'layout_widths')
maxdim : (dim, row) ->
if row.length == 0
return 0
else
return _.max(_.map(row, ((x) -> return x.get(dim))))
layout_heights : () =>
row_heights=(@maxdim('outerheight',row) for row in @get('childviewstates'))
return row_heights
layout_widths : () =>
num_cols = @get('childviewstates')[0].length
columns = ((row[n] for row in @get('childviewstates')) for n in _.range(num_cols))
col_widths = (@maxdim('outerwidth', col) for col in columns)
return col_widths
Bokeh.GridViewState::defaults = _.clone(Bokeh.GridViewState::defaults)
_.extend(Bokeh.GridViewState::defaults
,
childviewstates : [[]]
border_space : 0
)
class XYRenderer extends HasParent
XYRenderer::defaults = _.clone(XYRenderer::defaults)
_.extend(XYRenderer::defaults , {
xdata_range : null
ydata_range : null
xfield : null
yfield : null
data_source : null |
axes fit here | }) |
Utility Classes for vis | class Range1d extends HasProperties
type : 'Range1d'
Range1d::defaults = _.clone(Range1d::defaults)
_.extend(Range1d::defaults
,
start : 0
end : 1
)
class Range1ds extends Continuum.Collection
model : Range1d
class DataRange1d extends Range1d
type : 'DataRange1d'
_get_minmax : () ->
columns = []
for source in @get('sources')
sourceobj = @resolve_ref(source['ref'])
for colname in source['columns']
columns.push(sourceobj.getcolumn(colname))
columns = _.reduce(columns, ((x, y) -> return x.concat(y)), [])
columns = _.filter(columns, (x) -> typeof(x) != "string")
[min, max] = [_.min(columns), _.max(columns)]
span = (max - min) * (1 + @get('rangepadding'))
center = (max + min) / 2.0
[min, max] = [center - span/2.0, center + span/2.0]
return [min, max]
_get_start : () ->
if not _.isNullOrUndefined(@get('_start'))
return @get('_start')
else
return @get('minmax')[0]
_set_start : (start) ->
@set('_start', start)
_get_end : () ->
if not _.isNullOrUndefined(@get('_end'))
return @get('_end')
else
return @get('minmax')[1]
_set_end : (end) ->
@set('_end', end)
dinitialize : (attrs, options) ->
super(attrs, options)
@register_property('minmax', @_get_minmax, true)
@add_dependencies('minmax', this, ['sources'], ['rangepadding'])
for source in @get('sources')
source = @resolve_ref(source.ref)
@add_dependencies('minmax', source, 'data')
@register_property('start', @_get_start, true)
@register_setter('start', @_set_start)
@add_dependencies('start', this, ['minmax', '_start'])
@register_property('end', @_get_end, true)
@register_setter('end', @_set_end)
@add_dependencies('end', this, ['minmax', '_end'])
DataRange1d::defaults = _.clone(DataRange1d::defaults)
_.extend(DataRange1d::defaults
,
sources : []
rangepadding : 0.1
)
class DataRange1ds extends Continuum.Collection
model : DataRange1d
class Range1ds extends Continuum.Collection
model : Range1d
class FactorRange extends HasProperties
type : 'FactorRange'
FactorRange::defaults = _.clone(FactorRange::defaults)
_.extend(FactorRange::defaults
,
values : []
)
class DataFactorRange extends FactorRange
type : 'DataFactorRange'
_get_values : () =>
columns = (@get_obj('data_source').getcolumn(x) for x in @get('columns'))
columns = _.reduce(columns, ((x, y) -> return x.concat(y)), [])
temp = {}
for val in columns
temp[val] = true
uniques = _.keys(temp)
uniques = _.sortBy(uniques, ((x) -> return x))
return uniques
dinitialize : (attrs, options) ->
super(attrs, options)
@register_property
@register_property('values', @_get_values, true)
@add_dependencies('values', this, ['data_source', 'columns'])
@add_dependencies('values', @get_obj('data_source'),
['data_source', 'columns'])
DataFactorRange::defaults = _.clone(DataFactorRange::defaults)
_.extend(DataFactorRange::defaults
,
values : []
columns : []
data_source : null
)
class DataFactorRanges extends Continuum.Collection
model : DataFactorRange
class FactorRanges extends Continuum.Collection
model : FactorRange |
should move to bokeh_model.coffee | class Bokeh.LinearMapper extends HasParent |
XY View state - handles mapper functionality along 2 axes | initialize : (attrs, options) ->
super(attrs, options)
@data_range = options.data_range
@viewstate = options.viewstate
@screendim = options.screendim #height or width
@register_property('scalestate', @_get_scale, true) |
if height/width changes, updated mapper | @add_dependencies('scalestate', @viewstate, @screendim) |
if range limits change, update | @add_dependencies('scalestate', @data_range,
['start', 'end'])
_get_scale : () ->
screendim = @viewstate.get(@screendim)
scale_factor = @viewstate.get(@screendim)
scale_factor = scale_factor/(@data_range.get('end')-@data_range.get('start'))
offset = -(scale_factor * @data_range.get('start'))
return [scale_factor, offset]
v_map_screen : (datav) ->
[scale_factor, offset] = @get('scalestate')
for data, idx in datav
datav[idx] = scale_factor * data + offset
return datav
map_screen : (data) ->
[scale_factor, offset] = @get('scalestate')
return scale_factor * data + offset
map_data : (screen) ->
[scale_factor, offset] = @get('scalestate')
return (screen - offset) / scale_factor
class DiscreteColorMapper extends HasProperties
type : 'DiscreteColorMapper'
_get_factor_map : () =>
domain_map = {}
for val, index in @get_obj('data_range').get('values')
domain_map[val] = index
return domain_map
_get_scale : () =>
return d3.scale.ordinal().domain(_.values(@get('factor_map')))
.range(@get('colors'))
dinitialize : (attrs, options) ->
super(attrs, options)
@register_property('factor_map', @_get_factor_map, true)
@add_dependencies('factor_map', this, 'data_range')
@register_property('scale', @_get_scale, true)
@add_dependencies('scale', this, ['colors', 'factor_map'])
map_screen : (data) ->
@get('scale')(@get('factor_map')[data]);
DiscreteColorMapper::defaults = _.clone(DiscreteColorMapper::defaults)
_.extend(DiscreteColorMapper::defaults
,
colors : [
"#1f77b4", "#aec7e8",
"#ff7f0e", "#ffbb78",
"#2ca02c", "#98df8a",
"#d62728", "#ff9896",
"#9467bd", "#c5b0d5",
"#8c564b", "#c49c94",
"#e377c2", "#f7b6d2",
"#7f7f7f", "#c7c7c7",
"#bcbd22", "#dbdb8d",
"#17becf", "#9edae5"
],
data_range : null
)
class DiscreteColorMappers extends Continuum.Collection
model : DiscreteColorMapper |
Data Sources | class ObjectArrayDataSource extends HasProperties
type : 'ObjectArrayDataSource'
initialize : (attrs, options) ->
super(attrs, options)
@cont_ranges = {}
@discrete_ranges = {}
getcolumn: (colname) ->
return (x[colname] for x in @get('data'))
compute_cont_range : (field) ->
data = @getcolumn(field)
return [_.max(data), _.min(data)]
compute_discrete_factor : (field) ->
temp = {}
for val in @getcolumn(field)
temp[val] = true
uniques = _.keys(temp)
uniques = _.sortBy(uniques, ((x) -> return x))
get_cont_range : (field, padding) ->
padding = 1.0 if _.isUndefined(padding)
if not _.exists(@cont_ranges, field)
[min, max] = @compute_cont_range(field)
span = (max - min) * (1 + padding)
center = (max + min) / 2.0
[min, max] = [center - span/2.0, center + span/2.0]
@cont_ranges[field] = Collections['Range1d'].create(
start : min
end : max
)
@on('change:data'
,
() =>
[max, min] = @compute_cont_range(field)
@cont_ranges[field].set('start', min)
@cont_ranges[field].set('end', max)
)
return @cont_ranges[field]
get_discrete_range : (field) ->
if not _.exists(@discrete_ranges, field)
factors = @compute_discrete_factor(field)
@discrete_ranges[field] = Collections['FactorRange'].create(
values : factors
)
@on('change:data'
,
() =>
factors = @compute_discrete_factor(field)
@discrete_ranges[field] = Collections['FactorRange'].set(
'values', factors)
)
return @discrete_ranges[field]
select : (fields, func) ->
selected = []
for val, idx in @get('data')
args = (val[x] for x in fields)
if func.apply(func, args)
selected.push(idx)
selected.sort()
return selected
ObjectArrayDataSource::defaults = _.clone(ObjectArrayDataSource::defaults)
_.extend(ObjectArrayDataSource::defaults
,
data : [{}]
name : 'data'
selected : []
selecting : false
)
class ObjectArrayDataSources extends Continuum.Collection
model : ObjectArrayDataSource
class ColumnDataSource extends ObjectArrayDataSource |
Datasource where the data is defined column-wise, i.e. each key in the the data attribute is a column name, and its value is an array of scalars. Each column should be the same length. | type : 'ColumnDataSource'
initialize : (attrs, options) ->
super(attrs, options)
@cont_ranges = {}
@discrete_ranges = {}
getcolumn: (colname) ->
return @get('data')[colname]
datapoints: () ->
data = @get('data')
fields = _.keys(data)
points = []
for i in [0..data[fields[0]].length-1]
point = {}
for field in fields
point[field] = data[field][i]
points.push(point)
return points
class ColumnDataSources extends Continuum.Collection
model : ColumnDataSource
class GridPlotContainer extends HasParent
type : 'GridPlotContainer'
default_view : Bokeh.GridPlotContainerView
GridPlotContainer::defaults = _.clone(GridPlotContainer::defaults)
_.extend(GridPlotContainer::defaults
,
children : [[]]
border_space : 0
)
class GridPlotContainers extends Continuum.Collection
model : GridPlotContainer
class Plot extends HasParent
type : 'Plot'
default_view : Bokeh.PlotView
parent_properties : ['background_color', 'foreground_color',
'width', 'height', 'border_space', 'unselected_color']
Plot::defaults = _.clone(Plot::defaults)
_.extend(Plot::defaults , {
'data_sources' : {},
'renderers' : [],
'axes' : [],
'legends' : [],
'tools' : [],
'overlays' : [],
'usedialog' : false,
'title' : 'Plot' |
axes fit here | })
Plot::display_defaults = _.clone(Plot::display_defaults)
_.extend(Plot::display_defaults
,
background_color : "#eee"
foreground_color : "#333"
unselected_color : "#ccc"
)
class Plots extends Continuum.Collection
model : Plot
class LinearAxis extends HasParent
type : 'LinearAxis'
default_view : Bokeh.LinearAxisView
display_defaults :
tick_color : '#fff'
LinearAxis::defaults = _.clone(LinearAxis::defaults)
_.extend(LinearAxis::defaults
,
data_range : null
orientation : 'bottom'
ticks : 10
ticksSubdivide : 1
tickSize : null
tickPadding : 3
)
class LinearAxes extends Continuum.Collection
model : LinearAxis
class LinearDateAxis extends LinearAxis
type : "LinearDateAxis"
default_view : Bokeh.LinearDateAxisView
class LinearDateAxes extends Continuum.Collection
model : LinearDateAxis
class BarRenderer extends XYRenderer
type : 'BarRenderer'
default_view : Bokeh.BarRendererView
BarRenderer::defaults = _.clone(BarRenderer::defaults)
_.extend(BarRenderer::defaults
,
xmapper : null
ymapper: null
orientation : 'vertical' |
orientation determines whether xfield, or yfield will be treated as a domain for continuous fields, we support specifying a field name, the width of the bar in screen space can be specified, or we can calculate a width xstart and xend can be used to specify the width of each bar in data space xfield : {'start' : 'start', 'end' : 'yend'}, xfield : {'field' : 'x', width : 10} | xfield : 'x'
yfield : 'y'
color : "#000"
)
class BarRenderers extends Continuum.Collection
model : BarRenderer
class LineRenderer extends XYRenderer
type : 'LineRenderer'
default_view : Bokeh.LineRendererView
LineRenderer::defaults = _.clone(LineRenderer::defaults)
_.extend(LineRenderer::defaults
,
xmapper : null,
ymapper: null,
xfield : null,
yfield : null,
color : "#000",
)
class LineRenderers extends Continuum.Collection
model : LineRenderer
class ScatterRenderer extends XYRenderer
type : 'ScatterRenderer'
default_view : Bokeh.ScatterRendererView
ScatterRenderer::defaults = _.clone(ScatterRenderer::defaults)
_.extend(ScatterRenderer::defaults, {
data_source : null,
xmapper : null,
ymapper: null,
xfield : null,
yfield : null, |
if colorfield, we use a color mapper | colormapper : null,
colorfield : null,
mark : 'circle',
})
class ScatterRenderers extends Continuum.Collection
model : ScatterRenderer |
class : GlyphRenderer | class GlyphRenderer extends HasParent |
Example definition | type : 'GlyphRenderer'
default_view : Bokeh.GlyphRendererView
GlyphRenderer::defaults = _.clone(GlyphRenderer::defaults)
_.extend(GlyphRenderer::defaults,
data_source : null
scatter_size : 3
color : 'black'
)
GlyphRenderer::display_defaults = _.clone(GlyphRenderer::display_defaults)
_.extend(GlyphRenderer::display_defaults, {
radius : 5
radius_units: 'screen'
color : 'gray'
outline_color: 'none'
outline_width: 1
angle_units: 'deg' |
Rects glyph | height: 1
width: 1
top: 1
bottom: 0
left: 0
right: 1
})
class GlyphRenderers extends Continuum.Collection
model : GlyphRenderer
class PanTool extends Continuum.HasParent
type : "PanTool"
default_view : Bokeh.PanToolView
PanTool::defaults = _.clone(PanTool::defaults)
_.extend(PanTool::defaults
,
dimensions : [] #height/width
dataranges : [] #references of datarange objects
)
class PanTools extends Continuum.Collection
model : PanTool
class ZoomTool extends Continuum.HasParent
type : "ZoomTool"
default_view : Bokeh.ZoomToolView
ZoomTool::defaults = _.clone(ZoomTool::defaults)
_.extend(ZoomTool::defaults
,
dimensions : []
dataranges : []
speed : 1/600
)
class ZoomTools extends Continuum.Collection
model : ZoomTool
class SelectionTool extends Continuum.HasParent
type : "SelectionTool"
default_view : Bokeh.SelectionToolView
SelectionTool::defaults = _.clone(SelectionTool::defaults)
_.extend(SelectionTool::defaults
,
renderers : []
select_x : true
select_y : true
data_source_options : {} #backbone options for save on datasource
)
class SelectionTools extends Continuum.Collection
model : SelectionTool |
# | class Legend extends Continuum.HasParent
type : "Legend"
default_view : Bokeh.LegendRendererView
defaults :
renderers : []
unselected_color : "#ccc"
positions :
top_left : [ 20, 20]
top_right : [-80, 20]
bottom_left : [ 20, -60]
bottom_right : [-80, -60]
position : "top_left"
initialize : (options) ->
super(options)
console.log("options", options)
ptype = typeof options.position
if ptype == "string"
@set('coords', @defaults.positions[options.position])
else if ptype == "object"
@set('coords', options.position)
class Legends extends Continuum.Collection
model : Legend |
# | class PlotContext extends Continuum.HasParent
type : 'PlotContext',
default_view : Bokeh.PlotContextView
url : () ->
return super()
defaults :
children : []
render_loop : true
class PlotContexts extends Backbone.Collection
model : PlotContext
if not Continuum.Collections.PlotContext
Continuum.Collections.PlotContext = new PlotContexts() |
backwards compatability | if not Continuum.Collections.CDXPlotContext
Continuum.Collections.CDXPlotContext = Continuum.Collections.PlotContext |
Preparing the name space | if not Continuum.Collections.Plot
Continuum.Collections.Plot = new Plots
if not Continuum.Collections.ScatterRenderer
Continuum.Collections.ScatterRenderer = new ScatterRenderers
if not Continuum.Collections.GlyphRenderer
Continuum.Collections.GlyphRenderer = new GlyphRenderers
if not Continuum.Collections.LineRenderer
Continuum.Collections.LineRenderer = new LineRenderers
if not Continuum.Collections.BarRenderer
Continuum.Collections.BarRenderer = new BarRenderers
if not Continuum.Collections.ObjectArrayDataSource
Continuum.Collections.ObjectArrayDataSource = new ObjectArrayDataSources
if not Continuum.Collections.ColumnDataSource
Continuum.Collections.ColumnDataSource = new ColumnDataSources
if not Continuum.Collections.Range1d
Continuum.Collections.Range1d = new Range1ds
if not Continuum.Collections.LinearAxis
Continuum.Collections.LinearAxis = new LinearAxes
if not Continuum.Collections.LinearDateAxis
Continuum.Collections.LinearDateAxis = new LinearDateAxes
if not Continuum.Collections.DiscreteColorMapper
Continuum.Collections.DiscreteColorMapper = new DiscreteColorMappers
if not Continuum.Collections.FactorRange
Continuum.Collections.FactorRange = new FactorRanges
if not Continuum.Collections.GridPlotContainer
Continuum.Collections.GridPlotContainer = new GridPlotContainers
if not Continuum.Collections.DataRange1d
Continuum.Collections.DataRange1d = new DataRange1ds
if not Continuum.Collections.DataFactorRange
Continuum.Collections.DataFactorRange = new DataFactorRanges
if not Continuum.Collections.PanTool
Continuum.Collections.PanTool = new PanTools
if not Continuum.Collections.ZoomTool
Continuum.Collections.ZoomTool = new ZoomTools
if not Continuum.Collections.SelectionTool
Continuum.Collections.SelectionTool = new SelectionTools
if not Continuum.Collections.Legend
Continuum.Collections.Legend = new Legends
Bokeh.Collections = Collections
Bokeh.ObjectArrayDataSource = ObjectArrayDataSource
Bokeh.Plot = Plot
Bokeh.ScatterRenderer = ScatterRenderer
Bokeh.LinearAxis = LinearAxis
Bokeh.LineRenderers = LineRenderers
Bokeh.LineRenderer = LineRenderer
Bokeh.BarRenderers = BarRenderers
Bokeh.BarRenderer = BarRenderer
Bokeh.GridPlotContainers = GridPlotContainers
Bokeh.GridPlotContainer = GridPlotContainer
Bokeh.PanTools = PanTools
Bokeh.PanTool = PanTool
Bokeh.ZoomTools = ZoomTools
Bokeh.ZoomTool = ZoomTool
Bokeh.SelectionTools = SelectionTools
Bokeh.SelectionTool = SelectionTool
Bokeh.Legends = Legends
Bokeh.Legend = Legend
|