How to set colour of background plane to white using Bokeh in Python

I am looking for the matplotlib set plane color equivalent in Bokeh. The image I have looks like this:


I want the background to be white instead of the shadow currently visible. Anyone know how to do this?


@manini229 There is is no equivalent, since Bokeh is purely a 2d vis library. It’s not really possible to offer any suggestions without actual code. For that matter, it’s also not even clear if the image above is something you generated with Bokeh, or not. In general, more context and explanation is needed in order to help.

@Bryan I used Surface3d to plot the above figure by wrapping a TS code from an example in the Bokeh doc:

TS_CODE1 = """
// This custom model wraps one part of the third-party vis.js library:
// Making it easy to hook up python data analytics tools (NumPy, SciPy,
// Pandas, etc.) to web presentations using the Bokeh server.

import {LayoutDOM, LayoutDOMView} from "models/layouts/layout_dom"
import {ColumnDataSource} from "models/sources/column_data_source"
import {LayoutItem} from "core/layout"
import * as p from "core/properties"

declare namespace vis {
  class Graph3d {
    constructor(el: HTMLElement, data: object, OPTIONS: object)
    setData(data: vis.DataSet): void

  class DataSet {
    add(data: unknown): void

// This defines some default options for the Graph3d feature of vis.js
// See: for more details.
const OPTIONS = {
  width: '500px',
  height: '500px',
  style: 'surface',
  showPerspective: false,
  showGrid: true,
  keepAspectRatio: true,
  verticalRatio: 1.0,
  legendLabel: 'stuff',
  cameraPosition: {
    vertical: 0.5,
    distance: 1.8,
// To create custom model extensions that will render on to the HTML canvas
// or into the DOM, we must create a View subclass for the model.
// In this case we will subclass from the existing BokehJS ``LayoutDOMView``
export class Surface3d1View extends LayoutDOMView {
  model: Surface3d1

  private _graph: vis.Graph3d

  initialize(): void {

    const url = ""
    const script = document.createElement("script")
    script.onload = () => this._init()
    script.async = false
    script.src = url

  private _init(): void {
    // Create a new Graph3s using the vis.js API. This assumes the vis.js has
    // already been loaded (e.g. in a custom app template). In the future Bokeh
    // models will be able to specify and load external scripts automatically.
    // BokehJS Views create <div> elements by default, accessible as this.el.
    // Many Bokeh views ignore this default <div>, and instead do things like
    // draw to the HTML canvas. In this case though, we use the <div> to attach
    // a Graph3d to the DOM.
    this._graph = new vis.Graph3d(this.el, this.get_data(), OPTIONS)

    // Set a listener so that when the Bokeh data source has a change
    // event, we can process the new data
    this.connect(this.model.data_source.change, () => {

  // This is the callback executed when the Bokeh data has an change. Its basic
  // function is to adapt the Bokeh data source to the vis.js DataSet format.
  get_data(): vis.DataSet {
    const data = new vis.DataSet()
    const source = this.model.data_source
    for (let i = 0; i < source.get_length()!; i++) {
    return data

  get child_models(): LayoutDOM[] {
    return []

  _update_layout(): void {
    this.layout = new LayoutItem()

// We must also create a corresponding JavaScript BokehJS model subclass to
// correspond to the python Bokeh model subclass. In this case, since we want
// an element that can position itself in the DOM according to a Bokeh layout,
// we subclass from ``LayoutDOM``
export namespace Surface3d1 {
  export type Attrs = p.AttrsOf<Props>

  export type Props = LayoutDOM.Props & {
    x: p.Property<string>
    y: p.Property<string>
    z: p.Property<string>
    data_source: p.Property<ColumnDataSource>

export interface Surface3d1 extends Surface3d1.Attrs {}

export class Surface3d1 extends LayoutDOM {
  properties: Surface3d1.Props
  __view_type__: Surface3d1View

  constructor(attrs?: Partial<Surface3d1.Attrs>) {

  // The ``__name__`` class attribute should generally match exactly the name
  // of the corresponding Python class. Note that if using TypeScript, this
  // will be automatically filled in during compilation, so except in some
  // special cases, this shouldn't be generally included manually, to avoid
  // typos, which would prohibit serialization/deserialization of this model.
  static __name__ = "Surface3d1"

  static init_Surface3d1() {
    // This is usually boilerplate. In some cases there may not be a view.
    this.prototype.default_view = Surface3d1View

    // The @define block adds corresponding "properties" to the JS model. These
    // should basically line up 1-1 with the Python model class. Most property
    // types have counterparts, e.g. ```` will be
    // ``p.String`` in the JS implementatin. Where the JS type system is not yet
    // as rich, you can use ``p.Any`` as a "wildcard" property type.
      x:            [ p.String   ],
      y:            [ p.String   ],
      z:            [ p.String   ],
      data_source:  [ p.Instance ],

# This custom extension model will have a DOM view that should layout-able in
# Bokeh layouts, so use ``LayoutDOM`` as the base class. If you wanted to create
# a custom tool, you could inherit from ``Tool``, or from ``Glyph`` if you
# wanted to create a custom glyph, etc.
class Surface3d1(LayoutDOM):

    # The special class attribute ``__implementation__`` should contain a string
    # of JavaScript code that implements the browser side of the extension model.
    __implementation__ = TypeScript(TS_CODE1)

    # Below are all the "properties" for this model. Bokeh properties are
    # class attributes that define the fields (and their types) that can be
    # communicated automatically between Python and the browser. Properties
    # also support type validation. More information about properties in
    # can be found here:

    # This is a Bokeh ColumnDataSource that can be updated in the Bokeh
    # server by Python code
    data_source = Instance(ColumnDataSource)

    # The vis.js library that we are wrapping expects data for x, y, and z.
    # The data will actually be stored in the ColumnDataSource, but these
    # properties let us specify the *name* of the column that should be
    # used for each field.
    x = String

    y = String

    z = String

surface1 = Surface3d1(x="x", y="y", z="z", data_source=source, width=600, height=600)
indent preformatted text by 4 spaces

where x,y,z is data from a dataframe

@manini229 Surface3d is not a part of the Bokeh API. It is only part of an example, and that example only intends to be demonstration of how it is possible to wrap outside libraries with a custom extension, and nothing more. In this case the outside library is vis.js and it is not something we maintain or support. If there is a forum for support for vis.js that would be a better place to ask this question.