Skip to content

Commit

Permalink
deploy: 7021e10
Browse files Browse the repository at this point in the history
  • Loading branch information
ksunden committed Aug 16, 2024
0 parents commit ad931a3
Show file tree
Hide file tree
Showing 157 changed files with 37,645 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .buildinfo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 4aee839fe731f715ff87f679f4fdb3db
tags: 33eac41acc08762151beb8f3b7b86c8f
Empty file added .nojekyll
Empty file.
Binary file not shown.
43 changes: 43 additions & 0 deletions _downloads/0e7d7952485b73289daa910c8be00ede/units.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n# Using pint units with PathCollectionWrapper\n\nUsing third party units functionality in conjunction with Matplotlib Axes\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\nfrom collections import defaultdict\n\nimport matplotlib.pyplot as plt\nimport matplotlib.markers as mmarkers\n\nfrom data_prototype.artist import CompatibilityAxes\nfrom data_prototype.containers import ArrayContainer\nfrom data_prototype.conversion_edge import FuncEdge\nfrom data_prototype.description import Desc\n\nfrom data_prototype.line import Line\n\nimport pint\n\nureg = pint.UnitRegistry()\nureg.setup_matplotlib()\n\nmarker_obj = mmarkers.MarkerStyle(\"o\")\n\n\ncoords = defaultdict(lambda: \"auto\")\ncoords[\"x\"] = coords[\"y\"] = \"units\"\ncont = ArrayContainer(\n coords,\n x=np.array([0, 1, 2]) * ureg.m,\n y=np.array([1, 4, 2]) * ureg.m,\n paths=np.array([marker_obj.get_path()]),\n sizes=np.array([12]),\n edgecolors=np.array([\"k\"]),\n facecolors=np.array([\"C3\"]),\n)\n\nfig, nax = plt.subplots()\nax = CompatibilityAxes(nax)\nnax.add_artist(ax)\nax.set_xlim(-0.5, 7)\nax.set_ylim(0, 5)\n\nscalar = Desc((), \"units\")\nunit_vector = Desc((\"N\",), \"units\")\n\nxconv = FuncEdge.from_func(\n \"xconv\",\n lambda x, xunits: x.to(xunits).magnitude,\n {\"x\": unit_vector, \"xunits\": scalar},\n {\"x\": Desc((\"N\",), \"data\")},\n)\nyconv = FuncEdge.from_func(\n \"yconv\",\n lambda y, yunits: y.to(yunits).magnitude,\n {\"y\": unit_vector, \"yunits\": scalar},\n {\"y\": Desc((\"N\",), \"data\")},\n)\nlw = Line(cont, [xconv, yconv])\n\nax.add_artist(lw)\nnax.xaxis.set_units(ureg.ft)\nnax.yaxis.set_units(ureg.m)\n\nplt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
94 changes: 94 additions & 0 deletions _downloads/12252586a39c52c1e308241c43ab220c/lissajous.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""
==========================
An animated lissajous ball
==========================
Inspired by https://twitter.com/_brohrer_/status/1584681864648065027
An animated scatter plot using a custom container and :class:`.wrappers.PathCollectionWrapper`
"""

import time
from typing import Dict, Tuple, Any, Union
from functools import partial

import numpy as np

import matplotlib.pyplot as plt
import matplotlib.markers as mmarkers
from matplotlib.animation import FuncAnimation

from data_prototype.conversion_edge import Graph
from data_prototype.description import Desc

from data_prototype.wrappers import PathCollectionWrapper


class Lissajous:
N = 1024
# cycles per minutes
scale = 2

def describe(self):
return {
"x": Desc((self.N,)),
"y": Desc((self.N,)),
"time": Desc(()),
"sizes": Desc(()),
"paths": Desc(()),
"edgecolors": Desc(()),
"facecolors": Desc((self.N,)),
}

def query(
self,
graph: Graph,
parent_coordinates: str = "axes",
) -> Tuple[Dict[str, Any], Union[str, int]]:
def next_time():
cur_time = time.time()
cur_time = np.array(
[cur_time, cur_time - 0.1, cur_time - 0.2, cur_time - 0.3]
)

phase = 15 * np.pi * (self.scale * cur_time % 60) / 150
marker_obj = mmarkers.MarkerStyle("o")
return {
"x": np.cos(5 * phase),
"y": np.sin(3 * phase),
"sizes": np.array([256]),
"paths": [
marker_obj.get_path().transformed(marker_obj.get_transform())
],
"edgecolors": "k",
"facecolors": ["#4682b4ff", "#82b446aa", "#46b48288", "#8246b433"],
"time": cur_time[0],
}, hash(cur_time[0])

return next_time()


def update(frame, art):
return art


sot_c = Lissajous()

fig, ax = plt.subplots()
ax.set_xlim(-1.1, 1.1)
ax.set_ylim(-1.1, 1.1)
lw = PathCollectionWrapper(sot_c, offset_transform=ax.transData)
ax.add_artist(lw)
# ax.set_xticks([])
# ax.set_yticks([])
ax.set_aspect(1)
ani = FuncAnimation(
fig,
partial(update, art=(lw,)),
frames=60,
interval=1000 / 100 * 15,
# TODO: blitting does not work because wrappers do not inherent from Artist
# blit=True,
)
plt.show()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
43 changes: 43 additions & 0 deletions _downloads/1c53d85aadacff2886f767f44fd5bfe2/widgets.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n# Slider\n\nIn this example, sliders are used to control the frequency and amplitude of\na sine wave.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import inspect\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom matplotlib.widgets import Slider, Button\n\nfrom data_prototype.artist import CompatibilityArtist as CA\nfrom data_prototype.line import Line\nfrom data_prototype.containers import FuncContainer\nfrom data_prototype.description import Desc\nfrom data_prototype.conversion_edge import FuncEdge\n\n\nclass SliderContainer(FuncContainer):\n def __init__(self, xfuncs, /, **sliders):\n self._sliders = sliders\n for slider in sliders.values():\n slider.on_changed(\n lambda _, sld=slider: sld.ax.figure.canvas.draw_idle(),\n )\n\n def get_needed_keys(f, offset=1):\n return tuple(inspect.signature(f).parameters)[offset:]\n\n super().__init__(\n {\n k: (\n s,\n # this line binds the correct sliders to the functions\n # and makes lambdas that match the API FuncContainer needs\n lambda x, keys=get_needed_keys(f), f=f: f(\n x, *(sliders[k].val for k in keys)\n ),\n )\n for k, (s, f) in xfuncs.items()\n },\n )\n\n def _query_hash(self, graph, parent_coordinates):\n key = super()._query_hash(graph, parent_coordinates)\n # inject the slider values into the hashing logic\n return hash((key, tuple(s.val for s in self._sliders.values())))\n\n\n# Define initial parameters\ninit_amplitude = 5\ninit_frequency = 3\n\n# Create the figure and the line that we will manipulate\nfig, ax = plt.subplots()\nax.set_xlim(0, 1)\nax.set_ylim(-7, 7)\n\nax.set_xlabel(\"Time [s]\")\n\n# adjust the main plot to make room for the sliders\nfig.subplots_adjust(left=0.25, bottom=0.25, right=0.75)\n\n# Make a horizontal slider to control the frequency.\naxfreq = fig.add_axes([0.25, 0.1, 0.65, 0.03])\nfreq_slider = Slider(\n ax=axfreq,\n label=\"Frequency [Hz]\",\n valmin=0.1,\n valmax=30,\n valinit=init_frequency,\n)\n\n# Make a vertically oriented slider to control the amplitude\naxamp = fig.add_axes([0.1, 0.25, 0.0225, 0.63])\namp_slider = Slider(\n ax=axamp,\n label=\"Amplitude\",\n valmin=0,\n valmax=10,\n valinit=init_amplitude,\n orientation=\"vertical\",\n)\n\n# Make a vertically oriented slider to control the phase\naxphase = fig.add_axes([0.85, 0.25, 0.0225, 0.63])\nphase_slider = Slider(\n ax=axphase,\n label=\"Phase [rad]\",\n valmin=-2 * np.pi,\n valmax=2 * np.pi,\n valinit=0,\n orientation=\"vertical\",\n)\n\n# pick a cyclic color map\ncmap = plt.get_cmap(\"twilight\")\n\n# set up the data container\nfc = SliderContainer(\n {\n # the x data does not need the sliders values\n \"x\": ((\"N\",), lambda t: t),\n \"y\": (\n (\"N\",),\n # the y data needs all three sliders\n lambda t, amplitude, frequency, phase: amplitude\n * np.sin(2 * np.pi * frequency * t + phase),\n ),\n # the color data has to take the x (because reasons), but just\n # needs the phase\n \"color\": ((1,), lambda _, phase: phase),\n },\n # bind the sliders to the data container\n amplitude=amp_slider,\n frequency=freq_slider,\n phase=phase_slider,\n)\nlw = Line(\n fc,\n # color map phase (scaled to 2pi and wrapped to [0, 1])\n [\n FuncEdge.from_func(\n \"color\",\n lambda color: cmap((color / (2 * np.pi)) % 1),\n {\"color\": Desc((1,))},\n {\"color\": Desc((), \"display\")},\n )\n ],\n linewidth=5.0,\n linestyle=\"-\",\n)\nax.add_artist(CA(lw))\n\n\n# Create a `matplotlib.widgets.Button` to reset the sliders to initial values.\nresetax = fig.add_axes([0.8, 0.025, 0.1, 0.04])\nbutton = Button(resetax, \"Reset\", hovercolor=\"0.975\")\nbutton.on_clicked(\n lambda _: [sld.reset() for sld in (freq_slider, amp_slider, phase_slider)]\n)\n\nplt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
43 changes: 43 additions & 0 deletions _downloads/1d0b7c60915fdc25194d452d702ef50d/mulivariate_cmap.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n# Custom bivariate colormap\n\n\nUsing ``nu`` functions to account for two values when computing the color\nof each pixel.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom data_prototype.wrappers import ImageWrapper\nfrom data_prototype.containers import FuncContainer\nfrom data_prototype.conversion_node import FunctionConversionNode\n\nfrom matplotlib.colors import hsv_to_rgb\n\n\ndef func(x, y):\n return (\n (np.sin(x).reshape(1, -1) * np.cos(y).reshape(-1, 1)) ** 2,\n np.arctan2(np.cos(y).reshape(-1, 1), np.sin(x).reshape(1, -1)),\n )\n\n\ndef image_nu(image):\n saturation, angle = image\n hue = (angle + np.pi) / (2 * np.pi)\n value = np.ones_like(hue)\n return np.clip(hsv_to_rgb(np.stack([hue, saturation, value], axis=2)), 0, 1)\n\n\nfc = FuncContainer(\n {},\n xyfuncs={\n \"xextent\": ((2,), lambda x, y: [x[0], x[-1]]),\n \"yextent\": ((2,), lambda x, y: [y[0], y[-1]]),\n \"image\": ((\"N\", \"M\", 2), func),\n },\n)\n\nim = ImageWrapper(fc, FunctionConversionNode.from_funcs({\"image\": image_nu}))\n\nfig, ax = plt.subplots()\nax.add_artist(im)\nax.set_xlim(-5, 5)\nax.set_ylim(-5, 5)\nplt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
43 changes: 43 additions & 0 deletions _downloads/1dfc18ed16c3e8e6146b6197b56ecc2f/mapped.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n# Mapping Line Properties\n\nLeveraging the converter functions to transform users space data to visualization data.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom matplotlib.colors import Normalize\n\nfrom data_prototype.wrappers import FormattedText\nfrom data_prototype.artist import CompatibilityArtist as CA\nfrom data_prototype.line import Line\nfrom data_prototype.containers import ArrayContainer\nfrom data_prototype.description import Desc\nfrom data_prototype.conversion_node import FunctionConversionNode\nfrom data_prototype.conversion_edge import FuncEdge\n\n\ncmap = plt.colormaps[\"viridis\"]\ncmap.set_over(\"k\")\ncmap.set_under(\"r\")\nnorm = Normalize(1, 8)\n\nline_edges = [\n FuncEdge.from_func(\n \"lw\",\n lambda lw: min(1 + lw, 5),\n {\"lw\": Desc((), \"auto\")},\n {\"linewidth\": Desc((), \"display\")},\n ),\n # Probably should separate out norm/cmap step\n # Slight lie about color being a string here, because of limitations in impl\n FuncEdge.from_func(\n \"cmap\",\n lambda j: cmap(norm(j)),\n {\"j\": Desc((), \"auto\")},\n {\"color\": Desc((), \"display\")},\n ),\n FuncEdge.from_func(\n \"ls\",\n lambda cat: {\"A\": \"-\", \"B\": \":\", \"C\": \"--\"}[cat],\n {\"cat\": Desc((), \"auto\")},\n {\"linestyle\": Desc((), \"display\")},\n ),\n]\n\ntext_converter = FunctionConversionNode.from_funcs(\n {\n \"text\": lambda j, cat: f\"index={j[()]} class={cat!r}\",\n \"y\": lambda j: j,\n \"x\": lambda x: 2 * np.pi,\n },\n)\n\n\nth = np.linspace(0, 2 * np.pi, 128)\ndelta = np.pi / 9\n\nfig, ax = plt.subplots()\n\nfor j in range(10):\n ac = ArrayContainer(\n **{\n \"x\": th,\n \"y\": np.sin(th + j * delta) + j,\n \"j\": np.asarray(j),\n \"lw\": np.asarray(j),\n \"cat\": {0: \"A\", 1: \"B\", 2: \"C\"}[j % 3],\n }\n )\n ax.add_artist(\n CA(\n Line(\n ac,\n line_edges,\n )\n )\n )\n ax.add_artist(\n FormattedText(\n ac,\n text_converter,\n x=2 * np.pi,\n ha=\"right\",\n bbox={\"facecolor\": \"gray\", \"alpha\": 0.5},\n )\n )\nax.set_xlim(0, np.pi * 2)\nax.set_ylim(-1.1, 10.1)\n\nplt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
88 changes: 88 additions & 0 deletions _downloads/1f0966d964d55653ad834adb5f7aa687/animation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""
================
An animated line
================
An animated line using a custom container class,
:class:`.wrappers.LineWrapper`, and :class:`.wrappers.FormattedText`.
"""

