diff --git a/docs/source/api_reference/isocolor.rst b/docs/source/api_reference/isocolor.rst index 8ed7b61..0b47659 100644 --- a/docs/source/api_reference/isocolor.rst +++ b/docs/source/api_reference/isocolor.rst @@ -6,7 +6,7 @@ The ``IsoColor`` widget colorize your mesh given. .. note:: Currently, you can only use the default Viridis colormap, we'd like to support all paraview colormaps -The ``input`` attribute should be the name of the ``Component`` you want to use for colorizing the mesh. You also need to pass the ``min`` and ``max`` of the component array. +The ``input`` attribute should be the name of the ``Component`` you want to use for colorizing the mesh. You also need to pass the ``min`` and ``max`` (or ``range`` as a min/max tuple) of the component array. For example, if you have a 1-D ``Data`` named ``"height"``, you can simply pass its name as input: @@ -27,8 +27,8 @@ Examples .. jupyter-execute:: import numpy as np - from ipywidgets import FloatSlider, FloatRangeSlider, VBox, jslink - from ipygany import Scene, IsoColor, PolyMesh, Component + from ipywidgets import FloatSlider, FloatRangeSlider, Dropdown, Select, VBox, AppLayout, jslink + from ipygany import Scene, IsoColor, PolyMesh, Component, ColorBar, colormaps # Create triangle indices @@ -77,12 +77,24 @@ Examples colored_mesh = IsoColor(mesh, input='height', min=height_min, max=height_max) # Create a slider that will dynamically change the boundaries of the colormap - colormap_slider_min = FloatSlider(value=height_min, min=0., max=height_max) - colormap_slider_max = FloatSlider(value=height_max, min=0., max=height_max) - colormap_slider_range = FloatRangeSlider(value=[height_min, height_max], min=0., max=1.0, step=0.1) + colormap_slider_range = FloatRangeSlider(value=[height_min, height_max], min=height_min, max=height_max, step=(height_max - height_min) / 100.) - jslink((colored_mesh, 'min'), (colormap_slider_min, 'value')) - jslink((colored_mesh, 'max'), (colormap_slider_max, 'value')) jslink((colored_mesh, 'range'), (colormap_slider_range, 'value')) - VBox((Scene([colored_mesh]), colormap_slider_min, colormap_slider_max, colormap_slider_range)) + # Create a colorbar widget + colorbar = ColorBar(colored_mesh) + + # Colormap choice widget + colormap = Dropdown( + options=colormaps, + description='colormap:' + ) + + jslink((colored_mesh, 'colormap'), (colormap, 'index')) + + + AppLayout( + left_sidebar=Scene([colored_mesh]), + right_sidebar=VBox((colormap_slider_range, colormap, colorbar)), + pane_widths=[2, 0, 1] + ) diff --git a/docs/source/api_reference/threshold.rst b/docs/source/api_reference/threshold.rst index b902a14..32a232a 100644 --- a/docs/source/api_reference/threshold.rst +++ b/docs/source/api_reference/threshold.rst @@ -3,7 +3,7 @@ Threshold The ``Threshold`` widget hides part of your mesh for which the does not fit in a given range. -The ``input`` attribute should be the name of the ``Component`` you want to use for hiding the mesh. You also need to pass the ``min`` and ``max`` of that the component should respect. +The ``input`` attribute should be the name of the ``Component`` you want to use for hiding the mesh. You also need to pass the ``min`` and ``max`` (or ``range`` as a min/max tuple) of that the component should respect. For example, if you have a 1-D ``Data`` named ``"height"``, you can simply pass its name as input: @@ -74,12 +74,8 @@ Examples threshold_mesh = Threshold(mesh, input='height', min=height_min, max=height_max) # Create a slider that will dynamically change the boundaries of the threshold - threshold_slider_min = FloatSlider(value=height_min, min=-0.3, max=1., step=0.006) - threshold_slider_max = FloatSlider(value=height_max, min=-0.3, max=1., step=0.006) - threshold_slider_range = FloatRangeSlider(value=[height_min, height_max], min=-0.3, max=1.0, step=0.006) + threshold_slider_range = FloatRangeSlider(value=[height_min, height_max], min=height_min, max=height_max, step=(height_max - height_min) / 100.) - jslink((threshold_mesh, 'min'), (threshold_slider_min, 'value')) - jslink((threshold_mesh, 'max'), (threshold_slider_max, 'value')) jslink((threshold_mesh, 'range'), (threshold_slider_range, 'value')) - VBox((Scene([threshold_mesh]), threshold_slider_min, threshold_slider_max, threshold_slider_range)) + VBox((Scene([threshold_mesh]), threshold_slider_range)) diff --git a/examples/isocolor.ipynb b/examples/isocolor.ipynb new file mode 100644 index 0000000..cc90e63 --- /dev/null +++ b/examples/isocolor.ipynb @@ -0,0 +1,114 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "coral-breed", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from ipywidgets import FloatSlider, FloatRangeSlider, Dropdown, Select, VBox, AppLayout, jslink\n", + "from ipygany import Scene, IsoColor, PolyMesh, Component, ColorBar, colormaps\n", + "\n", + "\n", + "# Create triangle indices\n", + "nx = 100\n", + "ny = 100\n", + "\n", + "triangle_indices = np.empty((ny - 1, nx - 1, 2, 3), dtype=int)\n", + "\n", + "r = np.arange(nx * ny).reshape(ny, nx)\n", + "\n", + "triangle_indices[:, :, 0, 0] = r[:-1, :-1]\n", + "triangle_indices[:, :, 1, 0] = r[:-1, 1:]\n", + "triangle_indices[:, :, 0, 1] = r[:-1, 1:]\n", + "\n", + "triangle_indices[:, :, 1, 1] = r[1:, 1:]\n", + "triangle_indices[:, :, :, 2] = r[1:, :-1, None]\n", + "\n", + "triangle_indices.shape = (-1, 3)\n", + "\n", + "# Create vertices\n", + "x = np.arange(-5, 5, 10/nx)\n", + "y = np.arange(-5, 5, 10/ny)\n", + "\n", + "xx, yy = np.meshgrid(x, y, sparse=True)\n", + "\n", + "z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)\n", + "\n", + "vertices = np.empty((ny, nx, 3))\n", + "vertices[:, :, 0] = xx\n", + "vertices[:, :, 1] = yy\n", + "vertices[:, :, 2] = z\n", + "vertices = vertices.reshape(nx * ny, 3)\n", + "\n", + "height_component = Component(name='value', array=z)\n", + "\n", + "mesh = PolyMesh(\n", + " vertices=vertices,\n", + " triangle_indices=triangle_indices,\n", + " data={'height': [height_component]}\n", + ")\n", + "\n", + "height_min = np.min(z)\n", + "height_max = np.max(z)\n", + "\n", + "# Colorize by height\n", + "colored_mesh = IsoColor(mesh, input='height', min=height_min, max=height_max)\n", + "\n", + "# Create a slider that will dynamically change the boundaries of the colormap\n", + "colormap_slider_range = FloatRangeSlider(value=[height_min, height_max], min=height_min, max=height_max, step=(height_max - height_min) / 100.)\n", + "\n", + "jslink((colored_mesh, 'range'), (colormap_slider_range, 'value'))\n", + "\n", + "# Create a colorbar widget\n", + "colorbar = ColorBar(colored_mesh)\n", + "\n", + "# Colormap choice widget\n", + "colormap = Dropdown(\n", + " options=colormaps,\n", + " description='colormap:'\n", + ")\n", + "\n", + "jslink((colored_mesh, 'colormap'), (colormap, 'index'))\n", + "\n", + "\n", + "AppLayout(\n", + " left_sidebar=Scene([colored_mesh]), \n", + " right_sidebar=VBox((colormap_slider_range, colormap, colorbar)),\n", + " pane_widths=[2, 0, 1]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "romance-inquiry", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/ipygany/colormaps.py b/ipygany/colormaps.py index 75e6fe0..96d0f2a 100644 --- a/ipygany/colormaps.py +++ b/ipygany/colormaps.py @@ -1,42 +1,42 @@ from traitlets.utils.bunch import Bunch colormaps = Bunch( - BrBG='BrBG', - PRGn='PRGn', - PiYG='PiYG', - PuOr='PuOr', - RdBu='RdBu', - RdGy='RdGy', - RdYlBu='RdYlBu', - RdYlGn='RdYlGn', - Spectral='Spectral', - BuGn='BuGn', - BuPu='BuPu', - GnBu='GnBu', - OrRd='OrRd', - PuBuGn='PuBuGn', - PuBu='PuBu', - PuRd='PuRd', - RdPu='RdPu', - YlGnBu='YlGnBu', - YlGn='YlGn', - YlOrBr='YlOrBr', - YlOrRd='YlOrRd', - Blues='Blues', - Greens='Greens', - Greys='Greys', - Purples='Purples', - Reds='Reds', - Oranges='Oranges', - Cividis='Cividis', - CubehelixDefault='CubehelixDefault', - Rainbow='Rainbow', - Warm='Warm', - Cool='Cool', - Sinebow='Sinebow', - Turbo='Turbo', - Viridis='Viridis', - Magma='Magma', - Inferno='Inferno', - Plasma='Plasma' + BrBG=0, + PRGn=1, + PiYG=2, + PuOr=3, + RdBu=4, + RdGy=5, + RdYlBu=6, + RdYlGn=7, + Spectral=8, + BuGn=9, + BuPu=10, + GnBu=11, + OrRd=12, + PuBuGn=13, + PuBu=14, + PuRd=15, + RdPu=16, + YlGnBu=17, + YlGn=18, + YlOrBr=19, + YlOrRd=20, + Blues=21, + Greens=22, + Greys=23, + Purples=24, + Reds=25, + Oranges=26, + Cividis=27, + CubehelixDefault=28, + Rainbow=29, + Warm=30, + Cool=31, + Sinebow=32, + Turbo=33, + Viridis=34, + Magma=35, + Inferno=36, + Plasma=37 ) diff --git a/src/widget.ts b/src/widget.ts index bd1f3a8..d8bde87 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -27,6 +27,14 @@ import { Water, UnderWater, } from 'ganyjs'; +const colormaps: string[] = [ + 'BrBG', 'PRGn', 'PiYG', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', + 'Spectral', 'BuGn', 'BuPu', 'GnBu', 'OrRd', 'PuBuGn', 'PuBu', 'PuRd', 'RdPu', + 'YlGnBu', 'YlGn', 'YlOrBr', 'YlOrRd', 'Blues', 'Greens', 'Greys', 'Purples', 'Reds', + 'Oranges', 'Cividis', 'CubehelixDefault', 'Rainbow', 'Warm', 'Cool', 'Sinebow', 'Turbo', + 'Viridis', 'Magma', 'Inferno', 'Plasma' +] + function deserialize_float32array (data: any, manager: any) { return new Float32Array(data.data.buffer); @@ -498,7 +506,7 @@ class IsoColorModel extends EffectModel { min: 0., max: 0., range: [0., 0.], - colormap: 'Viridis', + colormap: 34, type: 'linear', }; } @@ -528,7 +536,7 @@ class IsoColorModel extends EffectModel { } get colormap () : string { - return this.get('colormap'); + return colormaps[this.get('colormap')]; } get type () {