Skip to content

Commit

Permalink
app: first draft of dash app
Browse files Browse the repository at this point in the history
  • Loading branch information
abhidg committed Oct 29, 2024
1 parent a9c0342 commit 5ceb986
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 1 deletion.
77 changes: 76 additions & 1 deletion src/arcmapper/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import os
import time
import socket
import logging
import threading
import subprocess
import webbrowser

import pandas as pd
from waitress import serve
from .app import app
from .arc import read_arc_schema
from .dictionary import read_data_dictionary
from .strategies import tf_idf, sbert

__version__ = "0.1.0"

ARCMAPPER_HOST = os.getenv("ARCMAPPER_HOST", "127.0.0.1")
ARCMAPPER_PORT = int(os.getenv("ARCMAPPER_PORT", 8050))
ARCMAPPER_TIMEOUT = 30


def map(
method: str,
Expand All @@ -20,4 +36,63 @@ def map(
raise ValueError(f"Unknown mapping method: {method}")


__all__ = ["read_arc_schema", "map", "read_data_dictionary"]
def launch_app():
logging.getLogger("waitress.queue").setLevel(logging.ERROR)
serve(app.server, host=ARCMAPPER_HOST, port=ARCMAPPER_PORT)


def launch_subprocess():
logging.getLogger("waitress.queue").setLevel(logging.ERROR)
return subprocess.Popen(
[
"waitress-serve",
"--host",
ARCMAPPER_HOST,
"--port",
str(ARCMAPPER_PORT),
"arcmapper.app:app.server",
]
)


def check_port(host: str, port: int) -> bool:
try:
with socket.create_connection((host, port), timeout=1):
return True
except (OSError, ConnectionRefusedError):
return False


def wait_for_server(
host=ARCMAPPER_HOST, port=ARCMAPPER_PORT, timeout=ARCMAPPER_TIMEOUT
) -> bool:
start_time = time.time()
while time.time() - start_time < timeout:
try:
if check_port(host, port):
return True
except (OSError, ConnectionRefusedError):
time.sleep(1)
raise TimeoutError(f"Server did not start within {timeout} seconds")


def main():
if check_port(ARCMAPPER_HOST, ARCMAPPER_PORT):
logging.info("Port is already in use. Opening browser.")
webbrowser.open(f"http://{ARCMAPPER_HOST}:{ARCMAPPER_PORT}")
return
# Launch the server in a separate thread
server_thread = threading.Thread(target=launch_app)
server_thread.start()
# Wait for startup before opening web browser
wait_for_server(
ARCMAPPER_HOST,
ARCMAPPER_PORT,
ARCMAPPER_TIMEOUT,
)
webbrowser.open(f"http://{ARCMAPPER_HOST}:{ARCMAPPER_PORT}")
# Join the server thread and wait for it to finish or be closed
server_thread.join()


__all__ = ["read_arc_schema", "map", "read_data_dictionary", "main"]
21 changes: 21 additions & 0 deletions src/arcmapper/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import logging
import argparse
from . import main
from .app import app


if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("--debug", action="store_true")
args = p.parse_args()

if args.debug:
# Dash launches a Flask development server
root_logger = logging.getLogger()
if root_logger.hasHandlers():
root_logger.handlers.clear()
logging.basicConfig(level=logging.INFO)
app.run(debug=True)
else:
# Otherwise, launch the production server
main()
39 changes: 39 additions & 0 deletions src/arcmapper/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Dash frontend for the arcmapper library"""

import dash
from dash import html
import dash_bootstrap_components as dbc


app = dash.Dash("arcmapper", external_stylesheets=[dbc.themes.BOOTSTRAP])
app.title = "ARCMapper"

navbar = dbc.Navbar(
dbc.Container(
[
html.A(
# Use row and col to control vertical alignment of logo / brand
dbc.Row(
[
dbc.Col(
html.Img(src="assets/ISARIC_logo_wh.png", height="60px")
),
dbc.Col(dbc.NavbarBrand("ARCMapper", className="ms-2")),
],
align="center",
className="g-0",
),
href="https://isaric.org/",
style={"textDecoration": "none"},
),
dbc.NavbarToggler(id="navbar-toggler", n_clicks=0),
]
),
color="#BA0225",
dark=True,
)

main_content = dbc.Container([dbc.Row([html.H1("Hello world")])])

app.layout = dbc.Container([navbar, main_content])
server = app.server

0 comments on commit 5ceb986

Please sign in to comment.