You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+8-3Lines changed: 8 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,15 @@
1
1

2
2
3
-
# `plotjs`: bridge between static matplotlib and interactive storytelling
3
+
# `plotjs`: Turn static matplotlib charts into interactive web visualizations
4
4
5
-
`plotjs` is a proof of concept, inspired by [mpld3](https://github.com/mpld3/mpld3), to make matplotlib plots interactive (for the browser) with minimum user inputs.
Copy file name to clipboardExpand all lines: docs/developers/how-it-works.md
+31-31Lines changed: 31 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,36 +1,36 @@
1
-
Transforming a static plot into something that you can interact with can't be done (unfortunately) just by saying "make this interactive".
1
+
Transforming a static plot into something interactive can't be done (unfortunately) just by saying "make this interactive."
2
2
3
-
But that does not mean we have to do mystic things to make it to work, because,**yes** that's perfectly possible without weird hacking stuff.
3
+
But that doesn't mean we have to do mystic things to make it work, because **yes**, that's perfectly possible without weird hacking stuff.
4
4
5
5
## Overview
6
6
7
-
There are 2 ways to tackle this problem:
7
+
There are two ways to tackle this problem:
8
8
9
-
- Take a matplotlib Figure (instance containing all plot elements) and convert it to a more common format such as json. We call this **serialization**. Then, with this json file, we recreate the figure with an interactive tool such as D3.js (that's what [mpld3](https://github.com/mpld3/mpld3) does btw!).
10
-
- Use native matplotlib figure output format (especially SVG) and parse this instead (that's what `plotjs` does).
9
+
- Take a matplotlib Figure (an instance containing all plot elements) and convert it to a more common format such as JSON. We call this **serialization**. Then, with this JSON file, we recreate the figure with an interactive tool such as D3.js (that's what [mpld3](https://github.com/mpld3/mpld3) does, by the way!).
10
+
- Use the native matplotlib figure output format (especially SVG) and parse this instead (that's what `plotjs` does).
11
11
12
-
The second option is **much simpler** (well, it depends) because we don't have to
12
+
The second option is **much simpler** (well, it depends), because we don't have to:
13
13
14
-
- translate the figure to JSON (which can be painfully complex if you want to handle all egde cases and make it robust).
15
-
- recreate the chart: browsers can display SVG perfectly.
14
+
- translate the figure to JSON (which can be painfully complex if you want to handle all edge cases and make it robust),
15
+
- recreate the chart (browsers can display SVG perfectly).
16
16
17
-
But it means that we don't have full control over how the plot is structured (from the browser point of view). We need to find a way to parse this SVG.
17
+
But it means we don't have full control over how the plot is structured (from the browser's point of view). We need to find a way to parse this SVG.
18
18
19
19
## Parsing SVG
20
20
21
-
For the moment, we just take user's matplotlib figure and save it as SVG. This is just:
21
+
For the moment, we just take the user's matplotlib figure and save it as SVG. This is just:
22
22
23
23
```python
24
24
fig.savefig("plot.svg")
25
25
```
26
26
27
-
Now let's say the Figure contains a scatterplot we want to add a tooltip: when someone passes his mouse over a point, it displays a label.
27
+
Now, let's say the figure contains a scatter plot and we want to add a tooltip: when someone hovers their mouse over a point, it displays a label.
28
28
29
-
The **core problem to solve** is: "how do I know what elements from the SVG are points"?
29
+
The **core problem to solve** is: "how do I know what elements from the SVG are points?"
30
30
31
31
If we're able to find a solution to this, then we're able to do pretty much **anything we want**.
32
32
33
-
The thing is that, there's nothing in the SVG output file that tells us "this element is a point from the scatter plot".**Even worse**: we don't even know if that's a scatter plot or something completly unrelated like a choropleth map.
33
+
The thing is, there's nothing in the SVG output file that tells us "this element is a point from the scatter plot."**Even worse**, we don't even know if it's a scatter plot or something completely unrelated, like a choropleth map.
34
34
35
35
For example, here is a polygon of a choropleth map:
36
36
@@ -91,47 +91,47 @@ If you pay close attention, you'll see potential patterns in the structure of ce
91
91
92
92
That's exactly what we'll use to determine what kind of plot elements we have.
93
93
94
-
> Note: determining the kind of plot elements could have been done (partially) from the Python side, but this felt easier to me to do it from the JavaScript side.
94
+
> Note: determining the kind of plot elements could have been done (partially) from the Python side, but this felt easier to me to do from the JavaScript side.
95
95
96
-
The next step is to understand matplotlib underlying objects (called [artists](https://matplotlib.org/stable/users/explain/artists/artist_intro.html){target="\_blank"}) and how that translate to SVG.
96
+
The next step is to understand matplotlib's underlying objects (called [artists](https://matplotlib.org/stable/users/explain/artists/artist_intro.html){target="\_blank"}) and how that translates to SVG.
97
97
98
-
## TLDR: artists in matplotlib
98
+
## TL;DR: Artists in matplotlib
99
99
100
-
In matplotlib, artists are all the visual elements you see on a plot. There is the `Artist` base class, and all others artists inherits from this class.
100
+
In matplotlib, artists are all the visual elements you see on a plot. There is the `Artist` base class, and all other artists inherit from this class.
101
101
102
102
For example:
103
103
104
-
- the `scatter()` function returns a `PathCollection` object, a subclass of `Artist`.
105
-
- the `plot()` function returns a `Line2D` object, a subclass of `Artist`.
106
-
- and so on
104
+
- the `scatter()` function returns a `PathCollection` object, a subclass of `Artist`,
105
+
- the `plot()` function returns a `Line2D` object, a subclass of `Artist`,
106
+
- and so on.
107
107
108
108
## Selecting artists from SVG
109
109
110
110
In the SVG output of `savefig("plot.svg")`, we can find some info about what object was used.
111
111
112
-
For example, all `PathCollection`object looks like `<g id="PathCollection_1">`, `<g id="PathCollection_2">`. And since `PathCollection` is just one or multiple points, we can easily know how many scatter plots there are.
112
+
For example, all `PathCollection`objects look like `<g id="PathCollection_1">`, `<g id="PathCollection_2">`. And since `PathCollection` is just one or multiple points, we can easily know how many scatter plots there are.
113
113
114
-
For lines, there are represented by `Line2D`. In the SVG, they look like `<g id="line2d_1">`, `<g id="line2d_2">`, etc. With this, we can easily detect that there are lines the chart.
114
+
For lines, they are represented by `Line2D`. In the SVG, they look like `<g id="line2d_1">`, `<g id="line2d_2">`, etc. With this, we can easily detect that there are lines in the chart.
115
115
116
-
But there is a major issue here: not all `PathCollection` are relevant, same for `Line2D`, and so on.
116
+
But there's a major issue here: not all `PathCollection` elements are relevant, same for `Line2D`, and so on.
117
117
118
-
By relevant I mean that we want to add interactivity to them. For example, what elements here are considered to be a `Line2D`:
118
+
By "relevant," I mean those we want to add interactivity to. For example, what elements here are considered to be a `Line2D`?
119
119
120
120

121
121
122
-
At first, I thought there was 3: one for each main line. But in practice, it's much more:
122
+
At first, I thought there were three: one for each main line. But in practice, it's much more:
123
123
124
124

125
125
126
-
What that means is that we can't select all `Line2D` and give them an hover effect, for instance. We need to find a way to discriminate relevant lines (the 3 big ones) and the other ones.
126
+
What that means is that we can't just select all `Line2D`elements and give them a hover effect, for instance. We need to find a way to discriminate relevant lines (the three big ones) from the other ones.
127
127
128
128
## Filtering artists from SVG
129
129
130
-
This section might not be up to date to the latest version, but it'll give you the idea of how `plotjs`detect what is a "core" plot elements, and what is not.
130
+
This section might not be up to date with the latest version, but it'll give you an idea of how `plotjs`detects what is a "core" plot element and what is not.
131
131
132
-
It's mostly consist of handling edge cases here, and is very different depending on the plot element (`Line2D`, `PathCollection`, etc).
132
+
It mostly consists of handling edge cases here, and is very different depending on the plot element (`Line2D`, `PathCollection`, etc.).
133
133
134
-
For example, in order to select only "core" `Line2D` (the 3 colored ones in the previous image), we do:
134
+
For example, in order to select only "core" `Line2D`elements (the three colored ones in the previous image), we do:
In order to apply CSS or [JavaScript](../javascript/index.md), you need to select elements from the DOM[^1]. You can find most of them using the [inspector](../troubleshooting/index.md) of your browser. All the common ones are defined below:
94
+
To style or add interactivity, you need to select elements using the DOM[^1]. These are the most common selectors:
90
95
91
-
####Plot elements
96
+
### Plot elements
92
97
93
-
-`.point`: all points from a scatter plot
94
-
-`.line`: all lines from a line chart
95
-
-`.area`: all areas from an area chart
96
-
-`.bar`: all bars from a bar chart
97
-
-`.plot-element`: all previous elements (points, lines, areas and bars)
98
+
-`.point`: scatter plot points
99
+
-`.line`: line chart lines
100
+
-`.area`: area chart fills
101
+
-`.bar`: bar chart bars
102
+
-`.plot-element`: all of the above
98
103
99
-
For all of those previous elements, you can add `.hovered` or `.not-hovered` (e.g, `.point.not-hovered`) to, respectively, select currently hovered and not hovered elements.
104
+
You can combine with `.hovered` or `.not-hovered`, e.g., `.point.hovered`.
100
105
101
-
####Misc
106
+
### Misc
102
107
103
-
-`.tooltip`: the tooltip displayed when hovering elements
104
-
-`svg`: the entire SVG containing the chart
108
+
-`.tooltip`: tooltip shown on hover
109
+
-`svg`: the entire SVG element
105
110
106
111
???+ question
107
112
108
-
Something's missing? Please [tell me](https://github.com/y-sunflower/plotjs/issues) about it by opening a new issue!
113
+
Something missing? Please [open an issue](https://github.com/y-sunflower/plotjs/issues)!
114
+
115
+
## Default CSS
116
+
117
+
You can find the default CSS applied by plotjs [here](https://github.com/y-sunflower/plotjs/blob/main/plotjs/static/default.css)
109
118
110
119
## Appendix
111
120
112
-
[^1]: The DOM (Document Object Model) is a tree-like structure that represents all the elements of a web page, allowing JavaScript to read, change, and interact with them. Think of it as a live map of the webpage that your code can explore and update in real time.
121
+
[^1]: The DOM (Document Object Model) is like a tree structure representing your webpage. JavaScript and CSS use it to select, modify, and interact with elements dynamically.
Copy file name to clipboardExpand all lines: docs/guides/javascript/index.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,8 @@
1
-
Under the hood, JavaScript is what is used to make the charts interactive. But `plotjs` allows anyone to add some more JavaScript for a finer control of what is happening and basically do whatever you want!
1
+
Under the hood, JavaScript is what is used to make the charts interactive. But `plotjs` allows anyone to add some more JavaScript for finer control of what is happening and basically do whatever you want!
This allows you to write JavaScript in a separate file so that you can have a code formatter (prettier, etc), code completion, syntax highlighting, and so on. This is what is recommended to do if you're writing a significant amount of code.
64
+
This allows you to write JavaScript in a separate file so that you can have a code formatter (prettier, etc.), code completion, syntax highlighting, and so on. This is what is recommended to do if you're writing a significant amount of code.
65
65
66
66
## Advanced usage
67
67
@@ -140,9 +140,9 @@ In order to apply [CSS](../css/index.md) or JavaScript, you need to select eleme
140
140
-`.line`: all lines from a line chart
141
141
-`.area`: all areas from an area chart
142
142
-`.bar`: all bars from a bar chart
143
-
-`.plot-element`: all previous elements (points, lines, areas and bars)
143
+
-`.plot-element`: all previous elements (points, lines, areas, and bars)
144
144
145
-
For all of those previous elements, you can add `.hovered` or `.not-hovered` (e.g, `.point.not-hovered`) to, respectively, select currently hovered and nothovered elements.
145
+
For all of those previous elements, you can add `.hovered` or `.not-hovered` (e.g., `.point.not-hovered`) to, respectively, select currently hovered and not-hovered elements.
Copy file name to clipboardExpand all lines: docs/guides/troubleshooting/index.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,22 +1,22 @@
1
-
Since `plotjs` does many things via JavaScript (e.g, in your browser when you open your html file), you may easily encounter "silent" errors.
1
+
Since `plotjs` does many things via JavaScript (e.g., in your browser when you open your HTML file), you may easily encounter "silent" errors.
2
2
3
-
In practice you will run you Python and everything will seems fine, but that does not mean what you'll see in the output is what you expected. There may multiple reasons for this. Here I'll explain common things that can happen, and how to debug them.
3
+
In practice, you will run your Python and everything will seem fine, but that does not mean what you'll see in the output is what you expected. There may be multiple reasons for this. Here I'll explain common things that can happen, and how to debug them.
4
4
5
5
## Developer tools
6
6
7
7
Your browser has a thing called developer tools. It allows you to view many things, but here we're mostly interested in its "console" section.
8
8
9
-
The console displays all the messages, including error messages, that the web page encountered at some point. Many of them are not necessarly interesting and are standard messages, but some of them might come from `plotjs` doing something wrong.
9
+
The console displays all the messages, including error messages, that the web page encountered at some point. Many of them are not necessarily interesting and are standard messages, but some of them might come from `plotjs` doing something wrong.
10
10
11
11
How to open the developer tools is browser-specific, but there's likely a shortcut to make it convenient. For instance, on macOS + Firefox I use ++option+cmd+i++.
12
12
13
13
## Debug `plotjs`
14
14
15
15
### Workflow
16
16
17
-
Since currently `plotjs` can't (yet) really be displayed in tools like Jupyter notebooks, marimo, etc, you have to open the output html file in your browser.
17
+
Since currently `plotjs` can't (yet) really be displayed in tools like Jupyter notebooks, marimo, etc., you have to open the output HTML file in your browser.
18
18
19
-
In order to have a comfortable workflow, it's recommend to have [`live-server`](https://www.npmjs.com/package/live-server) installed on your machine for automatic reload on file changes. Assuming you name your html file `mychart.html`, you'll just have to run `live-server mychart.html` and it'll open your plot in your default browser. Every time `mychart.html` is updated, it'll refresh the page. This makes debugging and iterating much faster and easier.
19
+
In order to have a comfortable workflow, it's recommended to have [`live-server`](https://www.npmjs.com/package/live-server) installed on your machine for automatic reload on file changes. Assuming you name your HTML file `mychart.html`, you'll just have to run `live-server mychart.html` and it'll open your plot in your default browser. Every time `mychart.html` is updated, it'll refresh the page. This makes debugging and iterating much faster and easier.
0 commit comments