{ "cells": [ { "cell_type": "markdown", "id": "fbe37a9b-976e-4fb9-ab7a-62d1536bfed0", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "# Specifying Inputs & Outputs\n", "\n", "The idea of [`xyzpy`](xyzpy) is to ease the some of the pain generating data with a large parameter space.\n", "The central aim being that, once you know what a single run of a function looks like, it should be as easy as saying, \"run these combinations of parameters, now run these particular cases\" with everything automatically aggregated into a fully self-described dataset." ] }, { "cell_type": "code", "execution_count": 1, "id": "23b27d56-726a-4390-852e-63d10a480c00", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "\n", "import numpy as np\n", "\n", "import xyzpy as xyz" ] }, { "cell_type": "markdown", "id": "38a8074e-cd2f-4736-8f15-d37f05f62603", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "## Combos & Cases\n", "\n", "The main backend function is [`xyz.combo_runner`](xyzpy.combo_runner), which in its simplest form takes a function, say:" ] }, { "cell_type": "code", "execution_count": 2, "id": "d60d8306-c15c-4189-a888-d4b976a6ba0e", "metadata": {}, "outputs": [], "source": [ "def foo(a, b, c):\n", " return f\"{a}-{b}-{c}\", np.sin(a)" ] }, { "cell_type": "markdown", "id": "58ca1ee8-2bc5-447e-890d-932170911e9d", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "and ``combos`` of the form:" ] }, { "cell_type": "code", "execution_count": 3, "id": "943d0f3c-06ab-4a4f-9871-63470b65db96", "metadata": {}, "outputs": [], "source": [ "combos = [\n", " (\"a\", [1, 2, 3]),\n", " (\"b\", [\"x\", \"y\", \"z\"]),\n", " (\"c\", [True, False]),\n", "]" ] }, { "cell_type": "markdown", "id": "df476929-7ca5-45c3-8242-c3c45510476a", "metadata": {}, "source": [ "and generates a nested (here 3 dimensional) array of all the outputs of ``foo`` with the ``3 * 3 * 2 = 18`` combinations of input arguments:" ] }, { "cell_type": "code", "execution_count": 4, "id": "0835dcf1-d969-4d58-9acd-01cfa28e58d5", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|##########| 18/18 [00:00<00:00, 56090.25it/s]\n" ] }, { "data": { "text/plain": [ "(((('1-x-True', np.float64(0.8414709848078965)),\n", " ('1-x-False', np.float64(0.8414709848078965))),\n", " (('1-y-True', np.float64(0.8414709848078965)),\n", " ('1-y-False', np.float64(0.8414709848078965))),\n", " (('1-z-True', np.float64(0.8414709848078965)),\n", " ('1-z-False', np.float64(0.8414709848078965)))),\n", " ((('2-x-True', np.float64(0.9092974268256817)),\n", " ('2-x-False', np.float64(0.9092974268256817))),\n", " (('2-y-True', np.float64(0.9092974268256817)),\n", " ('2-y-False', np.float64(0.9092974268256817))),\n", " (('2-z-True', np.float64(0.9092974268256817)),\n", " ('2-z-False', np.float64(0.9092974268256817)))),\n", " ((('3-x-True', np.float64(0.1411200080598672)),\n", " ('3-x-False', np.float64(0.1411200080598672))),\n", " (('3-y-True', np.float64(0.1411200080598672)),\n", " ('3-y-False', np.float64(0.1411200080598672))),\n", " (('3-z-True', np.float64(0.1411200080598672)),\n", " ('3-z-False', np.float64(0.1411200080598672)))))" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "xyz.combo_runner(foo, combos)" ] }, { "cell_type": "markdown", "id": "91fc38e2-5015-47cc-abf6-049e2b633c5a", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Note the progress bar shown. If the function was slower (generally the target case for ``xyzpy``), this would show the remaining time before completion.\n", "\n", "There is also [`xyz.case_runner`](xyzpy.case_runner) for running isolated cases:" ] }, { "cell_type": "code", "execution_count": 5, "id": "ffa19e4b-f228-41e4-83c8-02dd5b54e596", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|##########| 2/2 [00:00<00:00, 22982.49it/s]\n" ] }, { "data": { "text/plain": [ "(('4-z-False', np.float64(-0.7568024953079283)),\n", " ('5-y-True', np.float64(-0.9589242746631385)))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cases = [(4, \"z\", False), (5, \"y\", True)]\n", "xyz.case_runner(foo, fn_args=(\"a\", \"b\", \"c\"), cases=cases)" ] }, { "cell_type": "markdown", "id": "de9bc9d2-1d51-47a5-b581-135006342e02", "metadata": {}, "source": [ "You can also mix the two, supplying some function arguments as ``cases`` and some as ``combos``.\n", "In this situation, **for each case, all sub combinations are run**:" ] }, { "cell_type": "code", "execution_count": 6, "id": "0f6a44c3-2aa8-45b3-8deb-87427ceab4b8", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|##########| 9/9 [00:00<00:00, 97541.95it/s]\n" ] }, { "data": { "text/plain": [ "((((array(nan), array(nan)),\n", " (array(nan), array(nan)),\n", " (array(nan), array(nan))),\n", " (('1-x-True', np.float64(0.8414709848078965)),\n", " ('1-y-True', np.float64(0.8414709848078965)),\n", " ('1-z-True', np.float64(0.8414709848078965)))),\n", " ((('2-x-False', np.float64(0.9092974268256817)),\n", " ('2-y-False', np.float64(0.9092974268256817)),\n", " ('2-z-False', np.float64(0.9092974268256817))),\n", " ((array(nan), array(nan)),\n", " (array(nan), array(nan)),\n", " (array(nan), array(nan)))),\n", " (((array(nan), array(nan)),\n", " (array(nan), array(nan)),\n", " (array(nan), array(nan))),\n", " (('3-x-True', np.float64(0.1411200080598672)),\n", " ('3-y-True', np.float64(0.1411200080598672)),\n", " ('3-z-True', np.float64(0.1411200080598672)))))" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "xyz.combo_runner(\n", " foo,\n", " cases=[\n", " {\"a\": 1, \"c\": True},\n", " {\"a\": 2, \"c\": False},\n", " {\"a\": 3, \"c\": True},\n", " ],\n", " combos={\n", " \"b\": [\"x\", \"y\", \"z\"],\n", " },\n", ")" ] }, { "cell_type": "markdown", "id": "5ed9c89a-7a5f-4138-8a4f-916c9e31be86", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Note now that for the ``combo_runner`` missing results are automatically filled with ``nan``, (or possibly ``None`` depending on shape and dtype).\n", "Note we also avoided specifying the specific function argument order by supplying a list of dicts.\n", "You can supply both ``combos`` and ``cases`` to either [`combo_runner`](xyzpy.combo_runner), or [`case_runner`](xyzpy.case_runner), the main difference is\n", "\n", "1. [`combo_runner`](xyzpy.combo_runner) outputs a nested tuple suitable to be turned into an array\n", "2. [`case_runner`](xyzpy.case_runner) outputs a flat tuple of results suitable to be put into a table\n", "\n", "You will likely not use these functions in their raw form, but they illustrate the concept of ``combos`` and ``cases`` and underly most other functionality.\n", "\n", "\n", "## Describing the function - ``Runner``\n", "\n", "To automatically put the generated data into a labelled {class}`xarray.Dataset` you need to describe your function using the [`xyz.Runner`](xyzpy.Runner) class. In the simplest case this is just a matter of naming the outputs:" ] }, { "cell_type": "code", "execution_count": 7, "id": "870cb4d2-1b27-4a56-8879-4d7819e72924", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|##########| 18/18 [00:00<00:00, 67650.06it/s]\n" ] }, { "data": { "text/html": [ "
<xarray.Dataset> Size: 830B\n",
"Dimensions: (a: 3, b: 3, c: 2)\n",
"Coordinates:\n",
" * a (a) int64 24B 1 2 3\n",
" * b (b) <U1 12B 'x' 'y' 'z'\n",
" * c (c) bool 2B True False\n",
"Data variables:\n",
" a_out (a, b, c) <U9 648B '1-x-True' '1-x-False' ... '3-z-False'\n",
" b_out (a, b, c) float64 144B 0.8415 0.8415 0.8415 ... 0.1411 0.1411<xarray.Dataset> Size: 67kB\n",
"Dimensions: (i: 3, j: 3, k: 3, x: 3, t: 101)\n",
"Coordinates:\n",
" * i (i) int64 24B 5 6 7\n",
" * j (j) float64 24B 0.5 0.6 0.7\n",
" * k (k) float64 24B 0.05 0.06 0.07\n",
" * x (x) int64 24B 10 20 30\n",
" * t (t) float64 808B 0.0 0.01 0.02 0.03 0.04 ... 0.97 0.98 0.99 1.0\n",
"Data variables:\n",
" A (i, j, k) float64 216B 0.3676 0.9331 0.4158 ... 0.3203 0.2549\n",
" B (i, j, k, x) float64 648B 0.6944 0.08939 0.137 ... 0.9456 0.3549\n",
" C (i, j, k, x, t) float64 65kB 0.8575 0.05207 ... 0.8448 0.08909<xarray.Dataset> Size: 1kB\n",
"Dimensions: (a: 6, b: 5, c: 2)\n",
"Coordinates:\n",
" * a (a) int64 48B 1 2 3 4 5 6\n",
" * b (b) <U1 20B 'v' 'w' 'x' 'y' 'z'\n",
" * c (c) bool 2B True False\n",
"Data variables:\n",
" a_out (a, b, c) object 480B nan nan nan nan ... nan nan nan nan\n",
" b_out (a, b, c) float64 480B nan nan nan nan 0.8415 ... nan nan nan nan