{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Lookup Tables {#lookup_table_example}\n\nDemonstrate the usage of a lookup table within PyVista\n\nThe `pyvista.LookupTable`{.interpreted-text role=\"class\"} can be used to\nhave fine-tuned control over the mapping between a\n`pyvista.DataSet`{.interpreted-text role=\"class\"}\\'s scalars and RGBA\ncolors.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import pyvista as pv\nfrom pyvista import examples\n\n\n# download an example dataset\nbracket = examples.download_fea_bracket().cell_data_to_point_data()\nbracket" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Default Color Map - Lookup Table\n\nFirst, let\\'s plot using the default color map, \\\"viridis\\\". Internally,\nPyVista will automatically create a lookup table to map the scalars\n(stored here within [point_data]{.title-ref}) to RGBA colors. This is\nshown here as a nested attribute to the\n`pyvista.DataSetMapper`{.interpreted-text role=\"class\"} and it has a\nhelpful `repr` method:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pl = pv.Plotter()\nactor = pl.add_mesh(bracket)\nactor.mapper.lookup_table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Plot the Lookup Table\n\nYou can also plot lookup table to see the mapping between the scalar\nvalues (here, between 0 and 23.3) and RGBA colors.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pl = pv.Plotter()\nactor = pl.add_mesh(bracket)\nactor.mapper.lookup_table.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Plot the DataSet\n\nLet\\'s plot the dataset using the automatically generated lookup table.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pl = pv.Plotter()\npl.add_mesh(bracket)\npl.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Create a Custom Lookup Table using a Matplotlib Color Map\n\nHere we create a lookup table with a narrow table range (same as `clim`)\nand color values above and below the range.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "lut = pv.LookupTable(cmap='magma')\nlut.scalar_range = (5, 15)\nlut.below_range_color = pv.Color('grey', opacity=0.5)\nlut.above_range_color = 'r'\nlut.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Plot the bracket with the custom colormap\n\nYou can set assign the lookup table when using `add_mesh` with `cmap=`.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pl = pv.Plotter()\nactor = pl.add_mesh(bracket, cmap=lut, lighting=False)\npl.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Create a Custom Lookup Table using VTK\\'s Methods\n\nIf you want to create a completely unique color map, you can use\nattributes like `pyvista.LookupTable.hue_range`{.interpreted-text\nrole=\"attr\"} and `pyvista.LookupTable.value_range`{.interpreted-text\nrole=\"attr\"} to create your own lookup table.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "lut = pv.LookupTable()\nlut.value_range = (0.35, 1) # dark grey to white\nlut.hue_range = (0.35, 0.7) # green to cyna\nlut.saturation_range = (0.75, 0.5) # reduce saturation near the upper end\nlut.alpha_range = (0.0, 0.9) #\nlut.scalar_range = (2, 18)\nlut.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Plot the bracket with the custom colormap\n\nAssign this custom color map to the plotter and disable lighting to\nimprove the plot.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pl = pv.Plotter()\nactor = pl.add_mesh(bracket, cmap=lut, lighting=False)\npl.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Custom colormap with widgets\n\nHere we plot the scalars and dynamically change the lookup table through\nwidgets. We create several overlapping single slider widgets to simulate\na double ended slider widget.\n\nThis example just controls the alpha channel.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pl = pv.Plotter()\nactor = pl.add_mesh(bracket, cmap=lut, lighting=False)\npl.add_text('Alpha Range Demo')\n\n\ndef set_min_alpha(min_value):\n max_value = lut.alpha_range[1]\n if min_value > max_value:\n # force the movement of the maximum value\n max_value = min_value\n pl.slider_widgets[1].GetRepresentation().SetValue(max_value)\n lut.alpha_range = (min_value, max_value)\n\n\ndef set_max_alpha(max_value):\n min_value = lut.alpha_range[0]\n if max_value < min_value:\n # force the movement of the minimum value\n min_value = max_value\n pl.slider_widgets[0].GetRepresentation().SetValue(min_value)\n\n lut.alpha_range = (min_value, max_value)\n\n\n# create two overlapping slider bars by hiding the tube of the second\npl.add_slider_widget(\n set_min_alpha,\n (0, 1),\n value=lut.alpha_range[0],\n interaction_event='always',\n title='Alpha Range',\n tube_width=0.003,\n)\npl.add_slider_widget(\n set_max_alpha,\n (0, 1),\n value=lut.alpha_range[1],\n interaction_event='always',\n tube_width=0.0,\n)\n\npl.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Control Several Lookup Table Attributes\n\nDemonstrate the use of several slider bar widgets with lookup table\ncallbacks.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Create a new lookup table with oranges\nlut = pv.LookupTable()\nlut.value_range = (0.3, 0.75)\nlut.hue_range = (0.0, 0.095)\nlut.saturation_range = (0.0, 0.67)\nlut.alpha_range = (0.0, 1.0)\nlut.scalar_range = (2, 18)\n\nscalars_rng = (bracket.active_scalars.min(), bracket.active_scalars.max())\n\n\ndef make_double_slider(attr, idx):\n \"\"\"Create a double slider for a given lookup table attribute.\"\"\"\n\n def set_min(min_value):\n max_value = getattr(lut, attr)[1]\n if min_value > max_value:\n # force the movement of the maximum value\n max_value = min_value\n pl.slider_widgets[idx * 2 + 1].GetRepresentation().SetValue(max_value)\n setattr(lut, attr, (min_value, max_value))\n\n if attr == 'scalar_range':\n actor.mapper.scalar_range = getattr(lut, attr)\n\n def set_max(max_value):\n min_value = getattr(lut, attr)[0]\n if max_value < min_value:\n # force the movement of the minimum value\n min_value = max_value\n pl.slider_widgets[idx * 2].GetRepresentation().SetValue(min_value)\n setattr(lut, attr, (min_value, max_value))\n\n if attr == 'scalar_range':\n actor.mapper.scalar_range = getattr(lut, attr)\n\n rng = scalars_rng if attr == 'scalar_range' else (0, 1)\n\n # create two overlapping slider bars by hiding the tube of the second\n pl.add_slider_widget(\n set_min,\n rng,\n value=getattr(lut, attr)[0],\n interaction_event='always',\n title=' '.join(attr.split('_')).capitalize(),\n tube_width=0.003,\n pointa=(0.6, 0.9 - 0.165 * idx),\n pointb=(0.9, 0.9 - 0.165 * idx),\n )\n pl.add_slider_widget(\n set_max,\n rng,\n value=getattr(lut, attr)[1],\n interaction_event='always',\n tube_width=0.0,\n pointa=(0.6, 0.9 - 0.165 * idx),\n pointb=(0.9, 0.9 - 0.165 * idx),\n )\n\n\npl = pv.Plotter()\nactor = pl.add_mesh(bracket, cmap=lut, lighting=False)\nmake_double_slider('alpha_range', 0)\nmake_double_slider('hue_range', 1)\nmake_double_slider('value_range', 2)\nmake_double_slider('saturation_range', 3)\nmake_double_slider('scalar_range', 4)\n\npl.camera_position = [(9.021, 5.477, 7.780), (-0.679, 1.349, 0.874), (-0.498, -0.228, 0.836)]\ncpos = pl.show(return_cpos=True)" ] } ], "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.12.2" } }, "nbformat": 4, "nbformat_minor": 0 }