5  Developer notes

This page contains notes for DemoLand developers. You should not need to read this unless you are actively working on the codebase, or maintaining any of the associated systems.

5.1 API specification

The calculation of indicators for custom scenarios in the web app relies on an API. Right now, the web app uses an API which is hosted as an Azure Function.

In particular, the function must accept a POST body that looks like this. Only output areas which are changed relative to the baseline need to be included in the inner JSON object:

{
  "model_identifier": string,
  "scenario_json": {
    output_area_name: {
      "signature_type": int | null,
      "job": float | null,
      "use": float | null,
      "greenspace": float | null
    },
    ...
  }
}

Upon success, this must return a JSON response with the following format (all output areas must be included):

{
  output_area_name: {
    "air_quality": float,
    "house_price": float,
    "job_accessibility": float,
    "greenspace_accessibility": float,
    "signature_type": int
  },
  ...
}

The function demoland_engine.api.scenario_calc() obeys this schema, and both the FastAPI and the Azure Functions apps simply wrap this function.

5.2 FastAPI, local

Note: If you are running the web app in development mode and want to use the ‘Local REST API’ for custom scenario calculation, this is the section to follow.

One way to run the API is to run it locally or over Docker. To do this, there is a FastAPI app located at api/main.py. First make sure you have the optional dependencies for the FastAPI app installed. Go to the top-level directory of the repo and run

python -m pip install .[api]

The [api] instructs pip to install the optional dependencies, which can be seen in pyproject.toml.

Then, again from the top-level directory, run:

uvicorn main:app --app-dir api --port 5178

You should now be able to test the API using:

curl http://localhost:5178/api/scenario -X POST -d "{\"scenario_json\": {}, \"model_identifier\": \"tyne_and_wear\"}" -v -H 'Content-Type: application/json'

(Note that the Content-Type header is mandatory, otherwise FastAPI doesn’t accept the input.)

5.3 FastAPI, over Docker

Dockerfile.api provides the specification for running the FastAPI app over Docker. Simply do:

docker build . -f Dockerfile.api -t demoland-api
docker run -it demoland-api

The Dockerfile is configured to expose the API on port 80 (which is the default port for HTTP), so you can omit the port number when testing:

curl http://localhost/api/scenario -X POST -d "{\"scenario_json\": {}, \"model_identifier\": \"tyne_and_wear\"}" -v -H 'Content-Type: application/json'

5.4 Azure Functions

Note: There is a GitHub Action on the demoland-engine repository which automatically deploys the Azure Function instance from the main branch. You should not need to manually update the Azure Functions deployment, but the steps are kept here in case you need to troubleshoot.

To deploy a new version of the Azure function, make sure you are a member of the “Land Use Indicator” Azure subscription (the subscription ID is 86307bb0-6d16-4077-b1f7-939370d5289a). If you are not, get Dani to add you.

Then, follow these instructions:

  1. Log in to Azure. This will open a browser window where you can log in with your Microsoft account.

     az login
  2. Set your active subscription to the one above:

    az account set -s 86307bb0-6d16-4077-b1f7-939370d5289a
  3. Install the Azure Functions Core Tools. The following Homebrew command works on macOS; for other operating systems, refer to the Azure docs

    brew tap azure/functions
    brew install azure-functions-core-tools@4
  4. Clone the demoland-engine repository (if you don’t already have it), and cd to the top level of the demoland-engine repository. Check that the files function_app.py and local.settings.json are present in the top-level directory.

  5. To test the function locally, run:

    func start

    You should then be able to access the API at http://localhost:7071/api/scenario. For example, you can test it using the following command, which asks it to calculate the baseline indicators (an empty scenario means no changes relative to the baseline):

    curl http://localhost:7071/api/scenario -X POST -d "{\"scenario_json\": {}, \"model_identifier\": \"tyne_and_wear\"}" -v
  6. To deploy it to Azure, run the following, which will take a few minutes:

    func azure functionapp publish demolandapi

    Test it with:

    curl https://demolandapi.azurewebsites.net/api/scenario -X POST -d "{\"scenario_json\": {}, \"model_identifier\": \"tyne_and_wear\"}" -v