In this blog post, I present an idea for remote workshops, which make strong, interactive use of Jupyter Notebooks to teach content: let’s call it for now “discreet assistance”.
Context
The context I am working in is the data-driven analysis of software systems: Software Analytics. Back then, at the time of offline workshops on Software Analytics, I covered large parts with interactive programming exercises. Using Jupyter Notebook and available online platforms like mybinder.org, the technical possibilities are vast. In the workshop, I first introduce the basics of Jupyter Notebook (e. g. the idea, functionality and most important shortcuts), and then I do a small analysis task together with the participants. Here, participants will learn the syntax of Python and pandas and how to apply is at the same time (and much more, which, among others, happens to be in the guide “Teaching and Learning with Jupyter”, which I got to know a few days ago. Great resource!). If something doesn’t work out, I’ll go into detail again at offline events instant and on-demand. With this approach, I get direct feedback during the interactive parts of the workshop.
Context Switch
COVID-19. No more on-site workshops! Although I partly miss traveling and on-site workshops, remote workshops work surprisingly well. I like Miro, for example, very much to involve participants interactively. This has certain parallels to the offline workshops with Jupyter Notebook. But it’s the latter that worries me: the direct feedback channel is no longer there. Moreover, in online video conferences, participants are (it seems to me) also a bit shy when support is needed.
So I was looking for a way to help participants discreetly with interactive Jupyter Notebook exercises without compromising the ease of use of Jupyter Notebook. Together with the online video conference Zoom, I am now pursuing the concept of “discreete assistance” in remote workshops: Participants can engage in the joint analysis tasks and discussions, but always can uncover a possible solution in the notebooks to follow along. Should complications arise, they will have assistance at hand. The following animation gives you an impression how it works:
Discreet assistance in Jupyter Notebook
Implementation
So how does this work? To be honest, it’s a big hack! I used the Unofficial Jupyter Notebook Extensions, a creative way to configure some of its extensions and a little Python script for some magic. Let me take you through the main ideas.
Instructor’s notebook
Because I’m lazy thriving for efficiency, I have one leading notebook with a possible solution to the presented software data analysis. I then convert this notebook in the executed version to a special version. There are two things you have to do in your instructor’s notebook:
- mark the cell with the code (or markdown text, in the case that you want to display an answer instead of code/results) with a special tag (I’ve called this tag “delete”)
- Make a subsequent cell a markdown cell with a heading
Extensions’ configuration
In a minimal configuration, you’ll need two Jupyter Notebook extensions, which “creative” configuration:
Collapsible Headings
The Collapsible Headings extension allows you to collapse cells that have a markdown heading on top. Text in the cell itself will not collapse, but all the following cells that don’t have a markdown heading on the top.
The Collapsible Headings extension in action
I personally didn’t liked all the other down-facing arrows in the notebook because I found them distracting. So I deleted the entry of “font-awesome class for the toggle control icon on uncollapsed (expanded) headings” in the Collapsible Headings configuration.
Freeze
The other extension that is needed is “Freeze”. You can tell Jupyter Notebook not to execute the specific cells and make cells read-only by freezing. For aesthetic reasons, I’ve just changed the color of the frozen code cell’s background to green to make a solution cell better visible.
Both extensions just must be activated and configured. The reminder will be addressed by a little (ugly) Python script.
The Python Script
This is the little helper script I’m currently using to do the magic (please just fly over it. I’ll explain it after the code block; feedback and improvement suggestions very welcome!):
It does mainly two things:
- Make a copy of the instructor’s notebook for the participants
- Put the code cells and their results under a markdown cell with a heading named “SOLUTION” (+ some explaining text)
To avoid work for me as an instructor, the hiding and freezing of cells is done directly with the script. The script is a little bit longer because it works with two kinds of discreet assistance circumstances: code cells (with solution code and displayed results) and markdown cells (with formatted text as result).
In both cases, we need a preceding, new cell (named solution_markdown_cell
) that begins with a markdown heading on top to use the Collapsible Headings feature. This cell is also set to “hidden” (=collapsed) so that participants don’t see the subsequent cells (until the next markdown heading). This cell setting enables the participant to click on the little arrow next to the cell to see the answer.
Bonus: the arrow on the left side disappears, so participants can’t switch back. I think this side effect is a good self-motivational challenge for participants to unlock as few solutions as possible in a notebook.
Further, in the script, there is a different treating for markdown cells and code cells. Markdown cells contain possible answers to questions that are in the notebook. They are just inserted after the solution_markdown_cell
and therefore hidden in the participant’s version of the notebook.
The code cells are treated a little differently because, besides the markdown cell with the solution heading, we also need an empty cell for the participant’s code. So the original cell is deep-copied to have a solution_code_cell
. The solution_code_cell
is frozen and is placed under the empty cell. The original cell is then emptied and added to the notebook, followed by the solution_markdown_cell
and the solution_code_cell
.
All other cells (which don’t have the “delete” tag set) are added as they appear in the notebook’s list of cells as well.
Finally, for aesthetic reasons, the execution_count
is set to None
for all cells.
The script writes the data then back to the new participant’s version of the file.
Summary
I hope I could explain the reasons and the implementation of my discreet assistance approach. I deliberately avoided using grading systems because I think I have a slightly different use case. If you know any alternative solutions for interactive remote Jupyter Notebook sessions, please let me know.
An here is a video that shows the solution in action in a remote workshop setting:
Video demonstrating the discreet assistance feature