Skip to content

Compare with Observable Plot

Colight provides a complete Python interface to the Observable Plot API, designed to be as consistent as possible with the original.

import colight.plot as Plot
data = [{"x": 1, "y": 2}, {"x": 2, "y": 3}, {"x": 3, "y": 4}]

Basic Plot Creation

Let's start with a simple scatter plot to compare the syntax:

Observable Plot

Plot.plot({
  marks: [
    Plot.dot(data, {x: "x", y: "y"})
  ]
})

Colight

Plot.dot(data, {"x": "x", "y": "y"})

As you can see, the basic structure is very similar. The main difference is that in Colight, we don't wrap marks in a Plot.plot() call - the Plot.dot() function returns a PlotSpec object that can be displayed directly.

Combining Marks

In Observable Plot, you typically combine marks by including them in the marks array. In Colight, you use the + operator to combine marks and options:

Observable Plot

Plot.plot({
  marks: [
    Plot.dot(data, {x: "x", y: "y"}),
    Plot.line(data, {x: "x", y: "y"})
  ]
})

Colight

Plot.dot(data, {"x": "x", "y": "y"}) + Plot.line(data, {"x": "x", "y": "y"})

Adding Plot Options

In Observable Plot, you typically add options to the Plot.plot() call. In Colight, you can add options using the + operator:

Observable Plot

Plot.plot({
  marks: [Plot.dot(data, {x: "x", y: "y"})],
  x: {domain: [0, 4]},
  y: {domain: [0, 5]}
})

Colight

Plot.dot(data, {"x": "x", "y": "y"}) + Plot.domain([0, 4], [0, 5])

JavaScript Functions in Options

Observable Plot allows you to use JavaScript functions directly in your options. Colight provides a similar capability using Plot.js():

Observable Plot

Plot.plot({
  marks: [
    Plot.dot(data, {
      x: "x",
      y: "y",
      fill: d => d.x > 2 ? "red" : "blue"
    })
  ]
})

Colight

Plot.dot(data, {"x": "x", "y": "y", "fill": Plot.js("d => d.x > 2 ? 'red' : 'blue'")})

Interactivity

Both Observable Plot and Colight support interactivity, but the approaches differ slightly due to the different environments.

Observable Plot In Observable Plot, you typically use Observable's reactive programming model:

viewof frequency = Inputs.range([0.1, 10], {step: 0.1, label: "Frequency"})

Plot.plot({
  marks: [
    Plot.line(d3.range(100), {
      x: (d, i) => i,
      y: (d, i) => Math.sin(i * frequency * Math.PI / 50)
    })
  ]
})

Colight

(
    Plot.line(
        {"x": range(100)},
        {
            "y": Plot.js("""(d, i) => {
                return Math.sin(i * $state.frequency * Math.PI / 50)
            }"""),
            "curve": "natural",
        },
    )
    + Plot.domain([0, 99], [-1, 1])
) | Plot.Slider(
    key="frequency",
    label="Frequency:",
    showValue=True,
    range=[0.1, 10],
    step=0.1,
    init=1,
)

In Colight, we use the Plot.Slider function to create interactive elements, and $state to access their values in our JavaScript functions.

Additional Features in Colight

Colight includes some additional marks that aren't part of the core Observable Plot library.