# textual-plotext
![PlotextPlot in action](https://raw.githubusercontent.com/Textualize/textual-plotext/main/textual-plotext-example.png)
A Textual widget wrapper for the [Plotext plotting
library](https://github.com/piccolomo/plotext).
## Introduction
The library makes one widget available: `PlotextPlot`. This widget provides
a `plt` property, which should be used where you would normally use `plt` as
seen in the Plotext documentation.
Let's take [the first
example](https://github.com/piccolomo/plotext/blob/master/readme/basic.md#scatter-plot)
from [the Plotext README](https://github.com/piccolomo/plotext#readme):
```python
import plotext as plt
y = plt.sin() # sinusoidal test signal
plt.scatter(y)
plt.title("Scatter Plot") # to apply a title
plt.show() # to finally plot
```
The Textual equivalent of this (including everything needed to make this a
fully-working Textual application) is:
```python
from textual.app import App, ComposeResult
from textual_plotext import PlotextPlot
class ScatterApp(App[None]):
def compose(self) -> ComposeResult:
yield PlotextPlot()
def on_mount(self) -> None:
plt = self.query_one(PlotextPlot).plt
y = plt.sin() # sinusoidal test signal
plt.scatter(y)
plt.title("Scatter Plot") # to apply a title
if __name__ == "__main__":
ScatterApp().run()
```
The main differences to note are:
- We're not directly importing `plotext`.
- We use `PlotextPlot.plt` rather than `plt`.
- We don't call Plotext's `show` method, `PlotextPlot` takes care of this.
## Installation
The library can be installed from PyPi:
```sh
$ pip install textual-plotext
```
Once installed you can quickly test the library by running the demo:
```sh
$ python -m textual_plotext
```
The demo app includes many of the examples shown in the Plotext README.
## Longer example
For a longer example of how to use the `PlotextPlot` widget, take a look at
[`examples/textual_towers_weather.py`](./examples/textual_towers_weather.py).
As a bonus it also shows an example of using Textual's [worker
API](https://textual.textualize.io/guide/workers/) to create a [threaded
worker](https://textual.textualize.io/guide/workers/#thread-workers) to pull
the data from the backend.
## What is supported?
The following utility functions are provided (via `PlotextPlot.plt`):
- `plt.sin`
- `plt.square`
- `plt.colorize`
- `plt.uncolorize`
## What isn't supported?
Some functions are not supported at all; mainly those that would not make
sense inside a Textual application. These include:
- `plt.interactive`
- `plt.script_folder`
- `plt.parent_folder`
- `plt.join_paths`
- `plt.save_text`
- `plt.read_data`
- `plt.write_data`
- `plt.download`
- `plt.delete_file`
- `plt.test`
- `plt.time`
- `plt.test_data_url`
- `plt.test_bar_data_url`
- `plt.test_image_url`
- `plt.test_gif_url`
- `plt.test_video_url`
- `plt.test_youtube_url`
The following properties and sub-modules also aren't exposed because they
too are designed for REPL-based interactive use and don't lend themselves to
being used in a Textual application:
- `plt.doc`
- `plt.markers`
- `plt.colors`
- `plt.styles`
- `plt.themes`
Also, currently, there is no support for [GIF
plots](https://github.com/piccolomo/plotext/blob/master/readme/image.md#gif-plot) or
[playing
videos](https://github.com/piccolomo/plotext/blob/master/readme/video.md);
one or both could follow at some point in the future.
## What functions are no-ops?
Some functions are supported as calls but are redefined to be
non-operations; these are the sorts of code that wouldn't generally have a
negative side-effect but which don't make sense for a Textual application.
These include:
- `plt.clear_terminal`
- `plt.show`
- `plt.save_fig`
## Themes
Plotext has [a system of
themes](https://github.com/piccolomo/plotext/blob/master/readme/aspect.md#themes).
The themes provided by Plotext are supported by `PlotextPlot`. However, some
of those themes use "ANSI colors" and so may end up looking different
depending on which terminal you use, and what terminal theme is in use (if
your terminal supports themes); the issue here is that your plots may look
very different in different environments.
To help with this `textual-plotext` provides an additional set of copies of
those themes, all prefixed with `textual-`, that use full RGB coloring to
ensure that, when using a given Plotext theme, it will look the same
everywhere.
In addition to the Plotext themes, `textual-plotext` also adds two themes
called:
- `textual-design-dark`
- `textual-design-light`
These are two similar themes designed to look good in dark mode and light
mode respectively. Out of the box, `PlotextPlot` will use these and will
switch between them when your [Textual application switches between dark and
light mode](https://textual.textualize.io/api/app/#textual.app.App.dark). If
you wish to turn off this behaviour, simply set the `auto_theme` property of
your plot to `False`.
## Known issues
At the moment, due to what appears to be a bug in Plotext when it comes to
repeated calls to `show` or `build`[^1] for a plot with x or y scales set to
`"log"`, it isn't possible to easily build such a plot. In other words, even
in the REPL with Plotext itself, a session such as this:
```python
>>> import plotext as plt
>>> plt.xscale("log")
>>> plt.plot(plt.sin(periods=2, length=10**4))
>>> plt.show()
<plot is drawn in the terminal here>
>>> plt.show()
```
results in a `ValueError: math domain error`.
There is a workaround for this, which will work for Plotext use in general
and would also work nicely in a Textual app. After the first `show` or
`build`, set the problematic scale back to `"linear"`. So the REPL session
should above would become:
```python
>>> import plotext as plt
>>> plt.xscale("log")
>>> plt.plot(plt.sin(periods=2, length=10**4))
>>> plt.show()
<plot is drawn in the terminal here>
>>> plt.xscale("linear") # Note this here!
>>> plt.show()
<plot is drawn in the terminal here>
>>> plt.show()
<plot is drawn in the terminal here>
etc...
```
In a Textual app, this would mean adding (assuming the `xscale` was the
problem here) this at the end of the code to create the plot:
```python
_ = self.plt.build()
self.plt.xscale("linear")
```
## Need more help?
If you need help with this library, or with anything relating to Textual,
feel free to come join the [Textualize](https://www.textualize.io/)
[devs](https://www.textualize.io/about-us/) [on
Discord](https://discord.gg/Enf6Z3qhVr) or [the other places where we
provide support](https://textual.textualize.io/help/).
[^1]: Repeated calls to `build` will happen when the `PlottextPlot` widget
needs to `render` the plot again, on resize for example.
Raw data
{
"_id": null,
"home_page": "https://github.com/Textualize/textual-plotext",
"name": "textual-plotext",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7.2,<4.0",
"maintainer_email": "",
"keywords": "",
"author": "Dave Pearson",
"author_email": "dave@textualize.io",
"download_url": "https://files.pythonhosted.org/packages/6d/bf/195b67009154bb9eceb02028fb50fb39ab6a81b628b9451397fa9b0c7da6/textual_plotext-0.2.1.tar.gz",
"platform": null,
"description": "# textual-plotext\n\n![PlotextPlot in action](https://raw.githubusercontent.com/Textualize/textual-plotext/main/textual-plotext-example.png)\n\nA Textual widget wrapper for the [Plotext plotting\nlibrary](https://github.com/piccolomo/plotext).\n\n## Introduction\n\nThe library makes one widget available: `PlotextPlot`. This widget provides\na `plt` property, which should be used where you would normally use `plt` as\nseen in the Plotext documentation.\n\nLet's take [the first\nexample](https://github.com/piccolomo/plotext/blob/master/readme/basic.md#scatter-plot)\nfrom [the Plotext README](https://github.com/piccolomo/plotext#readme):\n\n```python\nimport plotext as plt\ny = plt.sin() # sinusoidal test signal\nplt.scatter(y)\nplt.title(\"Scatter Plot\") # to apply a title\nplt.show() # to finally plot\n```\n\nThe Textual equivalent of this (including everything needed to make this a\nfully-working Textual application) is:\n\n```python\nfrom textual.app import App, ComposeResult\n\nfrom textual_plotext import PlotextPlot\n\nclass ScatterApp(App[None]):\n\n def compose(self) -> ComposeResult:\n yield PlotextPlot()\n\n def on_mount(self) -> None:\n plt = self.query_one(PlotextPlot).plt\n y = plt.sin() # sinusoidal test signal\n plt.scatter(y)\n plt.title(\"Scatter Plot\") # to apply a title\n\nif __name__ == \"__main__\":\n ScatterApp().run()\n```\n\nThe main differences to note are:\n\n- We're not directly importing `plotext`.\n- We use `PlotextPlot.plt` rather than `plt`.\n- We don't call Plotext's `show` method, `PlotextPlot` takes care of this.\n\n## Installation\n\nThe library can be installed from PyPi:\n\n```sh\n$ pip install textual-plotext\n```\n\nOnce installed you can quickly test the library by running the demo:\n\n```sh\n$ python -m textual_plotext\n```\n\nThe demo app includes many of the examples shown in the Plotext README.\n\n## Longer example\n\nFor a longer example of how to use the `PlotextPlot` widget, take a look at\n[`examples/textual_towers_weather.py`](./examples/textual_towers_weather.py).\nAs a bonus it also shows an example of using Textual's [worker\nAPI](https://textual.textualize.io/guide/workers/) to create a [threaded\nworker](https://textual.textualize.io/guide/workers/#thread-workers) to pull\nthe data from the backend.\n\n## What is supported?\n\nThe following utility functions are provided (via `PlotextPlot.plt`):\n\n- `plt.sin`\n- `plt.square`\n- `plt.colorize`\n- `plt.uncolorize`\n\n## What isn't supported?\n\nSome functions are not supported at all; mainly those that would not make\nsense inside a Textual application. These include:\n\n- `plt.interactive`\n- `plt.script_folder`\n- `plt.parent_folder`\n- `plt.join_paths`\n- `plt.save_text`\n- `plt.read_data`\n- `plt.write_data`\n- `plt.download`\n- `plt.delete_file`\n- `plt.test`\n- `plt.time`\n- `plt.test_data_url`\n- `plt.test_bar_data_url`\n- `plt.test_image_url`\n- `plt.test_gif_url`\n- `plt.test_video_url`\n- `plt.test_youtube_url`\n\nThe following properties and sub-modules also aren't exposed because they\ntoo are designed for REPL-based interactive use and don't lend themselves to\nbeing used in a Textual application:\n\n- `plt.doc`\n- `plt.markers`\n- `plt.colors`\n- `plt.styles`\n- `plt.themes`\n\nAlso, currently, there is no support for [GIF\nplots](https://github.com/piccolomo/plotext/blob/master/readme/image.md#gif-plot) or\n[playing\nvideos](https://github.com/piccolomo/plotext/blob/master/readme/video.md);\none or both could follow at some point in the future.\n\n## What functions are no-ops?\n\nSome functions are supported as calls but are redefined to be\nnon-operations; these are the sorts of code that wouldn't generally have a\nnegative side-effect but which don't make sense for a Textual application.\nThese include:\n\n- `plt.clear_terminal`\n- `plt.show`\n- `plt.save_fig`\n\n## Themes\n\nPlotext has [a system of\nthemes](https://github.com/piccolomo/plotext/blob/master/readme/aspect.md#themes).\nThe themes provided by Plotext are supported by `PlotextPlot`. However, some\nof those themes use \"ANSI colors\" and so may end up looking different\ndepending on which terminal you use, and what terminal theme is in use (if\nyour terminal supports themes); the issue here is that your plots may look\nvery different in different environments.\n\nTo help with this `textual-plotext` provides an additional set of copies of\nthose themes, all prefixed with `textual-`, that use full RGB coloring to\nensure that, when using a given Plotext theme, it will look the same\neverywhere.\n\nIn addition to the Plotext themes, `textual-plotext` also adds two themes\ncalled:\n\n- `textual-design-dark`\n- `textual-design-light`\n\nThese are two similar themes designed to look good in dark mode and light\nmode respectively. Out of the box, `PlotextPlot` will use these and will\nswitch between them when your [Textual application switches between dark and\nlight mode](https://textual.textualize.io/api/app/#textual.app.App.dark). If\nyou wish to turn off this behaviour, simply set the `auto_theme` property of\nyour plot to `False`.\n\n## Known issues\n\nAt the moment, due to what appears to be a bug in Plotext when it comes to\nrepeated calls to `show` or `build`[^1] for a plot with x or y scales set to\n`\"log\"`, it isn't possible to easily build such a plot. In other words, even\nin the REPL with Plotext itself, a session such as this:\n\n```python\n>>> import plotext as plt\n>>> plt.xscale(\"log\")\n>>> plt.plot(plt.sin(periods=2, length=10**4))\n>>> plt.show()\n<plot is drawn in the terminal here>\n>>> plt.show()\n```\n\nresults in a `ValueError: math domain error`.\n\nThere is a workaround for this, which will work for Plotext use in general\nand would also work nicely in a Textual app. After the first `show` or\n`build`, set the problematic scale back to `\"linear\"`. So the REPL session\nshould above would become:\n\n```python\n>>> import plotext as plt\n>>> plt.xscale(\"log\")\n>>> plt.plot(plt.sin(periods=2, length=10**4))\n>>> plt.show()\n<plot is drawn in the terminal here>\n>>> plt.xscale(\"linear\") # Note this here!\n>>> plt.show()\n<plot is drawn in the terminal here>\n>>> plt.show()\n<plot is drawn in the terminal here>\netc...\n```\n\nIn a Textual app, this would mean adding (assuming the `xscale` was the\nproblem here) this at the end of the code to create the plot:\n\n```python\n_ = self.plt.build()\nself.plt.xscale(\"linear\")\n```\n\n## Need more help?\n\nIf you need help with this library, or with anything relating to Textual,\nfeel free to come join the [Textualize](https://www.textualize.io/)\n[devs](https://www.textualize.io/about-us/) [on\nDiscord](https://discord.gg/Enf6Z3qhVr) or [the other places where we\nprovide support](https://textual.textualize.io/help/).\n\n[^1]: Repeated calls to `build` will happen when the `PlottextPlot` widget\n needs to `render` the plot again, on resize for example.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Textual widget wrapper for the Plotext plotting library",
"version": "0.2.1",
"project_urls": {
"Bug Tracker": "https://github.com/Textualize/textual-plotext/issues",
"Homepage": "https://github.com/Textualize/textual-plotext",
"Repository": "https://github.com/Textualize/textual-plotext"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "4900125486e77be52a4222ba5690af564814688f1d5466df1d566540d1950db5",
"md5": "59592de18d7c9016a60dc3a90894a353",
"sha256": "a1055cf50fac9af11f56b5ff73442570eb5fd051e513b20aeb8b15a6a2abfcff"
},
"downloads": -1,
"filename": "textual_plotext-0.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "59592de18d7c9016a60dc3a90894a353",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7.2,<4.0",
"size": 16513,
"upload_time": "2023-10-26T12:54:48",
"upload_time_iso_8601": "2023-10-26T12:54:48.246346Z",
"url": "https://files.pythonhosted.org/packages/49/00/125486e77be52a4222ba5690af564814688f1d5466df1d566540d1950db5/textual_plotext-0.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6dbf195b67009154bb9eceb02028fb50fb39ab6a81b628b9451397fa9b0c7da6",
"md5": "45df8213d66d284a468f21d07029ad0f",
"sha256": "bc6f2d75d8e20dda6321f8254dc3decda8f41f60e6e70a3ddd83b652b890c081"
},
"downloads": -1,
"filename": "textual_plotext-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "45df8213d66d284a468f21d07029ad0f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7.2,<4.0",
"size": 16397,
"upload_time": "2023-10-26T12:54:50",
"upload_time_iso_8601": "2023-10-26T12:54:50.224956Z",
"url": "https://files.pythonhosted.org/packages/6d/bf/195b67009154bb9eceb02028fb50fb39ab6a81b628b9451397fa9b0c7da6/textual_plotext-0.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-10-26 12:54:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Textualize",
"github_project": "textual-plotext",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "textual-plotext"
}