{ "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", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from ipywidgets import IntSlider, link, VBox, RadioButtons, HBox, interact" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "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": {}, "outputs": [], "source": [ "wid_img.unregister_all()\n", "oEditor = JupEditor(oEnv, wid_img)\n", "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", "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", " 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": { "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", "wid_output" ] }, { "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." ] }, { "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" ] }, { "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()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Save the image (change the filename...)" ] }, { "cell_type": "code", "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", "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(ev)\n", " print(x, y, (x-21) / 35, (y-6) / 35, rcCell)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "# wid_img.register_click(evListen)\n", "#wid_img.register(evListen)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "#wid_img.unregister_all()" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "adf698700a634775bfe4da0909912b96", "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": [], "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", "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", "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']" ] }, "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" ] } ], "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 }