{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "# Getting started\n", "\n", "scicode-widgets can be installed with:\n", "\n", "```bash\n", " pip install scicode-widgets\n", "```" ] }, { "cell_type": "raw", "id": "1", "metadata": { "editable": true, "raw_mimetype": "text/restructuredtext", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ ".. important::\n", " Jupyter widgets cannot be run within in documentation. To be able to interact with the widget you must run a mybinder instance. To run a mybinder instance of this notebook please use this link https://mybinder.org/v2/gh/osscar-org/scicode-widgets/HEAD?labpath=docs%2Fsrc%2Fgetting_started.ipynb." ] }, { "cell_type": "markdown", "id": "2", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Creating a code execrcise\n", "This is how a simple coding exercise can look like." ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "from scwidgets import CodeExercise\n", "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "# This is what the students sees and can adapt\n", "def sin(x, omega):\n", " import numpy as np\n", " # We provide already the solution for the demo\n", " return np.sin(x*omega)\n", "\n", "\n", "x = np.linspace(-2*np.pi, 2*np.pi, 100)\n", "def update_func(code_ex):\n", " y = code_ex.code(x, code_ex.parameters[\"omega\"])\n", " ax = code_ex.figure.gca()\n", " ax.plot(x, y)\n", "\n", "code_ex = CodeExercise(\n", " code=sin,\n", " outputs=plt.figure(),\n", " parameters={\"omega\": (0.5, 3.14, 0.1)},\n", " update=update_func,\n", " update_mode=\"continuous\",\n", " title=\"Sinus function\",\n", " description=\"Implements $\\\\sin(x\\\\omega)$\",\n", ")\n", "\n", "code_ex.run_update() # For the demonstration we run the widget one time\n", "display(code_ex)" ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "Please look at __[section exercises](./exercises.html)__ for more information about the execrises that can be created and their customization options." ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "## Check students solution\n", "\n", "You can create checks for student that work like unit tests helping the student to verify the students solution" ] }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": { "lines_to_next_cell": 2, "tags": [] }, "outputs": [], "source": [ "from scwidgets import (\n", " CheckRegistry,\n", " assert_numpy_allclose,\n", " assert_shape,\n", " assert_type,\n", ")\n", "\n", "\n", "check_registry = CheckRegistry()\n", "\n", "def sinus(arr):\n", " import numpy as np\n", " return np.cos(arr) # oops! wrong solution\n", "\n", "check_code_ex = CodeExercise(\n", " code=sinus,\n", " update=lambda code_ex: print(code_ex.code(np.pi)),\n", " check_registry=check_registry,\n", ")\n", "\n", "def assert_2pi_periodic() -> str:\n", " out = check_code_ex.code([0, 2*np.pi])\n", " if not np.allclose(out[0], out[1]):\n", " return \"Function is not periodic.\"\n", " return \"\" # empty strings means it passes\n", "\n", "check_registry.add_check(\n", " check_code_ex,\n", " asserts=[\n", " assert_2pi_periodic,\n", " ]\n", ")\n", "\n", "check_registry.add_check(\n", " check_code_ex,\n", " asserts=[\n", " assert_type, # checks if same type as reference values \n", " assert_shape, # checks if same shape as reference values\n", " assert_numpy_allclose, # checks if allclose to reference values\n", " ],\n", " inputs_parameters=[{\"arr\": np.asarray([0., 0.78539816, 1.57079633, 2.35619449, 3.14159265])}],\n", " outputs_references=[(np.asarray([0., 7.07106781e-01, 1.00000000e+00, 7.07106781e-01, 0.]),)]\n", ")\n", "\n", "check_code_ex.run_check()\n", "check_code_ex" ] }, { "cell_type": "markdown", "id": "7", "metadata": { "lines_to_next_cell": 2 }, "source": [ "Please look at the __[section how to add checks](check.html)__ for all options to create checks." ] }, { "cell_type": "markdown", "id": "8", "metadata": { "lines_to_next_cell": 2 }, "source": [ "## nbgrader integration \n", "\n", "One can use nbgrader by using their macros.\n", "\n", "```python\n", "def sin(arr: np.ndarray):\n", " \"\"\"\n", " :param arr: array of arbitrary shape\n", " :return: returns the sinus\n", " \"\"\"\n", " import numpy as np\n", " ### BEGIN SOLUTION\n", " sin_arr = np.sin(arr)\n", " ### END SOLTUION\n", " return sin_arr\n", "```\n", "\n", "Then nbgrader will convert this to" ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": { "tags": [] }, "outputs": [], "source": [ "def sin(arr: np.ndarray):\n", " \"\"\"\n", " :param arr: array of arbitrary shape\n", " :return: returns the sinus\n", " \"\"\"\n", " import numpy as np\n", " # YOUR CODE HERE\n", " raise NotImplementedError()\n", " return sin_arr\n", "\n", "code_ex = CodeExercise(\n", " code=sin\n", ")\n", "\n", "display(code_ex)" ] }, { "cell_type": "markdown", "id": "10", "metadata": { "tags": [] }, "source": [ "It requires to add a hook in the config to copy over the students answers to the grading subfolder. A step-by-step tutorial how to make an nbgrader project compatible with scicode-widget can be seen in the repo TODO." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.11.10" }, "tags": [] }, "nbformat": 4, "nbformat_minor": 5 }