Skip to content

Commit e599f5a

Browse files
committed
roughly working
1 parent 6bb1142 commit e599f5a

4 files changed

Lines changed: 122 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
55

66
## [Unreleased]
77

8+
### Added
9+
- new artists submodule `animate` as a convenient wrapper for matplotlib's `FuncAnimate`
10+
11+
### Changed
12+
- `interact2D`: replaced SimpleNamespace object with a dataclass for more explicit typing
13+
814
## [3.6.2]
915

1016
### Fixed

WrightTools/artists/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22

33
# flake8: noqa
44

5+
import pathlib
6+
for x in pathlib.Path(__file__).parent.walk():
7+
print(x)
58

9+
10+
from ._animate import *
611
from ._base import *
712
from ._colors import *
813
from ._helpers import *
9-
from ._quick import *
1014
from ._interact import *
15+
from ._quick import *

WrightTools/artists/_animate.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""library for making animations"""
2+
"""TODO: push these functions into WrightTools"""
3+
4+
import matplotlib.pyplot as plt
5+
import numpy as np
6+
7+
from functools import partial
8+
from matplotlib.animation import FuncAnimation
9+
10+
# typing
11+
from ._interact import interact2D_fig
12+
13+
__all__ = ["animate2D", "animate_interact2D"]
14+
15+
16+
def animate2D(
17+
d,
18+
cmap, norm,
19+
snake=False,
20+
back_and_forth=False,
21+
**ani_kwargs,
22+
):
23+
"""
24+
animate pcolormesh of a nd dataset (ndim >=2),
25+
mesh plots last two axes of the dataset (use `Data.transform` if needed)
26+
uses first channel in dataset (use `bring_to_front` if needed)
27+
28+
Note: snake, back_and_forth are not yet implemented are no-ops
29+
"""
30+
31+
# initialize canvas
32+
# need fig, ax, art, and norm to get this working
33+
fig, ax = plt.subplots(subplot_kw=dict(projection="wright"), dpi=140, layout="constrained")
34+
art = ax.pcolormesh(d[tuple([0 for i in d.shape[:-2]])], cmap=cmap, norm=norm)
35+
fig.colorbar(art, ax=ax)
36+
37+
# funcs for updating
38+
def title(ind):
39+
parts = [
40+
f"{var.natural_name} = {var[:].squeeze()[ind]:.2f} {var.units}"
41+
for var in map(lambda a: a.variables[0], d.axes[:-2])
42+
]
43+
return "\n".join(parts)
44+
45+
ax.set_title(title(0))
46+
47+
def update2D(frame, data, fig, ax, mesh, norm):
48+
print(frame)
49+
# for ind, axis in zip(frame, data.axes[:-2]):
50+
mesh.set_array(data.channels[0][frame])
51+
ax.set_title(title(frame))
52+
mesh.set_norm(norm)
53+
fig.canvas.draw_idle()
54+
return mesh
55+
56+
frames = list(np.ndindex(d.shape[:-2]))
57+
58+
return FuncAnimation(
59+
fig=fig,
60+
func=partial(update2D, data=d, mesh=art, fig=fig, ax=ax, norm=norm),
61+
frames=frames,
62+
**ani_kwargs,
63+
)
64+
65+
66+
def animate_interact2D(
67+
interact2D:interact2D_fig,
68+
snake=False,
69+
back_and_forth=False,
70+
**kwargs
71+
):
72+
"""
73+
Take an interact2D figure and create an animation by moving the sliders.
74+
75+
Note: snake, back_and_forth are not yet implemented are no-ops
76+
"""
77+
78+
def update(frame):
79+
print(frame)
80+
for ind, slider in zip(frame, interact2D.sliders.values()):
81+
slider.set_val(ind)
82+
83+
frames = list(np.ndindex(tuple([s.valmax+1 for s in interact2D.sliders.values()])))
84+
print(f"beginning animation: {len(frames)} frames to write")
85+
return FuncAnimation(
86+
fig=interact2D.fig,
87+
func=update,
88+
frames=frames,
89+
)
90+

WrightTools/artists/_interact.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,29 @@
44
import matplotlib as mpl
55
import matplotlib.pyplot as plt
66
from matplotlib.widgets import Slider, RadioButtons
7+
from typing import Any
78
from types import SimpleNamespace
89

10+
from dataclasses import dataclass
11+
912
from ._helpers import create_figure, plot_colorbar, add_sideplot
1013
from ._base import _order_for_imshow
1114
from ._colors import colormaps
1215
from ..exceptions import DimensionalityError
1316
from .. import kit as wt_kit
1417
from .. import data as wt_data
1518

16-
__all__ = ["interact2D"]
19+
__all__ = ["interact2D", "interact2D_fig"]
20+
21+
22+
@dataclass
23+
class interact2D_fig:
24+
fig:plt.figure
25+
image:Any
26+
sliders:dict[str, Slider]
27+
crosshairs:list
28+
radio:RadioButtons
29+
cax: plt.axes
1730

1831

1932
class Focus:
@@ -206,7 +219,7 @@ def interact2D(
206219
207220
Returns
208221
-------
209-
out : types.SimpleNamespace
222+
out : wt.artists.interact2D_fig
210223
container for important interactive elements of the plot.
211224
212225
Properties
@@ -583,11 +596,13 @@ def update_key_press(info):
583596
for slider in sliders.values():
584597
slider.on_changed(update_slider)
585598

586-
out = SimpleNamespace(
599+
return interact2D_fig(
600+
fig=fig,
587601
image=obj2D,
588602
sliders=sliders,
589603
crosshairs=[crosshair_hline, crosshair_vline],
590604
radio=radio,
591-
colorbar=colorbar,
605+
cax=cax,
592606
)
593-
return out
607+
608+

0 commit comments

Comments
 (0)