import time
from typing import Dict, Tuple, Any, Union
from functools import partial

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

from data_prototype.conversion_edge import Graph
from data_prototype.description import Desc

from data_prototype.conversion_node import FunctionConversionNode

from data_prototype.wrappers import FormattedText
from data_prototype.artist import CompatibilityArtist as CA
from data_prototype.line import Line


class SinOfTime:
N = 1024
# cycles per minutes
scale = 10

def describe(self):
return {
"x": Desc((self.N,)),
"y": Desc((self.N,)),
"phase": Desc(()),
"time": Desc(()),
}

def query(
self,
graph: Graph,
parent_coordinates: str = "axes",
) -> Tuple[Dict[str, Any], Union[str, int]]:
th = np.linspace(0, 2 * np.pi, self.N)

cur_time = time.time()

phase = 2 * np.pi * (self.scale * cur_time % 60) / 60
return {
"x": th,
"y": np.sin(th + phase),
"phase": phase,
"time": cur_time,
}, hash(cur_time)


def update(frame, art):
return art


sot_c = SinOfTime()
lw = CA(Line(sot_c, linewidth=5, color="green", label="sin(time)"))
fc = FormattedText(
sot_c,
FunctionConversionNode.from_funcs(
{"text": lambda phase: f"ϕ={phase:.2f}", "x": lambda: 2 * np.pi, "y": lambda: 1}
),
ha="right",
)
fig, ax = plt.subplots()
ax.add_artist(lw)
ax.add_artist(fc)
ax.set_xlim(0, 2 * np.pi)
ax.set_ylim(-1.1, 1.1)
ani = FuncAnimation(
fig,
partial(update, art=(lw, fc)),
frames=25,
interval=1000 / 60,
# TODO: blitting does not work because wrappers do not inherent from Artist
# blit=True,
)

plt.show()
Loading

0 comments on commit ad931a3

Please sign in to comment.