From dceaaf18e8a82a0f6ef282928141c0c6c0806a65 Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Sat, 2 Feb 2019 14:17:10 +0100 Subject: [PATCH 1/2] add muc + binder --- .../Munich-MUC++-2019.ipynb | 2112 +++++++++++++++++ 2019-01-30-muc++-meetup/README.md | 25 + 2019-01-30-muc++-meetup/images/cheatsheet.png | Bin 0 -> 230115 bytes .../images/jupyter_connection.png | Bin 0 -> 59149 bytes .../images/jupyter_connection.svg | 1035 ++++++++ .../images/jupyter_server.png | Bin 0 -> 49271 bytes .../images/jupyter_server.svg | 855 +++++++ .../images/jupyter_server_after.png | Bin 0 -> 62225 bytes .../images/jupyter_server_after.svg | 828 +++++++ .../images/jupyterpreview.png | Bin 0 -> 75135 bytes 2019-01-30-muc++-meetup/images/pyjlr.png | Bin 0 -> 63297 bytes 2019-01-30-muc++-meetup/images/saber.png | Bin 0 -> 28694 bytes 2019-01-30-muc++-meetup/images/strides.png | Bin 0 -> 8324 bytes 2019-01-30-muc++-meetup/images/team.png | Bin 0 -> 610495 bytes 2019-01-30-muc++-meetup/images/xeus-cling.png | Bin 0 -> 42527 bytes 2019-01-30-muc++-meetup/images/xeus-cling.svg | 18 + 2019-01-30-muc++-meetup/images/xframe.png | Bin 0 -> 26590 bytes 2019-01-30-muc++-meetup/images/xframe.svg | 11 + 2019-01-30-muc++-meetup/images/xplot.png | Bin 0 -> 31630 bytes 2019-01-30-muc++-meetup/images/xplot.svg | 14 + 2019-01-30-muc++-meetup/images/xtensor.png | Bin 0 -> 27782 bytes 2019-01-30-muc++-meetup/images/xtensor.svg | 35 + 2019-01-30-muc++-meetup/julia-challenge.ipynb | 820 +++++++ 2019-01-30-muc++-meetup/random.hpp | 49 + .../xleaflet_example.ipynb | 153 ++ 2019-01-30-muc++-meetup/xplot_demo_1.ipynb | 112 + 2019-01-30-muc++-meetup/xplot_demo_2.ipynb | 195 ++ .../xvolume_parametric.ipynb | 261 ++ environment.yml | 14 + 29 files changed, 6537 insertions(+) create mode 100644 2019-01-30-muc++-meetup/Munich-MUC++-2019.ipynb create mode 100644 2019-01-30-muc++-meetup/README.md create mode 100644 2019-01-30-muc++-meetup/images/cheatsheet.png create mode 100644 2019-01-30-muc++-meetup/images/jupyter_connection.png create mode 100644 2019-01-30-muc++-meetup/images/jupyter_connection.svg create mode 100644 2019-01-30-muc++-meetup/images/jupyter_server.png create mode 100644 2019-01-30-muc++-meetup/images/jupyter_server.svg create mode 100644 2019-01-30-muc++-meetup/images/jupyter_server_after.png create mode 100644 2019-01-30-muc++-meetup/images/jupyter_server_after.svg create mode 100644 2019-01-30-muc++-meetup/images/jupyterpreview.png create mode 100644 2019-01-30-muc++-meetup/images/pyjlr.png create mode 100644 2019-01-30-muc++-meetup/images/saber.png create mode 100644 2019-01-30-muc++-meetup/images/strides.png create mode 100644 2019-01-30-muc++-meetup/images/team.png create mode 100644 2019-01-30-muc++-meetup/images/xeus-cling.png create mode 100644 2019-01-30-muc++-meetup/images/xeus-cling.svg create mode 100644 2019-01-30-muc++-meetup/images/xframe.png create mode 100644 2019-01-30-muc++-meetup/images/xframe.svg create mode 100644 2019-01-30-muc++-meetup/images/xplot.png create mode 100644 2019-01-30-muc++-meetup/images/xplot.svg create mode 100644 2019-01-30-muc++-meetup/images/xtensor.png create mode 100644 2019-01-30-muc++-meetup/images/xtensor.svg create mode 100644 2019-01-30-muc++-meetup/julia-challenge.ipynb create mode 100644 2019-01-30-muc++-meetup/random.hpp create mode 100644 2019-01-30-muc++-meetup/xleaflet_example.ipynb create mode 100644 2019-01-30-muc++-meetup/xplot_demo_1.ipynb create mode 100644 2019-01-30-muc++-meetup/xplot_demo_2.ipynb create mode 100644 2019-01-30-muc++-meetup/xvolume_parametric.ipynb create mode 100644 environment.yml diff --git a/2019-01-30-muc++-meetup/Munich-MUC++-2019.ipynb b/2019-01-30-muc++-meetup/Munich-MUC++-2019.ipynb new file mode 100644 index 0000000..006aae4 --- /dev/null +++ b/2019-01-30-muc++-meetup/Munich-MUC++-2019.ipynb @@ -0,0 +1,2112 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Interactive Demos Here:\n", + "\n", + "To access the interactive demos *ONLINE* and *WITHOUT* installation, click the \"Binder\" Button on each of these. \n", + "\n", + "Like this → [![Binder](https://img.shields.io/badge/launch-binder-brightgreen.svg)](https://mybinder.org/v2/gh/QuantStack/xtensor/stable?filepath=notebooks/xtensor.ipynb)\n", + "\n", + "- https://github.com/QuantStack/xeus-cling\n", + "- https://github.com/QuantStack/xtensor\n", + "- https://github.com/QuantStack/xwidgets\n", + "- https://github.com/QuantStack/xleaflet\n", + "- https://github.com/QuantStack/xplot\n", + "- https://github.com/QuantStack/xvolume\n", + "\n", + "## Join the community on gitter\n", + "\n", + "\n", + "https://gitter.im/QuantStack/Lobby" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Munich MUC++ Meetup 31.1.2019\n", + "\n", + "### A Universal Data Science Framework in C++\n", + "\n", + "Wolf Vollprecht\n", + " - w.vollprecht@gmail.com\n", + " - @wolfv (github)\n", + " - @wuoulf (Twitter)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Structure of the Talk\n", + "\n", + "- Intro\n", + "- Interactive C++ in the browser\n", + "- Overview over xtensor\n", + "- A minimal C++17 \"xtensor\" implementation\n", + "- Widgets and Plotting for C++" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# What is QuantStack\n", + "\n", + "\n", + "\n", + "- Scientific C++ & Python Shop in Paris\n", + "- Only doing Open Source at the moment!\n", + "- Currently 4 full timers\n", + "- Always looking to grow :)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#include " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "#include \n", + "\n", + "std::cout << \"Hello MUC++ Meetup!\" << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Jupyter Notebooks\n", + "\n", + "\n", + "\n", + "- Everywhere in Data Science\n", + "- Mix of Markdown + Code\n", + "- $0 = 1 + e ^ {i \\pi}$\n", + "- Cell-based execution\n", + "- Widgets (sliders, buttons ... )" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "![](images/jupyter_server.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "![](images/jupyter_server_after.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\n", + "\n", + "- xeus + cling\n", + "- cling: clang based C++ interpreter from the CERN\n", + "- xeus: C++ implementation of the \"Jupyter Kernel Protocol\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "int a_var = 5;\n", + "// without semicolon: prints value\n", + "a_var" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_var = 100" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "std::string func(int A)\n", + "{\n", + " return std::string(\"This was executed \") + std::to_string(A) + \" 👍\";\n", + "}\n", + "\n", + "std::cout << func(111 + 222) << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "double sqr(double a)\n", + "{\n", + " return a * a;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sqr(9)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Classes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Foo\n", + "{\n", + "public:\n", + "\n", + " virtual ~Foo() {}\n", + " \n", + " virtual void print(double value) const\n", + " {\n", + " std::cout << \"Foo value = \" << value << std::endl;\n", + " }\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Foo bar;\n", + "bar.print(1.2);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "class Bar : public Foo\n", + "{\n", + "public:\n", + "\n", + " virtual ~Bar() {}\n", + " \n", + " virtual void print(double value) const\n", + " {\n", + " std::cout << \"Bar value = \" << 2 * value << std::endl;\n", + " }\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Foo* bar2 = new Bar;\n", + "bar2->print(1.2);\n", + "delete bar2;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Fast help" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "a_Var" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "?std::vector" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "std::vector temp_vec;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "?temp_vec.push_back" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "?xt::xtensor" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Magics" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "\n", + "std::vector to_shuffle = {1, 2, 3, 4};" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%timeit std::random_shuffle(to_shuffle.begin(), to_shuffle.end());" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# xeus-cling Installation\n", + "\n", + "- https://github.com/QuantStack/xeus-cling\n", + "- Interactive: https://mybinder.org/v2/gh/QuantStack/xeus-cling/stable?filepath=notebooks/xcpp.ipynb\n", + "\n", + "- We distribute our software through conda!\n", + "- `conda install $INSERT_PKG_NAME -c quantstack -c conda-forge`\n", + "- Or use `cmake` ;)\n", + "\n", + "(Shoutout to binder: free hosted jupyter for Open Source!)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "![](images/jupyter_server_after.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# N-D arrays are everywhere\n", + "\n", + "- ... except for C++\n", + "- Basic building block of data science\n", + "- Images, Videos, Music, Point Clouds – all are expressed as N-dimensional data" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\n", + "\n", + "- n-dimensional array computing library\n", + "- Support for lazy computation, broadcasting \n", + "- C++14\n", + "- API close to NumPy\n", + "- Online demo: https://mybinder.org/v2/gh/QuantStack/xtensor/stable?filepath=notebooks/xtensor.ipynb" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Anatomy of a N-dimensional container\n", + "\n", + "- Shape of length N\n", + "- Strides to describe offset in linear data\n", + "- Example: shape (2, 3) with strides (3, 1)\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "\n", + "xt::xarray a = {{1,2,3}, {4,5,6}};\n", + "\n", + "std::cout << a << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### STL interface" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "for (auto& el : a)\n", + "{\n", + " std::cout << el << std::endl;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "a(0, 1) = 10;\n", + "\n", + "std::cout << a << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "std::sort(a.begin(), a.end());\n", + "\n", + "std::cout << a << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "std::cout << xt::transpose(a) << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a.reshape({1, 1, 6, 1});\n", + "\n", + "std::cout << a << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a.reshape({2, 3});" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "auto xfunc = sin(a) * 2;\n", + "\n", + "std::cout << xfunc << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Expression Templates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "template \n", + "void print_type(T) { std::cout << __PRETTY_FUNCTION__ << std::endl; }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print_type(xfunc);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "auto xfunc_el = xfunc(0, 1);\n", + "std::cout << xfunc_el << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xt::xarray xfunc_result = xfunc;\n", + "\n", + "std::cout << xfunc_result << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Broadcasting\n", + "\n", + "- Automagically extend operands to match shape\n", + "- Broadcasting rules copied from NumPy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xt::xarray brcast = {-10, +1, -10};" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "std::cout << a * brcast << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cells do not work on Binder, unfortunately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "// #include \n", + "// #include \n", + "\n", + "// std::vector read_file(const char* filename)\n", + "// {\n", + "// std::basic_ifstream file(filename, std::ios::binary);\n", + "// return std::vector((std::istreambuf_iterator(file)), std::istreambuf_iterator());\n", + "// }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "// template \n", + "// std::vector to_png_buffer(const xt::xexpression& e)\n", + "// {\n", + "// const char* temp_filename = \"/tmp/xio_image.png\";\n", + "// xt::dump_image(temp_filename, e);\n", + "// return read_file(temp_filename);\n", + "// }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "// template \n", + "// auto display(const E& e)\n", + "// {\n", + "// xw::image ls_image;\n", + "// ls_image.value = to_png_buffer(e);\n", + "// return ls_image;\n", + "// }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "// auto lightsaber = xt::load_image(\"./images/saber.png\");" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// xw::image ls_image;\n", + "// ls_image.value = to_png_buffer(lightsaber);\n", + "// ls_image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// lightsaber = xt::load_image(\"./images/saber.png\");\n", + "\n", + "// lightsaber = lightsaber * xt::xarray({0.2, 0.8, 0.2});\n", + "\n", + "// ls_image.value = to_png_buffer(lightsaber);" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Memory Layout\n", + "\n", + "- Freely choose row, column-major or custom strides" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "xt::xarray a_cm = {{1,2,3}, {4,5,6}};\n", + "\n", + "std::cout << a_cm << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Container optimizations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// uses a std::array for shape & strides\n", + "#include \n", + "\n", + "xt::xtensor b = {{1, 2, 3}, {4, 5, 6}};\n", + "std::cout << b << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// uses a fixed size container for data (std::array)\n", + "// strides computed constexpr at compile time (no storage)\n", + "#include \n", + "\n", + "xt::xtensor_fixed> c = {{1,2,3}, {4,5,6}};\n", + "std::cout << c << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Views\n", + "\n", + "- powerful views to reference sub-arrays\n", + "- compute shapes statically if possible" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "using namespace xt::placeholders;\n", + "\n", + "std::cout << a << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "std::cout << xt::view(a, 1, xt::all()) << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// numpy equivalent: a[:, ::2]\n", + "std::cout << xt::view(a, xt::all(), xt::range(_, _, 2)) << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "xt::view(a, xt::all(), xt::range(_, _, 2)) *= 100;\n", + "\n", + "std::cout << a << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "std::cout << a << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "std::cout << xt::view(a, xt::keep(0, 0, 0) , xt::all()) << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Adapting a 1D container" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "\n", + "std::vector vdata = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n", + "auto adapted_vdata = xt::adapt(vdata, {3, 3});" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "std::cout << adapted_vdata << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "adapted_vdata(1, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \n", + "\n", + "std::cout << sum(adapted_vdata) << std::endl;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "std::cout << sum(adapted_vdata, {1}) << std::endl;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# NumPy to xtensor Cheatsheet\n", + "\n", + "\n", + "\n", + "Many functions that I haven't discussed:\n", + "\n", + "- More reducers: `mean`, `prod` ...\n", + "- Accumulators: `cumsum`, `cumprod` ...\n", + "- Random numbers, generators\n", + "- Sorting, filtering\n", + "- Optional (masked) values\n", + "- NPY, CSV file format support\n", + "\n", + "https://xtensor.readthedocs.io/en/latest/numpy.html" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# xtensor\n", + "\n", + "- Modular sub-packages:\n", + " - xsimd: for SIMD vectorization support\n", + " (batch classes, hi-speed implementations of trigo, exp, ... functions) \n", + " - Intel TBB: parallelization\n", + "- On top of xtensor:\n", + " - xtensor-blas: bindings to BLAS & LAPACK – matrix multiplication, inverse, svd, ...\n", + " - xtensor-io: image, sound, NPZ, HDF5, (soon video support)\n", + " - xtensor-fftw, xtensor-interpolate and more" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# xtensor as a building block\n", + "\n", + "\n", + "\n", + "- xtensor-python / julia / R\n", + "- Seamlessly use arrays from each language\n", + "- Better performance for dynamic languages" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Binding a Python / NumPy container\n", + "\n", + "```c++\n", + "double sum_of_sines(xt::pyarray& m)\n", + "{\n", + " auto sines = xt::sin(m); // sines does not actually hold values.\n", + " return std::accumulate(sines.begin(), sines.end(), 0.0);\n", + "}\n", + "\n", + "PYBIND11_MODULE(xtensor_python_test, m)\n", + "{\n", + " xt::import_numpy();\n", + " m.doc() = \"Test module for xtensor python bindings\";\n", + "\n", + " m.def(\"sum_of_sines\", sum_of_sines, \"Sum the sines of the input values\");\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# xtensor vs Blitz++\n", + "\n", + "- No runtime dimension container in Blitz (xarray)\n", + "- Blitz++ unmaintained/dead\n", + "- Legacy code, already broken with new compilers" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# xtensor vs Eigen3\n", + "\n", + "- n-Dimensions from the start (Eigen has Tensor Module in /unsupported)\n", + "- modularity vs monolithical Eigen\n", + "- API subjectively \"nicer\", modern C++ features\n", + "- extensibility (Python/Julia/R)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Walkthrough qview + qfunc\n", + "\n", + "- Walk-through a simple template expression engine in C++17\n", + "- Supporting some xtensor mechanisms!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Interactive Widgets in C++\n", + "\n", + "- Easy way to create simple graphical interfaces\n", + "- such as sliders, buttons, boxes ... much more!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "#include \"xwidgets/xslider.hpp\"\n", + "xw::slider slider_exmpl;\n", + "\n", + "slider_exmpl" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \"xwidgets/xslider.hpp\"\n", + "xw::slider slider;\n", + "\n", + "slider" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slider.value = 20; // Modifying properties of widgets triggers the update of the frontend." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slider.value() // Reading the value requires using the call operator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#include \"xcpp/xdisplay.hpp\"\n", + "xcpp::display(slider); // xcpp::display can be called to explicitely trigger a the display of an object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "xcpp::display(slider); // xcpp::display can be called to explicitely trigger a the display of an object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// changine some more properties\n", + "slider.max = 40;\n", + "slider.style().handle_color = \"blue\";\n", + "slider.orientation = \"vertical\";\n", + "slider.description = \"A slider\";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \n", + "#include \"xwidgets/xbutton.hpp\"\n", + "\n", + "xw::button bt;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "void foo()\n", + "{\n", + " std::cout << \"Clicked!\" << std::endl;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bt.on_click(foo);\n", + "bt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bt.description = \"button\";\n", + "bt.button_style = \"success\";" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Value Semantics of Widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xw::button bt_copy = bt;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bt_copy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bt_copy.style().button_color = \"green\";\n", + "bt.style().button_color = \"red\";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \"xwidgets/xdropdown.hpp\"\n", + "\n", + "xw::dropdown dd(std::vector({\"foo\", \"bar\"}), \"foo\");\n", + "\n", + "dd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dd.value()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \"xwidgets/xtab.hpp\"\n", + "#include \"xwidgets/xbutton.hpp\"\n", + "#include \"xwidgets/xslider.hpp\"\n", + "\n", + "xw::tab tabs;\n", + "\n", + "xw::slider tab_slid;\n", + "tabs.add(bt);\n", + "tabs.add(tab_slid);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tabs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tabs.set_title(0, \"zero\");\n", + "tabs.set_title(1, \"one\");" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \"xwidgets/xhtml.hpp\"\n", + "xw::html html;\n", + "\n", + "html.value = R\"xhtml(\n", + "
Some HTML\n", + "
\n", + ")xhtml\";\n", + "\n", + "html" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### xwidgets\n", + "\n", + "- All other base widgets supported:\n", + "\n", + "- TextArea, HTML, Text Input, Password, Box, Gamepad Controller, Color Picker ... " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# More demos\n", + "\n", + "- xplot\n", + "- xleaflet\n", + "- xvolume" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# The future\n", + "\n", + "- Already released: xframe, Pandas-like dataframe in C++\n", + "- More widgets!\n", + "- More bindings!\n", + "- More speed (always!)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Thanks!\n", + "\n", + "Come contribute! \n", + "Or talk to us 24/7 on gitter: https://gitter.im/QuantStack/Lobby\n", + "\n", + "Check out: https://github.com/QuantStack\n", + "\n", + "Twitter: @wuoulf | Github: @wolfv " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# xtensor tricks\n", + "\n", + "- Closure type\n", + "- Keyword arguments\n", + "- SIMDification of Lambdas" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# xtensor move semantics\n", + "\n", + "- xfunction and xview need to decide to store value or reference value\n", + "- closure type: compliment to move semantics of STL\n", + "- perfect forwarding let's you tell who should own memory" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Problem: Dangling reference\n", + "\n", + "```c++\n", + "auto sin_of_1234() {\n", + " xarray tmp = {{1,2}, {3, 4}};\n", + " return xt::sin(tmp);\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "### Solution: Use std::move\n", + "\n", + "```c++\n", + "auto sin_of_1234() {\n", + " xarray tmp = {{1,2}, {3, 4}};\n", + " return xt::sin(std::move(tmp));\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Closure Type\n", + "\n", + "- if lvalue reference: keep reference\n", + "- if rvalue reference, or value: store value\n", + "\n", + "```cpp\n", + "template \n", + "struct closure_type {\n", + " using underlying_type = std::conditional_t<\n", + " std::is_const>::value,\n", + " const std::decay_t,\n", + " std::decay_t>;\n", + " using type = typename std::conditional<\n", + " std::is_lvalue_reference::value,\n", + " underlying_type&,\n", + " underlying_type>::type;\n", + "};\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "```c++\n", + "template \n", + "struct reference_or_store_value {\n", + " CT m_value;\n", + "}\n", + "\n", + "template \n", + "auto func(T&& val) {\n", + " using CT = closure_type_t;\n", + " return reference_or_store_value{ std::forward(val) };\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Problem: keyword args for clean API\n", + "\n", + "- Some functions take many independent arguments\n", + "- E.g. NumPy reduction: \n", + "```python\n", + "np.sum(array, initial=123.0, keep_dims=True,\n", + " evaluation_strategy=\"lazy\")\n", + "```\n", + "\n", + "### Goals\n", + "\n", + "- Arguments unordered\n", + "- Can influence return type – allow tag dispatching\n", + "- Allow for some checking on args\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# C++ Keyword Arguments\n", + "\n", + "- No standard way to do keyword args in C++14\n", + "- C++ designated initializers arrive by C++20 :/\n", + "\n", + "```c++\n", + "struct params { int x; double c = 0.0; };\n", + "\n", + "void func(const params& p);\n", + "\n", + "int main()\n", + "{\n", + " func({.x = 123, .c = 12.5 });\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# C++14 Solution\n", + "\n", + "- Goal: use operator overloading to do something like\n", + "\n", + "```c++\n", + "xt::sum(array, keep_dims | initial(10.0) | rapid_eval);\n", + "```\n", + "- Problem: keep_dims modifies the return type! (`xtensor` vs `xtensor`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "#include \n", + "template