Skip to content

Commit 5cb80ff

Browse files
authored
Merge pull request #150 from ianhi/thresholding
More natural behavior for scalar arguments
2 parents 575ff44 + be016a6 commit 5cb80ff

20 files changed

+1022
-141
lines changed

README.md

Lines changed: 4 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,66 +6,16 @@
66

77
## Welcome!
88

9-
mpl_interactions' library provides helpful ways to interact with [Matplotlib](https://matplotlib.org/) plots. A summary of key components can be found below. Fuller narrative, further examples, and more information can be found on [ReadtheDocs](https://mpl-interactions.readthedocs.io/en/latest/#).
9+
mpl_interactions' library provides helpful ways to interact with [Matplotlib](https://matplotlib.org/) plots. Full narrative documentation and example can be found on [ReadtheDocs](https://mpl-interactions.readthedocs.io/en/stable/#).
1010

1111
<img src=https://raw.githubusercontent.com/ianhi/mpl-interactions/master/docs/_static/images/short-interactive.gif width=45%> <img src=https://raw.githubusercontent.com/ianhi/mpl-interactions/master/docs/_static/images/heatmap_slicer.gif width=45%>
1212

13-
There are three submodules:
14-
15-
**pyplot**
16-
17-
Control Matplotlib plots using sliders and other widgets to adjust the parameters of the functions you are plotting. If working in a notebook then ipywidgets will be used to make the sliders, otherwise Matplotlib widgets will be used.
18-
19-
This is a different approach to controlling plots with sliders than `ipywidgets.interact` as when using `interact` you are responsible for:
20-
1. Defining the function to plot `f(x,...) => y`
21-
2. Handling the plotting logic (`plt.plot`, `fig.cla`, `ax.set_ylim`, etc)
22-
23-
In contrast, with `mpl-interactions` you only need to provide `f(x, ...) => y` and the plotting and updating boilerplate are handled for you.
24-
25-
```python
26-
x = np.linspace(0,6,100)
27-
beta = np.linspace(0,5*np.pi)
28-
def f(x, beta):
29-
return np.sin(x*4+beta)
30-
interactive_plot(f, x=x, beta=beta)
31-
```
32-
33-
These functions are designed to be used with [ipympl](https://github.com/matplotlib/ipympl), the backend that is designed for use in Jupyter Notebooks. So for optimal performance, make sure you set the backend with `%matplotlib ipympl`. That said, these functions will also work with any interactive backend (e.g. `%matplotlib qt5`).
34-
35-
36-
**generic**
37-
38-
Provides ways to interact with Matplotlib that will work outside of a Jupyter Notebook; this should work equally well with any backend.
39-
1. A very niche (but very cool) way to compare 2D heatmaps
40-
2. Scroll to zoom
41-
3. Middle click to pan
42-
43-
**utils**
44-
45-
This module includes utility functions to make things just that little bit easier.
46-
47-
1. `ioff` as a context manager
48-
49-
```python
50-
from mpl_interactions.utils import ioff
51-
with ioff:
52-
# interactive mode will be off
53-
fig = plt.figure()
54-
# other stuff
55-
# interactive mode will be on
56-
```
57-
2. `figure` that accepts a scalar for `figsize` (this will scale the default dimensions)
58-
```python
59-
from mpl_interactions.utils import figure
60-
fig = figure(3)
61-
# the default figsize is [6.4, 4.8], this figure will have figsize = [6.4*3, 4.8*3]
62-
```
63-
64-
3. `nearest_idx` -- avoid ever having to write `np.argmin(np.abs(arr - value))` again
65-
6613

6714
## Installation
6815
```bash
16+
pip install mpl_interactions["jupyter"] # will install necessary deps for using in jupyter
17+
18+
# for use only outside of jupyter:
6919
pip install mpl_interactions
7020

7121
# if using jupyterlab
@@ -82,24 +32,6 @@ I use the GitHub [issues](https://github.com/ianhi/mpl-interactions/issues) to k
8232

8333
The fuller narrative documentation can be found on [ReadTheDocs](https://mpl-interactions.readthedocs.io/en/latest/). You may also find it helpful to check out the [examples directory](https://github.com/ianhi/mpl-interactions/tree/master/examples).
8434

85-
86-
## Examples with GIFs!
87-
Tragically, neither GitHub nor the sphinx documentation render the actual moving plots so instead, here are gifs of the functions. The code for these can be found in the notebooks in the examples directory.
88-
89-
90-
### interactive_plot
91-
Easily make a line plot interactive:
92-
![](docs/_static/images/interactive-plot.gif)
93-
94-
95-
### heatmap_slicer
96-
Compare vertical and horizontal slices across multiple heatmaps:
97-
![](docs/_static/images/heatmap_slicer.gif)
98-
99-
100-
### scrolling zoom + middle click pan
101-
![](docs/_static/images/zoom-and-pan.gif)
102-
10335
## Contributors ✨
10436

10537
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

docs/Contributing.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ Also feel free to ask for help/advice on the relevant Github `issue <https://git
5151
Documentation
5252
-------------
5353

54+
For the most part the Documentation is generated from the Notebooks in the `examples` folder. So to write new
55+
examples work in a notebook in the ``examples`` directory. When the docs are generated then they will be
56+
converted to html via `nbsphinx <https://nbsphinx.readthedocs.io/en/latest/>`_.
57+
58+
If you are adding a new example then you need to include it in the toctree in ``docs/index.rst``.
59+
60+
5461
Following changes to the source files, you can view recent adjustments by building the documentation.
5562

5663
1. Make sure you have installed the requirements for building the documentation:
@@ -69,6 +76,16 @@ Following changes to the source files, you can view recent adjustments by buildi
6976
7077
If you open the ``index.html`` file in your browser you should now be able to see the rendered documentation.
7178

79+
Embedding GIFs
80+
^^^^^^^^^^^^^^
81+
82+
Unfortunately the interactive plots are not interactive on readthedocs, this is because they require an active
83+
Python kernel to work. So instead we short gifs or apngs of interacting with the plots and embed them. To accomplish this
84+
the GIFs are stored in ``docs/_static/images`` and they are automatically embedded when the notebooks are converted to html
85+
based on the file names in the cell metadata. For example here is the process of setting the metadata of a cell when using JupyterLab.
86+
87+
.. image:: _static/images/how-to-embed-gif.gif
88+
7289
Autobuild the documentation
7390
^^^^^^^^^^^^^^^^^^^^^^^^^^^
7491

373 KB
Binary file not shown.
-671 KB
Binary file not shown.
234 KB
Binary file not shown.

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ Further discussion of the behavior as a function of backend can be found on the
9797
examples/mpl-sliders.ipynb
9898
examples/scatter-selector.ipynb
9999
examples/animations.ipynb
100+
examples/range-sliders.ipynb
101+
examples/scalar-arguments.ipynb
100102
examples/image-segmentation.ipynb
101103
examples/zoom-factory.ipynb
102104
examples/heatmap-slicer.ipynb

examples/Lotka-Volterra.ipynb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@
3838
"t = np.linspace(0, 15, 1000) # time\n",
3939
"X0 = np.array([10, 5]) # initials conditions: 10 rabbits and 5 foxes\n",
4040
"\n",
41+
"# use `c_` instead of `c` because `c` is an argument to plt.scatter\n",
4142
"\n",
42-
"def f(a, b, c, d):\n",
43+
"def f(a, b, c_, d):\n",
4344
" def dX_dt(X, t=0):\n",
4445
" \"\"\" Return the growth rate of fox and rabbit populations. \"\"\"\n",
4546
" rabbits, foxes = X\n",
4647
" dRabbit_dt = a * rabbits - b * foxes * rabbits\n",
47-
" dFox_dt = -c * foxes + d * b * rabbits * foxes\n",
48+
" dFox_dt = -c_ * foxes + d * b * rabbits * foxes\n",
4849
" return [dRabbit_dt, dFox_dt]\n",
4950
"\n",
5051
" X, _ = integrate.odeint(dX_dt, X0, t, full_output=True)\n",
@@ -70,7 +71,7 @@
7071
"source": [
7172
"fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 4.8))\n",
7273
"controls = iplt.plot(\n",
73-
" f, ax=ax1, a=(0.5, 2), b=(0.1, 3), c=(1, 3), d=(0.1, 2), parametric=True\n",
74+
" f, ax=ax1, a=(0.5, 2), b=(0.1, 3), c_=(1, 3), d=(0.1, 2), parametric=True\n",
7475
")\n",
7576
"ax1.set_xlabel(\"rabbits\")\n",
7677
"ax1.set_ylabel(\"foxes\")\n",
@@ -118,7 +119,7 @@
118119
"name": "python",
119120
"nbconvert_exporter": "python",
120121
"pygments_lexer": "ipython3",
121-
"version": "3.7.8"
122+
"version": "3.9.0"
122123
}
123124
},
124125
"nbformat": 4,

