-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Web UI - stage1, readonly part (#606)
* added fastapi as web ui backend * Added cube + benchmark basic listing * Adds navigation * Aded mlcube detailed page * Improved mlcubes detailed layout * Improved mlcube layout * yaml displaying * yaml: spinner * yaml panel improvement * yaml panel layout improvement * layout fixes * Added benchmark detailed page * added links to mlcube * benchmark page: added owner * Colors refactoring * Dataset detailed page * Forgot to add js file * Unified data format for all data fields automatically * (mlcube-detailed) Display image tarball and additional files always * Fixed scrolling and reinvented basic page layout * Fix navbar is hiding * Make templates & static files independent of user's workdir * Added error handling * Display invalid entities correctly * Added invalid entities highlighting + badges * Added benchmark associations * Improved association panel style * Added association card * Sorted associations by status / timestamp * Sorted mlcubes and datasets: mine first * Added associations to dataset page * Added associations to mlcube page * Refactored details page - extracted common styles to the base template * Refactored association sorting to common util * Display my benchmarks first * Hid empty links * Mlcube-as-a-link unified view * resources.path cannot return a dir with subdirs for py3.9 * Fixed resources path for templates also * linter fix * static local resources instead of remote ones * layout fix: align mlcubes vertically * bugfix: add some dependencies for isolated run * Fixes after merging main * MedperfSchema requires a name field * Linter fix * Pass mlcube params instead of url * Pass mlcube parameters to fetch-yaml --------- Co-authored-by: Alejandro Aristizabal <[email protected]>
- Loading branch information
1 parent
9e49f56
commit 01e4617
Showing
43 changed files
with
1,076 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from datetime import datetime | ||
from typing import Optional | ||
|
||
from medperf.entities.schemas import ApprovableSchema, MedperfSchema | ||
|
||
|
||
class Association(MedperfSchema, ApprovableSchema): | ||
id: int | ||
metadata: dict | ||
dataset: Optional[int] | ||
model_mlcube: Optional[int] | ||
benchmark: int | ||
initiated_by: int | ||
created_at: Optional[datetime] | ||
modified_at: Optional[datetime] | ||
name: str = "Association" # The server data doesn't have name, while MedperfSchema requires it |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from importlib import resources | ||
from pathlib import Path | ||
|
||
import typer | ||
from fastapi import FastAPI | ||
from fastapi.responses import RedirectResponse | ||
from fastapi.staticfiles import StaticFiles | ||
|
||
from medperf import config | ||
from medperf.decorators import clean_except | ||
from medperf.web_ui.common import custom_exception_handler | ||
from medperf.web_ui.datasets.routes import router as datasets_router | ||
from medperf.web_ui.benchmarks.routes import router as benchmarks_router | ||
from medperf.web_ui.mlcubes.routes import router as mlcubes_router | ||
from medperf.web_ui.yaml_fetch.routes import router as yaml_fetch_router | ||
|
||
web_app = FastAPI() | ||
|
||
web_app.include_router(datasets_router, prefix="/datasets") | ||
web_app.include_router(benchmarks_router, prefix="/benchmarks") | ||
web_app.include_router(mlcubes_router, prefix="/mlcubes") | ||
web_app.include_router(yaml_fetch_router) | ||
|
||
static_folder_path = Path(resources.files("medperf.web_ui")) / "static" # noqa | ||
web_app.mount( | ||
"/static", | ||
StaticFiles( | ||
directory=static_folder_path, | ||
) | ||
) | ||
|
||
web_app.add_exception_handler(Exception, custom_exception_handler) | ||
|
||
|
||
@web_app.get("/", include_in_schema=False) | ||
def read_root(): | ||
return RedirectResponse(url="/benchmarks/ui") | ||
|
||
|
||
app = typer.Typer() | ||
|
||
|
||
@app.command("run") | ||
@clean_except | ||
def run( | ||
port: int = typer.Option(8100, "--port", help="port to use"), | ||
): | ||
"""Runs a local web UI""" | ||
import uvicorn | ||
uvicorn.run(web_app, host="127.0.0.1", port=port, log_level=config.loglevel) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import logging | ||
|
||
from fastapi import APIRouter | ||
from fastapi.responses import HTMLResponse | ||
from fastapi import Request | ||
|
||
from medperf.entities.benchmark import Benchmark | ||
from medperf.entities.dataset import Dataset | ||
from medperf.entities.cube import Cube | ||
from medperf.account_management import get_medperf_user_data | ||
from medperf.web_ui.common import templates, sort_associations_display | ||
|
||
router = APIRouter() | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
@router.get("/ui", response_class=HTMLResponse) | ||
def benchmarks_ui(request: Request, mine_only: bool = False): | ||
filters = {} | ||
my_user_id = get_medperf_user_data()["id"] | ||
if mine_only: | ||
filters["owner"] = my_user_id | ||
|
||
benchmarks = Benchmark.all( | ||
filters=filters, | ||
) | ||
|
||
benchmarks = sorted(benchmarks, key=lambda x: x.created_at, reverse=True) | ||
# sort by (mine recent) (mine oldish), (other recent), (other oldish) | ||
mine_benchmarks = [d for d in benchmarks if d.owner == my_user_id] | ||
other_benchmarks = [d for d in benchmarks if d.owner != my_user_id] | ||
benchmarks = mine_benchmarks + other_benchmarks | ||
return templates.TemplateResponse("benchmarks.html", {"request": request, "benchmarks": benchmarks}) | ||
|
||
|
||
@router.get("/ui/{benchmark_id}", response_class=HTMLResponse) | ||
def benchmark_detail_ui(request: Request, benchmark_id: int): | ||
benchmark = Benchmark.get(benchmark_id) | ||
data_preparation_mlcube = Cube.get(cube_uid=benchmark.data_preparation_mlcube) | ||
reference_model_mlcube = Cube.get(cube_uid=benchmark.reference_model_mlcube) | ||
metrics_mlcube = Cube.get(cube_uid=benchmark.data_evaluator_mlcube) | ||
datasets_associations = Benchmark.get_datasets_associations(benchmark_uid=benchmark_id) | ||
models_associations = Benchmark.get_models_associations(benchmark_uid=benchmark_id) | ||
|
||
datasets_associations = sort_associations_display(datasets_associations) | ||
models_associations = sort_associations_display(models_associations) | ||
|
||
datasets = {assoc.dataset: Dataset.get(assoc.dataset) for assoc in datasets_associations if assoc.dataset} | ||
models = {assoc.model_mlcube: Cube.get(assoc.model_mlcube) for assoc in models_associations if assoc.model_mlcube} | ||
|
||
return templates.TemplateResponse( | ||
"benchmark_detail.html", | ||
{ | ||
"request": request, | ||
"entity": benchmark, | ||
"entity_name": benchmark.name, | ||
"data_preparation_mlcube": data_preparation_mlcube, | ||
"reference_model_mlcube": reference_model_mlcube, | ||
"metrics_mlcube": metrics_mlcube, | ||
"datasets_associations": datasets_associations, | ||
"models_associations": models_associations, | ||
"datasets": datasets, | ||
"models": models | ||
} | ||
) |
Oops, something went wrong.