Skip to content

Commit

Permalink
Merge branch 'main' into ignite-issue
Browse files Browse the repository at this point in the history
  • Loading branch information
SachidanandAlle authored Nov 21, 2024
2 parents 9c46f01 + d2d7d20 commit 5b78a4d
Show file tree
Hide file tree
Showing 86 changed files with 1,654 additions and 633 deletions.
24 changes: 20 additions & 4 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,24 @@
__pycache__
.idea
.vscode

Dockerfile
sample-apps/**/model
node_modules
.webpack
node_modules/
*.log

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
.venv/
ubuntu_venv/

# apps
sample-apps/*/logs
sample-apps/*/train
sample-apps/*/model
docs/build
docs/source/apidocs
2 changes: 1 addition & 1 deletion .github/workflows/blossom-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
github.actor == 'diazandr3s' ||
github.actor == 'tangy5' ||
github.actor == 'wyli' ||
github.actor == 'YanxuanLiu'
github.actor == 'wendell-hom'
)
steps:
- name: Check if comment is issued by authorized person
Expand Down
25 changes: 11 additions & 14 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,23 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: clean up
- name: Cleanup
run: |
sudo rm -rf /usr/share/dotnet
echo Before Cleanup...
df -h
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
- name: Install dependencies
run: |
python -m pip install --upgrade pip wheel
rm -rf /opt/hostedtoolcache
rm -rf /usr/share/dotnet/
cd /opt
find . -maxdepth 1 -mindepth 1 '!' -path ./containerd '!' -path ./actionarchivecache '!' -path ./runner '!' -path ./runner-cache -exec rm -rf '{}' ';'
cd -
echo After Cleanup...
df -h
- name: Build
run: |
rm -rf /opt/hostedtoolcache
./runtests.sh --clean
docker system prune -f
DOCKER_BUILDKIT=1 docker build -t projectmonai/monailabel:${{ github.event.inputs.tag || 'latest' }} -f Dockerfile .
DOCKER_BUILDKIT=0 docker build -t projectmonai/monailabel:${{ github.event.inputs.tag || 'latest' }} -f Dockerfile .
- name: Verify
run: |
./runtests.sh --clean
docker run --rm -i --ipc=host --net=host -v $(pwd):/workspace projectmonai/monailabel:${{ github.event.inputs.tag || 'latest' }} /workspace/runtests.sh --net
- name: Publish
run: |
Expand Down
19 changes: 13 additions & 6 deletions .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ jobs:
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- if: runner.os == 'Linux'
name: Cleanup (Linux only)
run: |
rm -rf /opt/hostedtoolcache
- name: Install dependencies
run: |
python -m pip install --upgrade pip wheel
Expand All @@ -50,7 +54,7 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
Expand All @@ -59,6 +63,7 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
rm -rf /opt/hostedtoolcache
sudo apt-get install openslide-tools -y
python -m pip install --upgrade pip wheel
pip install -r requirements-dev.txt
Expand All @@ -72,7 +77,7 @@ jobs:
run: |
$(pwd)/runtests.sh --unittests
- name: Upload coverage
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
fail_ci_if_error: false
file: ./coverage.xml
Expand All @@ -83,7 +88,7 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -107,9 +112,10 @@ jobs:
key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }}
- name: Install dependencies
run: |
rm -rf /opt/hostedtoolcache
sudo apt-get install openslide-tools -y
python -m pip install --user --upgrade pip setuptools wheel
python -m pip install torch>=1.7 torchvision
python -m pip install torch torchvision
- name: Build Package
run: |
./runtests.sh --clean
Expand Down Expand Up @@ -144,7 +150,7 @@ jobs:
MONAI_ZOO_AUTH_TOKEN: ${{ github.token }}
strategy:
matrix:
python-version: ["3.9"]
python-version: ["3.10"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
Expand All @@ -165,6 +171,7 @@ jobs:
key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }}
- name: Install dependencies
run: |
rm -rf /opt/hostedtoolcache
sudo apt-get install openslide-tools -y
python -m pip install --upgrade pip wheel
python -m pip install -r docs/requirements.txt
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ jobs:
key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }}
- name: Install dependencies
run: |
rm -rf /opt/hostedtoolcache
sudo apt-get install openslide-tools -y
python -m pip install --user --upgrade pip setuptools wheel
python -m pip install torch>=1.7 torchvision
python -m pip install torch torchvision
- name: Build Package
run: |
rm -rf /opt/hostedtoolcache
./runtests.sh --clean
BUILD_OHIF=true python setup.py sdist bdist_wheel --build-number $(date +'%Y%m%d%H%M')
ls -l dist
Expand Down Expand Up @@ -91,7 +91,7 @@ jobs:
run: |
rm dist/monai*.tar.gz
- name: Publish distribution to Test PyPI
- name: Publish distribution to Test
if: ${{ github.event.inputs.test_py == 'true' }}
uses: pypa/gh-action-pypi-publish@master
with:
Expand Down
10 changes: 3 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ venv/
ENV/
env.bak/
venv.bak/
.venv/
ubuntu_venv/

# Spyder project settings
.spyderproject
Expand All @@ -139,12 +141,6 @@ dmypy.json
# Pyre type checker
.pyre/

# virtualenv
.venv/
venv/
ENV/
ubuntu_venv/

# IDE
.idea/
.vscode/
Expand All @@ -166,7 +162,7 @@ junit
test-output.xml
studies
tests/data
yarn.lock

# Packages
node_modules
yarn.lock
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "3.8"
python: "3.10"

# Build documentation in the docs/ directory with Sphinx
sphinx:
Expand Down
40 changes: 24 additions & 16 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,37 @@

# To build with a different base image
# please run `./runtests.sh --clean && DOCKER_BUILDKIT=1 docker build -t projectmonai/monailabel:latest .`
# to use different version of MONAI pass `--build-arg MONAI_IMAGE=...`

ARG MONAI_IMAGE=projectmonai/monai:1.4.0
# to use different version of MONAI pass `--build-arg FINAL_IMAGE=...`

#ARG FINAL_IMAGE=pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime
ARG FINAL_IMAGE=ubuntu:22.04
ARG BUILD_IMAGE=python:3.10
ARG NODE_IMAGE=node:slim

FROM ${NODE_IMAGE} as ohifbuild
ADD . /opt/monailabel
# Phase1: Build OHIF Viewer
FROM ${NODE_IMAGE} AS ohifbuild
COPY plugins/ohifv3 /opt/ohifv3
RUN apt update -y && apt install -y git
RUN cd /opt/monailabel/plugins/ohifv3 && ./build.sh

FROM ${MONAI_IMAGE} as build
LABEL maintainer="[email protected]"
RUN cd /opt/ohifv3 && ./build.sh /opt/ohifv3/release

# Phase2: Build MONAI Label Package
FROM ${BUILD_IMAGE} AS build
WORKDIR /opt/monailabel
RUN python -m pip install pip setuptools wheel twine
ADD . /opt/monailabel/
COPY --from=ohifbuild /opt/monailabel/monailabel/endpoints/static/ohif /opt/monailabel/monailabel/endpoints/static/ohif
RUN python -m pip install --upgrade --no-cache-dir pip setuptools wheel twine \
&& cd /opt/monailabel \
&& BUILD_OHIF=false python setup.py sdist bdist_wheel --build-number $(date +'%Y%m%d%H%M')
COPY --from=ohifbuild /opt/ohifv3/release /opt/monailabel/monailabel/endpoints/static/ohif
RUN BUILD_OHIF=false python setup.py bdist_wheel --build-number $(date +'%Y%m%d%H%M')

FROM ${MONAI_IMAGE}
# Phase3: Build Final Docker
FROM ${FINAL_IMAGE}
LABEL maintainer="[email protected]"
WORKDIR /opt/monailabel
COPY requirements.txt /opt/monailabel/requirements.txt

RUN apt update -y && apt install -y git curl openslide-tools python3 python-is-python3 python3-pip
RUN python -m pip install --no-cache-dir pytest torch torchvision torchaudio

COPY --from=build /opt/monailabel/dist/monailabel* /opt/monailabel/dist/
RUN python -m pip install --upgrade --no-cache-dir pip \
&& python -m pip install /opt/monailabel/dist/monailabel*.whl
RUN python -m pip install -v --no-cache-dir /opt/monailabel/dist/monailabel*.whl
RUN python -m pip uninstall sam2 -y
RUN python -m pip install -v --no-cache-dir -r /opt/monailabel/requirements.txt
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ In addition, you can find a table of the basic supported fields, modalities, vie
<li>Segmentation</li>
<li>DeepGrow</li>
<li>DeepEdit</li>
<li>SAM2 (2D/3D)</li>
</ul>
</td>
<td>
Expand Down Expand Up @@ -114,6 +115,7 @@ In addition, you can find a table of the basic supported fields, modalities, vie
<li>NuClick</li>
<li>Segmentation</li>
<li>Classification</li>
<li>SAM2 (2D)</li>
</ul>
</td>
<td>
Expand Down Expand Up @@ -143,6 +145,7 @@ In addition, you can find a table of the basic supported fields, modalities, vie
<li>DeepEdit</li>
<li>Tooltracking</li>
<li>InBody/OutBody</li>
<li>SAM2 (2D)</li>
</ul>
</td>
<td>
Expand Down Expand Up @@ -210,6 +213,19 @@ To install the _**latest features**_ using one of the following options:
<pre>docker run --gpus all --rm -ti --ipc=host --net=host projectmonai/monailabel:latest bash</pre>
</details>

### SAM-2

> By default, [**SAM2**](https://github.com/facebookresearch/sam2/) model is included for all the Apps when **_python >= 3.10_**
> - **sam_2d**: for any organ or tissue and others over a given slice/2D image.
> - **sam_3d**: to support SAM2 propagation over multiple slices (Radiology/MONAI-Bundle).
If you are using `pip install monailabel` by default it uses [SAM-2](https://huggingface.co/facebook/sam2-hiera-large) models.
<br/>
To use [SAM-2.1](https://huggingface.co/facebook/sam2.1-hiera-large) use one of following options.
- Use monailabel [Docker](https://hub.docker.com/r/projectmonai/monailabel) instead of pip package
- Run monailabel in dev mode (git checkout)
- If you have installed monailabel via pip then uninstall **_sam2_** package `pip uninstall sam2` and then run `pip install -r requirements.txt` or install latest **SAM-2** from it's [github](https://github.com/facebookresearch/sam2/tree/main?tab=readme-ov-file#installation).

## Step 2 MONAI Label Sample Applications

<h3>Radiology</h3>
Expand Down
Binary file modified docs/images/dsa.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/quickstart/monai-label-plugin-favorite-modules-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/qupath.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/sample-apps/deepedit_brain_tumor.png
Binary file not shown.
Binary file removed docs/images/sample-apps/deepedit_left_atrium.png
Binary file not shown.
Binary file removed docs/images/sample-apps/deepedit_left_ventricle.png
Binary file not shown.
Binary file removed docs/images/sample-apps/deepedit_lungs.png
Binary file not shown.
Binary file removed docs/images/sample-apps/deepedit_spleen.png
Binary file not shown.
Binary file removed docs/images/sample-apps/deepedit_vertebra.png
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions monailabel/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ def infer(self, model, image_id, params, label_in=None, file=None, session_id=No
fields = {"params": json.dumps(params) if params else "{}"}
files = {"label": label_in} if label_in else {}
files.update({"file": file} if file and not session_id else {})
logger.info(f"Files: {files}")

status, form, files, _ = MONAILabelUtils.http_multipart(
"POST", self._server_url, selector, fields, files, headers=self._headers
Expand Down Expand Up @@ -584,6 +585,9 @@ def send_response(conn, content_type="application/json"):

@staticmethod
def save_result(files, tmpdir):
if not files:
return None

for name in files:
data = files[name]
result_file = os.path.join(tmpdir, name)
Expand Down
19 changes: 18 additions & 1 deletion monailabel/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
from importlib.metadata import distributions
from typing import Any, Dict, List, Optional

from pydantic import AnyHttpUrl
from pydantic_settings import BaseSettings, SettingsConfigDict


def is_package_installed(name):
return name in sorted(x.name for x in distributions())


class Settings(BaseSettings):
MONAI_LABEL_API_STR: str = ""
MONAI_LABEL_PROJECT_NAME: str = "MONAILabel"
Expand Down Expand Up @@ -98,6 +102,19 @@ class Settings(BaseSettings):
MONAI_ZOO_REPO: str = "Project-MONAI/model-zoo/hosting_storage_v1"
MONAI_ZOO_AUTH_TOKEN: str = ""

# Refer: https://github.com/facebookresearch/sam2?tab=readme-ov-file#model-description
# Refer: https://huggingface.co/facebook/sam2-hiera-large
MONAI_SAM_MODEL_PT: str = (
"https://huggingface.co/facebook/sam2.1-hiera-large/resolve/main/sam2.1_hiera_large.pt"
if is_package_installed("SAM-2")
else "https://huggingface.co/facebook/sam2-hiera-large/resolve/main/sam2_hiera_large.pt"
)
MONAI_SAM_MODEL_CFG: str = (
"https://huggingface.co/facebook/sam2.1-hiera-large/resolve/main/sam2.1_hiera_l.yaml"
if is_package_installed("SAM-2")
else "https://huggingface.co/facebook/sam2-hiera-large/resolve/main/sam2_hiera_l.yaml"
)

model_config = SettingsConfigDict(
env_file=".env",
case_sensitive=True,
Expand Down
6 changes: 2 additions & 4 deletions monailabel/endpoints/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,8 @@ def send_response(datastore, result, output, background_tasks):
if output == "json":
return res_json

m_type = get_mime_type(res_img)

if output == "image":
return FileResponse(res_img, media_type=m_type, filename=os.path.basename(res_img))
return FileResponse(res_img, media_type=get_mime_type(res_img), filename=os.path.basename(res_img))

if output == "dicom_seg":
res_dicom_seg = result.get("dicom_seg")
Expand All @@ -106,7 +104,7 @@ def send_response(datastore, result, output, background_tasks):
res_fields = dict()
res_fields["params"] = (None, json.dumps(res_json), "application/json")
if res_img and os.path.exists(res_img):
res_fields["image"] = (os.path.basename(res_img), open(res_img, "rb"), m_type)
res_fields["image"] = (os.path.basename(res_img), open(res_img, "rb"), get_mime_type(res_img))
else:
logger.info(f"Return only Result Json as Result Image is not available: {res_img}")
return res_json
Expand Down
Loading

0 comments on commit 5b78a4d

Please sign in to comment.