<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def launch_on_demand(request, username, notebook_context):
 """See if we have notebook already running this context and if not then launch new one."""

    security_check(request, username)

    settings = request.registry.settings

    notebook_folder = settings.get("pyramid_notebook.notebook_folder", None)
    if not notebook_folder:
        raise RuntimeError("Setting missing: pyramid_notebook.notebook_folder")

    kill_timeout = settings.get("pyramid_notebook.kill_timeout", None)
    if not kill_timeout:
        raise RuntimeError("Setting missing: pyramid_notebook.kill_timeout")

    kill_timeout = int(kill_timeout)

    if not notebook_context:
        notebook_context = {}

    # Override notebook Jinja templates
    if "extra_template_paths" not in notebook_context:
        notebook_context["extra_template_paths"] = [os.path.join(os.path.dirname(__file__), "server", "templates")]

    # Furious invalid state follows if we let this slip through
    assert type(notebook_context["extra_template_paths"]) == list, "Got bad extra_template_paths {}".format(notebook_context["extra_template_paths"])
    notebook_folder = settings.get("pyramid_notebook.notebook_folder", None)
    if not notebook_folder:
        raise RuntimeError("Setting missing: pyramid_notebook.notebook_folder")

    kill_timeout = settings.get("pyramid_notebook.kill_timeout", None)
    if not kill_timeout:
        raise RuntimeError("Setting missing: pyramid_notebook.kill_timeout")

    kill_timeout = int(kill_timeout)

    prepare_notebook_context(request, notebook_context)

    # Configure websockets
    # websocket_url = settings.get("pyramid_notebook.websocket_url")
    # assert websocket_url, "pyramid_notebook.websocket_url setting missing"
    # assert websocket_url.startswith("ws:/") or websocket_url.startswith("wss:/")

    if request.registry.settings.get("pyramid_notebook.websocket_proxy", ""):
        websocket_url = route_to_alt_domain(request, request.host_url)
        websocket_url = websocket_url.replace("http://", "ws://").replace("https://", "wss://")
        notebook_context["websocket_url"] = websocket_url
    else:
        # Connect websockets directly to localhost notebook server, do not try to proxy them
        websocket_url = "ws://localhost:{port}/notebook/"

    # Record the hash of the current parameters, so we know if this user accesses the notebook in this or different context
    if "context_hash" not in notebook_context:
        notebook_context["context_hash"] = make_dict_hash(notebook_context)

    manager = NotebookManager(notebook_folder, kill_timeout=kill_timeout)
    notebook_info, creates = manager.start_notebook_on_demand(username, notebook_context)
    return notebook_info