Skip to content

Plotly support #1226

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

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- `plotly` support (#1226)

## [0.30.2] - 2025-07-22

### Fixed
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@sentry/tracing": "7.16.0",
"@szhsin/react-menu": "^3.2.0",
"apollo-link-sentry": "^3.2.3",
"assert": "^2.1.0",
"axios": "^0.24.0",
"classnames": "^2.3.2",
"codemirror": "^6.0.1",
Expand All @@ -51,6 +52,7 @@
"node-html-parser": "^6.1.5",
"oidc-client": "^1.11.5",
"parse-link-header": "^2.0.0",
"plotly.js": "^3.0.2",
"prismjs": "^1.29.0",
"prompts": "2.4.0",
"prop-types": "^15.8.1",
Expand All @@ -76,6 +78,7 @@
"react-toggle": "^4.1.3",
"redux-oidc": "^4.0.0-beta1",
"skulpt": "^1.2.0",
"stream-browserify": "^3.0.0",
"three": "0.169.0",
"ts-pnp": "1.2.0",
"url": "^0.11.4",
Expand Down
26 changes: 26 additions & 0 deletions src/PyodideWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,32 @@ const PyodideWorker = () => {
`);
},
},
plotly: {
before: async () => {
if (!pyodide.micropip) {
await pyodide.loadPackage("micropip");
pyodide.micropip = pyodide.pyimport("micropip");
}

// If the import is for a PyPi package then load it.
// Otherwise, don't error now so that we get an error later from Python.
await pyodide.micropip.install("plotly").catch(() => {});
await pyodide.micropip.install("pandas").catch(() => {});
pyodide.registerJsModule("basthon", fakeBasthonPackage);
pyodide.runPython(`
import plotly.graph_objs as go

def _hacked_show(self, *args, **kwargs):
basthon.kernel.display_event({
"display_type": "plotly",
"content": self.to_json()
})

go.Figure.show = _hacked_show
`);
},
after: () => {},
},
};

const fakeBasthonPackage = {
Expand Down
1 change: 1 addition & 0 deletions src/assets/stylesheets/ExternalStyles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
@use "../../../node_modules/prismjs/plugins/line-highlight/prism-line-highlight.css";
@use "../../../node_modules/@raspberrypifoundation/design-system-core/scss/components/alert.scss";
@use "../../../node_modules/material-symbols/sharp.scss";
@use "../../../node_modules/plotly.js/src/css/style.scss" as plotlyStyle;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useRef } from "react";
import { useSelector } from "react-redux";
import AstroPiModel from "../../../../AstroPiModel/AstroPiModel";
import Highcharts from "highcharts";
import Plotly from "plotly.js";

const VisualOutputPane = ({ visuals, setVisuals }) => {
const senseHatEnabled = useSelector((s) => s.editor.senseHatEnabled);
Expand Down Expand Up @@ -49,6 +50,13 @@ const VisualOutputPane = ({ visuals, setVisuals }) => {
)}`;
output.current.innerHTML = img.outerHTML;
break;
case "plotly":
const plotlyJson = visual.content;
// Parse the JSON
const figure = JSON.parse(plotlyJson);
// Render using Plotly.js
Plotly.newPlot(output.current, figure.data, figure.layout);
break;
default:
throw new Error(`Unsupported origin: ${visual.origin}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,31 @@ describe("When there is a matplotlib output", () => {
});
});

describe("when there is plotly output", () => {
beforeEach(() => {
const visuals = [
{
origin: "plotly",
content: JSON.stringify({
data: [{ x: [1, 2, 3], y: [4, 5, 6], type: "scatter" }],
layout: { title: { text: "Test Plot" } },
}),
},
];
renderPaneWithVisuals(visuals);
});

test("it renders without crashing", () => {
expect(document.getElementsByClassName("pythonrunner-graphic").length).toBe(
1,
);
});

test("it renders the plotly chart as an svg", () => {
expect(screen.getByText("Test Plot")).toBeInTheDocument();
});
});

describe("When there is an unsupported origin", () => {
test("it throws an error", () => {
const visuals = [
Expand Down
2 changes: 2 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ module.exports = {
resolve: {
extensions: [".*", ".js", ".jsx", ".css"],
fallback: {
stream: require.resolve("stream-browserify"),
assert: require.resolve("assert"),
path: require.resolve("path-browserify"),
url: require.resolve("url/"),
},
Expand Down
Loading
Loading