Turn a Jupyter Notebook into a Web App
Tags: python, datascience, tutorial, webdev
Published: 2021-05-04 16:14:27

Let’s say you’re a data scientist, and you’ve been asked to solve a problem. Of course, what you really want is to build an interactive tool, so your colleagues can solve the problem themselves!

In this tutorial, I'll show you how to take a machine-learning model in a Jupyter notebook, and **turn it into a web application** using the [Anvil Uplink](https://anvil.works/docs/uplink?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app).

Here's what we'll do: 
1. Set up a Jupyter notebook
2. Connect it to an [Anvil app](https://anvil.works?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app)
3. Make a user interface

## Setting up the Jupyter Notebook

We'll start with a [pre-existing Jupyter Notebook](https://www.kaggle.com/uysimty/keras-cnn-dog-or-cat-classification) containing a classification model that distinguishes between cats and dogs. You give it an image and it scores it as ‘cat’ or ‘dog’.

(Thanks to [Uysim Ty](https://uysim.com/) for sharing it on Kaggle.)

## Connecting to the Uplink

We'll use the [Anvil Uplink](https://anvil.works/docs/uplink?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app) to connect a Jupyter Notebook to Anvil. It’s a library you can `pip install` on your computer or wherever your Notebook is running.

It allows you to: 
- call functions in your Jupyter Notebook from your Anvil app
- call functions in your Anvil app from your Juypter Notebook - store data in your Anvil app from your Jupyter Notebook 
- use the [Anvil server library](https://anvil.works/docs/server) inside your Jupyter Notebook

It works for any Python process - this happens to be a Jupyter Notebook, but it could be an ordinary Python script, a Flask app, even the Python REPL!

To connect our notebook, we'll first need to enable the Uplink in the [Anvil IDE](https://anvil.works/?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app). 

![Image](https://anvil.works/docs/uplink/img/uplink-dialog-location.png)

This gives us a key that we can then use in our code.

![Image](https://anvil.works/learn/tutorials/img/jupyter-notebook-to-web-app/enable-uplink.png)

We then need to `pip install` the Uplink library on the machine the Jupyter Notebook is running on:

```
pip install anvil-uplink
```

By adding the following lines to our Jupyter notebook, we can connect it to our Anvil app:

```python
import anvil.server

anvil.server.connect('<YOUR-UPLINK-KEY>')
```
Now we can do anything in our Jupyter Notebook that we can do in an Anvil [Server Module](https://anvil.works/docs/server?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app) - call Anvil server functions, store data in [Data Tables](https://anvil.works/docs/data-tables?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app), and define server functions to be called from other parts of the app.

## Loading an image into the Notebook

We'll load an image into the Jupyter Notebook by making an `anvil.server.callable` function in the Jupyter Notebook. It will classify the input image as either a cat or a dog.

```python
import anvil.media

@anvil.server.callable
def classify_image(file):
   with anvil.media.TempFile(file) as filename:
      img = load_img(filename)
```

We’re passing the image in as an Anvil [Media object](https://anvil.works/docs/media?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app), which we then write to a temporary file.

The load_img function loads the file into [Pillow](https://python-pillow.org/), a Python imaging library.

Then we can do a bit of post-processing of the image to get it into a format that the model likes:

```python
    # Inside the classify_image function

    img = img.resize((128, 128), resample=PIL.Image.BICUBIC)
    arr = img_to_array(img)
    arr = np.expand_dims(arr, axis=0)
    arr /= 255
```

Then we can just pass it into our model and return the result:

```python
    # Inside the classify_image function

    score = model.predict(arr)
    return ('dog' if score < 0.5 else 'cat', float(score))
```

## Building a User Interface

We can [drag-and-drop components](https://anvil.works/articles/drag-and-drop-builder?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app) to create a User Interface. It consists of a [FileLoader](https://anvil.works/docs/client/components/basic#fileloader?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app) to upload the images, an [Image](https://anvil.works/docs/client/components/basic#image?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app) to display them, and a [Label](https://anvil.works/docs/client/components/basic#label?utm_source=crosspost:dev.to:/learn/tutorials/jupyter-notebook-to-web-app) to display the classification.

![Image](https://anvil.works/learn/tutorials/img/jupyter-notebook-to-web-app/create-ui-drag-and-drop.png)

## Making the UI call the Notebook

Now we need to write some Python code that runs in the browser so the app responds when an image is loaded in.

We can define an event handler that triggers when the FileLoader gets a new file:

```python
  def file_loader_1_change(self, file, **event_args):
    """This method is called when a new file is loaded into this FileLoader."""
    result, score = anvil.server.call('classify_image', file)
    
    self.result_lbl.text = "%s (%0.2f)" % (result, score)
    self.image_1.source = file
```

The first line calls the `classify_image` function in the Jupyter Notebook, passing in the image file.

Then we display the result (cat or dog) and the score (0 to 1; completely dog or completely cat).

We also put the image file into the Image component so that the user can see their cat or dog (or other cat-or-dog-like image) and decide if they agree with the result.

![Image](https://anvil.works/learn/tutorials/img/jupyter-notebook-to-web-app/its-a-cat.png)

Your app is already published at a private URL, but we can give it a public URL. You can check out this finished app at https://cat-or-dog.anvil.app.

Check out the whole tutorial:

{% youtube yh0B4HjQxOU %}