{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using Custom Callbacks When Running TARDIS" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "import warnings\n", "warnings.filterwarnings('ignore')\n", "\n", "from tardis import run_tardis\n", "import tardis\n", "\n", "tardis.logger.setLevel(0)\n", "tardis.logging.captureWarnings(False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The command `run_tardis` allows users to provide a set of callbacks to the simulation. These callbacks are called at the end of each iteration. This example will show you how to create a custom callback and run a model with TARDIS. As an example, we create a custom callback that prints out some basic information about our model at every iteration. Specifically, we'll print out a table of the inner velocities of each shell as well as the radiative temperature of each shell. The first thing to note is that the callback function must have the simulation object as the first argument. This grants the user access to the state of the simulation at each iteration." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def display_table(sim):\n", " '''Display a table of velocities and \n", " radiative temperatures at each iteration\n", " '''\n", " \n", " # We have direct access to the attributes of the simulation\n", " columns = zip(sim.model.v_inner[::5].to('km/s'), \n", " sim.model.t_rad[::5].to('K'))\n", " print(\"Iteration:\", sim.iterations_executed)\n", " print(\" {:<15} {:<15}\".format('v_inner', 't_rad'))\n", " format_string = \" {0.value:<8.2f} {0.unit:<6s}\\\n", " {1.value:<8.2f} {1.unit:<6s}\"\n", " for velocity, temperature in columns:\n", " print(format_string.format(velocity, temperature))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we give the callback to `run_tardis`. `run_tardis` offers the keyword argument `simulation_callbacks` which takes a list of lists containing the callback as well as any optional arguments you wish to include with your callback. For this example our function requires no extra arguments and we only have a single callback, so we give `run_tardis` a 2D list containing the callback as its only element." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Iteration: 1\n", " v_inner t_rad \n", " 11000.00 km / s 10171.21 K \n", " 13250.00 km / s 10306.11 K \n", " 15500.00 km / s 10174.38 K \n", " 17750.00 km / s 9910.44 K \n", "Iteration: 2\n", " v_inner t_rad \n", " 11000.00 km / s 11518.52 K \n", " 13250.00 km / s 11554.41 K \n", " 15500.00 km / s 11373.57 K \n", " 17750.00 km / s 11040.79 K \n", "Iteration: 3\n", " v_inner t_rad \n", " 11000.00 km / s 10501.13 K \n", " 13250.00 km / s 10869.94 K \n", " 15500.00 km / s 10558.27 K \n", " 17750.00 km / s 10185.65 K \n", "Iteration: 4\n", " v_inner t_rad \n", " 11000.00 km / s 11527.01 K \n", " 13250.00 km / s 11706.14 K \n", " 15500.00 km / s 11444.21 K \n", " 17750.00 km / s 11085.86 K \n", "Iteration: 5\n", " v_inner t_rad \n", " 11000.00 km / s 10659.38 K \n", " 13250.00 km / s 11038.24 K \n", " 15500.00 km / s 10790.70 K \n", " 17750.00 km / s 10450.67 K \n", "Iteration: 6\n", " v_inner t_rad \n", " 11000.00 km / s 11507.44 K \n", " 13250.00 km / s 11634.57 K \n", " 15500.00 km / s 11418.59 K \n", " 17750.00 km / s 10999.62 K \n", "Iteration: 7\n", " v_inner t_rad \n", " 11000.00 km / s 10679.65 K \n", " 13250.00 km / s 11048.27 K \n", " 15500.00 km / s 10825.71 K \n", " 17750.00 km / s 10506.32 K \n", "Iteration: 8\n", " v_inner t_rad \n", " 11000.00 km / s 11459.83 K \n", " 13250.00 km / s 11688.14 K \n", " 15500.00 km / s 11441.77 K \n", " 17750.00 km / s 11099.45 K \n", "Iteration: 9\n", " v_inner t_rad \n", " 11000.00 km / s 10666.22 K \n", " 13250.00 km / s 11000.29 K \n", " 15500.00 km / s 10822.88 K \n", " 17750.00 km / s 10384.18 K \n", "Iteration: 10\n", " v_inner t_rad \n", " 11000.00 km / s 11427.41 K \n", " 13250.00 km / s 11612.35 K \n", " 15500.00 km / s 11373.25 K \n", " 17750.00 km / s 11047.96 K \n", "Iteration: 11\n", " v_inner t_rad \n", " 11000.00 km / s 10741.34 K \n", " 13250.00 km / s 11230.52 K \n", " 15500.00 km / s 10870.70 K \n", " 17750.00 km / s 10538.17 K \n", "Iteration: 12\n", " v_inner t_rad \n", " 11000.00 km / s 11507.88 K \n", " 13250.00 km / s 11808.85 K \n", " 15500.00 km / s 11557.41 K \n", " 17750.00 km / s 11117.76 K \n", "Iteration: 13\n", " v_inner t_rad \n", " 11000.00 km / s 10727.22 K \n", " 13250.00 km / s 11171.76 K \n", " 15500.00 km / s 10971.72 K \n", " 17750.00 km / s 10574.92 K \n", "Iteration: 14\n", " v_inner t_rad \n", " 11000.00 km / s 11413.63 K \n", " 13250.00 km / s 11697.01 K \n", " 15500.00 km / s 11424.45 K \n", " 17750.00 km / s 11047.43 K \n", "Iteration: 15\n", " v_inner t_rad \n", " 11000.00 km / s 10712.62 K \n", " 13250.00 km / s 11125.89 K \n", " 15500.00 km / s 10816.39 K \n", " 17750.00 km / s 10421.69 K \n", "Iteration: 16\n", " v_inner t_rad \n", " 11000.00 km / s 11352.16 K \n", " 13250.00 km / s 11644.97 K \n", " 15500.00 km / s 11320.70 K \n", " 17750.00 km / s 10965.23 K \n", "Iteration: 17\n", " v_inner t_rad \n", " 11000.00 km / s 10738.80 K \n", " 13250.00 km / s 11210.27 K \n", " 15500.00 km / s 10911.46 K \n", " 17750.00 km / s 10545.07 K \n", "Iteration: 18\n", " v_inner t_rad \n", " 11000.00 km / s 11316.67 K \n", " 13250.00 km / s 11599.09 K \n", " 15500.00 km / s 11403.51 K \n", " 17750.00 km / s 10958.97 K \n", "Iteration: 19\n", " v_inner t_rad \n", " 11000.00 km / s 10862.51 K \n", " 13250.00 km / s 11194.46 K \n", " 15500.00 km / s 11065.62 K \n", " 17750.00 km / s 10599.85 K \n", "Iteration: 20\n", " v_inner t_rad \n", " 11000.00 km / s 10862.51 K \n", " 13250.00 km / s 11194.46 K \n", " 15500.00 km / s 11065.62 K \n", " 17750.00 km / s 10599.85 K \n" ] } ], "source": [ "sim = run_tardis('tardis_example.yml', \n", " simulation_callbacks=[[display_table]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Running Callbacks with Extra Arguments\n", "\n", "The callbacks provided to `run_tardis` can also take extra arguments. As an example, we'll make a callback that appends the value of the radiative temperature at each iteration to a list so we can watch how the model converges. The callback will take a list we want to append to as an argument. We'll send both this new callback and our original `display_table` callback to `run_tardis` as an example of using multiple callbacks at once." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def append_t_rad_to_table(sim, table):\n", " '''append the array for the radiative temperature\n", " at each iteration to a given table'''\n", " \n", " table.append(sim.model.t_rad.copy())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to add our new callback, we just create another entry in our list of callbacks. Since `append_t_rad_to_table` takes an extra argument, we will provide that argument in the inner list containing the callback." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Iteration: 1\n", " v_inner t_rad \n", " 11000.00 km / s 10171.21 K \n", " 13250.00 km / s 10306.11 K \n", " 15500.00 km / s 10174.38 K \n", " 17750.00 km / s 9910.44 K \n", "Iteration: 2\n", " v_inner t_rad \n", " 11000.00 km / s 11518.52 K \n", " 13250.00 km / s 11554.41 K \n", " 15500.00 km / s 11373.57 K \n", " 17750.00 km / s 11040.79 K \n", "Iteration: 3\n", " v_inner t_rad \n", " 11000.00 km / s 10501.13 K \n", " 13250.00 km / s 10869.94 K \n", " 15500.00 km / s 10558.27 K \n", " 17750.00 km / s 10185.65 K \n", "Iteration: 4\n", " v_inner t_rad \n", " 11000.00 km / s 11527.01 K \n", " 13250.00 km / s 11706.14 K \n", " 15500.00 km / s 11444.21 K \n", " 17750.00 km / s 11085.86 K \n", "Iteration: 5\n", " v_inner t_rad \n", " 11000.00 km / s 10659.38 K \n", " 13250.00 km / s 11038.24 K \n", " 15500.00 km / s 10790.70 K \n", " 17750.00 km / s 10450.67 K \n", "Iteration: 6\n", " v_inner t_rad \n", " 11000.00 km / s 11507.44 K \n", " 13250.00 km / s 11634.57 K \n", " 15500.00 km / s 11418.59 K \n", " 17750.00 km / s 10999.62 K \n", "Iteration: 7\n", " v_inner t_rad \n", " 11000.00 km / s 10679.65 K \n", " 13250.00 km / s 11048.27 K \n", " 15500.00 km / s 10825.71 K \n", " 17750.00 km / s 10506.32 K \n", "Iteration: 8\n", " v_inner t_rad \n", " 11000.00 km / s 11459.83 K \n", " 13250.00 km / s 11688.14 K \n", " 15500.00 km / s 11441.77 K \n", " 17750.00 km / s 11099.45 K \n", "Iteration: 9\n", " v_inner t_rad \n", " 11000.00 km / s 10666.22 K \n", " 13250.00 km / s 11000.29 K \n", " 15500.00 km / s 10822.88 K \n", " 17750.00 km / s 10384.18 K \n", "Iteration: 10\n", " v_inner t_rad \n", " 11000.00 km / s 11427.41 K \n", " 13250.00 km / s 11612.35 K \n", " 15500.00 km / s 11373.25 K \n", " 17750.00 km / s 11047.96 K \n", "Iteration: 11\n", " v_inner t_rad \n", " 11000.00 km / s 10741.34 K \n", " 13250.00 km / s 11230.52 K \n", " 15500.00 km / s 10870.70 K \n", " 17750.00 km / s 10538.17 K \n", "Iteration: 12\n", " v_inner t_rad \n", " 11000.00 km / s 11507.88 K \n", " 13250.00 km / s 11808.85 K \n", " 15500.00 km / s 11557.41 K \n", " 17750.00 km / s 11117.76 K \n", "Iteration: 13\n", " v_inner t_rad \n", " 11000.00 km / s 10727.22 K \n", " 13250.00 km / s 11171.76 K \n", " 15500.00 km / s 10971.72 K \n", " 17750.00 km / s 10574.92 K \n", "Iteration: 14\n", " v_inner t_rad \n", " 11000.00 km / s 11413.63 K \n", " 13250.00 km / s 11697.01 K \n", " 15500.00 km / s 11424.45 K \n", " 17750.00 km / s 11047.43 K \n", "Iteration: 15\n", " v_inner t_rad \n", " 11000.00 km / s 10712.62 K \n", " 13250.00 km / s 11125.89 K \n", " 15500.00 km / s 10816.39 K \n", " 17750.00 km / s 10421.69 K \n", "Iteration: 16\n", " v_inner t_rad \n", " 11000.00 km / s 11352.16 K \n", " 13250.00 km / s 11644.97 K \n", " 15500.00 km / s 11320.70 K \n", " 17750.00 km / s 10965.23 K \n", "Iteration: 17\n", " v_inner t_rad \n", " 11000.00 km / s 10738.80 K \n", " 13250.00 km / s 11210.27 K \n", " 15500.00 km / s 10911.46 K \n", " 17750.00 km / s 10545.07 K \n", "Iteration: 18\n", " v_inner t_rad \n", " 11000.00 km / s 11316.67 K \n", " 13250.00 km / s 11599.09 K \n", " 15500.00 km / s 11403.51 K \n", " 17750.00 km / s 10958.97 K \n", "Iteration: 19\n", " v_inner t_rad \n", " 11000.00 km / s 10862.51 K \n", " 13250.00 km / s 11194.46 K \n", " 15500.00 km / s 11065.62 K \n", " 17750.00 km / s 10599.85 K \n", "Iteration: 20\n", " v_inner t_rad \n", " 11000.00 km / s 10862.51 K \n", " 13250.00 km / s 11194.46 K \n", " 15500.00 km / s 11065.62 K \n", " 17750.00 km / s 10599.85 K \n" ] } ], "source": [ "t_rad_table = [] # list to store t_rad at each iteration\n", "\n", "callbacks = [[display_table], \n", " [append_t_rad_to_table, t_rad_table]]\n", "sim = run_tardis('tardis_example.yml', \n", " simulation_callbacks=callbacks)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can look at the way the radiative temperature changes in each shell every iteration." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Populating the interactive namespace from numpy and matplotlib\n" ] }, { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '');\n", " var titletext = $(\n", " '');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", " 'ui-button-icon-only');\n", " button.attr('role', 'button');\n", " button.attr('aria-disabled', 'false');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", "\n", " var icon_img = $('');\n", " icon_img.addClass('ui-button-icon-primary ui-icon');\n", " icon_img.addClass(image);\n", " icon_img.addClass('ui-corner-all');\n", "\n", " var tooltip_span = $('');\n", " tooltip_span.addClass('ui-button-text');\n", " tooltip_span.html(tooltip);\n", "\n", " button.append(icon_img);\n", " button.append(tooltip_span);\n", "\n", " nav_element.append(button);\n", " }\n", "\n", " var fmt_picker_span = $('');\n", "\n", " var fmt_picker = $('');\n", " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", " fmt_picker_span.append(fmt_picker);\n", " nav_element.append(fmt_picker_span);\n", " this.format_dropdown = fmt_picker[0];\n", "\n", " for (var ind in mpl.extensions) {\n", " var fmt = mpl.extensions[ind];\n", " var option = $(\n", " '', {selected: fmt === mpl.default_extension}).html(fmt);\n", " fmt_picker.append(option);\n", " }\n", "\n", " // Add hover states to the ui-buttons\n", " $( \".ui-button\" ).hover(\n", " function() { $(this).addClass(\"ui-state-hover\");},\n", " function() { $(this).removeClass(\"ui-state-hover\");}\n", " );\n", "\n", " var status_bar = $('