Getting started¶
scicode-widgets can be installed with:
pip install scwidgets
Important
Jupyter widgets cannot be run within the documentation. 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. Note that also the LaTeX rendering is resolved when running the notebook.
Creating a code exercise¶
This is how a simple coding exercise can look like.
[1]:
from scwidgets import CodeExercise
import matplotlib.pyplot as plt
import numpy as np
# This is what the students sees and can adapt
def sin(x, omega):
import numpy as np
# We already provide the solution for the demo
return np.sin(x*omega)
x = np.linspace(-2*np.pi, 2*np.pi, 100)
def update_func(code_ex):
y = code_ex.code(x, code_ex.parameters["omega"])
ax = code_ex.figure.gca()
ax.plot(x, y)
code_ex = CodeExercise(
code=sin,
outputs=plt.figure(),
parameters={"omega": (0.5, 3.14, 0.1)},
update=update_func,
update_mode="continuous",
title="Sine function",
description="Implements $\\sin(x\\omega)$",
)
code_ex.run_update() # For the demonstration we run the widget one time
display(code_ex)
Please look at exercises section for more information about the exercises that can be created and their customization options.
Check student’s solution¶
You can create checks (like unit tests) to help students verify their solutions:
[2]:
from scwidgets import (
CheckRegistry,
assert_numpy_allclose,
assert_shape,
assert_type,
)
check_registry = CheckRegistry()
def sine(arr):
import numpy as np
return np.cos(arr) # oops! wrong solution
check_code_ex = CodeExercise(
code=sine,
update=lambda code_ex: print(code_ex.code(np.pi)),
check_registry=check_registry,
)
def assert_2pi_periodic() -> str:
out = check_code_ex.code([0, 2*np.pi])
if not np.allclose(out[0], out[1]):
return "Function is not periodic."
return "" # empty strings means it passes
check_registry.add_check(
check_code_ex,
asserts=[
assert_2pi_periodic,
]
)
check_registry.add_check(
check_code_ex,
asserts=[
assert_type, # checks if same type as reference values
assert_shape, # checks if same shape as reference values
assert_numpy_allclose, # checks if allclose to reference values
],
inputs_parameters=[{"arr": np.asarray([0., 0.78539816, 1.57079633, 2.35619449, 3.14159265])}],
outputs_references=[(np.asarray([0., 7.07106781e-01, 1.00000000e+00, 7.07106781e-01, 0.]),)]
)
check_code_ex.run_check()
check_code_ex
[2]:
Please look at the section on how to add checks for all options to create them.
nbgrader integration¶
One can use nbgrader by using their macros.
def sin(arr: np.ndarray):
"""
:param arr: array of arbitrary shape
:return: returns the sine
"""
import numpy as np
### BEGIN SOLUTION
sin_arr = np.sin(arr)
### END SOLUTION
return sin_arr
Then, nbgrader will convert this to
[3]:
def sin(arr: np.ndarray):
"""
:param arr: array of arbitrary shape
:return: returns the sine
"""
import numpy as np
# YOUR CODE HERE
raise NotImplementedError()
return sin_arr
code_ex = CodeExercise(
code=sin
)
display(code_ex)
It requires to add a hook in the config to copy over the student’s answers to the grading subfolder. A step-by-step tutorial how to make an nbgrader project compatible with scwidget can be seen in the repo.