Skip to content
Snippets Groups Projects
CanvasEditor.ipynb 17.2 KiB
Newer Older
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Jupyter Canvas Widget - Rail Editor\n",
    "\n",
    "From - https://github.com/Who8MyLunch/Jupyter_Canvas_Widget/blob/master/notebooks/example%20mouse%20events.ipynb\n",
    "Follow his instructions to do a local dev install and enable the widget."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## You need to run all cells before trying to edit the rails!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import image_attendant as imat\n",
    "import ipywidgets\n",
    "import IPython\n",
    "import jpy_canvas\n",
    "import numpy as np\n",
    "from numpy import array\n",
    "import time\n",
    "from collections import deque\n",
    "from matplotlib import pyplot as plt\n",
    "import io\n",
    "from PIL import Image"
   ]
  },
  {
   "cell_type": "code",
hagrid67's avatar
hagrid67 committed
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ipywidgets import IntSlider, link, VBox, RadioButtons, HBox, interact"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
hagrid67's avatar
hagrid67 committed
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cpu\n"
     ]
    }
   ],
   "source": [
    "import flatland.core.env\n",
    "from flatland.envs.rail_env import RailEnv, random_rail_generator\n",
    "from flatland.core.transitions import RailEnvTransitions\n",
    "from flatland.core.env_observation_builder import TreeObsForRailEnv\n",
    "import flatland.utils.rendertools as rt\n",
    "from flatland.utils.editor import JupEditor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>.container { width:90% !important; }</style>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.core.display import display, HTML\n",
    "display(HTML(\"<style>.container { width:90% !important; }</style>\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "oEnv = RailEnv(width=20,\n",
    "              height=20,\n",
    "              rail_generator=random_rail_generator(cell_type_relative_proportion=[1,1] + [0.5] * 6),\n",
    "              number_of_agents=0,\n",
    "              obs_builder_object=TreeObsForRailEnv(max_depth=2))\n",
    "obs = oEnv.reset()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "sfEnv = \"../flatland/env-data/tests/test1.npy\"\n",
    "if True:\n",
    "    oEnv.rail.load_transition_map(sfEnv)\n",
    "    oEnv.width = oEnv.rail.width\n",
    "    oEnv.height = oEnv.rail.height"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "oRT = rt.RenderTool(oEnv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "oEnv.width"
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['/home/jeremy/projects/heating',\n",
       " '/home/jeremy/projects/aicrowd/rl-trains/MAgent/python',\n",
       " '/home/jeremy/ve367/lib/python36.zip',\n",
       " '/home/jeremy/ve367/lib/python3.6',\n",
       " '/home/jeremy/ve367/lib/python3.6/lib-dynload',\n",
       " '/usr/lib/python3.6',\n",
       " '',\n",
       " '/home/jeremy/ve367/lib/python3.6/site-packages',\n",
       " '/home/jeremy/projects/aicrowd/rl-trains/torch-rl/torch_rl',\n",
       " '/home/jeremy/projects/aicrowd/rl-trains/gym-minigrid',\n",
       " '/home/jeremy/projects/aicrowd/rl-trains/flatland',\n",
       " '/home/jeremy/projects/aicrowd/rl-trains/Jupyter_Canvas_Widget',\n",
       " '/home/jeremy/ve367/lib/python3.6/site-packages/IPython/extensions',\n",
       " '/home/jeremy/.ipython']"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sys\n",
    "sys.path"
   ]
  },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Clear the rails"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "oEnv.rail.grid[:,:] = 0"
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Render the env in the usual way, and take an image snapshot as numpy array\n",
    "If you have already edited the env in the cell below, these changes should be reflected here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 720x720 with 0 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "oFig = plt.figure(figsize=(10,10))\n",
    "oRT.renderEnv(spacing=False, arrows=False, sRailColor=\"gray\", show=False)\n",
    "img = oRT.getImage()\n",
    "print(type(img))\n",
    "plt.clf()   # if you don't want the image to appear here\n",
    "pass\n",
    "\n",
    "wid_img = jpy_canvas.Canvas(img)"
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Update the function - in case external code updated"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "source": [
    "wid_img.unregister_all()\n",
    "oEditor = JupEditor(oEnv, wid_img)\n",
hagrid67's avatar
hagrid67 committed
    "wid_img.register_move(oEditor.event_handler)\n",
    "wid_img.register_click(oEditor.on_click)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Some more widgets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "wid_drawMode = ipywidgets.RadioButtons(options=[\"Draw\", \"Erase\", \"Origin\", \"Destination\"])\n",
    "wid_drawMode.observe(oEditor.setDrawMode, names=\"value\")\n",
    "wid_debug = ipywidgets.Checkbox(description = \"Debug\")\n",
    "wid_debug.observe(oEditor.setDebug, names=\"value\")\n",
    "wid_debug_move = ipywidgets.Checkbox(description = \"Debug mouse move\")\n",
    "wid_debug_move.observe(oEditor.setDebugMove, names=\"value\")\n",
    "\n",
    "wid_output = ipywidgets.Output()\n",
    "oEditor.setOutput(wid_output)\n",
    "wid_filename = ipywidgets.Text(description = \"Filename\")\n",
    "wid_filename.value = sfEnv\n",
    "oEditor.setFilename(sfEnv)\n",
    "wid_filename.observe(oEditor.setFilename_event, names=\"value\")\n",
    "\n",
    "wid_size = ipywidgets.IntSlider(min=5, max=30, step=5, description=\"Regen Size\")\n",
    "wid_size.observe(oEditor.setRegenSize_event, names=\"value\")\n",
    "\n",
hagrid67's avatar
hagrid67 committed
    "prog_steps = ipywidgets.IntProgress(value=0, min=0, max=20, step=1, description=\"Step\")\n",
    "#prog_steps.observe(oEditor.)\n",
    "\n",
    "\n",
    "ldButtons = [\n",
    "    dict(name = \"Refresh\", method = oEditor.redraw_event),\n",
    "    dict(name = \"Clear\", method = oEditor.clear),\n",
    "    dict(name = \"Regenerate\", method = oEditor.regenerate_event),\n",
    "    dict(name = \"Load\", method = oEditor.load),\n",
hagrid67's avatar
hagrid67 committed
    "    dict(name = \"Save\", method = oEditor.save),\n",
    "    dict(name = \"Step\", method = oEditor.step_event),\n",
    "    dict(name = \"Run Steps\", method = oEditor.start_run_event),\n",
    "]\n",
    "\n",
    "lwid_buttons = []\n",
    "for dButton in ldButtons:\n",
    "    wid_button = ipywidgets.Button(description = dButton[\"name\"])\n",
    "    wid_button.on_click(dButton[\"method\"])\n",
    "    lwid_buttons.append(wid_button)\n",
    "    \n",
    "\n",
    "#wid_debug = interact(oEditor.setDebug, debug=False)\n",
    "vbox_controls = VBox([wid_filename, wid_drawMode, *lwid_buttons, wid_size, wid_debug, wid_debug_move])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Edit the map below here by dragging the mouse to create transitions\n",
    "You can create a dead-end by dragging foward and backward, ie Cell A -> Adjacent Cell B -> back to Cell A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "cddcd8e9e5fb48c185a129ff73b1ef40",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(Canvas(), VBox(children=(Text(value='../flatland/env-data/tests/test1.npy', description='Filena…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# wid_box\n",
    "wid_main = HBox([wid_img, vbox_controls])\n",
    "wid_output.clear_output()\n",
    "wid_main"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
hagrid67's avatar
hagrid67 committed
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b4d521d96fc44ea6bf7cd9e4e299673b",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output(outputs=({'output_type': 'stream', 'text': \"Set Debug: True\\ndebug: {'type': 'click', 'shiftKey': False…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wid_output.clear_output()\n",
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Experimental\n",
    "enable the thread.start below to try background stepping of the agents.  It tends to make a mess."
   ]
  },
hagrid67's avatar
hagrid67 committed
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "import threading\n",
    "def bgUpdate(editor):\n",
    "    for i in range(100):\n",
    "        editor.step_event()\n",
    "        time.sleep(0.2)\n"
hagrid67's avatar
hagrid67 committed
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "thread = threading.Thread(target=bgUpdate, args = (oEditor,))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "if False:\n",
    "    thread.start()"
hagrid67's avatar
hagrid67 committed
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save the image (change the filename...)"
   ]
  },
  {
   "cell_type": "code",
hagrid67's avatar
hagrid67 committed
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "if False: \n",
    "    oEnv.rail.save_transition_map(\"../flatland/env-data/tests/test-editor.npy\")"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Junk below here"
   ]
  },
  {
   "cell_type": "code",
hagrid67's avatar
hagrid67 committed
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "def evListen(wid, ev):\n",
    "    x = ev[\"canvasX\"]\n",
    "    y=ev[\"canvasY\"]\n",
    "    yxBase = array([6, 21])\n",
    "    nPixCell = 35\n",
    "    rcCell = ((array([y, x]) - yxBase) / nPixCell).astype(int)\n",
    "    print(x, y, (x-21) / 35, (y-6) / 35, rcCell)"
   ]
  },
  {
   "cell_type": "code",
hagrid67's avatar
hagrid67 committed
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# wid_img.register_click(evListen)\n",
    "#wid_img.register(evListen)"
   ]
  },
  {
   "cell_type": "code",
hagrid67's avatar
hagrid67 committed
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "#wid_img.unregister_all()"
   ]
  },
  {
   "cell_type": "code",
hagrid67's avatar
hagrid67 committed
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "adf698700a634775bfe4da0909912b96",
hagrid67's avatar
hagrid67 committed
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "IntText(value=0)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ipywidgets.IntText(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
hagrid67's avatar
hagrid67 committed
   "source": [
    "from examples.play_model import Player"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "oP = Player(oEnv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "oP.step()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "import asyncio\n",
    "def wait_for_change(widget, value):\n",
    "    future = asyncio.Future()\n",
    "    def getvalue(change):\n",
    "        # make the new value available\n",
    "        future.set_result(change.new)\n",
    "        widget.unobserve(getvalue, value)\n",
    "    widget.observe(getvalue, value)\n",
    "    return future"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e6bf851f84bd471f8f4a4771e9d9b668",
hagrid67's avatar
hagrid67 committed
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "IntSlider(value=0)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "slider = ipywidgets.IntSlider()\n",
    "\n",
    "async def f():\n",
    "    for i in range(10):\n",
    "        print('did work %s'%i)\n",
    "        x = await wait_for_change(slider, 'value')\n",
    "        print('async function continued with value %s'%x)\n",
    "asyncio.ensure_future(f())\n",
    "\n",
    "slider"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4de1e7a8162e460f8b1ecc732d3c1e2e",
hagrid67's avatar
hagrid67 committed
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "FloatProgress(value=0.0, max=1.0)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "import threading\n",
    "from IPython.display import display\n",
    "import time\n",
    "progress = ipywidgets.FloatProgress(value=0.0, min=0.0, max=1.0)\n",
    "\n",
    "def work(progress):\n",
    "    total = 100\n",
    "    for i in range(total):\n",
    "        time.sleep(0.2)\n",
    "        progress.value = float(i+1)/total\n",
    "\n",
    "thread = threading.Thread(target=work, args=(progress,))\n",
    "display(progress)\n",
    "thread.start()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['1000', '0000', '0010', '0000']"
hagrid67's avatar
hagrid67 committed
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binTrans = format(32800, \"#016b\")\n",
    "[binTrans[i+2:i+6] for i in range(0, len(binTrans)-2, 4)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n"
hagrid67's avatar
hagrid67 committed
   ]
  }
 ],
 "metadata": {
  "hide_input": false,
  "kernelspec": {
   "display_name": "ve367",
   "language": "python",
   "name": "ve367"
  },
  "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.6.7"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}