examples/Usage-Guide.ipynb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,34 @@
212212
"controls = iplt.plot(x, f, tau=(5, 10, 5), beta=(0.25, 1))"
213213
]
214214
},
215+
{
216+
"cell_type": "markdown",
217+
"metadata": {},
218+
"source": [
219+
"### Tuples for RangeSliders\n",
220+
"\n",
221+
"You can create a RangeSlider by passing a tuple prefixed with an \"r\"."
222+
]
223+
},
224+
{
225+
"cell_type": "code",
226+
"execution_count": null,
227+
"metadata": {
228+
"gif": "usage-rangeslider.apng"
229+
},
230+
"outputs": [],
231+
"source": [
232+
"def f_x(min_max, **kwargs):\n",
233+
" # break up the tuple\n",
234+
" min_, max_ = min_max\n",
235+
" return np.linspace(min_, max_, 100)\n",
236+
" # break up the tuple\n",
237+
"def f_range(x, tau, **kwargs):\n",
238+
" return np.sin(x*tau)\n",
239+
"fig, ax = plt.subplots()\n",
240+
"controls = iplt.plot(f_x, f_range, tau=(5, 10, 5), min_max = (\"r\", 0, 10))"
241+
]
242+
},
215243
{
216244
"cell_type": "markdown",
217245
"metadata": {},

examples/imshow.ipynb

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
"source": [
100100
"### vmin and vmax: thresholding an image\n",
101101
"\n",
102-
"You can also pass `vmin` and `vmax` as functions. Additionally you do not need to use a function to provide the image, you can also provide an array"
102+
"Here we use the `vmin_vmax` argument along with the syntax for a RangeSlider to easily threshold the image. For more on how to use RangeSliders see [their example page](range-sliders.ipynb). Additionally you do not need to use a function to provide the image, you can also provide an array"
103103
]
104104
},
105105
{
@@ -113,16 +113,8 @@
113113
"img = plt.imread(\"https://matplotlib.org/3.3.1/_images/stinkbug.png\")\n",
114114
"\n",
115115
"\n",
116-
"def vmin(min_, max_):\n",
117-
" return min(min_, max_)\n",
118-
"\n",
119-
"\n",
120-
"def vmax(min_, max_):\n",
121-
" return max(min_, max_)\n",
122-
"\n",
123-
"\n",
124116
"fig4, ax4 = plt.subplots()\n",
125-
"controls4 = iplt.imshow(img, vmin=vmin, vmax=vmax, min_=(0, 0.7), max_=(0.3, 1))"
117+
"controls4 = iplt.imshow(img, vmin_vmax=(\"r\", img.min(), img.max()))"
126118
]
127119
},
128120
{
@@ -149,7 +141,7 @@
149141
"name": "python",
150142
"nbconvert_exporter": "python",
151143
"pygments_lexer": "ipython3",
152-
"version": "3.7.8"
144+
"version": "3.9.0"
153145
}
154146
},
155147
"nbformat": 4,

examples/mpl-sliders.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
"name": "python",
134134
"nbconvert_exporter": "python",
135135
"pygments_lexer": "ipython3",
136-
"version": "3.8.5"
136+
"version": "3.9.0"
137137
}
138138
},
139139
"nbformat": 4,

0 commit comments

Comments
 (0)