Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
jose-rfj authored Apr 24, 2024
2 parents 5890150 + 747f1d9 commit 091ff17
Show file tree
Hide file tree
Showing 24 changed files with 122 additions and 131 deletions.
1 change: 0 additions & 1 deletion .github/workflows/blossom-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ jobs:
diazandr3s,\
tangy5,\
wyli,\
pxLi,\
YanxuanLiu,\
', format('{0},', github.actor)) && github.event.comment.body == '/build'
steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docker-plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.8
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: 3.9
- name: clean up
run: |
sudo rm -rf /usr/share/dotnet
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.8
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: 3.9
- name: clean up
run: |
sudo rm -rf /usr/share/dotnet
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
python-version: ["3.8", "3.9"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
Expand All @@ -50,7 +50,7 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
strategy:
matrix:
python-version: ["3.8", "3.9"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
Expand Down Expand Up @@ -83,7 +83,7 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
strategy:
matrix:
python-version: ["3.8", "3.9"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v4
with:
Expand Down
3 changes: 0 additions & 3 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,6 @@ On the local machine follow the commands listed below to install MONAI Label, an
monailabel datasets --download --name Task09_Spleen --output .
# start the bundle app in MONAI label server
# the MONAI Bundle app requires access to MODEL ZOO, please set the authentication token first.
export MONAI_ZOO_AUTH_TOKEN=<Your github auth token>
# and start annotating the images using bundle with the Swin UNETR bundle
monailabel start_server --app monaibundle --studies Task09_Spleen/imagesTr --conf models swin_unetr_btcv_segmentation
Expand Down Expand Up @@ -450,7 +448,6 @@ Prerequisite: Check Model Zoo `Release <https://github.com/Project-MONAI/model-z
# Step 4: start the bundle app in MONAI label server
# the MONAI Bundle app requires access to MODEL ZOO, please set the authentication token first.
export MONAI_ZOO_AUTH_TOKEN=<Your github auth token>
monailabel start_server --app monaibundle --studies Task09_Spleen/imagesTr --conf models renalStructures_UNEST_segmentation
Expand Down
21 changes: 14 additions & 7 deletions monailabel/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import os
import pathlib
from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware import Middleware
Expand Down Expand Up @@ -41,11 +42,24 @@
origins = [str(origin) for origin in settings.MONAI_LABEL_CORS_ORIGINS] if settings.MONAI_LABEL_CORS_ORIGINS else ["*"]
print(f"Allow Origins: {origins}")


@asynccontextmanager
async def lifespan(app: FastAPI):
print("App Init...")
instance = app_instance()
instance.server_mode(True)
instance.on_init_complete()

yield
print("App Shutdown...")


app = FastAPI(
title=settings.MONAI_LABEL_PROJECT_NAME,
openapi_url="/openapi.json",
docs_url=None,
redoc_url="/docs",
lifespan=lifespan,
middleware=[
Middleware(
CORSMiddleware,
Expand Down Expand Up @@ -101,10 +115,3 @@ async def favicon():
def reload():
clear_cache()
return {}


@app.on_event("startup")
async def startup_event():
instance = app_instance()
instance.server_mode(True)
instance.on_init_complete()
17 changes: 10 additions & 7 deletions monailabel/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import os
from typing import Any, Dict, List, Optional

from pydantic import AnyHttpUrl, BaseSettings
from pydantic import AnyHttpUrl
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
Expand All @@ -21,7 +22,7 @@ class Settings(BaseSettings):

MONAI_LABEL_APP_DIR: str = ""
MONAI_LABEL_STUDIES: str = ""
MONAI_LABEL_APP_CONF: Dict[str, str] = {}
MONAI_LABEL_APP_CONF: Dict[str, Any] = {}

MONAI_LABEL_AUTH_ENABLE: bool = False
MONAI_LABEL_AUTH_REALM_URI: str = "http://localhost:8080/realms/monailabel"
Expand Down Expand Up @@ -82,7 +83,7 @@ class Settings(BaseSettings):
MONAI_LABEL_SERVER_PORT: int = 8000
MONAI_LABEL_CORS_ORIGINS: List[AnyHttpUrl] = []

MONAI_LABEL_AUTO_UPDATE_SCORING = True
MONAI_LABEL_AUTO_UPDATE_SCORING: bool = True

MONAI_LABEL_SESSIONS: bool = True
MONAI_LABEL_SESSION_PATH: str = ""
Expand All @@ -93,13 +94,15 @@ class Settings(BaseSettings):
MONAI_LABEL_TRACKING_ENABLED: bool = True
MONAI_LABEL_TRACKING_URI: str = ""

MONAI_ZOO_SOURCE: str = os.environ.get("BUNDLE_DOWNLOAD_SRC", "github")
MONAI_ZOO_SOURCE: str = os.environ.get("BUNDLE_DOWNLOAD_SRC", "monaihosting")
MONAI_ZOO_REPO: str = "Project-MONAI/model-zoo/hosting_storage_v1"
MONAI_ZOO_AUTH_TOKEN: str = ""

class Config:
env_file = ".env"
case_sensitive = True
model_config = SettingsConfigDict(
env_file=".env",
case_sensitive=True,
extra="ignore",
)


settings = Settings()
Expand Down
9 changes: 5 additions & 4 deletions monailabel/datastore/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ def get_dataset_archive(self, limit_cases: Optional[int]) -> str:
path = d[key]
archive.write(path, arcname=os.path.join(key, os.path.basename(path)))
# add metadata
datastore_metadata: str = self._datastore.json(exclude={"base_path"})
datastore_metadata: str = self._datastore.model_dump_json(exclude={"base_path"})
archive.writestr("metadata.json", datastore_metadata)

assert archive.filename is not None, "ZIP archive could not be created"
Expand Down Expand Up @@ -670,7 +670,8 @@ def _init_from_datastore_file(self, throw_exception=False):
ts = os.stat(self._datastore_config_path).st_mtime
if self._config_ts != ts:
logger.debug(f"Reload Datastore; old ts: {self._config_ts}; new ts: {ts}")
self._datastore = LocalDatastoreModel.parse_file(self._datastore_config_path)
with open(self._datastore_config_path) as fp:
self._datastore = LocalDatastoreModel.model_validate_json(fp.read())
self._datastore.base_path = self._datastore_path
self._config_ts = ts
logger.debug("Release the Lock...")
Expand All @@ -684,7 +685,7 @@ def _write_to_file():
logger.debug("+++ Datastore is updated...")
self._ignore_event_config = True
with open(self._datastore_config_path, "w") as f:
f.write(json.dumps(self._datastore.dict(exclude={"base_path"}), indent=2, default=str))
f.write(json.dumps(self._datastore.model_dump(exclude={"base_path"}), indent=2, default=str))
self._config_ts = os.stat(self._datastore_config_path).st_mtime

if lock:
Expand Down Expand Up @@ -716,4 +717,4 @@ def status(self) -> Dict[str, Any]:
}

def json(self):
return self._datastore.dict(exclude={"base_path"})
return self._datastore.model_dump(exclude={"base_path"})
2 changes: 1 addition & 1 deletion monailabel/endpoints/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ async def access_token(form_data: OAuth2PasswordRequestForm = Depends()):

@router.get("/token/valid", summary="Check If current token is Valid")
async def valid_token(user: User = Depends(get_current_user)):
return user.dict()
return user.model_dump()
4 changes: 2 additions & 2 deletions monailabel/endpoints/wsi_infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def run_wsi_inference(

config = instance.info().get("config", {}).get("infer", {})
request.update(config)
request.update(wsi.dict(exclude={"params"}))
request.update(wsi.model_dump(exclude={"params"}))
if wsi.params:
request.update(wsi.params)

Expand Down Expand Up @@ -139,7 +139,7 @@ async def api_run_wsi_v2_inference(
image: str = "",
session_id: str = "",
file: UploadFile = File(None),
wsi: str = Form(WSIInput().json()),
wsi: str = Form(WSIInput().model_dump_json()),
output: Optional[ResultType] = None,
user: User = Depends(RBAC(settings.MONAI_LABEL_AUTH_ROLE_USER)),
):
Expand Down
2 changes: 1 addition & 1 deletion monailabel/interfaces/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ def train(self, request):
if not task:
raise MONAILabelException(
MONAILabelError.INVALID_INPUT,
f"Train Task is not Initialized. There is no model '{model}' available",
f"Train Task is not Initialized. There is no model '{model}' available; {request}",
)

request = copy.deepcopy(request)
Expand Down
2 changes: 1 addition & 1 deletion monailabel/interfaces/utils/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def run_main():
logger.debug("------------------------------------------------------")
logger.debug("SETTINGS")
logger.debug("------------------------------------------------------")
logger.debug(json.dumps(settings.dict(), indent=2))
logger.debug(json.dumps(settings.model_dump(), indent=2))
logger.debug("")

app_dir = args.app if args.app else settings.MONAI_LABEL_APP_DIR
Expand Down
8 changes: 4 additions & 4 deletions monailabel/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def args_start_server(self, parser):
parser.add_argument("--workers", default=None, type=int, help="Number of worker processes")
parser.add_argument("--limit_concurrency", default=None, type=int, help="Max concurrent connections")
parser.add_argument("--access_log", action="store_true", help="Enable access log")
parser.add_argument("--root_path", default="/", help="Application root path")
parser.add_argument("--root_path", default="", help="Application root path")
parser.add_argument("--log_level", default="info", help="Log level")

parser.add_argument("-l", "--log_config", default=None, type=str, help="Logging config")
Expand Down Expand Up @@ -290,7 +290,7 @@ def start_server_validate_args(self, args):
"MONAI_LABEL_DATASTORE_PASSWORD",
"MONAI_LABEL_DATASTORE_API_KEY",
]
for k, v in settings.dict().items():
for k, v in settings.model_dump().items():
v = f"'{json.dumps(v)}'" if isinstance(v, list) or isinstance(v, dict) else v
logger.debug(f"ENV SETTINGS:: {k} = {'*' * len(v) if k in sensitive else v}")
logger.info("")
Expand All @@ -316,7 +316,7 @@ def start_server_init_settings(self, args):
if args.dryrun:
export_key = "set " if any(platform.win32_ver()) else "export "
with open("env.bat" if any(platform.win32_ver()) else ".env", "w") as f:
for k, v in settings.dict().items():
for k, v in settings.model_dump().items():
v = f"'{json.dumps(v)}'" if isinstance(v, list) or isinstance(v, dict) else v
e = f"{export_key}{k}={v}"
f.write(e)
Expand All @@ -338,7 +338,7 @@ def start_server_init_settings(self, args):
logger.debug("**********************************************************")
logger.debug(" ENV VARIABLES/SETTINGS ")
logger.debug("**********************************************************")
for k, v in settings.dict().items():
for k, v in settings.model_dump().items():
if isinstance(v, list) or isinstance(v, dict):
v = json.dumps(v)
elif v is not None:
Expand Down
19 changes: 4 additions & 15 deletions monailabel/utils/others/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,22 +255,11 @@ def is_openslide_supported(name):

def get_zoo_bundle(model_dir, conf, models, conf_key):
zoo_repo = conf.get("zoo_repo", settings.MONAI_ZOO_REPO)
auth_token = conf.get("auth_token", settings.MONAI_ZOO_AUTH_TOKEN)
auth_token = auth_token if auth_token else None
try:
zoo_info = get_all_bundles_list(auth_token=auth_token)
except:
print("")
print("---------------------------------------------------------------------------------------")
print(
"Github access rate limit reached, please provide personal auth token by setting env MONAI_ZOO_AUTH_TOKEN"
)
print("or --conf auth_token <personal auth token>")
exit(-1)
zoo_info = get_all_bundles_list()

# filter model zoo bundle with MONAI Label supported bundles according to the maintaining list, return all version bundles list
available = [i[0] for i in zoo_info if i[0] in MAINTAINED_BUNDLES]
available_with_version = {b: get_bundle_versions(b, auth_token=auth_token)["all_versions"] for b in available}
available_with_version = {b: get_bundle_versions(b)["all_versions"] for b in available}

available_both = available + [k + "_v" + v for k, versions in available_with_version.items() for v in versions]

Expand Down Expand Up @@ -316,7 +305,7 @@ def get_zoo_bundle(model_dir, conf, models, conf_key):
if not os.path.exists(p):
name = k if k in available else version_to_name.get(k)
version = None if k in available else name_to_version.get(k)
download(name=name, version=version, bundle_dir=model_dir, source="github", repo=zoo_repo)
download(name=name, version=version, bundle_dir=model_dir, source="monaihosting", repo=zoo_repo)
if version:
shutil.move(os.path.join(model_dir, name), p)
bundles[k] = p
Expand Down Expand Up @@ -350,7 +339,7 @@ def get_bundle_models(app_dir, conf, conf_key="models"):
models = models.split(",")
models = [m.strip() for m in models]

if zoo_source == "github": # if in github env, access model zoo
if zoo_source == "monaihosting": # if in github env, access model zoo
bundles = get_zoo_bundle(model_dir, conf, models, conf_key)
else: # if not in github env, no "model zoo" access, users either provide bundles locally, or auto download with latest
bundles: Dict[str, str] = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.io.InputStream;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
Expand Down Expand Up @@ -190,7 +191,7 @@ public static Document infer(String model, String image, String imageFile, Strin

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(response.getBytes());
InputStream inputStream = new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8));
Document dom = builder.parse(inputStream);
return dom;
}
Expand Down
8 changes: 4 additions & 4 deletions plugins/slicer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ project(MONAILabel)

#-----------------------------------------------------------------------------
# Extension meta-information
set(EXTENSION_HOMEPAGE "https://github.com/Project-MONAI/MONAILabel/tree/main/plugins/slicer/MONAILabel")
set(EXTENSION_HOMEPAGE "https://github.com/Project-MONAI/MONAILabel/tree/main/plugins/slicer")
set(EXTENSION_CATEGORY "Active Learning")
set(EXTENSION_CONTRIBUTORS "NVIDIA, KCL")
set(EXTENSION_DESCRIPTION "This is Active Learning solution developed under project MONAILabel")
set(EXTENSION_CONTRIBUTORS "Sachidanand Alle (NVIDIA), Andres Diaz-Pinto (KCL), Alvin Ihsani (NVIDIA), Fernando Perez-Garcia (UCL/KCL)")
set(EXTENSION_DESCRIPTION "This extension offers Active Learning solution developed under project MONAILabel (Powered by the NVIDIA, KCL).")
set(EXTENSION_ICONURL "https://github.com/Project-MONAI/MONAILabel/raw/main/plugins/slicer/MONAILabel/Resources/Icons/MONAILabel.png")
set(EXTENSION_SCREENSHOTURLS "https://github.com/Project-MONAI/MONAILabel/raw/main/plugins/slicer/MONAILabel/Screenshots/1.png https://github.com/Project-MONAI/MONAILabel/raw/main/plugins/slicer/MONAILabel/Screenshots/2.png")
set(EXTENSION_SCREENSHOTURLS "https://github.com/Project-MONAI/MONAILabel/raw/main/plugins/slicer/MONAILabel/Screenshots/1.png https://github.com/Project-MONAI/MONAILabel/raw/main/plugins/slicer/MONAILabel/Screenshots/2.png https://github.com/Project-MONAI/MONAILabel/raw/main/plugins/slicer/MONAILabel/Screenshots/3.png")
set(EXTENSION_DEPENDS "NA") # Specified as a list or "NA" if no dependencies

#-----------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 091ff17

Please sign in to comment.