{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "import numpy as np\n",
    "import pyvista as pv\n",
    "\n",
    "pn.extension('vtk', sizing_mode=\"stretch_width\", template='fast')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Temporal function inspired from http://holoviews.org/user_guide/Live_Data.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "alpha = 2\n",
    "xvals  = np.linspace(-4, 4,101)\n",
    "yvals  = np.linspace(-4, 4,101)\n",
    "xs, ys = np.meshgrid(xvals, yvals)\n",
    "\n",
    "#temporal function to create data on a plane\n",
    "def time_function(time):\n",
    "    return np.sin(((ys/alpha)**alpha+time)*xs)\n",
    "\n",
    "# 3d plane to support the data\n",
    "mesh_ref = pv.UniformGrid(\n",
    "    dimensions=(xvals.size, yvals.size, 1), #dims\n",
    "    spacing=(xvals[1]-xvals[0],yvals[1]-yvals[0],1), #spacing\n",
    "    origin=(xvals.min(),yvals.min(),0) #origin\n",
    ")\n",
    "mesh_ref.point_data['values'] = time_function(0).flatten(order='F')  #add data for time=0\n",
    "pl_ref = pv.Plotter()\n",
    "pl_ref.add_mesh(mesh_ref, cmap='rainbow')\n",
    "\n",
    "pn.pane.VTK(pl_ref.ren_win, min_height=600)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will demonstrate how to warp the surface and plot a temporal animation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh_warped = mesh_ref.warp_by_scalar() # warp the mesh using data at time=0\n",
    "#create the pyvista plotter\n",
    "pl = pv.Plotter()\n",
    "pl.add_mesh(mesh_warped, cmap='rainbow')\n",
    "\n",
    "#initialize panel and widgets\n",
    "camera = {\n",
    "    'position': [13.443258285522461, 12.239550590515137, 12.731934547424316],\n",
    "    'focalPoint': [0, 0, 0],\n",
    "     'viewUp': [-0.41067028045654297, -0.40083757042884827, 0.8189500570297241]\n",
    "}\n",
    "vtkpan = pn.pane.VTK(pl.ren_win, orientation_widget=True, sizing_mode='stretch_both', camera=camera)\n",
    "frame = pn.widgets.Player(value=0, start=0, end=50, interval=100, loop_policy=\"reflect\", height=100)\n",
    "\n",
    "def update_3d_warp(event):\n",
    "    #the player value range in between 0 and 50, however we want time between 0 and 10\n",
    "    time = event.new/5\n",
    "    data = time_function(time).flatten(order='F')\n",
    "    mesh_ref.point_data['values'] = data\n",
    "    mesh_warped.point_data['values'] = data\n",
    "    mesh_warped.points = mesh_ref.warp_by_scalar(factor=0.5).points\n",
    "    vtkpan.synchronize()\n",
    "    \n",
    "frame.param.watch(update_3d_warp, 'value')\n",
    "\n",
    "pn.Column(\n",
    "    \"This app demonstrates the use of Panel to animate a `VTK` rendering.\",\n",
    "    frame,\n",
    "    vtkpan,\n",
    "    min_height=800\n",
    ").servable(title='VTK Warp')"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
