{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-05-01T09:27:13.438054Z", "start_time": "2020-05-01T09:27:13.191491Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Populating the interactive namespace from numpy and matplotlib\n" ] } ], "source": [ "%pylab inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Notebook magic" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-08-03T18:32:45.342280Z", "start_time": "2020-08-03T18:32:45.338442Z" } }, "outputs": [], "source": [ "from IPython.core.magic import Magics, magics_class, line_cell_magic\n", "from IPython.core.magic import cell_magic, register_cell_magic, register_line_magic\n", "from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring\n", "import subprocess\n", "import os" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2020-07-23T20:31:25.296014Z", "start_time": "2020-07-23T20:31:25.265937Z" } }, "outputs": [], "source": [ "@magics_class\n", "class PyboardMagic(Magics):\n", " @cell_magic\n", " @magic_arguments()\n", " @argument('-skip')\n", " @argument('-unix')\n", " @argument('-pyboard')\n", " @argument('-file')\n", " @argument('-data')\n", " @argument('-time')\n", " @argument('-memory')\n", " def micropython(self, line='', cell=None):\n", " args = parse_argstring(self.micropython, line)\n", " if args.skip: # doesn't care about the cell's content\n", " print('skipped execution')\n", " return None # do not parse the rest\n", " if args.unix: # tests the code on the unix port. Note that this works on unix only\n", " with open('/dev/shm/micropython.py', 'w') as fout:\n", " fout.write(cell)\n", " proc = subprocess.Popen([\"../../micropython/ports/unix/micropython\", \"/dev/shm/micropython.py\"], \n", " stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n", " print(proc.stdout.read().decode(\"utf-8\"))\n", " print(proc.stderr.read().decode(\"utf-8\"))\n", " return None\n", " if args.file: # can be used to copy the cell content onto the pyboard's flash\n", " spaces = \" \"\n", " try:\n", " with open(args.file, 'w') as fout:\n", " fout.write(cell.replace('\\t', spaces))\n", " printf('written cell to {}'.format(args.file))\n", " except:\n", " print('Failed to write to disc!')\n", " return None # do not parse the rest\n", " if args.data: # can be used to load data from the pyboard directly into kernel space\n", " message = pyb.exec(cell)\n", " if len(message) == 0:\n", " print('pyboard >>>')\n", " else:\n", " print(message.decode('utf-8'))\n", " # register new variable in user namespace\n", " self.shell.user_ns[args.data] = string_to_matrix(message.decode(\"utf-8\"))\n", " \n", " if args.time: # measures the time of executions\n", " pyb.exec('import utime')\n", " message = pyb.exec('t = utime.ticks_us()\\n' + cell + '\\ndelta = utime.ticks_diff(utime.ticks_us(), t)' + \n", " \"\\nprint('execution time: {:d} us'.format(delta))\")\n", " print(message.decode('utf-8'))\n", " \n", " if args.memory: # prints out memory information \n", " message = pyb.exec('from micropython import mem_info\\nprint(mem_info())\\n')\n", " print(\"memory before execution:\\n========================\\n\", message.decode('utf-8'))\n", " message = pyb.exec(cell)\n", " print(\">>> \", message.decode('utf-8'))\n", " message = pyb.exec('print(mem_info())')\n", " print(\"memory after execution:\\n========================\\n\", message.decode('utf-8'))\n", "\n", " if args.pyboard:\n", " message = pyb.exec(cell)\n", " print(message.decode('utf-8'))\n", "\n", "ip = get_ipython()\n", "ip.register_magics(PyboardMagic)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## pyboard" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "ExecuteTime": { "end_time": "2020-05-07T07:35:35.126401Z", "start_time": "2020-05-07T07:35:35.105824Z" } }, "outputs": [], "source": [ "import pyboard\n", "pyb = pyboard.Pyboard('/dev/ttyACM0')\n", "pyb.enter_raw_repl()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-05-19T19:11:18.145548Z", "start_time": "2020-05-19T19:11:18.137468Z" } }, "outputs": [], "source": [ "pyb.exit_raw_repl()\n", "pyb.close()" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "ExecuteTime": { "end_time": "2020-05-07T07:35:38.725924Z", "start_time": "2020-05-07T07:35:38.645488Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "%%micropython -pyboard 1\n", "\n", "import utime\n", "import ulab as np\n", "\n", "def timeit(n=1000):\n", " def wrapper(f, *args, **kwargs):\n", " func_name = str(f).split(' ')[1]\n", " def new_func(*args, **kwargs):\n", " run_times = np.zeros(n, dtype=np.uint16)\n", " for i in range(n):\n", " t = utime.ticks_us()\n", " result = f(*args, **kwargs)\n", " run_times[i] = utime.ticks_diff(utime.ticks_us(), t)\n", " print('{}() execution times based on {} cycles'.format(func_name, n, (delta2-delta1)/n))\n", " print('\\tbest: %d us'%np.min(run_times))\n", " print('\\tworst: %d us'%np.max(run_times))\n", " print('\\taverage: %d us'%np.mean(run_times))\n", " print('\\tdeviation: +/-%.3f us'%np.std(run_times)) \n", " return result\n", " return new_func\n", " return wrapper\n", "\n", "def timeit(f, *args, **kwargs):\n", " func_name = str(f).split(' ')[1]\n", " def new_func(*args, **kwargs):\n", " t = utime.ticks_us()\n", " result = f(*args, **kwargs)\n", " print('execution time: ', utime.ticks_diff(utime.ticks_us(), t), ' us')\n", " return result\n", " return new_func" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__END_OF_DEFS__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Polynomials\n", "\n", "Functions in the polynomial sub-module can be invoked by importing the module first." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## polyval\n", "\n", "`numpy`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.polyval.html\n", "\n", "`polyval` takes two arguments, both arrays or other iterables." ] }, { "cell_type": "code", "execution_count": 187, "metadata": { "ExecuteTime": { "end_time": "2019-11-01T12:53:22.448303Z", "start_time": "2019-11-01T12:53:22.435176Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "coefficients: [1, 1, 1, 0]\n", "independent values: [0, 1, 2, 3, 4]\n", "\n", "values of p(x): array([0.0, 3.0, 14.0, 39.0, 84.0], dtype=float)\n", "\n", "ndarray (a): array([0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)\n", "value of p(a): array([0.0, 3.0, 14.0, 39.0, 84.0], dtype=float)\n", "\n", "\n" ] } ], "source": [ "%%micropython -unix 1\n", "\n", "import ulab as np\n", "from ulab import poly\n", "\n", "p = [1, 1, 1, 0]\n", "x = [0, 1, 2, 3, 4]\n", "print('coefficients: ', p)\n", "print('independent values: ', x)\n", "print('\\nvalues of p(x): ', poly.polyval(p, x))\n", "\n", "# the same works with one-dimensional ndarrays\n", "a = np.array(x)\n", "print('\\nndarray (a): ', a)\n", "print('value of p(a): ', poly.polyval(p, a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## polyfit\n", "\n", "`numpy`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.polyfit.html\n", "\n", "polyfit takes two, or three arguments. The last one is the degree of the polynomial that will be fitted, the last but one is an array or iterable with the `y` (dependent) values, and the first one, an array or iterable with the `x` (independent) values, can be dropped. If that is the case, `x` will be generated in the function, assuming uniform sampling. \n", "\n", "If the length of `x`, and `y` are not the same, the function raises a `ValueError`." ] }, { "cell_type": "code", "execution_count": 189, "metadata": { "ExecuteTime": { "end_time": "2019-11-01T12:54:08.326802Z", "start_time": "2019-11-01T12:54:08.311182Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "independent values:\t array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0], dtype=float)\n", "dependent values:\t array([9.0, 4.0, 1.0, 0.0, 1.0, 4.0, 9.0], dtype=float)\n", "fitted values:\t\t array([1.0, -6.0, 9.000000000000004], dtype=float)\n", "\n", "dependent values:\t array([9.0, 4.0, 1.0, 0.0, 1.0, 4.0, 9.0], dtype=float)\n", "fitted values:\t\t array([1.0, -6.0, 9.000000000000004], dtype=float)\n", "\n", "\n" ] } ], "source": [ "%%micropython -unix 1\n", "\n", "import ulab as np\n", "from ulab import poly\n", "\n", "x = np.array([0, 1, 2, 3, 4, 5, 6])\n", "y = np.array([9, 4, 1, 0, 1, 4, 9])\n", "print('independent values:\\t', x)\n", "print('dependent values:\\t', y)\n", "print('fitted values:\\t\\t', poly.polyfit(x, y, 2))\n", "\n", "# the same with missing x\n", "print('\\ndependent values:\\t', y)\n", "print('fitted values:\\t\\t', poly.polyfit(y, 2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Execution time\n", "\n", "`polyfit` is based on the inversion of a matrix (there is more on the background in https://en.wikipedia.org/wiki/Polynomial_regression), and it requires the intermediate storage of `2*N*(deg+1)` floats, where `N` is the number of entries in the input array, and `deg` is the fit's degree. The additional computation costs of the matrix inversion discussed in [inv](#inv) also apply. The example from above needs around 150 microseconds to return:" ] }, { "cell_type": "code", "execution_count": 560, "metadata": { "ExecuteTime": { "end_time": "2019-10-20T07:24:39.002243Z", "start_time": "2019-10-20T07:24:38.978687Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "execution time: 153 us\n", "\n" ] } ], "source": [ "%%micropython -pyboard 1\n", "\n", "import ulab as np\n", "from ulab import poly\n", "\n", "@timeit\n", "def time_polyfit(x, y, n):\n", " return poly.polyfit(x, y, n)\n", "\n", "x = np.array([0, 1, 2, 3, 4, 5, 6])\n", "y = np.array([9, 4, 1, 0, 1, 4, 9])\n", "\n", "time_polyfit(x, y, 2)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.8.5" }, "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": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "382.797px" }, "toc_section_display": true, "toc_window_display": true }, "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": 4 }